From 710ad8ce1bd5d01ce048851d210ac3831ca17dde Mon Sep 17 00:00:00 2001 From: Andrew Knight Date: Wed, 3 Apr 2013 19:57:09 +0300 Subject: Upgrade ANGLE to DX11 Proto Upgrades ANGLE to dx11proto (dx11-MRT-support tag), which splits out support for DirectX9 & DirectX11. The DX9 codepath is used by default; CONFIG+=angle_d3d11 must be passed to the ANGLE project to build for DX11. Existing patches to ANGLE have been updated (or removed if no longer needed), and a patch has been added to make DX9/DX11 codepaths mutually exclusive. Change-Id: Ibe13befadb94f04883eca449d0ee1f0da955ff92 Reviewed-by: Oswald Buddenhagen Reviewed-by: Gunnar Sletta Reviewed-by: Friedemann Kleint Reviewed-by: Axel Waggershauser --- src/3rdparty/angle/.gitignore | 21 +- src/3rdparty/angle/include/GLES2/gl2ext.h | 46 + src/3rdparty/angle/include/GLSLANG/ShaderLang.h | 103 +- src/3rdparty/angle/src/common/angleutils.h | 28 + src/3rdparty/angle/src/common/debug.cpp | 15 +- src/3rdparty/angle/src/common/debug.h | 7 + src/3rdparty/angle/src/common/system.h | 26 + src/3rdparty/angle/src/common/version.h | 6 +- src/3rdparty/angle/src/compiler/BaseTypes.h | 6 +- src/3rdparty/angle/src/compiler/CodeGenHLSL.cpp | 10 +- src/3rdparty/angle/src/compiler/Compiler.cpp | 43 +- src/3rdparty/angle/src/compiler/ConstantUnion.h | 3 +- .../angle/src/compiler/DetectDiscontinuity.cpp | 22 +- .../angle/src/compiler/DetectDiscontinuity.h | 2 + src/3rdparty/angle/src/compiler/Diagnostics.cpp | 2 +- src/3rdparty/angle/src/compiler/Diagnostics.h | 2 +- src/3rdparty/angle/src/compiler/DirectiveHandler.h | 2 +- .../angle/src/compiler/ExtensionBehavior.h | 2 +- src/3rdparty/angle/src/compiler/ForLoopUnroll.cpp | 4 +- src/3rdparty/angle/src/compiler/HashNames.h | 19 + src/3rdparty/angle/src/compiler/Initialize.cpp | 2 + src/3rdparty/angle/src/compiler/Intermediate.cpp | 40 +- .../angle/src/compiler/MapLongVariableNames.cpp | 6 +- .../angle/src/compiler/MapLongVariableNames.h | 2 +- src/3rdparty/angle/src/compiler/OutputESSL.cpp | 8 +- src/3rdparty/angle/src/compiler/OutputESSL.h | 6 +- src/3rdparty/angle/src/compiler/OutputGLSL.cpp | 8 +- src/3rdparty/angle/src/compiler/OutputGLSL.h | 6 +- src/3rdparty/angle/src/compiler/OutputGLSLBase.cpp | 168 +- src/3rdparty/angle/src/compiler/OutputGLSLBase.h | 25 +- src/3rdparty/angle/src/compiler/OutputHLSL.cpp | 1304 +++++--- src/3rdparty/angle/src/compiler/OutputHLSL.h | 35 +- src/3rdparty/angle/src/compiler/ParseHelper.cpp | 17 +- src/3rdparty/angle/src/compiler/ParseHelper.h | 5 +- src/3rdparty/angle/src/compiler/ShHandle.h | 23 +- src/3rdparty/angle/src/compiler/ShaderLang.cpp | 113 +- src/3rdparty/angle/src/compiler/SymbolTable.h | 16 +- src/3rdparty/angle/src/compiler/TranslatorESSL.cpp | 5 +- src/3rdparty/angle/src/compiler/TranslatorGLSL.cpp | 5 +- src/3rdparty/angle/src/compiler/TranslatorHLSL.cpp | 9 +- src/3rdparty/angle/src/compiler/TranslatorHLSL.h | 11 +- src/3rdparty/angle/src/compiler/Types.h | 37 + .../angle/src/compiler/UnfoldShortCircuit.cpp | 10 +- src/3rdparty/angle/src/compiler/Uniform.cpp | 21 + src/3rdparty/angle/src/compiler/Uniform.h | 35 + .../angle/src/compiler/ValidateLimitations.cpp | 2 +- src/3rdparty/angle/src/compiler/VariableInfo.cpp | 34 +- src/3rdparty/angle/src/compiler/VariableInfo.h | 5 +- src/3rdparty/angle/src/compiler/VariablePacker.cpp | 2 +- src/3rdparty/angle/src/compiler/glslang.h | 2 +- src/3rdparty/angle/src/compiler/glslang.l | 170 +- src/3rdparty/angle/src/compiler/glslang.y | 41 +- src/3rdparty/angle/src/compiler/intermOut.cpp | 2 +- src/3rdparty/angle/src/compiler/intermediate.h | 29 +- src/3rdparty/angle/src/compiler/osinclude.h | 21 +- src/3rdparty/angle/src/compiler/ossource_nspr.cpp | 43 - src/3rdparty/angle/src/compiler/parseConst.cpp | 7 + .../src/compiler/preprocessor/DiagnosticsBase.cpp | 127 + .../src/compiler/preprocessor/DiagnosticsBase.h | 87 + .../compiler/preprocessor/DirectiveHandlerBase.cpp | 16 + .../compiler/preprocessor/DirectiveHandlerBase.h | 43 + .../src/compiler/preprocessor/DirectiveParser.cpp | 932 ++++++ .../src/compiler/preprocessor/DirectiveParser.h | 82 + .../src/compiler/preprocessor/ExpressionParser.h | 34 + .../src/compiler/preprocessor/ExpressionParser.y | 285 ++ .../angle/src/compiler/preprocessor/Input.cpp | 54 + .../angle/src/compiler/preprocessor/Input.h | 49 + .../angle/src/compiler/preprocessor/Lexer.cpp | 16 + .../angle/src/compiler/preprocessor/Lexer.h | 25 + .../angle/src/compiler/preprocessor/Macro.cpp | 23 + .../angle/src/compiler/preprocessor/Macro.h | 44 + .../src/compiler/preprocessor/MacroExpander.cpp | 370 ++ .../src/compiler/preprocessor/MacroExpander.h | 75 + .../src/compiler/preprocessor/Preprocessor.cpp | 142 + .../angle/src/compiler/preprocessor/Preprocessor.h | 51 + .../src/compiler/preprocessor/SourceLocation.h | 38 + .../angle/src/compiler/preprocessor/Token.cpp | 83 + .../angle/src/compiler/preprocessor/Token.h | 106 + .../angle/src/compiler/preprocessor/Tokenizer.h | 58 + .../angle/src/compiler/preprocessor/Tokenizer.l | 342 ++ .../angle/src/compiler/preprocessor/atom.c | 737 ---- .../angle/src/compiler/preprocessor/atom.h | 63 - .../angle/src/compiler/preprocessor/compile.h | 100 - src/3rdparty/angle/src/compiler/preprocessor/cpp.c | 1118 ------- src/3rdparty/angle/src/compiler/preprocessor/cpp.h | 86 - .../angle/src/compiler/preprocessor/cppstruct.c | 152 - .../angle/src/compiler/preprocessor/memory.c | 158 - .../angle/src/compiler/preprocessor/memory.h | 58 - .../src/compiler/preprocessor/new/Diagnostics.cpp | 127 - .../src/compiler/preprocessor/new/Diagnostics.h | 87 - .../compiler/preprocessor/new/DirectiveHandler.cpp | 16 - .../compiler/preprocessor/new/DirectiveHandler.h | 43 - .../compiler/preprocessor/new/DirectiveParser.cpp | 932 ------ .../compiler/preprocessor/new/DirectiveParser.h | 82 - .../compiler/preprocessor/new/ExpressionParser.h | 34 - .../compiler/preprocessor/new/ExpressionParser.y | 279 -- .../angle/src/compiler/preprocessor/new/Input.cpp | 55 - .../angle/src/compiler/preprocessor/new/Input.h | 48 - .../angle/src/compiler/preprocessor/new/Lexer.cpp | 16 - .../angle/src/compiler/preprocessor/new/Lexer.h | 25 - .../angle/src/compiler/preprocessor/new/Macro.cpp | 23 - .../angle/src/compiler/preprocessor/new/Macro.h | 44 - .../compiler/preprocessor/new/MacroExpander.cpp | 370 -- .../src/compiler/preprocessor/new/MacroExpander.h | 75 - .../src/compiler/preprocessor/new/Preprocessor.cpp | 142 - .../src/compiler/preprocessor/new/Preprocessor.h | 49 - .../src/compiler/preprocessor/new/SourceLocation.h | 38 - .../angle/src/compiler/preprocessor/new/Token.cpp | 83 - .../angle/src/compiler/preprocessor/new/Token.h | 106 - .../src/compiler/preprocessor/new/Tokenizer.h | 58 - .../src/compiler/preprocessor/new/Tokenizer.l | 340 -- .../src/compiler/preprocessor/new/numeric_lex.h | 61 - .../angle/src/compiler/preprocessor/new/pp_utils.h | 18 - .../angle/src/compiler/preprocessor/numeric_lex.h | 61 + .../angle/src/compiler/preprocessor/parser.h | 93 - .../angle/src/compiler/preprocessor/pp_utils.h | 18 + .../angle/src/compiler/preprocessor/preprocess.h | 50 - .../angle/src/compiler/preprocessor/scanner.c | 698 ---- .../angle/src/compiler/preprocessor/scanner.h | 81 - .../angle/src/compiler/preprocessor/slglobals.h | 82 - .../angle/src/compiler/preprocessor/symbols.c | 288 -- .../angle/src/compiler/preprocessor/symbols.h | 111 - .../angle/src/compiler/preprocessor/tokens.c | 467 --- .../angle/src/compiler/preprocessor/tokens.h | 90 - src/3rdparty/angle/src/libEGL/Config.cpp | 117 +- src/3rdparty/angle/src/libEGL/Config.h | 15 +- src/3rdparty/angle/src/libEGL/Display.cpp | 874 +---- src/3rdparty/angle/src/libEGL/Display.h | 94 +- src/3rdparty/angle/src/libEGL/ShaderCache.h | 116 - src/3rdparty/angle/src/libEGL/Surface.cpp | 432 +-- src/3rdparty/angle/src/libEGL/Surface.h | 34 +- src/3rdparty/angle/src/libEGL/libEGL.cpp | 258 +- src/3rdparty/angle/src/libEGL/main.cpp | 3 +- src/3rdparty/angle/src/libEGL/main.h | 3 +- src/3rdparty/angle/src/libGLESv2/BinaryStream.h | 3 - src/3rdparty/angle/src/libGLESv2/Blit.cpp | 518 --- src/3rdparty/angle/src/libGLESv2/Blit.h | 94 - src/3rdparty/angle/src/libGLESv2/Buffer.cpp | 72 +- src/3rdparty/angle/src/libGLESv2/Buffer.h | 42 +- src/3rdparty/angle/src/libGLESv2/Context.cpp | 2867 ++++------------ src/3rdparty/angle/src/libGLESv2/Context.h | 248 +- .../angle/src/libGLESv2/D3DConstantTable.cpp | 231 -- .../angle/src/libGLESv2/D3DConstantTable.h | 117 - src/3rdparty/angle/src/libGLESv2/Fence.cpp | 104 +- src/3rdparty/angle/src/libGLESv2/Fence.h | 18 +- .../angle/src/libGLESv2/Float16ToFloat32.cpp | 1 + .../angle/src/libGLESv2/Float16ToFloat32.py | 8 +- src/3rdparty/angle/src/libGLESv2/Framebuffer.cpp | 361 +- src/3rdparty/angle/src/libGLESv2/Framebuffer.h | 69 +- .../angle/src/libGLESv2/HandleAllocator.cpp | 1 + .../angle/src/libGLESv2/IndexDataManager.cpp | 473 --- .../angle/src/libGLESv2/IndexDataManager.h | 149 - src/3rdparty/angle/src/libGLESv2/Program.cpp | 27 +- src/3rdparty/angle/src/libGLESv2/Program.h | 15 +- src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp | 1782 +++++----- src/3rdparty/angle/src/libGLESv2/ProgramBinary.h | 145 +- src/3rdparty/angle/src/libGLESv2/Query.cpp | 98 +- src/3rdparty/angle/src/libGLESv2/Query.h | 17 +- src/3rdparty/angle/src/libGLESv2/Renderbuffer.cpp | 230 +- src/3rdparty/angle/src/libGLESv2/Renderbuffer.h | 64 +- .../angle/src/libGLESv2/ResourceManager.cpp | 18 +- src/3rdparty/angle/src/libGLESv2/ResourceManager.h | 24 +- src/3rdparty/angle/src/libGLESv2/Shader.cpp | 79 +- src/3rdparty/angle/src/libGLESv2/Shader.h | 26 +- src/3rdparty/angle/src/libGLESv2/Texture.cpp | 2309 ++----------- src/3rdparty/angle/src/libGLESv2/Texture.h | 242 +- src/3rdparty/angle/src/libGLESv2/TextureSSE2.cpp | 100 - src/3rdparty/angle/src/libGLESv2/Uniform.cpp | 43 + src/3rdparty/angle/src/libGLESv2/Uniform.h | 48 + .../angle/src/libGLESv2/VertexDataManager.cpp | 783 ----- .../angle/src/libGLESv2/VertexDataManager.h | 169 - src/3rdparty/angle/src/libGLESv2/angletypes.h | 128 + src/3rdparty/angle/src/libGLESv2/constants.h | 34 + src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp | 1390 ++++---- src/3rdparty/angle/src/libGLESv2/libGLESv2.def | 3 + src/3rdparty/angle/src/libGLESv2/libGLESv2d.def | 2 + src/3rdparty/angle/src/libGLESv2/main.cpp | 35 +- src/3rdparty/angle/src/libGLESv2/main.h | 40 +- src/3rdparty/angle/src/libGLESv2/mathutil.h | 22 +- src/3rdparty/angle/src/libGLESv2/precompiled.cpp | 9 + src/3rdparty/angle/src/libGLESv2/precompiled.h | 45 + src/3rdparty/angle/src/libGLESv2/renderer/Blit.cpp | 595 ++++ src/3rdparty/angle/src/libGLESv2/renderer/Blit.h | 94 + .../angle/src/libGLESv2/renderer/BufferStorage.cpp | 40 + .../angle/src/libGLESv2/renderer/BufferStorage.h | 44 + .../src/libGLESv2/renderer/BufferStorage11.cpp | 342 ++ .../angle/src/libGLESv2/renderer/BufferStorage11.h | 56 + .../src/libGLESv2/renderer/BufferStorage9.cpp | 75 + .../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/FenceImpl.h | 45 + .../angle/src/libGLESv2/renderer/Image.cpp | 548 +++ src/3rdparty/angle/src/libGLESv2/renderer/Image.h | 131 + .../angle/src/libGLESv2/renderer/Image11.cpp | 457 +++ .../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/ImageSSE2.cpp | 100 + .../angle/src/libGLESv2/renderer/IndexBuffer.cpp | 202 ++ .../angle/src/libGLESv2/renderer/IndexBuffer.h | 137 + .../angle/src/libGLESv2/renderer/IndexBuffer11.cpp | 182 + .../angle/src/libGLESv2/renderer/IndexBuffer11.h | 53 + .../angle/src/libGLESv2/renderer/IndexBuffer9.cpp | 207 ++ .../angle/src/libGLESv2/renderer/IndexBuffer9.h | 53 + .../src/libGLESv2/renderer/IndexDataManager.cpp | 316 ++ .../src/libGLESv2/renderer/IndexDataManager.h | 66 + .../src/libGLESv2/renderer/InputLayoutCache.cpp | 166 + .../src/libGLESv2/renderer/InputLayoutCache.h | 74 + .../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 + .../angle/src/libGLESv2/renderer/QueryImpl.h | 42 + .../src/libGLESv2/renderer/RenderStateCache.cpp | 406 +++ .../src/libGLESv2/renderer/RenderStateCache.h | 101 + .../angle/src/libGLESv2/renderer/RenderTarget.h | 56 + .../src/libGLESv2/renderer/RenderTarget11.cpp | 378 +++ .../angle/src/libGLESv2/renderer/RenderTarget11.h | 58 + .../angle/src/libGLESv2/renderer/RenderTarget9.cpp | 113 + .../angle/src/libGLESv2/renderer/RenderTarget9.h | 40 + .../angle/src/libGLESv2/renderer/Renderer.cpp | 201 ++ .../angle/src/libGLESv2/renderer/Renderer.h | 238 ++ .../angle/src/libGLESv2/renderer/Renderer11.cpp | 3531 ++++++++++++++++++++ .../angle/src/libGLESv2/renderer/Renderer11.h | 348 ++ .../angle/src/libGLESv2/renderer/Renderer9.cpp | 3211 ++++++++++++++++++ .../angle/src/libGLESv2/renderer/Renderer9.h | 347 ++ .../angle/src/libGLESv2/renderer/ShaderCache.h | 110 + .../src/libGLESv2/renderer/ShaderExecutable.h | 51 + .../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 | 44 + .../angle/src/libGLESv2/renderer/SwapChain11.cpp | 767 +++++ .../angle/src/libGLESv2/renderer/SwapChain11.h | 78 + .../angle/src/libGLESv2/renderer/SwapChain9.cpp | 449 +++ .../angle/src/libGLESv2/renderer/SwapChain9.h | 55 + .../src/libGLESv2/renderer/TextureStorage.cpp | 122 + .../angle/src/libGLESv2/renderer/TextureStorage.h | 110 + .../src/libGLESv2/renderer/TextureStorage11.cpp | 676 ++++ .../src/libGLESv2/renderer/TextureStorage11.h | 120 + .../src/libGLESv2/renderer/TextureStorage9.cpp | 328 ++ .../angle/src/libGLESv2/renderer/TextureStorage9.h | 109 + .../angle/src/libGLESv2/renderer/VertexBuffer.cpp | 229 ++ .../angle/src/libGLESv2/renderer/VertexBuffer.h | 138 + .../src/libGLESv2/renderer/VertexBuffer11.cpp | 418 +++ .../angle/src/libGLESv2/renderer/VertexBuffer11.h | 73 + .../angle/src/libGLESv2/renderer/VertexBuffer9.cpp | 486 +++ .../angle/src/libGLESv2/renderer/VertexBuffer9.h | 90 + .../src/libGLESv2/renderer/VertexDataManager.cpp | 258 ++ .../src/libGLESv2/renderer/VertexDataManager.h | 65 + .../libGLESv2/renderer/VertexDeclarationCache.cpp | 217 ++ .../libGLESv2/renderer/VertexDeclarationCache.h | 58 + .../angle/src/libGLESv2/renderer/generatemip.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 | 33 + .../libGLESv2/renderer/shaders/Passthrough11.hlsl | 29 + .../src/libGLESv2/renderer/vertexconversion.h | 203 ++ src/3rdparty/angle/src/libGLESv2/shaders/Blit.ps | 39 - src/3rdparty/angle/src/libGLESv2/shaders/Blit.vs | 43 - src/3rdparty/angle/src/libGLESv2/utilities.cpp | 674 +--- src/3rdparty/angle/src/libGLESv2/utilities.h | 75 +- .../angle/src/libGLESv2/vertexconversion.h | 208 -- .../third_party/compiler/ArrayBoundsClamper.cpp | 106 + .../src/third_party/compiler/ArrayBoundsClamper.h | 62 + .../angle/src/third_party/compiler/LICENSE | 22 + .../angle/src/third_party/compiler/README.angle | 12 + .../angle/src/third_party/murmurhash/LICENSE | 2 + .../src/third_party/murmurhash/MurmurHash3.cpp | 334 ++ .../angle/src/third_party/murmurhash/MurmurHash3.h | 37 + 278 files changed, 31528 insertions(+), 20596 deletions(-) create mode 100644 src/3rdparty/angle/src/common/system.h create mode 100644 src/3rdparty/angle/src/compiler/HashNames.h create mode 100644 src/3rdparty/angle/src/compiler/Uniform.cpp create mode 100644 src/3rdparty/angle/src/compiler/Uniform.h delete mode 100644 src/3rdparty/angle/src/compiler/ossource_nspr.cpp create mode 100644 src/3rdparty/angle/src/compiler/preprocessor/DiagnosticsBase.cpp create mode 100644 src/3rdparty/angle/src/compiler/preprocessor/DiagnosticsBase.h create mode 100644 src/3rdparty/angle/src/compiler/preprocessor/DirectiveHandlerBase.cpp create mode 100644 src/3rdparty/angle/src/compiler/preprocessor/DirectiveHandlerBase.h create mode 100644 src/3rdparty/angle/src/compiler/preprocessor/DirectiveParser.cpp create mode 100644 src/3rdparty/angle/src/compiler/preprocessor/DirectiveParser.h create mode 100644 src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.h create mode 100644 src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.y create mode 100644 src/3rdparty/angle/src/compiler/preprocessor/Input.cpp create mode 100644 src/3rdparty/angle/src/compiler/preprocessor/Input.h create mode 100644 src/3rdparty/angle/src/compiler/preprocessor/Lexer.cpp create mode 100644 src/3rdparty/angle/src/compiler/preprocessor/Lexer.h create mode 100644 src/3rdparty/angle/src/compiler/preprocessor/Macro.cpp create mode 100644 src/3rdparty/angle/src/compiler/preprocessor/Macro.h create mode 100644 src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.cpp create mode 100644 src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.h create mode 100644 src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.cpp create mode 100644 src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.h create mode 100644 src/3rdparty/angle/src/compiler/preprocessor/SourceLocation.h create mode 100644 src/3rdparty/angle/src/compiler/preprocessor/Token.cpp create mode 100644 src/3rdparty/angle/src/compiler/preprocessor/Token.h create mode 100644 src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.h create mode 100644 src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.l delete mode 100644 src/3rdparty/angle/src/compiler/preprocessor/atom.c delete mode 100644 src/3rdparty/angle/src/compiler/preprocessor/atom.h delete mode 100644 src/3rdparty/angle/src/compiler/preprocessor/compile.h delete mode 100644 src/3rdparty/angle/src/compiler/preprocessor/cpp.c delete mode 100644 src/3rdparty/angle/src/compiler/preprocessor/cpp.h delete mode 100644 src/3rdparty/angle/src/compiler/preprocessor/cppstruct.c delete mode 100644 src/3rdparty/angle/src/compiler/preprocessor/memory.c delete mode 100644 src/3rdparty/angle/src/compiler/preprocessor/memory.h delete mode 100644 src/3rdparty/angle/src/compiler/preprocessor/new/Diagnostics.cpp delete mode 100644 src/3rdparty/angle/src/compiler/preprocessor/new/Diagnostics.h delete mode 100644 src/3rdparty/angle/src/compiler/preprocessor/new/DirectiveHandler.cpp delete mode 100644 src/3rdparty/angle/src/compiler/preprocessor/new/DirectiveHandler.h delete mode 100644 src/3rdparty/angle/src/compiler/preprocessor/new/DirectiveParser.cpp delete mode 100644 src/3rdparty/angle/src/compiler/preprocessor/new/DirectiveParser.h delete mode 100644 src/3rdparty/angle/src/compiler/preprocessor/new/ExpressionParser.h delete mode 100644 src/3rdparty/angle/src/compiler/preprocessor/new/ExpressionParser.y delete mode 100644 src/3rdparty/angle/src/compiler/preprocessor/new/Input.cpp delete mode 100644 src/3rdparty/angle/src/compiler/preprocessor/new/Input.h delete mode 100644 src/3rdparty/angle/src/compiler/preprocessor/new/Lexer.cpp delete mode 100644 src/3rdparty/angle/src/compiler/preprocessor/new/Lexer.h delete mode 100644 src/3rdparty/angle/src/compiler/preprocessor/new/Macro.cpp delete mode 100644 src/3rdparty/angle/src/compiler/preprocessor/new/Macro.h delete mode 100644 src/3rdparty/angle/src/compiler/preprocessor/new/MacroExpander.cpp delete mode 100644 src/3rdparty/angle/src/compiler/preprocessor/new/MacroExpander.h delete mode 100644 src/3rdparty/angle/src/compiler/preprocessor/new/Preprocessor.cpp delete mode 100644 src/3rdparty/angle/src/compiler/preprocessor/new/Preprocessor.h delete mode 100644 src/3rdparty/angle/src/compiler/preprocessor/new/SourceLocation.h delete mode 100644 src/3rdparty/angle/src/compiler/preprocessor/new/Token.cpp delete mode 100644 src/3rdparty/angle/src/compiler/preprocessor/new/Token.h delete mode 100644 src/3rdparty/angle/src/compiler/preprocessor/new/Tokenizer.h delete mode 100644 src/3rdparty/angle/src/compiler/preprocessor/new/Tokenizer.l delete mode 100644 src/3rdparty/angle/src/compiler/preprocessor/new/numeric_lex.h delete mode 100644 src/3rdparty/angle/src/compiler/preprocessor/new/pp_utils.h create mode 100644 src/3rdparty/angle/src/compiler/preprocessor/numeric_lex.h delete mode 100644 src/3rdparty/angle/src/compiler/preprocessor/parser.h create mode 100644 src/3rdparty/angle/src/compiler/preprocessor/pp_utils.h delete mode 100644 src/3rdparty/angle/src/compiler/preprocessor/preprocess.h delete mode 100644 src/3rdparty/angle/src/compiler/preprocessor/scanner.c delete mode 100644 src/3rdparty/angle/src/compiler/preprocessor/scanner.h delete mode 100644 src/3rdparty/angle/src/compiler/preprocessor/slglobals.h delete mode 100644 src/3rdparty/angle/src/compiler/preprocessor/symbols.c delete mode 100644 src/3rdparty/angle/src/compiler/preprocessor/symbols.h delete mode 100644 src/3rdparty/angle/src/compiler/preprocessor/tokens.c delete mode 100644 src/3rdparty/angle/src/compiler/preprocessor/tokens.h delete mode 100644 src/3rdparty/angle/src/libEGL/ShaderCache.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/Blit.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/Blit.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/D3DConstantTable.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/D3DConstantTable.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/IndexDataManager.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/IndexDataManager.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/TextureSSE2.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/Uniform.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/Uniform.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/VertexDataManager.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/VertexDataManager.h create mode 100644 src/3rdparty/angle/src/libGLESv2/angletypes.h create mode 100644 src/3rdparty/angle/src/libGLESv2/constants.h create mode 100644 src/3rdparty/angle/src/libGLESv2/precompiled.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/precompiled.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/Blit.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/Blit.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage11.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage11.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage9.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage9.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/Fence11.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/Fence11.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/Fence9.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/Fence9.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/FenceImpl.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/Image.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/Image.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/Image11.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/Image11.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/Image9.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/Image9.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/ImageSSE2.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer11.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer11.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer9.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer9.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/IndexDataManager.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/IndexDataManager.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/InputLayoutCache.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/InputLayoutCache.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/Query11.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/Query11.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/Query9.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/Query9.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/QueryImpl.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/RenderStateCache.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/RenderStateCache.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget11.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget11.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget9.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget9.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/Renderer11.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/Renderer11.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/Renderer9.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/Renderer9.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/ShaderCache.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable11.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable11.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable9.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable9.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/SwapChain11.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/SwapChain11.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/SwapChain9.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/SwapChain9.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage11.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage11.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage9.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage9.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer11.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer11.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer9.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer9.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/VertexDataManager.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/VertexDataManager.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/VertexDeclarationCache.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/VertexDeclarationCache.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/generatemip.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/renderer11_utils.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/renderer11_utils.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/renderer9_utils.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/renderer9_utils.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/shaders/Blit.ps create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/shaders/Blit.vs create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/shaders/Clear11.hlsl create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/shaders/Passthrough11.hlsl create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/vertexconversion.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/shaders/Blit.ps delete mode 100644 src/3rdparty/angle/src/libGLESv2/shaders/Blit.vs delete mode 100644 src/3rdparty/angle/src/libGLESv2/vertexconversion.h create mode 100644 src/3rdparty/angle/src/third_party/compiler/ArrayBoundsClamper.cpp create mode 100644 src/3rdparty/angle/src/third_party/compiler/ArrayBoundsClamper.h create mode 100644 src/3rdparty/angle/src/third_party/compiler/LICENSE create mode 100644 src/3rdparty/angle/src/third_party/compiler/README.angle create mode 100644 src/3rdparty/angle/src/third_party/murmurhash/LICENSE create mode 100644 src/3rdparty/angle/src/third_party/murmurhash/MurmurHash3.cpp create mode 100644 src/3rdparty/angle/src/third_party/murmurhash/MurmurHash3.h (limited to 'src/3rdparty') diff --git a/src/3rdparty/angle/.gitignore b/src/3rdparty/angle/.gitignore index cfa07de1ee..c53d356b04 100644 --- a/src/3rdparty/angle/.gitignore +++ b/src/3rdparty/angle/.gitignore @@ -19,17 +19,24 @@ DEPS codereview.settings # Generated by flex/bison -src/compiler/preprocessor/new/Tokenizer.cpp -src/compiler/preprocessor/new/ExpressionParser.cpp +src/compiler/preprocessor/Tokenizer.cpp +src/compiler/preprocessor/ExpressionParser.cpp src/compiler/glslang_lex.cpp src/compiler/glslang_tab.cpp src/compiler/glslang_tab.h # Generated by FXC -src/libGLESv2/shaders/standardvs.h -src/libGLESv2/shaders/flipyvs.h -src/libGLESv2/shaders/luminanceps.h -src/libGLESv2/shaders/componentmaskps.h -src/libGLESv2/shaders/passthroughps.h +src/libGLESv2/renderer/shaders/compiled/standardvs.h +src/libGLESv2/renderer/shaders/compiled/flipyvs.h +src/libGLESv2/renderer/shaders/compiled/luminanceps.h +src/libGLESv2/renderer/shaders/compiled/componentmaskps.h +src/libGLESv2/renderer/shaders/compiled/passthroughps.h +src/libGLESv2/renderer/shaders/compiled/PassthroughRGBA11ps.h +src/libGLESv2/renderer/shaders/compiled/PassthroughRGB11ps.h +src/libGLESv2/renderer/shaders/compiled/PassthroughLumAlpha11ps.h +src/libGLESv2/renderer/shaders/compiled/PassthroughLum11ps.h +src/libGLESv2/renderer/shaders/compiled/Passthrough11vs.h +src/libGLESv2/renderer/shaders/compiled/Clear11ps.h +src/libGLESv2/renderer/shaders/compiled/Clear11vs.h diff --git a/src/3rdparty/angle/include/GLES2/gl2ext.h b/src/3rdparty/angle/include/GLES2/gl2ext.h index e297fbfe87..bad50f9ccb 100644 --- a/src/3rdparty/angle/include/GLES2/gl2ext.h +++ b/src/3rdparty/angle/include/GLES2/gl2ext.h @@ -556,6 +556,44 @@ typedef void* GLeglImageOES; #define GL_COLOR_ATTACHMENT15_NV 0x8CEF #endif +/* GL_EXT_draw_buffers */ +#ifndef GL_EXT_draw_buffers +#define GL_MAX_DRAW_BUFFERS_EXT 0x8824 +#define GL_DRAW_BUFFER0_EXT 0x8825 +#define GL_DRAW_BUFFER1_EXT 0x8826 +#define GL_DRAW_BUFFER2_EXT 0x8827 +#define GL_DRAW_BUFFER3_EXT 0x8828 +#define GL_DRAW_BUFFER4_EXT 0x8829 +#define GL_DRAW_BUFFER5_EXT 0x882A +#define GL_DRAW_BUFFER6_EXT 0x882B +#define GL_DRAW_BUFFER7_EXT 0x882C +#define GL_DRAW_BUFFER8_EXT 0x882D +#define GL_DRAW_BUFFER9_EXT 0x882E +#define GL_DRAW_BUFFER10_EXT 0x882F +#define GL_DRAW_BUFFER11_EXT 0x8830 +#define GL_DRAW_BUFFER12_EXT 0x8831 +#define GL_DRAW_BUFFER13_EXT 0x8832 +#define GL_DRAW_BUFFER14_EXT 0x8833 +#define GL_DRAW_BUFFER15_EXT 0x8834 +#define GL_COLOR_ATTACHMENT0_EXT 0x8CE0 +#define GL_COLOR_ATTACHMENT1_EXT 0x8CE1 +#define GL_COLOR_ATTACHMENT2_EXT 0x8CE2 +#define GL_COLOR_ATTACHMENT3_EXT 0x8CE3 +#define GL_COLOR_ATTACHMENT4_EXT 0x8CE4 +#define GL_COLOR_ATTACHMENT5_EXT 0x8CE5 +#define GL_COLOR_ATTACHMENT6_EXT 0x8CE6 +#define GL_COLOR_ATTACHMENT7_EXT 0x8CE7 +#define GL_COLOR_ATTACHMENT8_EXT 0x8CE8 +#define GL_COLOR_ATTACHMENT9_EXT 0x8CE9 +#define GL_COLOR_ATTACHMENT10_EXT 0x8CEA +#define GL_COLOR_ATTACHMENT11_EXT 0x8CEB +#define GL_COLOR_ATTACHMENT12_EXT 0x8CEC +#define GL_COLOR_ATTACHMENT13_EXT 0x8CED +#define GL_COLOR_ATTACHMENT14_EXT 0x8CEE +#define GL_COLOR_ATTACHMENT15_EXT 0x8CEF +#define GL_MAX_COLOR_ATTACHMENTS_EXT 0x8CDF +#endif + /* GL_NV_fbo_color_attachments */ #ifndef GL_NV_fbo_color_attachments #define GL_MAX_COLOR_ATTACHMENTS_NV 0x8CDF @@ -1331,6 +1369,14 @@ GL_APICALL void GL_APIENTRY glDrawBuffersNV (GLsizei n, const GLenum *bufs); typedef void (GL_APIENTRYP PFNGLDRAWBUFFERSNVPROC) (GLsizei n, const GLenum *bufs); #endif +#ifndef GL_EXT_draw_buffers +#define GL_EXT_draw_buffers 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glDrawBuffersEXT (GLsizei n, const GLenum *bufs); +#endif +typedef void (GL_APIENTRYP PFNGLDRAWBUFFERSEXTPROC) (GLsizei n, const GLenum *bufs); +#endif + /* GL_NV_fbo_color_attachments */ #ifndef GL_NV_fbo_color_attachments #define GL_NV_fbo_color_attachments 1 diff --git a/src/3rdparty/angle/include/GLSLANG/ShaderLang.h b/src/3rdparty/angle/include/GLSLANG/ShaderLang.h index d925029a2c..da0f87aed9 100644 --- a/src/3rdparty/angle/include/GLSLANG/ShaderLang.h +++ b/src/3rdparty/angle/include/GLSLANG/ShaderLang.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// 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. // @@ -23,6 +23,9 @@ #define COMPILER_EXPORT #endif +#include "KHR/khrplatform.h" +#include + // // This is the platform independent interface between an OGL driver // and the shading language compiler. @@ -34,7 +37,7 @@ extern "C" { // Version number for shader translation API. // It is incremented everytime the API changes. -#define SH_VERSION 107 +#define ANGLE_SH_VERSION 110 // // The names of the following enums have been derived by replacing GL prefix @@ -75,9 +78,11 @@ typedef enum { } ShShaderSpec; typedef enum { - SH_ESSL_OUTPUT = 0x8B45, - SH_GLSL_OUTPUT = 0x8B46, - SH_HLSL_OUTPUT = 0x8B47 + SH_ESSL_OUTPUT = 0x8B45, + SH_GLSL_OUTPUT = 0x8B46, + SH_HLSL_OUTPUT = 0x8B47, + SH_HLSL9_OUTPUT = 0x8B47, + SH_HLSL11_OUTPUT = 0x8B48 } ShShaderOutput; typedef enum { @@ -110,7 +115,11 @@ typedef enum { SH_ACTIVE_UNIFORM_MAX_LENGTH = 0x8B87, SH_ACTIVE_ATTRIBUTES = 0x8B89, SH_ACTIVE_ATTRIBUTE_MAX_LENGTH = 0x8B8A, - SH_MAPPED_NAME_MAX_LENGTH = 0x8B8B + SH_MAPPED_NAME_MAX_LENGTH = 0x6000, + SH_NAME_MAX_LENGTH = 0x6001, + SH_HASHED_NAME_MAX_LENGTH = 0x6002, + SH_HASHED_NAMES_COUNT = 0x6003, + SH_ACTIVE_UNIFORMS_ARRAY = 0x6004 } ShShaderInfo; // Compile options. @@ -146,8 +155,25 @@ typedef enum { // Enforce the GLSL 1.017 Appendix A section 7 packing restrictions. SH_ENFORCE_PACKING_RESTRICTIONS = 0x0800, + + // This flag ensures all indirect (expression-based) array indexing + // is clamped to the bounds of the array. This ensures, for example, + // that you cannot read off the end of a uniform, whether an array + // vec234, or mat234 type. The ShArrayIndexClampingStrategy enum, + // specified in the ShBuiltInResources when constructing the + // compiler, selects the strategy for the clamping implementation. + SH_CLAMP_INDIRECT_ARRAY_BOUNDS = 0x1000 } ShCompileOptions; +// Defines alternate strategies for implementing array index clamping. +typedef enum { + // Use the clamp intrinsic for array index clamping. + SH_CLAMP_WITH_CLAMP_INTRINSIC = 1, + + // Use a user-defined function for array index clamping. + SH_CLAMP_WITH_USER_DEFINED_INT_CLAMP_FUNCTION +} ShArrayIndexClampingStrategy; + // // Driver must call this first, once, before doing any other // compiler operations. @@ -160,6 +186,10 @@ COMPILER_EXPORT int ShInitialize(); // COMPILER_EXPORT int ShFinalize(); +// The 64 bits hash function. The first parameter is the input string; the +// second parameter is the string length. +typedef khronos_uint64_t (*ShHashFunction64)(const char*, size_t); + // // Implementation dependent built-in resources (constants and extensions). // The names for these resources has been obtained by stripping gl_/GL_. @@ -181,6 +211,20 @@ typedef struct int OES_standard_derivatives; int OES_EGL_image_external; int ARB_texture_rectangle; + int EXT_draw_buffers; + + // Set to 1 if highp precision is supported in the fragment language. + // Default is 0. + int FragmentPrecisionHigh; + + // Name Hashing. + // Set a 64 bit hash function to enable user-defined name hashing. + // Default is NULL. + ShHashFunction64 HashFunction; + + // Selects a strategy to use when implementing array index clamping. + // Default is SH_CLAMP_WITH_CLAMP_INTRINSIC. + ShArrayIndexClampingStrategy ArrayIndexClampingStrategy; } ShBuiltInResources; // @@ -207,7 +251,7 @@ typedef void* ShHandle; // spec: Specifies the language spec the compiler must conform to - // SH_GLES2_SPEC or SH_WEBGL_SPEC. // output: Specifies the output code type - SH_ESSL_OUTPUT, SH_GLSL_OUTPUT, -// or SH_HLSL_OUTPUT. +// SH_HLSL9_OUTPUT or SH_HLSL11_OUTPUT. // resources: Specifies the built-in resources. COMPILER_EXPORT ShHandle ShConstructCompiler( ShShaderType type, @@ -244,7 +288,7 @@ COMPILER_EXPORT void ShDestruct(ShHandle handle); COMPILER_EXPORT int ShCompile( const ShHandle handle, const char* const shaderStrings[], - const int numStrings, + size_t numStrings, int compileOptions ); @@ -267,11 +311,16 @@ COMPILER_EXPORT int ShCompile( // termination character. // SH_MAPPED_NAME_MAX_LENGTH: the length of the mapped variable name including // the null termination character. -// +// SH_NAME_MAX_LENGTH: the max length of a user-defined name including the +// null termination character. +// SH_HASHED_NAME_MAX_LENGTH: the max length of a hashed name including the +// null termination character. +// SH_HASHED_NAMES_COUNT: the number of hashed names from the latest compile. +// // params: Requested parameter COMPILER_EXPORT void ShGetInfo(const ShHandle handle, ShShaderInfo pname, - int* params); + size_t* params); // Returns nul-terminated information log for a compiled shader. // Parameters: @@ -314,7 +363,7 @@ COMPILER_EXPORT void ShGetObjectCode(const ShHandle handle, char* objCode); // mappedName are the same. COMPILER_EXPORT void ShGetActiveAttrib(const ShHandle handle, int index, - int* length, + size_t* length, int* size, ShDataType* type, char* name, @@ -341,12 +390,42 @@ COMPILER_EXPORT void ShGetActiveAttrib(const ShHandle handle, // mappedName are the same. COMPILER_EXPORT void ShGetActiveUniform(const ShHandle handle, int index, - int* length, + size_t* length, int* size, ShDataType* type, char* name, char* mappedName); +// Returns information about a name hashing entry from the latest compile. +// Parameters: +// handle: Specifies the compiler +// index: Specifies the index of the name hashing entry to be queried. +// name: Returns a null terminated string containing the user defined name. +// It is assumed that name has enough memory to accomodate the name. +// The size of the buffer required to store the user defined name can +// be obtained by calling ShGetInfo with SH_NAME_MAX_LENGTH. +// hashedName: Returns a null terminated string containing the hashed name of +// the uniform variable, It is assumed that hashedName has enough +// memory to accomodate the name. The size of the buffer required +// to store the name can be obtained by calling ShGetInfo with +// SH_HASHED_NAME_MAX_LENGTH. +COMPILER_EXPORT void ShGetNameHashingEntry(const ShHandle handle, + int index, + char* name, + char* hashedName); + +// Returns a parameter from a compiled shader. +// Parameters: +// handle: Specifies the compiler +// pname: Specifies the parameter to query. +// The following parameters are defined: +// SH_ACTIVE_UNIFORMS_ARRAY: an STL vector of active uniforms. Valid only for +// HLSL output. +// params: Requested parameter +COMPILER_EXPORT void ShGetInfoPointer(const ShHandle handle, + ShShaderInfo pname, + void** params); + #ifdef __cplusplus } #endif diff --git a/src/3rdparty/angle/src/common/angleutils.h b/src/3rdparty/angle/src/common/angleutils.h index ff9730c4da..31ac559279 100644 --- a/src/3rdparty/angle/src/common/angleutils.h +++ b/src/3rdparty/angle/src/common/angleutils.h @@ -15,6 +15,31 @@ TypeName(const TypeName&); \ void operator=(const TypeName&) +template +inline unsigned int ArraySize(T(&)[N]) +{ + return N; +} + +template +void SafeRelease(T (&resourceBlock)[N]) +{ + for (unsigned int i = 0; i < N; i++) + { + SafeRelease(resourceBlock[i]); + } +} + +template +void SafeRelease(T& resource) +{ + if (resource) + { + resource->Release(); + resource = NULL; + } +} + #if defined(_MSC_VER) #define snprintf _snprintf #endif @@ -23,4 +48,7 @@ #define VENDOR_ID_INTEL 0x8086 #define VENDOR_ID_NVIDIA 0x10DE +#define GL_BGRA4_ANGLEX 0x6ABC +#define GL_BGR5_A1_ANGLEX 0x6ABD + #endif // COMMON_ANGLEUTILS_H_ diff --git a/src/3rdparty/angle/src/common/debug.cpp b/src/3rdparty/angle/src/common/debug.cpp index b2238f9708..438d3975e8 100644 --- a/src/3rdparty/angle/src/common/debug.cpp +++ b/src/3rdparty/angle/src/common/debug.cpp @@ -7,11 +7,12 @@ // debug.cpp: Debugging utilities. #include "common/debug.h" - -#include -#include +#include "common/system.h" +#ifdef ANGLE_ENABLE_D3D11 +typedef DWORD D3DCOLOR; +#else #include -#include +#endif namespace gl { @@ -84,6 +85,12 @@ bool perfActive() ScopedPerfEventHelper::ScopedPerfEventHelper(const char* format, ...) { #if !defined(ANGLE_DISABLE_PERF) +#if defined(ANGLE_DISABLE_TRACE) + if (!perfActive()) + { + return; + } +#endif va_list vararg; va_start(vararg, format); output(true, reinterpret_cast(D3DPERF_BeginEvent), format, vararg); diff --git a/src/3rdparty/angle/src/common/debug.h b/src/3rdparty/angle/src/common/debug.h index 5f8f60fe61..23ee26d23b 100644 --- a/src/3rdparty/angle/src/common/debug.h +++ b/src/3rdparty/angle/src/common/debug.h @@ -99,6 +99,13 @@ 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)) +#define HAS_DYNAMIC_TYPE(type, obj) (dynamic_cast(obj) != NULL) +#else +#define HAS_DYNAMIC_TYPE(type, obj) true +#endif + // A macro functioning as a compile-time assert to validate constant conditions #define META_ASSERT(condition) typedef int COMPILE_TIME_ASSERT_##__LINE__[static_cast(condition)?1:-1] diff --git a/src/3rdparty/angle/src/common/system.h b/src/3rdparty/angle/src/common/system.h new file mode 100644 index 0000000000..5eb140bccd --- /dev/null +++ b/src/3rdparty/angle/src/common/system.h @@ -0,0 +1,26 @@ +// +// 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 fec98a15c9..7913851e6a 100644 --- a/src/3rdparty/angle/src/common/version.h +++ b/src/3rdparty/angle/src/common/version.h @@ -1,10 +1,12 @@ #define MAJOR_VERSION 1 -#define MINOR_VERSION 0 +#define MINOR_VERSION 1 #define BUILD_VERSION 0 -#define BUILD_REVISION 1318 +#define BUILD_REVISION 2037 #define STRINGIFY(x) #x #define MACRO_STRINGIFY(x) STRINGIFY(x) #define REVISION_STRING MACRO_STRINGIFY(BUILD_REVISION) #define VERSION_STRING MACRO_STRINGIFY(MAJOR_VERSION) "." MACRO_STRINGIFY(MINOR_VERSION) "." MACRO_STRINGIFY(BUILD_VERSION) "." MACRO_STRINGIFY(BUILD_REVISION) + +#define VERSION_DWORD ((MAJOR_VERSION << 24) | (MINOR_VERSION << 16) | BUILD_REVISION) diff --git a/src/3rdparty/angle/src/compiler/BaseTypes.h b/src/3rdparty/angle/src/compiler/BaseTypes.h index 5f83185304..af4c7e3ed9 100644 --- a/src/3rdparty/angle/src/compiler/BaseTypes.h +++ b/src/3rdparty/angle/src/compiler/BaseTypes.h @@ -16,7 +16,7 @@ enum TPrecision EbpUndefined, EbpLow, EbpMedium, - EbpHigh, + EbpHigh }; inline const char* getPrecisionString(TPrecision p) @@ -47,7 +47,7 @@ enum TBasicType 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 + EbtInvariant // used as a type when qualifying a previously declared variable as being invariant }; inline const char* getBasicString(TBasicType t) @@ -114,7 +114,7 @@ enum TQualifier EvqFragData, // end of list - EvqLast, + EvqLast }; // diff --git a/src/3rdparty/angle/src/compiler/CodeGenHLSL.cpp b/src/3rdparty/angle/src/compiler/CodeGenHLSL.cpp index f46ff66d40..637ccc5e37 100644 --- a/src/3rdparty/angle/src/compiler/CodeGenHLSL.cpp +++ b/src/3rdparty/angle/src/compiler/CodeGenHLSL.cpp @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// 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. // @@ -14,9 +14,11 @@ TCompiler* ConstructCompiler( ShShaderType type, ShShaderSpec spec, ShShaderOutput output) { - switch (output) { - case SH_HLSL_OUTPUT: - return new TranslatorHLSL(type, spec); + switch (output) + { + case SH_HLSL9_OUTPUT: + case SH_HLSL11_OUTPUT: + return new TranslatorHLSL(type, spec, output); default: return NULL; } diff --git a/src/3rdparty/angle/src/compiler/Compiler.cpp b/src/3rdparty/angle/src/compiler/Compiler.cpp index 9e7f75c33a..c8c79e7147 100644 --- a/src/3rdparty/angle/src/compiler/Compiler.cpp +++ b/src/3rdparty/angle/src/compiler/Compiler.cpp @@ -19,6 +19,7 @@ #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) { @@ -37,6 +38,7 @@ bool InitializeSymbolTable( // The builtins deliberately don't specify precisions for the function // arguments and return types. For that reason we don't try to check them. TParseContext parseContext(symbolTable, extBehavior, intermediate, type, spec, 0, false, NULL, infoSink); + parseContext.fragmentPrecisionHigh = resources.FragmentPrecisionHigh == 1; GlobalParseContext = &parseContext; @@ -101,6 +103,8 @@ TShHandleBase::~TShHandleBase() { TCompiler::TCompiler(ShShaderType type, ShShaderSpec spec) : shaderType(type), shaderSpec(spec), + fragmentPrecisionHigh(false), + clampingStrategy(SH_CLAMP_WITH_CLAMP_INTRINSIC), builtInFunctionEmulator(type) { longNameMap = LongNameMap::GetInstance(); @@ -123,12 +127,18 @@ bool TCompiler::Init(const ShBuiltInResources& resources) 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[], - const int numStrings, + size_t numStrings, int compileOptions) { TScopedPoolAllocator scopedAlloc(&allocator, true); @@ -143,7 +153,7 @@ bool TCompiler::compile(const char* const shaderStrings[], // First string is path of source file if flag is set. The actual source follows. const char* sourcePath = NULL; - int firstSource = 0; + size_t firstSource = 0; if (compileOptions & SH_SOURCE_PATH) { sourcePath = shaderStrings[0]; @@ -154,6 +164,7 @@ bool TCompiler::compile(const char* const shaderStrings[], TParseContext parseContext(symbolTable, extensionBehavior, intermediate, shaderType, shaderSpec, compileOptions, true, sourcePath, infoSink); + parseContext.fragmentPrecisionHigh = fragmentPrecisionHigh; GlobalParseContext = &parseContext; // We preserve symbols at the built-in level from compile-to-compile. @@ -190,10 +201,15 @@ bool TCompiler::compile(const char* const shaderStrings[], 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); + // Call mapLongVariableNames() before collectAttribsUniforms() so in // collectAttribsUniforms() we already have the mapped symbol names and // we could composite mapped and original variable names. - if (success && (compileOptions & SH_MAP_LONG_VARIABLE_NAMES)) + // 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 && (compileOptions & SH_ATTRIBUTES_UNIFORMS)) { @@ -227,6 +243,7 @@ bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources& resources) { TBuiltIns builtIns; + compileResources = resources; builtIns.initialize(shaderType, shaderSpec, resources); return InitializeSymbolTable(builtIns.getBuiltInStrings(), shaderType, shaderSpec, resources, infoSink, symbolTable); @@ -234,6 +251,7 @@ bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources& resources) void TCompiler::clearResults() { + arrayBoundsClamper.Cleanup(); infoSink.info.erase(); infoSink.obj.erase(); infoSink.debug.erase(); @@ -242,6 +260,8 @@ void TCompiler::clearResults() uniforms.clear(); builtInFunctionEmulator.Cleanup(); + + nameMap.clear(); } bool TCompiler::detectRecursion(TIntermNode* root) @@ -317,7 +337,7 @@ bool TCompiler::enforceVertexShaderTimingRestrictions(TIntermNode* root) void TCompiler::collectAttribsUniforms(TIntermNode* root) { - CollectAttribsUniforms collect(attribs, uniforms); + CollectAttribsUniforms collect(attribs, uniforms, hashFunction); root->traverse(&collect); } @@ -344,6 +364,21 @@ 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 index fd9d94dc5a..32af4d38b0 100644 --- a/src/3rdparty/angle/src/compiler/ConstantUnion.h +++ b/src/3rdparty/angle/src/compiler/ConstantUnion.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// 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. // @@ -14,6 +14,7 @@ public: ConstantUnion() { iConst = 0; + type = EbtVoid; } POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator) diff --git a/src/3rdparty/angle/src/compiler/DetectDiscontinuity.cpp b/src/3rdparty/angle/src/compiler/DetectDiscontinuity.cpp index 472232a75d..7c3b68a0b3 100644 --- a/src/3rdparty/angle/src/compiler/DetectDiscontinuity.cpp +++ b/src/3rdparty/angle/src/compiler/DetectDiscontinuity.cpp @@ -16,11 +16,26 @@ 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) @@ -28,14 +43,19 @@ bool DetectLoopDiscontinuity::visitBranch(Visit visit, TIntermBranch *node) return false; } + if (!mLoopDepth) + { + return true; + } + switch (node->getFlowOp()) { case EOpKill: break; case EOpBreak: case EOpContinue: - mLoopDiscontinuity = true; case EOpReturn: + mLoopDiscontinuity = true; break; default: UNREACHABLE(); } diff --git a/src/3rdparty/angle/src/compiler/DetectDiscontinuity.h b/src/3rdparty/angle/src/compiler/DetectDiscontinuity.h index 8bda4c3dea..e5520bd5b0 100644 --- a/src/3rdparty/angle/src/compiler/DetectDiscontinuity.h +++ b/src/3rdparty/angle/src/compiler/DetectDiscontinuity.h @@ -23,8 +23,10 @@ class DetectLoopDiscontinuity : public TIntermTraverser protected: bool visitBranch(Visit visit, TIntermBranch *node); + bool visitLoop(Visit visit, TIntermLoop *loop); bool visitAggregate(Visit visit, TIntermAggregate *node); + int mLoopDepth; bool mLoopDiscontinuity; }; diff --git a/src/3rdparty/angle/src/compiler/Diagnostics.cpp b/src/3rdparty/angle/src/compiler/Diagnostics.cpp index 8aa1cb6b24..06f370dbe5 100644 --- a/src/3rdparty/angle/src/compiler/Diagnostics.cpp +++ b/src/3rdparty/angle/src/compiler/Diagnostics.cpp @@ -8,7 +8,7 @@ #include "compiler/debug.h" #include "compiler/InfoSink.h" -#include "compiler/preprocessor/new/SourceLocation.h" +#include "compiler/preprocessor/SourceLocation.h" TDiagnostics::TDiagnostics(TInfoSink& infoSink) : mInfoSink(infoSink), diff --git a/src/3rdparty/angle/src/compiler/Diagnostics.h b/src/3rdparty/angle/src/compiler/Diagnostics.h index 3670414b03..cb71bb1204 100644 --- a/src/3rdparty/angle/src/compiler/Diagnostics.h +++ b/src/3rdparty/angle/src/compiler/Diagnostics.h @@ -7,7 +7,7 @@ #ifndef COMPILER_DIAGNOSTICS_H_ #define COMPILER_DIAGNOSTICS_H_ -#include "compiler/preprocessor/new/Diagnostics.h" +#include "compiler/preprocessor/DiagnosticsBase.h" class TInfoSink; diff --git a/src/3rdparty/angle/src/compiler/DirectiveHandler.h b/src/3rdparty/angle/src/compiler/DirectiveHandler.h index 21d3dfc315..95ca59d6fe 100644 --- a/src/3rdparty/angle/src/compiler/DirectiveHandler.h +++ b/src/3rdparty/angle/src/compiler/DirectiveHandler.h @@ -9,7 +9,7 @@ #include "compiler/ExtensionBehavior.h" #include "compiler/Pragma.h" -#include "compiler/preprocessor/new/DirectiveHandler.h" +#include "compiler/preprocessor/DirectiveHandlerBase.h" class TDiagnostics; diff --git a/src/3rdparty/angle/src/compiler/ExtensionBehavior.h b/src/3rdparty/angle/src/compiler/ExtensionBehavior.h index 6040980837..5c1595fb21 100644 --- a/src/3rdparty/angle/src/compiler/ExtensionBehavior.h +++ b/src/3rdparty/angle/src/compiler/ExtensionBehavior.h @@ -16,7 +16,7 @@ typedef enum EBhEnable, EBhWarn, EBhDisable, - EBhUndefined, + EBhUndefined } TBehavior; inline const char* getBehaviorString(TBehavior b) diff --git a/src/3rdparty/angle/src/compiler/ForLoopUnroll.cpp b/src/3rdparty/angle/src/compiler/ForLoopUnroll.cpp index fdc3f44431..27a13eabab 100644 --- a/src/3rdparty/angle/src/compiler/ForLoopUnroll.cpp +++ b/src/3rdparty/angle/src/compiler/ForLoopUnroll.cpp @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. +// 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. // @@ -210,6 +210,6 @@ int ForLoopUnroll::getLoopIncrement(TIntermLoop* node) int ForLoopUnroll::evaluateIntConstant(TIntermConstantUnion* node) { ASSERT((node != NULL) && (node->getUnionArrayPointer() != NULL)); - return node->getUnionArrayPointer()->getIConst(); + return node->getIConst(0); } diff --git a/src/3rdparty/angle/src/compiler/HashNames.h b/src/3rdparty/angle/src/compiler/HashNames.h new file mode 100644 index 0000000000..d2141e2d85 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/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/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/Initialize.cpp b/src/3rdparty/angle/src/compiler/Initialize.cpp index 3e94ce7ba8..97b46f898e 100644 --- a/src/3rdparty/angle/src/compiler/Initialize.cpp +++ b/src/3rdparty/angle/src/compiler/Initialize.cpp @@ -654,4 +654,6 @@ void InitExtensionBehavior(const ShBuiltInResources& resources, 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; } diff --git a/src/3rdparty/angle/src/compiler/Intermediate.cpp b/src/3rdparty/angle/src/compiler/Intermediate.cpp index 92c450530e..edf279ef67 100644 --- a/src/3rdparty/angle/src/compiler/Intermediate.cpp +++ b/src/3rdparty/angle/src/compiler/Intermediate.cpp @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// 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. // @@ -12,6 +12,7 @@ #include #include +#include "compiler/HashNames.h" #include "compiler/localintermediate.h" #include "compiler/QualifierAlive.h" #include "compiler/RemoveTree.h" @@ -592,7 +593,7 @@ TIntermNode* TIntermediate::addSelection(TIntermTyped* cond, TIntermNodePair nod // if (cond->getAsTyped() && cond->getAsTyped()->getAsConstantUnion()) { - if (cond->getAsTyped()->getAsConstantUnion()->getUnionArrayPointer()->getBConst() == true) + 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; @@ -646,7 +647,7 @@ TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* true // if (cond->getAsConstantUnion() && trueBlock->getAsConstantUnion() && falseBlock->getAsConstantUnion()) { - if (cond->getAsConstantUnion()->getUnionArrayPointer()->getBConst()) + if (cond->getAsConstantUnion()->getBConst(0)) return trueBlock; else return falseBlock; @@ -845,6 +846,7 @@ bool TIntermUnary::promote(TInfoSink&) } setType(operand->getType()); + type.setQualifier(EvqTemporary); return true; } @@ -1161,7 +1163,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod case EbtFloat: if (rightUnionArray[i] == 0.0f) { infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine()); - tempConstArray[i].setFConst(FLT_MAX); + tempConstArray[i].setFConst(unionArray[i].getFConst() < 0 ? -FLT_MAX : FLT_MAX); } else tempConstArray[i].setFConst(unionArray[i].getFConst() / rightUnionArray[i].getFConst()); break; @@ -1376,7 +1378,6 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermConstantUnion* node) { - ConstantUnion *rightUnionArray = node->getUnionArrayPointer(); int size = node->getType().getObjectSize(); ConstantUnion *leftUnionArray = new ConstantUnion[size]; @@ -1387,13 +1388,13 @@ TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermC case EbtFloat: switch (node->getType().getBasicType()) { case EbtInt: - leftUnionArray[i].setFConst(static_cast(rightUnionArray[i].getIConst())); + leftUnionArray[i].setFConst(static_cast(node->getIConst(i))); break; case EbtBool: - leftUnionArray[i].setFConst(static_cast(rightUnionArray[i].getBConst())); + leftUnionArray[i].setFConst(static_cast(node->getBConst(i))); break; case EbtFloat: - leftUnionArray[i] = rightUnionArray[i]; + leftUnionArray[i].setFConst(static_cast(node->getFConst(i))); break; default: infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine()); @@ -1403,13 +1404,13 @@ TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermC case EbtInt: switch (node->getType().getBasicType()) { case EbtInt: - leftUnionArray[i] = rightUnionArray[i]; + leftUnionArray[i].setIConst(static_cast(node->getIConst(i))); break; case EbtBool: - leftUnionArray[i].setIConst(static_cast(rightUnionArray[i].getBConst())); + leftUnionArray[i].setIConst(static_cast(node->getBConst(i))); break; case EbtFloat: - leftUnionArray[i].setIConst(static_cast(rightUnionArray[i].getFConst())); + leftUnionArray[i].setIConst(static_cast(node->getFConst(i))); break; default: infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine()); @@ -1419,13 +1420,13 @@ TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermC case EbtBool: switch (node->getType().getBasicType()) { case EbtInt: - leftUnionArray[i].setBConst(rightUnionArray[i].getIConst() != 0); + leftUnionArray[i].setBConst(node->getIConst(i) != 0); break; case EbtBool: - leftUnionArray[i] = rightUnionArray[i]; + leftUnionArray[i].setBConst(node->getBConst(i)); break; case EbtFloat: - leftUnionArray[i].setBConst(rightUnionArray[i].getFConst() != 0.0f); + leftUnionArray[i].setBConst(node->getFConst(i) != 0.0f); break; default: infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine()); @@ -1445,3 +1446,14 @@ TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermC 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/MapLongVariableNames.cpp b/src/3rdparty/angle/src/compiler/MapLongVariableNames.cpp index a50310154d..a41d20f4e8 100644 --- a/src/3rdparty/angle/src/compiler/MapLongVariableNames.cpp +++ b/src/3rdparty/angle/src/compiler/MapLongVariableNames.cpp @@ -8,7 +8,7 @@ namespace { -TString mapLongName(int id, const TString& name, bool isGlobal) +TString mapLongName(size_t id, const TString& name, bool isGlobal) { ASSERT(name.size() > MAX_SHORTENED_IDENTIFIER_SIZE); TStringStream stream; @@ -70,7 +70,7 @@ void LongNameMap::Insert(const char* originalName, const char* mappedName) originalName, mappedName)); } -int LongNameMap::Size() const +size_t LongNameMap::Size() const { return mLongNameMap.size(); } @@ -115,7 +115,7 @@ TString MapLongVariableNames::mapGlobalLongName(const TString& name) const char* mappedName = mGlobalMap->Find(name.c_str()); if (mappedName != NULL) return mappedName; - int id = mGlobalMap->Size(); + 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 index fb2c7e81cb..d6352acb4b 100644 --- a/src/3rdparty/angle/src/compiler/MapLongVariableNames.h +++ b/src/3rdparty/angle/src/compiler/MapLongVariableNames.h @@ -31,7 +31,7 @@ public: void Insert(const char* originalName, const char* mappedName); // Return the number of entries in the map. - int Size() const; + size_t Size() const; private: LongNameMap(); diff --git a/src/3rdparty/angle/src/compiler/OutputESSL.cpp b/src/3rdparty/angle/src/compiler/OutputESSL.cpp index 64ee92d44e..c2048f1cec 100644 --- a/src/3rdparty/angle/src/compiler/OutputESSL.cpp +++ b/src/3rdparty/angle/src/compiler/OutputESSL.cpp @@ -6,8 +6,12 @@ #include "compiler/OutputESSL.h" -TOutputESSL::TOutputESSL(TInfoSinkBase& objSink) - : TOutputGLSLBase(objSink) +TOutputESSL::TOutputESSL(TInfoSinkBase& objSink, + ShArrayIndexClampingStrategy clampingStrategy, + ShHashFunction64 hashFunction, + NameMap& nameMap, + TSymbolTable& symbolTable) + : TOutputGLSLBase(objSink, clampingStrategy, hashFunction, nameMap, symbolTable) { } diff --git a/src/3rdparty/angle/src/compiler/OutputESSL.h b/src/3rdparty/angle/src/compiler/OutputESSL.h index 4fa73c8047..05db96e497 100644 --- a/src/3rdparty/angle/src/compiler/OutputESSL.h +++ b/src/3rdparty/angle/src/compiler/OutputESSL.h @@ -12,7 +12,11 @@ class TOutputESSL : public TOutputGLSLBase { public: - TOutputESSL(TInfoSinkBase& objSink); + TOutputESSL(TInfoSinkBase& objSink, + ShArrayIndexClampingStrategy clampingStrategy, + ShHashFunction64 hashFunction, + NameMap& nameMap, + TSymbolTable& symbolTable); protected: virtual bool writeVariablePrecision(TPrecision precision); diff --git a/src/3rdparty/angle/src/compiler/OutputGLSL.cpp b/src/3rdparty/angle/src/compiler/OutputGLSL.cpp index dd31b4b58b..206f403408 100644 --- a/src/3rdparty/angle/src/compiler/OutputGLSL.cpp +++ b/src/3rdparty/angle/src/compiler/OutputGLSL.cpp @@ -6,8 +6,12 @@ #include "compiler/OutputGLSL.h" -TOutputGLSL::TOutputGLSL(TInfoSinkBase& objSink) - : TOutputGLSLBase(objSink) +TOutputGLSL::TOutputGLSL(TInfoSinkBase& objSink, + ShArrayIndexClampingStrategy clampingStrategy, + ShHashFunction64 hashFunction, + NameMap& nameMap, + TSymbolTable& symbolTable) + : TOutputGLSLBase(objSink, clampingStrategy, hashFunction, nameMap, symbolTable) { } diff --git a/src/3rdparty/angle/src/compiler/OutputGLSL.h b/src/3rdparty/angle/src/compiler/OutputGLSL.h index 0fe2356eb7..199b6f3e46 100644 --- a/src/3rdparty/angle/src/compiler/OutputGLSL.h +++ b/src/3rdparty/angle/src/compiler/OutputGLSL.h @@ -12,7 +12,11 @@ class TOutputGLSL : public TOutputGLSLBase { public: - TOutputGLSL(TInfoSinkBase& objSink); + TOutputGLSL(TInfoSinkBase& objSink, + ShArrayIndexClampingStrategy clampingStrategy, + ShHashFunction64 hashFunction, + NameMap& nameMap, + TSymbolTable& symbolTable); protected: virtual bool writeVariablePrecision(TPrecision); diff --git a/src/3rdparty/angle/src/compiler/OutputGLSLBase.cpp b/src/3rdparty/angle/src/compiler/OutputGLSLBase.cpp index 552fa5066d..1b9a10deaa 100644 --- a/src/3rdparty/angle/src/compiler/OutputGLSLBase.cpp +++ b/src/3rdparty/angle/src/compiler/OutputGLSLBase.cpp @@ -7,37 +7,10 @@ #include "compiler/OutputGLSLBase.h" #include "compiler/debug.h" +#include + namespace { -TString getTypeName(const TType& type) -{ - TInfoSinkBase out; - if (type.isMatrix()) - { - out << "mat"; - out << type.getNominalSize(); - } - else if (type.isVector()) - { - switch (type.getBasicType()) - { - case EbtFloat: out << "vec"; break; - case EbtInt: out << "ivec"; break; - case EbtBool: out << "bvec"; break; - default: UNREACHABLE(); break; - } - out << type.getNominalSize(); - } - else - { - if (type.getBasicType() == EbtStruct) - out << type.getTypeName(); - else - out << type.getBasicString(); - } - return TString(out.c_str()); -} - TString arrayBrackets(const TType& type) { ASSERT(type.isArray()); @@ -66,10 +39,18 @@ bool isSingleStatement(TIntermNode* node) { } } // namespace -TOutputGLSLBase::TOutputGLSLBase(TInfoSinkBase& objSink) +TOutputGLSLBase::TOutputGLSLBase(TInfoSinkBase& objSink, + ShArrayIndexClampingStrategy clampingStrategy, + ShHashFunction64 hashFunction, + NameMap& nameMap, + TSymbolTable& symbolTable) : TIntermTraverser(true, true, true), mObjSink(objSink), - mDeclaringVariables(false) + mDeclaringVariables(false), + mClampingStrategy(clampingStrategy), + mHashFunction(hashFunction), + mNameMap(nameMap), + mSymbolTable(symbolTable) { } @@ -101,7 +82,7 @@ void TOutputGLSLBase::writeVariableType(const TType& type) if ((type.getBasicType() == EbtStruct) && (mDeclaredStructs.find(type.getTypeName()) == mDeclaredStructs.end())) { - out << "struct " << type.getTypeName() << "{\n"; + out << "struct " << hashName(type.getTypeName()) << "{\n"; const TTypeList* structure = type.getStruct(); ASSERT(structure != NULL); for (size_t i = 0; i < structure->size(); ++i) @@ -110,7 +91,7 @@ void TOutputGLSLBase::writeVariableType(const TType& type) ASSERT(fieldType != NULL); if (writeVariablePrecision(fieldType->getPrecision())) out << " "; - out << getTypeName(*fieldType) << " " << fieldType->getFieldName(); + out << getTypeName(*fieldType) << " " << hashName(fieldType->getFieldName()); if (fieldType->isArray()) out << arrayBrackets(*fieldType); out << ";\n"; @@ -140,7 +121,7 @@ void TOutputGLSLBase::writeFunctionParameters(const TIntermSequence& args) const TString& name = arg->getSymbol(); if (!name.empty()) - out << " " << name; + out << " " << hashName(name); if (type.isArray()) out << arrayBrackets(type); @@ -157,7 +138,7 @@ const ConstantUnion* TOutputGLSLBase::writeConstantUnion(const TType& type, if (type.getBasicType() == EbtStruct) { - out << type.getTypeName() << "("; + out << hashName(type.getTypeName()) << "("; const TTypeList* structure = type.getStruct(); ASSERT(structure != NULL); for (size_t i = 0; i < structure->size(); ++i) @@ -178,7 +159,7 @@ const ConstantUnion* TOutputGLSLBase::writeConstantUnion(const TType& type, { switch (pConstUnion->getType()) { - case EbtFloat: out << pConstUnion->getFConst(); break; + 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(); @@ -196,7 +177,7 @@ void TOutputGLSLBase::visitSymbol(TIntermSymbol* node) if (mLoopUnroll.NeedsToReplaceSymbolWithValue(node)) out << mLoopUnroll.GetLoopIndexValue(node); else - out << node->getSymbol(); + out << hashVariableName(node->getSymbol()); if (mDeclaringVariables && node->getType().isArray()) out << arrayBrackets(node->getType()); @@ -235,15 +216,59 @@ bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary* node) break; case EOpIndexDirect: - case EOpIndexIndirect: 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) { out << "."; // TODO(alokp): ASSERT - out << node->getType().getFieldName(); + TString fieldName = node->getType().getFieldName(); + + const TType& structType = node->getLeft()->getType(); + if (!mSymbolTable.findBuiltIn(structType.getTypeName())) + fieldName = hashName(fieldName); + + out << fieldName; visitChildren = false; } break; @@ -467,7 +492,7 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate* node) // Function declaration. ASSERT(visit == PreVisit); writeVariableType(node->getType()); - out << " " << node->getName(); + out << " " << hashName(node->getName()); out << "("; writeFunctionParameters(node->getSequence()); @@ -480,7 +505,7 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate* node) // Function definition. ASSERT(visit == PreVisit); writeVariableType(node->getType()); - out << " " << TFunction::unmangleName(node->getName()); + out << " " << hashFunctionName(node->getName()); incrementDepth(); // Function definition node contains one or two children nodes @@ -510,8 +535,7 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate* node) // Function call. if (visit == PreVisit) { - TString functionName = TFunction::unmangleName(node->getName()); - out << functionName << "("; + out << hashFunctionName(node->getName()) << "("; } else if (visit == InVisit) { @@ -572,7 +596,7 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate* node) { const TType& type = node->getType(); ASSERT(type.getBasicType() == EbtStruct); - out << type.getTypeName() << "("; + out << hashName(type.getTypeName()) << "("; } else if (visit == InVisit) { @@ -718,3 +742,59 @@ void TOutputGLSLBase::visitCodeBlock(TIntermNode* node) { 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.getTypeName()); + 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); +} diff --git a/src/3rdparty/angle/src/compiler/OutputGLSLBase.h b/src/3rdparty/angle/src/compiler/OutputGLSLBase.h index efd0b5fc2d..c9f72d5631 100644 --- a/src/3rdparty/angle/src/compiler/OutputGLSLBase.h +++ b/src/3rdparty/angle/src/compiler/OutputGLSLBase.h @@ -16,7 +16,11 @@ class TOutputGLSLBase : public TIntermTraverser { public: - TOutputGLSLBase(TInfoSinkBase& objSink); + TOutputGLSLBase(TInfoSinkBase& objSink, + ShArrayIndexClampingStrategy clampingStrategy, + ShHashFunction64 hashFunction, + NameMap& nameMap, + TSymbolTable& symbolTable); protected: TInfoSinkBase& objSink() { return mObjSink; } @@ -25,6 +29,7 @@ protected: 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); @@ -37,6 +42,15 @@ protected: 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: TInfoSinkBase& mObjSink; bool mDeclaringVariables; @@ -48,6 +62,15 @@ private: 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 index a430695744..f6a984148b 100644 --- a/src/3rdparty/angle/src/compiler/OutputHLSL.cpp +++ b/src/3rdparty/angle/src/compiler/OutputHLSL.cpp @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// 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. // @@ -8,13 +8,14 @@ #include "common/angleutils.h" #include "compiler/debug.h" +#include "compiler/DetectDiscontinuity.h" #include "compiler/InfoSink.h" -#include "compiler/UnfoldShortCircuit.h" #include "compiler/SearchSymbol.h" -#include "compiler/DetectDiscontinuity.h" +#include "compiler/UnfoldShortCircuit.h" -#include #include +#include +#include namespace sh { @@ -26,7 +27,8 @@ TString str(int i) return buffer; } -OutputHLSL::OutputHLSL(TParseContext &context) : TIntermTraverser(true, true, true), mContext(context) +OutputHLSL::OutputHLSL(TParseContext &context, const ShBuiltInResources& resources, ShShaderOutput outputType) + : TIntermTraverser(true, true, true), mContext(context), mOutputType(outputType) { mUnfoldShortCircuit = new UnfoldShortCircuit(context, this); mInsideFunction = false; @@ -46,6 +48,8 @@ OutputHLSL::OutputHLSL(TParseContext &context) : TIntermTraverser(true, true, tr mUsesTexture2DProjLod0_bias = false; mUsesTextureCubeLod0 = false; mUsesTextureCubeLod0_bias = false; + mUsesFragColor = false; + mUsesFragData = false; mUsesDepthRange = false; mUsesFragCoord = false; mUsesPointCoord = false; @@ -80,6 +84,8 @@ OutputHLSL::OutputHLSL(TParseContext &context) : TIntermTraverser(true, true, tr mUsesAtan2_3 = false; mUsesAtan2_4 = false; + mNumRenderTargets = resources.EXT_draw_buffers ? resources.MaxDrawBuffers : 1; + mScopeDepth = 0; mUniqueIndex = 0; @@ -89,6 +95,24 @@ OutputHLSL::OutputHLSL(TParseContext &context) : TIntermTraverser(true, true, tr 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() @@ -98,7 +122,7 @@ OutputHLSL::~OutputHLSL() void OutputHLSL::output() { - mContainsLoopDiscontinuity = containsLoopDiscontinuity(mContext.treeRoot); + 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(); @@ -112,6 +136,11 @@ 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; @@ -135,58 +164,71 @@ void OutputHLSL::header() out << *constructor; } - if (shaderType == SH_FRAGMENT_SHADER) + TString uniforms; + TString varyings; + TString attributes; + + for (ReferencedSymbols::const_iterator uniform = mReferencedUniforms.begin(); uniform != mReferencedUniforms.end(); uniform++) { - TString uniforms; - TString varyings; + const TType &type = uniform->second->getType(); + const TString &name = uniform->second->getSymbol(); - TSymbolTableLevel *symbols = mContext.symbolTable.getGlobalLevel(); - int semanticIndex = 0; + 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"; - for (TSymbolTableLevel::const_iterator namedSymbol = symbols->begin(); namedSymbol != symbols->end(); namedSymbol++) + uniforms += "uniform " + textureString(type) + " texture_" + decorateUniform(name, type) + arrayString(type) + + " : register(t" + str(index) + ");\n"; + } + else { - const TSymbol *symbol = (*namedSymbol).second; - const TString &name = symbol->getName(); + uniforms += "uniform " + typeString(type) + " " + decorateUniform(name, type) + arrayString(type) + + " : register(" + registerString(mReferencedUniforms[name]) + ");\n"; + } + } - if (symbol->isVariable()) - { - const TVariable *variable = static_cast(symbol); - const TType &type = variable->getType(); - TQualifier qualifier = type.getQualifier(); + for (ReferencedSymbols::const_iterator varying = mReferencedVaryings.begin(); varying != mReferencedVaryings.end(); varying++) + { + const TType &type = varying->second->getType(); + const TString &name = varying->second->getSymbol(); - if (qualifier == EvqUniform) - { - if (mReferencedUniforms.find(name.c_str()) != mReferencedUniforms.end()) - { - uniforms += "uniform " + typeString(type) + " " + decorateUniform(name, type) + arrayString(type) + ";\n"; - } - } - else if (qualifier == EvqVaryingIn || qualifier == EvqInvariantVaryingIn) - { - if (mReferencedVaryings.find(name.c_str()) != mReferencedVaryings.end()) - { - // Program linking depends on this exact format - varyings += "static " + typeString(type) + " " + decorate(name) + arrayString(type) + " = " + initializer(type) + ";\n"; + // Program linking depends on this exact format + varyings += "static " + typeString(type) + " " + decorate(name) + arrayString(type) + " = " + initializer(type) + ";\n"; + } - semanticIndex += type.isArray() ? type.getArraySize() : 1; - } - } - else if (qualifier == EvqGlobal || qualifier == EvqTemporary) - { - // Globals are declared and intialized as an aggregate node - } - else if (qualifier == EvqConst) - { - // Constants are repeated as literals where used - } - else UNREACHABLE(); - } - } + 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"); + bool usingMRTExtension = iter != mContext.extensionBehavior().end() && iter->second == EBhEnable; + + unsigned int numColorValues = usingMRTExtension ? mNumRenderTargets : 1; out << "// Varyings\n"; out << varyings; out << "\n" - "static float4 gl_Color[1] = {float4(0, 0, 0, 0)};\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 (mUsesFragCoord) { @@ -205,205 +247,379 @@ void OutputHLSL::header() out << "\n"; - if (mUsesFragCoord) + 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 << "uniform float4 dx_Coord;\n" - "uniform float2 dx_Depth;\n"; + 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 (mUsesFrontFacing) + 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 << "uniform bool dx_PointsOrLines;\n" - "uniform bool dx_FrontCCW;\n"; + out << "static gl_DepthRangeParameters gl_DepthRange = {dx_DepthRange.x, dx_DepthRange.y, dx_DepthRange.z};\n" + "\n"; } - out << "\n"; out << uniforms; out << "\n"; if (mUsesTexture2D) { - out << "float4 gl_texture2D(sampler2D s, float2 t)\n" - "{\n" - " return tex2D(s, t);\n" - "}\n" - "\n"; + if (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) { - out << "float4 gl_texture2D(sampler2D s, float2 t, float bias)\n" - "{\n" - " return tex2Dbias(s, float4(t.x, t.y, 0, bias));\n" - "}\n" - "\n"; + if (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) { - out << "float4 gl_texture2DProj(sampler2D s, float3 t)\n" - "{\n" - " return tex2Dproj(s, float4(t.x, t.y, 0, t.z));\n" - "}\n" - "\n" - "float4 gl_texture2DProj(sampler2D s, float4 t)\n" - "{\n" - " return tex2Dproj(s, t);\n" - "}\n" - "\n"; + if (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) { - out << "float4 gl_texture2DProj(sampler2D s, float3 t, float bias)\n" - "{\n" - " return tex2Dbias(s, float4(t.x / t.z, t.y / t.z, 0, bias));\n" - "}\n" - "\n" - "float4 gl_texture2DProj(sampler2D s, float4 t, float bias)\n" - "{\n" - " return tex2Dbias(s, float4(t.x / t.w, t.y / t.w, 0, bias));\n" - "}\n" - "\n"; + if (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) { - out << "float4 gl_textureCube(samplerCUBE s, float3 t)\n" - "{\n" - " return texCUBE(s, t);\n" - "}\n" - "\n"; + 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) { - 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"; + 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) { - out << "float4 gl_texture2DLod0(sampler2D s, float2 t)\n" - "{\n" - " return tex2Dlod(s, float4(t.x, t.y, 0, 0));\n" - "}\n" - "\n"; + 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) { - out << "float4 gl_texture2DLod0(sampler2D s, float2 t, float bias)\n" - "{\n" - " return tex2Dlod(s, float4(t.x, t.y, 0, 0));\n" - "}\n" - "\n"; + if (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) { - out << "float4 gl_texture2DProjLod0(sampler2D s, float3 t)\n" - "{\n" - " return tex2Dlod(s, float4(t.x / t.z, t.y / t.z, 0, 0));\n" - "}\n" - "\n" - "float4 gl_texture2DProjLod(sampler2D s, float4 t)\n" - "{\n" - " return tex2Dlod(s, float4(t.x / t.w, t.y / t.w, 0, 0));\n" - "}\n" - "\n"; + if (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) { - out << "float4 gl_texture2DProjLod0_bias(sampler2D s, float3 t, float bias)\n" - "{\n" - " return tex2Dlod(s, float4(t.x / t.z, t.y / t.z, 0, 0));\n" - "}\n" - "\n" - "float4 gl_texture2DProjLod_bias(sampler2D s, float4 t, float bias)\n" - "{\n" - " return tex2Dlod(s, float4(t.x / t.w, t.y / t.w, 0, 0));\n" - "}\n" - "\n"; + if (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) { - out << "float4 gl_textureCubeLod0(samplerCUBE s, float3 t)\n" - "{\n" - " return texCUBElod(s, float4(t.x, t.y, t.z, 0));\n" - "}\n" - "\n"; + if (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) { - 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"; + 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(); } - } - else // Vertex shader - { - TString uniforms; - TString attributes; - TString varyings; - TSymbolTableLevel *symbols = mContext.symbolTable.getGlobalLevel(); - - for (TSymbolTableLevel::const_iterator namedSymbol = symbols->begin(); namedSymbol != symbols->end(); namedSymbol++) + if (usingMRTExtension && mNumRenderTargets > 1) { - const TSymbol *symbol = (*namedSymbol).second; - const TString &name = symbol->getName(); - - if (symbol->isVariable()) - { - const TVariable *variable = static_cast(symbol); - const TType &type = variable->getType(); - TQualifier qualifier = type.getQualifier(); + out << "#define GL_USES_MRT\n"; + } - if (qualifier == EvqUniform) - { - if (mReferencedUniforms.find(name.c_str()) != mReferencedUniforms.end()) - { - uniforms += "uniform " + typeString(type) + " " + decorateUniform(name, type) + arrayString(type) + ";\n"; - } - } - else if (qualifier == EvqAttribute) - { - if (mReferencedAttributes.find(name.c_str()) != mReferencedAttributes.end()) - { - attributes += "static " + typeString(type) + " " + decorate(name) + arrayString(type) + " = " + initializer(type) + ";\n"; - } - } - else if (qualifier == EvqVaryingOut || qualifier == EvqInvariantVaryingOut) - { - if (mReferencedVaryings.find(name.c_str()) != mReferencedVaryings.end()) - { - // Program linking depends on this exact format - varyings += "static " + typeString(type) + " " + decorate(name) + arrayString(type) + " = " + initializer(type) + ";\n"; - } - } - else if (qualifier == EvqGlobal || qualifier == EvqTemporary) - { - // Globals are declared and intialized as an aggregate node - } - else if (qualifier == EvqConst) - { - // Constants are repeated as literals where used - } - else UNREACHABLE(); - } + 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" @@ -417,74 +633,194 @@ void OutputHLSL::header() out << "\n" "// Varyings\n"; out << varyings; - out << "\n" - "uniform float2 dx_HalfPixelSize;\n" - "\n"; - out << uniforms; out << "\n"; - - if (mUsesTexture2D) + + if (mUsesDepthRange) { - out << "float4 gl_texture2D(sampler2D s, float2 t)\n" + out << "struct gl_DepthRangeParameters\n" "{\n" - " return tex2Dlod(s, float4(t.x, t.y, 0, 0));\n" - "}\n" + " float near;\n" + " float far;\n" + " float diff;\n" + "};\n" "\n"; } - if (mUsesTexture2DLod) + if (mOutputType == SH_HLSL11_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" + 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 (mUsesTexture2DProj) + if (mUsesDepthRange) { - 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" + 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) { - out << "float4 gl_texture2DProjLod(sampler2D s, float3 t, float lod)\n" - "{\n" - " return tex2Dlod(s, float4(t.x / t.z, t.y / t.z, 0, lod));\n" - "}\n" - "\n" - "float4 gl_texture2DProjLod(sampler2D s, float4 t, float lod)\n" - "{\n" - " return tex2Dlod(s, float4(t.x / t.w, t.y / t.w, 0, lod));\n" - "}\n" - "\n"; + if (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) { - out << "float4 gl_textureCube(samplerCUBE s, float3 t)\n" - "{\n" - " return texCUBElod(s, float4(t.x, t.y, t.z, 0));\n" - "}\n" - "\n"; + if (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) { - out << "float4 gl_textureCubeLod(samplerCUBE s, float3 t, float lod)\n" - "{\n" - " return texCUBElod(s, float4(t.x, t.y, t.z, lod));\n" - "}\n" - "\n"; + if (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(); } } @@ -508,20 +844,6 @@ void OutputHLSL::header() out << "#define GL_USES_POINT_SIZE\n"; } - if (mUsesDepthRange) - { - out << "struct gl_DepthRangeParameters\n" - "{\n" - " float near;\n" - " float far;\n" - " float diff;\n" - "};\n" - "\n" - "uniform float3 dx_DepthRange;" - "static gl_DepthRangeParameters gl_DepthRange = {dx_DepthRange.x, dx_DepthRange.y, dx_DepthRange.z};\n" - "\n"; - } - if (mUsesXor) { out << "bool xor(bool p, bool q)\n" @@ -812,10 +1134,12 @@ void OutputHLSL::visitSymbol(TIntermSymbol *node) 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") { @@ -848,17 +1172,17 @@ void OutputHLSL::visitSymbol(TIntermSymbol *node) if (qualifier == EvqUniform) { - mReferencedUniforms.insert(name.c_str()); + mReferencedUniforms[name] = node; out << decorateUniform(name, node->getType()); } else if (qualifier == EvqAttribute) { - mReferencedAttributes.insert(name.c_str()); + mReferencedAttributes[name] = node; out << decorate(name); } else if (qualifier == EvqVaryingOut || qualifier == EvqInvariantVaryingOut || qualifier == EvqVaryingIn || qualifier == EvqInvariantVaryingIn) { - mReferencedVaryings.insert(name.c_str()); + mReferencedVaryings[name] = node; out << decorate(name); } else @@ -973,7 +1297,7 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node) if (element) { - int i = element->getUnionArrayPointer()[0].getIConst(); + int i = element->getIConst(0); switch (i) { @@ -1276,7 +1600,6 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) { TIntermSequence &sequence = node->getSequence(); TIntermTyped *variable = sequence[0]->getAsTyped(); - bool visit = true; if (variable && (variable->getQualifier() == EvqTemporary || variable->getQualifier() == EvqGlobal)) { @@ -1309,19 +1632,11 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) (*sit)->traverse(this); } - if (visit && this->inVisit) + if (*sit != sequence.back()) { - if (*sit != sequence.back()) - { - visit = this->visitAggregate(InVisit, node); - } + out << ", "; } } - - if (visit && this->postVisit) - { - this->visitAggregate(PostVisit, node); - } } else if (variable->getAsSymbolNode() && variable->getAsSymbolNode()->getSymbol() == "") // Type (struct) declaration { @@ -1329,7 +1644,24 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) } 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) @@ -1440,151 +1772,163 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) break; case EOpFunctionCall: { - if (visit == PreVisit) - { - TString name = TFunction::unmangleName(node->getName()); - bool lod0 = mInsideDiscontinuousLoop || mOutputLod0Function; + TString name = TFunction::unmangleName(node->getName()); + bool lod0 = mInsideDiscontinuousLoop || mOutputLod0Function; - if (node->isUserDefined()) - { - out << decorate(name) << (lod0 ? "Lod0(" : "("); - } - else + if (node->isUserDefined()) + { + out << decorate(name) << (lod0 ? "Lod0(" : "("); + } + else + { + if (name == "texture2D") { - if (name == "texture2D") + if (!lod0) { - if (!lod0) + if (node->getSequence().size() == 2) { - if (node->getSequence().size() == 2) - { - mUsesTexture2D = true; - } - else if (node->getSequence().size() == 3) - { - mUsesTexture2D_bias = true; - } - else UNREACHABLE(); - - out << "gl_texture2D("; + mUsesTexture2D = true; } - else + else if (node->getSequence().size() == 3) { - if (node->getSequence().size() == 2) - { - mUsesTexture2DLod0 = true; - } - else if (node->getSequence().size() == 3) - { - mUsesTexture2DLod0_bias = true; - } - else UNREACHABLE(); - - out << "gl_texture2DLod0("; + mUsesTexture2D_bias = true; } + else UNREACHABLE(); + + out << "gl_texture2D("; } - else if (name == "texture2DProj") + else { - if (!lod0) + if (node->getSequence().size() == 2) { - if (node->getSequence().size() == 2) - { - mUsesTexture2DProj = true; - } - else if (node->getSequence().size() == 3) - { - mUsesTexture2DProj_bias = true; - } - else UNREACHABLE(); - - out << "gl_texture2DProj("; + mUsesTexture2DLod0 = true; } - else + else if (node->getSequence().size() == 3) { - if (node->getSequence().size() == 2) - { - mUsesTexture2DProjLod0 = true; - } - else if (node->getSequence().size() == 3) - { - mUsesTexture2DProjLod0_bias = true; - } - else UNREACHABLE(); - - out << "gl_texture2DProjLod0("; + mUsesTexture2DLod0_bias = true; } + else UNREACHABLE(); + + out << "gl_texture2DLod0("; } - else if (name == "textureCube") + } + else if (name == "texture2DProj") + { + if (!lod0) { - if (!lod0) + if (node->getSequence().size() == 2) { - if (node->getSequence().size() == 2) - { - mUsesTextureCube = true; - } - else if (node->getSequence().size() == 3) - { - mUsesTextureCube_bias = true; - } - else UNREACHABLE(); - - out << "gl_textureCube("; + mUsesTexture2DProj = true; } - else + else if (node->getSequence().size() == 3) { - if (node->getSequence().size() == 2) - { - mUsesTextureCubeLod0 = true; - } - else if (node->getSequence().size() == 3) - { - mUsesTextureCubeLod0_bias = true; - } - else UNREACHABLE(); - - out << "gl_textureCubeLod0("; + mUsesTexture2DProj_bias = true; } + else UNREACHABLE(); + + out << "gl_texture2DProj("; } - else if (name == "texture2DLod") + else { - if (node->getSequence().size() == 3) + if (node->getSequence().size() == 2) + { + mUsesTexture2DProjLod0 = true; + } + else if (node->getSequence().size() == 3) { - mUsesTexture2DLod = true; + mUsesTexture2DProjLod0_bias = true; } else UNREACHABLE(); - out << "gl_texture2DLod("; + out << "gl_texture2DProjLod0("; } - else if (name == "texture2DProjLod") + } + else if (name == "textureCube") + { + if (!lod0) { - if (node->getSequence().size() == 3) + if (node->getSequence().size() == 2) + { + mUsesTextureCube = true; + } + else if (node->getSequence().size() == 3) { - mUsesTexture2DProjLod = true; + mUsesTextureCube_bias = true; } else UNREACHABLE(); - out << "gl_texture2DProjLod("; + out << "gl_textureCube("; } - else if (name == "textureCubeLod") + else { - if (node->getSequence().size() == 3) + if (node->getSequence().size() == 2) { - mUsesTextureCubeLod = true; + mUsesTextureCubeLod0 = true; + } + else if (node->getSequence().size() == 3) + { + mUsesTextureCubeLod0_bias = true; } else UNREACHABLE(); - out << "gl_textureCubeLod("; + out << "gl_textureCubeLod0("; + } + } + else if (name == "texture2DLod") + { + if (node->getSequence().size() == 3) + { + mUsesTexture2DLod = true; + } + else UNREACHABLE(); + + out << "gl_texture2DLod("; + } + else if (name == "texture2DProjLod") + { + if (node->getSequence().size() == 3) + { + mUsesTexture2DProjLod = true; } else UNREACHABLE(); + + out << "gl_texture2DProjLod("; } + else if (name == "textureCubeLod") + { + if (node->getSequence().size() == 3) + { + mUsesTextureCubeLod = true; + } + else UNREACHABLE(); + + out << "gl_textureCubeLod("; + } + else UNREACHABLE(); } - else if (visit == InVisit) - { - out << ", "; - } - else + + TIntermSequence &arguments = node->getSequence(); + + for (TIntermSequence::iterator arg = arguments.begin(); arg != arguments.end(); arg++) { - out << ")"; + 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; @@ -1778,14 +2122,17 @@ bool OutputHLSL::visitLoop(Visit visit, TIntermLoop *node) { bool wasDiscontinuous = mInsideDiscontinuousLoop; - if (!mInsideDiscontinuousLoop) + if (mContainsLoopDiscontinuity && !mInsideDiscontinuousLoop) { mInsideDiscontinuousLoop = containsLoopDiscontinuity(node); } - if (handleExcessiveLoop(node)) + if (mOutputType == SH_HLSL9_OUTPUT) { - return false; + if (handleExcessiveLoop(node)) + { + return false; + } } TInfoSinkBase &out = mBody; @@ -1976,7 +2323,7 @@ bool OutputHLSL::handleExcessiveLoop(TIntermLoop *node) if (constant->getBasicType() == EbtInt && constant->getNominalSize() == 1) { index = symbol; - initial = constant->getUnionArrayPointer()[0].getIConst(); + initial = constant->getIConst(0); } } } @@ -1998,7 +2345,7 @@ bool OutputHLSL::handleExcessiveLoop(TIntermLoop *node) if (constant->getBasicType() == EbtInt && constant->getNominalSize() == 1) { comparator = test->getOp(); - limit = constant->getUnionArrayPointer()[0].getIConst(); + limit = constant->getIConst(0); } } } @@ -2019,7 +2366,7 @@ bool OutputHLSL::handleExcessiveLoop(TIntermLoop *node) { if (constant->getBasicType() == EbtInt && constant->getNominalSize() == 1) { - int value = constant->getUnionArrayPointer()[0].getIConst(); + int value = constant->getIConst(0); switch (op) { @@ -2191,6 +2538,12 @@ TString OutputHLSL::argumentString(const TIntermSymbol *symbol) 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); } @@ -2285,10 +2638,28 @@ TString OutputHLSL::typeString(const TType &type) } } - UNIMPLEMENTED(); // FIXME + 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()) @@ -2565,7 +2936,7 @@ const ConstantUnion *OutputHLSL::writeConstantUnion(const TType &type, const Con { switch (constUnion->getType()) { - case EbtFloat: out << constUnion->getFConst(); break; + 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(); @@ -2640,11 +3011,7 @@ TString OutputHLSL::decorate(const TString &string) TString OutputHLSL::decorateUniform(const TString &string, const TType &type) { - if (type.isArray()) - { - return "ar_" + string; // Allows identifying arrays of size 1 - } - else if (type.getBasicType() == EbtSamplerExternalOES) + if (type.getBasicType() == EbtSamplerExternalOES) { return "ex_" + string; } @@ -2661,4 +3028,197 @@ TString OutputHLSL::decorateField(const TString &string, const TType &structure) 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) +{ + const TTypeList *structure = type.getStruct(); + + if (!structure) + { + mActiveUniforms.push_back(Uniform(glVariableType(type), glVariablePrecision(type), name.c_str(), type.getArraySize(), index)); + } + else + { + if (type.isArray()) + { + int elementIndex = index; + + for (int i = 0; i < type.getArraySize(); i++) + { + for (size_t j = 0; j < structure->size(); j++) + { + const TType &fieldType = *(*structure)[j].type; + const TString &fieldName = fieldType.getFieldName(); + + const TString uniformName = name + "[" + str(i) + "]." + fieldName; + declareUniform(fieldType, uniformName, elementIndex); + elementIndex += fieldType.totalRegisterCount(); + } + } + } + else + { + int fieldIndex = index; + + for (size_t i = 0; i < structure->size(); i++) + { + const TType &fieldType = *(*structure)[i].type; + const TString &fieldName = fieldType.getFieldName(); + + const TString uniformName = name + "." + fieldName; + 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 index dc843fb366..749a3461b3 100644 --- a/src/3rdparty/angle/src/compiler/OutputHLSL.h +++ b/src/3rdparty/angle/src/compiler/OutputHLSL.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// 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. // @@ -9,9 +9,14 @@ #include #include +#include + +#define GL_APICALL +#include #include "compiler/intermediate.h" #include "compiler/ParseHelper.h" +#include "compiler/Uniform.h" namespace sh { @@ -20,14 +25,16 @@ class UnfoldShortCircuit; class OutputHLSL : public TIntermTraverser { public: - explicit OutputHLSL(TParseContext &context); + 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); @@ -64,6 +71,7 @@ class OutputHLSL : public TIntermTraverser TString structLookup(const TString &typeName); TParseContext &mContext; + const ShShaderOutput mOutputType; UnfoldShortCircuit *mUnfoldShortCircuit; bool mInsideFunction; @@ -72,9 +80,10 @@ class OutputHLSL : public TIntermTraverser TInfoSinkBase mBody; TInfoSinkBase mFooter; - std::set mReferencedUniforms; - std::set mReferencedAttributes; - std::set mReferencedVaryings; + typedef std::map ReferencedSymbols; + ReferencedSymbols mReferencedUniforms; + ReferencedSymbols mReferencedAttributes; + ReferencedSymbols mReferencedVaryings; // Parameters determining what goes in the header output bool mUsesTexture2D; @@ -92,6 +101,8 @@ class OutputHLSL : public TIntermTraverser bool mUsesTexture2DProjLod0_bias; bool mUsesTextureCubeLod0; bool mUsesTextureCubeLod0_bias; + bool mUsesFragColor; + bool mUsesFragData; bool mUsesDepthRange; bool mUsesFragCoord; bool mUsesPointCoord; @@ -126,6 +137,8 @@ class OutputHLSL : public TIntermTraverser bool mUsesAtan2_3; bool mUsesAtan2_4; + int mNumRenderTargets; + typedef std::set Constructors; Constructors mConstructors; @@ -146,6 +159,18 @@ class OutputHLSL : public TIntermTraverser 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; }; } diff --git a/src/3rdparty/angle/src/compiler/ParseHelper.cpp b/src/3rdparty/angle/src/compiler/ParseHelper.cpp index 508f1726a7..441ff35e00 100644 --- a/src/3rdparty/angle/src/compiler/ParseHelper.cpp +++ b/src/3rdparty/angle/src/compiler/ParseHelper.cpp @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// 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. // @@ -10,7 +10,7 @@ #include #include "compiler/glslang.h" -#include "compiler/preprocessor/new/SourceLocation.h" +#include "compiler/preprocessor/SourceLocation.h" /////////////////////////////////////////////////////////////////////// // @@ -33,7 +33,7 @@ bool TParseContext::parseVectorFields(const TString& compString, int vecSize, TV enum { exyzw, ergba, - estpq, + estpq } fieldSet[4]; for (int i = 0; i < fields.num; ++i) { @@ -286,7 +286,7 @@ bool TParseContext::lValueErrorCheck(int line, const char* op, TIntermTyped* nod for (TIntermSequence::iterator p = aggrNode->getSequence().begin(); p != aggrNode->getSequence().end(); p++) { - int value = (*p)->getAsTyped()->getAsConstantUnion()->getUnionArrayPointer()->getIConst(); + int value = (*p)->getAsTyped()->getAsConstantUnion()->getIConst(0); offset[value]++; if (offset[value] > 1) { error(line, " l-value of swizzle cannot have duplicate components", op); @@ -493,7 +493,7 @@ bool TParseContext::constructorErrorCheck(int line, TIntermNode* node, TFunction bool overFull = false; bool matrixInMatrix = false; bool arrayArg = false; - for (int i = 0; i < function.getParamCount(); ++i) { + for (size_t i = 0; i < function.getParamCount(); ++i) { const TParameter& param = function.getParam(i); size += param.type->getObjectSize(); @@ -512,7 +512,7 @@ bool TParseContext::constructorErrorCheck(int line, TIntermNode* node, TFunction if (constType) type->setQualifier(EvqConst); - if (type->isArray() && type->getArraySize() != function.getParamCount()) { + if (type->isArray() && static_cast(type->getArraySize()) != function.getParamCount()) { error(line, "array constructor needs one argument per array element", "constructor"); return true; } @@ -680,7 +680,7 @@ bool TParseContext::arraySizeErrorCheck(int line, TIntermTyped* expr, int& size) return true; } - size = constant->getUnionArrayPointer()->getIConst(); + size = constant->getIConst(0); if (size <= 0) { error(line, "array size must be a positive integer", ""); @@ -1313,7 +1313,6 @@ TIntermTyped* TParseContext::addConstVectorNode(TVectorFields& fields, TIntermTy ConstantUnion *unionArray; if (tempConstantNode) { unionArray = tempConstantNode->getUnionArrayPointer(); - ASSERT(unionArray); if (!unionArray) { return node; @@ -1507,7 +1506,7 @@ bool TParseContext::structNestingErrorCheck(TSourceLoc line, const TType& fieldT // // Returns 0 for success. // -int PaParseStrings(int count, const char* const string[], const int length[], +int PaParseStrings(size_t count, const char* const string[], const int length[], TParseContext* context) { if ((count == 0) || (string == NULL)) return 1; diff --git a/src/3rdparty/angle/src/compiler/ParseHelper.h b/src/3rdparty/angle/src/compiler/ParseHelper.h index 824ee00f39..26a3ea1308 100644 --- a/src/3rdparty/angle/src/compiler/ParseHelper.h +++ b/src/3rdparty/angle/src/compiler/ParseHelper.h @@ -9,7 +9,7 @@ #include "compiler/Diagnostics.h" #include "compiler/DirectiveHandler.h" #include "compiler/localintermediate.h" -#include "compiler/preprocessor/new/Preprocessor.h" +#include "compiler/preprocessor/Preprocessor.h" #include "compiler/ShHandle.h" #include "compiler/SymbolTable.h" @@ -58,6 +58,7 @@ struct TParseContext { 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; bool AfterEOF; TDiagnostics diagnostics; @@ -134,7 +135,7 @@ struct TParseContext { bool structNestingErrorCheck(TSourceLoc line, const TType& fieldType); }; -int PaParseStrings(int count, const char* const string[], const int length[], +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/ShHandle.h b/src/3rdparty/angle/src/compiler/ShHandle.h index 6ba302ad04..28049305e0 100644 --- a/src/3rdparty/angle/src/compiler/ShHandle.h +++ b/src/3rdparty/angle/src/compiler/ShHandle.h @@ -18,13 +18,16 @@ #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, @@ -40,6 +43,7 @@ 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. @@ -59,7 +63,7 @@ public: bool Init(const ShBuiltInResources& resources); bool compile(const char* const shaderStrings[], - const int numStrings, + size_t numStrings, int compileOptions); // Get results of the last compilation. @@ -68,6 +72,10 @@ public: const TVariableInfoList& getUniforms() const { return uniforms; } 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; } @@ -100,7 +108,11 @@ protected: bool enforceFragmentShaderTimingRestrictions(const TDependencyGraph& graph); // 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: @@ -109,12 +121,17 @@ private: int maxUniformVectors; + 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. @@ -124,6 +141,10 @@ private: // Cached copy of the ref-counted singleton. LongNameMap* longNameMap; + + // name hashing. + ShHashFunction64 hashFunction; + NameMap nameMap; }; // diff --git a/src/3rdparty/angle/src/compiler/ShaderLang.cpp b/src/3rdparty/angle/src/compiler/ShaderLang.cpp index 56f5c7f2ec..92f39311c2 100644 --- a/src/3rdparty/angle/src/compiler/ShaderLang.cpp +++ b/src/3rdparty/angle/src/compiler/ShaderLang.cpp @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. +// 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. // @@ -14,6 +14,7 @@ #include "compiler/InitializeDll.h" #include "compiler/preprocessor/length_limits.h" #include "compiler/ShHandle.h" +#include "compiler/TranslatorHLSL.h" // // This is the platform independent interface between an OGL driver @@ -21,18 +22,18 @@ // static bool checkActiveUniformAndAttribMaxLengths(const ShHandle handle, - int expectedValue) + size_t expectedValue) { - int activeUniformLimit = 0; + size_t activeUniformLimit = 0; ShGetInfo(handle, SH_ACTIVE_UNIFORM_MAX_LENGTH, &activeUniformLimit); - int activeAttribLimit = 0; + size_t activeAttribLimit = 0; ShGetInfo(handle, SH_ACTIVE_ATTRIBUTE_MAX_LENGTH, &activeAttribLimit); return (expectedValue == activeUniformLimit && expectedValue == activeAttribLimit); } -static bool checkMappedNameMaxLength(const ShHandle handle, int expectedValue) +static bool checkMappedNameMaxLength(const ShHandle handle, size_t expectedValue) { - int mappedNameMaxLength = 0; + size_t mappedNameMaxLength = 0; ShGetInfo(handle, SH_MAPPED_NAME_MAX_LENGTH, &mappedNameMaxLength); return (expectedValue == mappedNameMaxLength); } @@ -40,7 +41,7 @@ static bool checkMappedNameMaxLength(const ShHandle handle, int expectedValue) static void getVariableInfo(ShShaderInfo varType, const ShHandle handle, int index, - int* length, + size_t* length, int* size, ShDataType* type, char* name, @@ -69,14 +70,14 @@ static void getVariableInfo(ShShaderInfo varType, // This size must match that queried by // SH_ACTIVE_UNIFORM_MAX_LENGTH and SH_ACTIVE_ATTRIBUTE_MAX_LENGTH // in ShGetInfo, below. - int activeUniformAndAttribLength = 1 + MAX_SYMBOL_NAME_LEN; + size_t activeUniformAndAttribLength = 1 + MAX_SYMBOL_NAME_LEN; ASSERT(checkActiveUniformAndAttribMaxLengths(handle, activeUniformAndAttribLength)); strncpy(name, varInfo.name.c_str(), activeUniformAndAttribLength); name[activeUniformAndAttribLength - 1] = 0; if (mappedName) { // This size must match that queried by // SH_MAPPED_NAME_MAX_LENGTH in ShGetInfo, below. - int maxMappedNameLength = 1 + MAX_SYMBOL_NAME_LEN; + size_t maxMappedNameLength = 1 + MAX_SYMBOL_NAME_LEN; ASSERT(checkMappedNameMaxLength(handle, maxMappedNameLength)); strncpy(mappedName, varInfo.mappedName.c_str(), maxMappedNameLength); mappedName[maxMappedNameLength - 1] = 0; @@ -125,6 +126,15 @@ void ShInitBuiltInResources(ShBuiltInResources* resources) resources->OES_standard_derivatives = 0; resources->OES_EGL_image_external = 0; resources->ARB_texture_rectangle = 0; + resources->EXT_draw_buffers = 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; } // @@ -172,7 +182,7 @@ void ShDestruct(ShHandle handle) int ShCompile( const ShHandle handle, const char* const shaderStrings[], - const int numStrings, + size_t numStrings, int compileOptions) { if (!InitThread()) @@ -190,7 +200,7 @@ int ShCompile( return success ? 1 : 0; } -void ShGetInfo(const ShHandle handle, ShShaderInfo pname, int* params) +void ShGetInfo(const ShHandle handle, ShShaderInfo pname, size_t* params) { if (!handle || !params) return; @@ -224,6 +234,22 @@ void ShGetInfo(const ShHandle handle, ShShaderInfo pname, int* params) // 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(); } } @@ -262,7 +288,7 @@ void ShGetObjectCode(const ShHandle handle, char* objCode) void ShGetActiveAttrib(const ShHandle handle, int index, - int* length, + size_t* length, int* size, ShDataType* type, char* name, @@ -274,7 +300,7 @@ void ShGetActiveAttrib(const ShHandle handle, void ShGetActiveUniform(const ShHandle handle, int index, - int* length, + size_t* length, int* size, ShDataType* type, char* name, @@ -283,3 +309,64 @@ void ShGetActiveUniform(const ShHandle handle, getVariableInfo(SH_ACTIVE_UNIFORMS, handle, index, length, size, type, name, mappedName); } + +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(); + } +} diff --git a/src/3rdparty/angle/src/compiler/SymbolTable.h b/src/3rdparty/angle/src/compiler/SymbolTable.h index a89499e4f4..d27aa332b7 100644 --- a/src/3rdparty/angle/src/compiler/SymbolTable.h +++ b/src/3rdparty/angle/src/compiler/SymbolTable.h @@ -169,8 +169,8 @@ public: void setDefined() { defined = true; } bool isDefined() { return defined; } - int getParamCount() const { return static_cast(parameters.size()); } - const TParameter& getParam(int i) const { return parameters[i]; } + size_t getParamCount() const { return parameters.size(); } + const TParameter& getParam(size_t i) const { return parameters[i]; } virtual void dump(TInfoSink &infoSink) const; TFunction(const TFunction&, TStructureMap& remapper); @@ -323,10 +323,16 @@ public: void dump(TInfoSink &infoSink) const; void copyTable(const TSymbolTable& copyOf); - void setDefaultPrecision( TBasicType type, TPrecision prec ){ - if( type != EbtFloat && type != EbtInt ) return; // Only set default precision for int/float + bool setDefaultPrecision( const TPublicType& type, TPrecision prec ){ + if (IsSampler(type.type)) + return true; // Skip sampler types for the time being + if (type.type != EbtFloat && type.type != EbtInt) + return false; // Only set default precision for int/float + 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] = prec; // Uses map operator [], overwrites the current value + 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 diff --git a/src/3rdparty/angle/src/compiler/TranslatorESSL.cpp b/src/3rdparty/angle/src/compiler/TranslatorESSL.cpp index e3a2c2a802..2900f8a8ed 100644 --- a/src/3rdparty/angle/src/compiler/TranslatorESSL.cpp +++ b/src/3rdparty/angle/src/compiler/TranslatorESSL.cpp @@ -22,8 +22,11 @@ void TranslatorESSL::translate(TIntermNode* root) { getBuiltInFunctionEmulator().OutputEmulatedFunctionDefinition( sink, getShaderType() == SH_FRAGMENT_SHADER); + // Write array bounds clamping emulation if needed. + getArrayBoundsClamper().OutputClampingFunctionDefinition(sink); + // Write translated shader. - TOutputESSL outputESSL(sink); + TOutputESSL outputESSL(sink, getArrayIndexClampingStrategy(), getHashFunction(), getNameMap(), getSymbolTable()); root->traverse(&outputESSL); } diff --git a/src/3rdparty/angle/src/compiler/TranslatorGLSL.cpp b/src/3rdparty/angle/src/compiler/TranslatorGLSL.cpp index bb07a1eb4e..7ca4341dcd 100644 --- a/src/3rdparty/angle/src/compiler/TranslatorGLSL.cpp +++ b/src/3rdparty/angle/src/compiler/TranslatorGLSL.cpp @@ -35,7 +35,10 @@ void TranslatorGLSL::translate(TIntermNode* root) { getBuiltInFunctionEmulator().OutputEmulatedFunctionDefinition( sink, false); + // Write array bounds clamping emulation if needed. + getArrayBoundsClamper().OutputClampingFunctionDefinition(sink); + // Write translated shader. - TOutputGLSL outputGLSL(sink); + TOutputGLSL outputGLSL(sink, getArrayIndexClampingStrategy(), getHashFunction(), getNameMap(), getSymbolTable()); root->traverse(&outputGLSL); } diff --git a/src/3rdparty/angle/src/compiler/TranslatorHLSL.cpp b/src/3rdparty/angle/src/compiler/TranslatorHLSL.cpp index f41decd48c..37408a07c4 100644 --- a/src/3rdparty/angle/src/compiler/TranslatorHLSL.cpp +++ b/src/3rdparty/angle/src/compiler/TranslatorHLSL.cpp @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// 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. // @@ -9,15 +9,16 @@ #include "compiler/InitializeParseContext.h" #include "compiler/OutputHLSL.h" -TranslatorHLSL::TranslatorHLSL(ShShaderType type, ShShaderSpec spec) - : TCompiler(type, spec) +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); + 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 index c3f672ba91..9550e15e8e 100644 --- a/src/3rdparty/angle/src/compiler/TranslatorHLSL.h +++ b/src/3rdparty/angle/src/compiler/TranslatorHLSL.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// 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. // @@ -8,13 +8,20 @@ #define COMPILER_TRANSLATORHLSL_H_ #include "compiler/ShHandle.h" +#include "compiler/Uniform.h" class TranslatorHLSL : public TCompiler { public: - TranslatorHLSL(ShShaderType type, ShShaderSpec spec); + 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 index d4576673b1..854bb44c07 100644 --- a/src/3rdparty/angle/src/compiler/Types.h +++ b/src/3rdparty/angle/src/compiler/Types.h @@ -136,6 +136,43 @@ public: return totalSize; } + int elementRegisterCount() const + { + TTypeList *structure = getStruct(); + + if (structure) + { + int registerCount = 0; + + for (size_t i = 0; i < structure->size(); i++) + { + registerCount += (*structure)[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; } diff --git a/src/3rdparty/angle/src/compiler/UnfoldShortCircuit.cpp b/src/3rdparty/angle/src/compiler/UnfoldShortCircuit.cpp index 1782ebc90c..47f0afca6a 100644 --- a/src/3rdparty/angle/src/compiler/UnfoldShortCircuit.cpp +++ b/src/3rdparty/angle/src/compiler/UnfoldShortCircuit.cpp @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// 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. // @@ -95,9 +95,9 @@ bool UnfoldShortCircuit::visitBinary(Visit visit, TIntermBinary *node) mTemporaryIndex = i + 1; } return false; + default: + return true; } - - return true; } bool UnfoldShortCircuit::visitSelection(Visit visit, TIntermSelection *node) @@ -111,6 +111,8 @@ bool UnfoldShortCircuit::visitSelection(Visit visit, TIntermSelection *node) out << mOutputHLSL->typeString(node->getType()) << " s" << i << ";\n"; + out << "{\n"; + mTemporaryIndex = i + 1; node->getCondition()->traverse(this); out << "if("; @@ -135,6 +137,8 @@ bool UnfoldShortCircuit::visitSelection(Visit visit, TIntermSelection *node) out << ";\n" "}\n"; + out << "}\n"; + mTemporaryIndex = i + 1; } diff --git a/src/3rdparty/angle/src/compiler/Uniform.cpp b/src/3rdparty/angle/src/compiler/Uniform.cpp new file mode 100644 index 0000000000..f367db2be8 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/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/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 new file mode 100644 index 0000000000..4c53ffa7d2 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/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/ValidateLimitations.cpp b/src/3rdparty/angle/src/compiler/ValidateLimitations.cpp index d69ec6bbaa..a5562d09a4 100644 --- a/src/3rdparty/angle/src/compiler/ValidateLimitations.cpp +++ b/src/3rdparty/angle/src/compiler/ValidateLimitations.cpp @@ -421,7 +421,7 @@ bool ValidateLimitations::validateFunctionCall(TIntermAggregate* node) return true; // List of param indices for which loop indices are used as argument. - typedef std::vector ParamIndex; + typedef std::vector ParamIndex; ParamIndex pIndex; TIntermSequence& params = node->getSequence(); for (TIntermSequence::size_type i = 0; i < params.size(); ++i) { diff --git a/src/3rdparty/angle/src/compiler/VariableInfo.cpp b/src/3rdparty/angle/src/compiler/VariableInfo.cpp index 3ff283627b..eb6bea9b0f 100644 --- a/src/3rdparty/angle/src/compiler/VariableInfo.cpp +++ b/src/3rdparty/angle/src/compiler/VariableInfo.cpp @@ -77,23 +77,25 @@ static void getBuiltInVariableInfo(const TType& type, static void getUserDefinedVariableInfo(const TType& type, const TString& name, const TString& mappedName, - TVariableInfoList& infoList); + TVariableInfoList& infoList, + ShHashFunction64 hashFunction); // Returns info for an attribute or uniform. static void getVariableInfo(const TType& type, const TString& name, const TString& mappedName, - TVariableInfoList& infoList) + 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); + getUserDefinedVariableInfo(type, lname, lmappedName, infoList, hashFunction); } } else { - getUserDefinedVariableInfo(type, name, mappedName, infoList); + getUserDefinedVariableInfo(type, name, mappedName, infoList, hashFunction); } } else { getBuiltInVariableInfo(type, name, mappedName, infoList); @@ -124,7 +126,8 @@ void getBuiltInVariableInfo(const TType& type, void getUserDefinedVariableInfo(const TType& type, const TString& name, const TString& mappedName, - TVariableInfoList& infoList) + TVariableInfoList& infoList, + ShHashFunction64 hashFunction) { ASSERT(type.getBasicType() == EbtStruct); @@ -133,8 +136,9 @@ void getUserDefinedVariableInfo(const TType& type, const TType* fieldType = (*structure)[i].type; getVariableInfo(*fieldType, name + "." + fieldType->getFieldName(), - mappedName + "." + fieldType->getFieldName(), - infoList); + mappedName + "." + TIntermTraverser::hash(fieldType->getFieldName(), hashFunction), + infoList, + hashFunction); } } @@ -149,9 +153,11 @@ TVariableInfo::TVariableInfo(ShDataType type, int size) } CollectAttribsUniforms::CollectAttribsUniforms(TVariableInfoList& attribs, - TVariableInfoList& uniforms) + TVariableInfoList& uniforms, + ShHashFunction64 hashFunction) : mAttribs(attribs), - mUniforms(uniforms) + mUniforms(uniforms), + mHashFunction(hashFunction) { } @@ -206,10 +212,16 @@ bool CollectAttribsUniforms::visitAggregate(Visit, TIntermAggregate* node) // 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(), - variable->getSymbol(), - infoList); + processedSymbol, + infoList, + mHashFunction); } } break; diff --git a/src/3rdparty/angle/src/compiler/VariableInfo.h b/src/3rdparty/angle/src/compiler/VariableInfo.h index fdcc08f5b5..4130a589f5 100644 --- a/src/3rdparty/angle/src/compiler/VariableInfo.h +++ b/src/3rdparty/angle/src/compiler/VariableInfo.h @@ -27,7 +27,8 @@ typedef std::vector TVariableInfoList; class CollectAttribsUniforms : public TIntermTraverser { public: CollectAttribsUniforms(TVariableInfoList& attribs, - TVariableInfoList& uniforms); + TVariableInfoList& uniforms, + ShHashFunction64 hashFunction); virtual void visitSymbol(TIntermSymbol*); virtual void visitConstantUnion(TIntermConstantUnion*); @@ -41,6 +42,8 @@ public: private: TVariableInfoList& mAttribs; TVariableInfoList& mUniforms; + + 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 index 2f0c4bc2a2..8957287763 100644 --- a/src/3rdparty/angle/src/compiler/VariablePacker.cpp +++ b/src/3rdparty/angle/src/compiler/VariablePacker.cpp @@ -85,7 +85,7 @@ int VariablePacker::GetNumRows(ShDataType type) case SH_FLOAT_MAT3: return 3; case SH_FLOAT_MAT2: - return 1; + return 2; case SH_FLOAT_VEC4: case SH_INT_VEC4: case SH_BOOL_VEC4: diff --git a/src/3rdparty/angle/src/compiler/glslang.h b/src/3rdparty/angle/src/compiler/glslang.h index 3a45daf3a4..f221199093 100644 --- a/src/3rdparty/angle/src/compiler/glslang.h +++ b/src/3rdparty/angle/src/compiler/glslang.h @@ -8,7 +8,7 @@ struct TParseContext; extern int glslang_initialize(TParseContext* context); extern int glslang_finalize(TParseContext* context); -extern int glslang_scan(int count, +extern int glslang_scan(size_t count, const char* const string[], const int length[], TParseContext* context); diff --git a/src/3rdparty/angle/src/compiler/glslang.l b/src/3rdparty/angle/src/compiler/glslang.l index e0483e2ea9..140a9aeb2d 100644 --- a/src/3rdparty/angle/src/compiler/glslang.l +++ b/src/3rdparty/angle/src/compiler/glslang.l @@ -38,7 +38,7 @@ WHICH GENERATES THE GLSL ES LEXER (glslang_lex.cpp). %{ #include "compiler/glslang.h" #include "compiler/ParseHelper.h" -#include "compiler/preprocessor/new/Token.h" +#include "compiler/preprocessor/Token.h" #include "compiler/util.h" #include "glslang_tab.h" @@ -51,7 +51,7 @@ WHICH GENERATES THE GLSL ES LEXER (glslang_lex.cpp). #define YY_INPUT(buf, result, max_size) \ result = string_input(buf, max_size, yyscanner); -static int string_input(char* buf, int max_size, yyscan_t yyscanner); +static 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); %} @@ -203,10 +203,10 @@ O [0-7] return check_type(yyscanner); } -0[xX]{H}+ { yylval->lex.i = strtol(yytext, 0, 0); return(INTCONSTANT); } -0{O}+ { yylval->lex.i = strtol(yytext, 0, 0); return(INTCONSTANT); } +0[xX]{H}+ { yylval->lex.i = static_cast(strtol(yytext, 0, 0)); return(INTCONSTANT); } +0{O}+ { yylval->lex.i = static_cast(strtol(yytext, 0, 0)); return(INTCONSTANT); } 0{D}+ { context->error(yylineno, "Invalid Octal number.", yytext); context->recover(); return 0;} -{D}+ { yylval->lex.i = strtol(yytext, 0, 0); return(INTCONSTANT); } +{D}+ { yylval->lex.i = static_cast(strtol(yytext, 0, 0)); return(INTCONSTANT); } {D}+{E} { yylval->lex.f = static_cast(atof_dot(yytext)); return(FLOATCONSTANT); } {D}+"."{D}*({E})? { yylval->lex.f = static_cast(atof_dot(yytext)); return(FLOATCONSTANT); } @@ -272,146 +272,13 @@ O [0-7] %% -// Old preprocessor interface. -extern "C" { -#include "compiler/preprocessor/preprocess.h" - -extern int InitPreprocessor(); -extern int FinalizePreprocessor(); -extern void PredefineIntMacro(const char *name, int value); - -#define SETUP_CONTEXT(pp) \ - TParseContext* context = (TParseContext*) pp->pC; \ - struct yyguts_t* yyg = (struct yyguts_t*) context->scanner; - -// Preprocessor callbacks. -void CPPDebugLogMsg(const char *msg) -{ - SETUP_CONTEXT(cpp); - context->trace(msg); -} - -void CPPWarningToInfoLog(const char *msg) -{ - SETUP_CONTEXT(cpp); - context->warning(yylineno, msg, ""); -} - -void CPPShInfoLogMsg(const char *msg) -{ - SETUP_CONTEXT(cpp); - context->error(yylineno, msg, ""); - context->recover(); -} - -void CPPErrorToInfoLog(const char *msg) -{ - SETUP_CONTEXT(cpp); - context->error(yylineno, msg, ""); - context->recover(); -} - -void SetLineNumber(int line) -{ - SETUP_CONTEXT(cpp); - int string = 0; - DecodeSourceLoc(yylineno, &string, NULL); - yylineno = EncodeSourceLoc(string, line); -} - -void SetStringNumber(int string) -{ - SETUP_CONTEXT(cpp); - int line = 0; - DecodeSourceLoc(yylineno, NULL, &line); - yylineno = EncodeSourceLoc(string, line); -} - -int GetStringNumber() -{ - SETUP_CONTEXT(cpp); - int string = 0; - DecodeSourceLoc(yylineno, &string, NULL); - return string; -} - -int GetLineNumber() -{ - SETUP_CONTEXT(cpp); - int line = 0; - DecodeSourceLoc(yylineno, NULL, &line); - return line; -} - -void IncLineNumber() -{ - SETUP_CONTEXT(cpp); - int string = 0, line = 0; - DecodeSourceLoc(yylineno, &string, &line); - yylineno = EncodeSourceLoc(string, ++line); -} - -void DecLineNumber() -{ - SETUP_CONTEXT(cpp); - int string = 0, line = 0; - DecodeSourceLoc(yylineno, &string, &line); - yylineno = EncodeSourceLoc(string, --line); -} - -void HandlePragma(const char **tokens, int numTokens) -{ - SETUP_CONTEXT(cpp); - - if (numTokens != 4) return; - if (strcmp(tokens[1], "(") != 0) return; - if (strcmp(tokens[3], ")") != 0) return; - - context->handlePragmaDirective(yylineno, tokens[0], tokens[2]); -} - -void StoreStr(const char *string) -{ - SETUP_CONTEXT(cpp); - TString strSrc; - strSrc = TString(string); - - context->HashErrMsg = context->HashErrMsg + " " + strSrc; -} - -const char* GetStrfromTStr(void) -{ - SETUP_CONTEXT(cpp); - cpp->ErrMsg = context->HashErrMsg.c_str(); - return cpp->ErrMsg; -} - -void ResetTString(void) -{ - SETUP_CONTEXT(cpp); - context->HashErrMsg = ""; -} - -void updateExtensionBehavior(const char* extName, const char* behavior) -{ - SETUP_CONTEXT(cpp); - context->handleExtensionDirective(yylineno, extName, behavior); -} -} // extern "C" - -int string_input(char* buf, int max_size, yyscan_t yyscanner) { - int len = 0; - -#if ANGLE_USE_NEW_PREPROCESSOR +yy_size_t string_input(char* buf, yy_size_t max_size, yyscan_t yyscanner) { pp::Token token; yyget_extra(yyscanner)->preprocessor.lex(&token); - len = token.type == pp::Token::LAST ? 0 : token.text.size(); - if ((len > 0) && (len < max_size)) + 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_lineno(EncodeSourceLoc(token.location.file, token.location.line), yyscanner); -#else - len = yylex_CPP(buf, max_size); -#endif // ANGLE_USE_NEW_PREPROCESSOR if (len >= max_size) YY_FATAL_ERROR("Input buffer overflow"); @@ -471,41 +338,28 @@ int glslang_finalize(TParseContext* context) { context->scanner = NULL; yylex_destroy(scanner); -#if !ANGLE_USE_NEW_PREPROCESSOR - FinalizePreprocessor(); -#endif return 0; } -int glslang_scan(int count, const char* const string[], const int length[], +int glslang_scan(size_t count, const char* const string[], const int length[], TParseContext* context) { yyrestart(NULL, context->scanner); yyset_lineno(EncodeSourceLoc(0, 1), context->scanner); context->AfterEOF = false; // Initialize preprocessor. -#if ANGLE_USE_NEW_PREPROCESSOR if (!context->preprocessor.init(count, string, length)) return 1; -#else - if (InitPreprocessor()) - return 1; - cpp->pC = context; - cpp->pastFirstStatement = 0; - if (InitScannerInput(cpp, count, string, length)) - return 1; -#endif // ANGLE_USE_NEW_PREPROCESSOR // Define extension macros. const TExtensionBehavior& extBehavior = context->extensionBehavior(); for (TExtensionBehavior::const_iterator iter = extBehavior.begin(); iter != extBehavior.end(); ++iter) { -#if ANGLE_USE_NEW_PREPROCESSOR context->preprocessor.predefineMacro(iter->first.c_str(), 1); -#else - PredefineIntMacro(iter->first.c_str(), 1); -#endif } + 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 index 39c9cee26e..8dbcee32ef 100644 --- a/src/3rdparty/angle/src/compiler/glslang.y +++ b/src/3rdparty/angle/src/compiler/glslang.y @@ -1,6 +1,6 @@ /* // -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// 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. // @@ -38,6 +38,9 @@ WHICH GENERATES THE GLSL ES PARSER (glslang_tab.cpp AND glslang_tab.h). #include "compiler/ParseHelper.h" #include "GLSLANG/ShaderLang.h" +#define YYENABLE_NLS 0 +#define YYLTYPE_IS_TRIVIAL 1 + #define YYLEX_PARAM context->scanner %} @@ -242,36 +245,36 @@ postfix_expression } if ($1->getType().getQualifier() == EvqConst && $3->getQualifier() == EvqConst) { if ($1->isArray()) { // constant folding for arrays - $$ = context->addConstArrayNode($3->getAsConstantUnion()->getUnionArrayPointer()->getIConst(), $1, $2.line); + $$ = context->addConstArrayNode($3->getAsConstantUnion()->getIConst(0), $1, $2.line); } else if ($1->isVector()) { // constant folding for vectors TVectorFields fields; fields.num = 1; - fields.offsets[0] = $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst(); // need to do it this way because v.xy sends fields integer array + fields.offsets[0] = $3->getAsConstantUnion()->getIConst(0); // need to do it this way because v.xy sends fields integer array $$ = context->addConstVectorNode(fields, $1, $2.line); } else if ($1->isMatrix()) { // constant folding for matrices - $$ = context->addConstMatrixNode($3->getAsConstantUnion()->getUnionArrayPointer()->getIConst(), $1, $2.line); + $$ = context->addConstMatrixNode($3->getAsConstantUnion()->getIConst(0), $1, $2.line); } } else { if ($3->getQualifier() == EvqConst) { - if (($1->isVector() || $1->isMatrix()) && $1->getType().getNominalSize() <= $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst() && !$1->isArray() ) { + if (($1->isVector() || $1->isMatrix()) && $1->getType().getNominalSize() <= $3->getAsConstantUnion()->getIConst(0) && !$1->isArray() ) { std::stringstream extraInfoStream; - extraInfoStream << "field selection out of range '" << $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst() << "'"; + extraInfoStream << "field selection out of range '" << $3->getAsConstantUnion()->getIConst(0) << "'"; std::string extraInfo = extraInfoStream.str(); context->error($2.line, "", "[", extraInfo.c_str()); context->recover(); } else { if ($1->isArray()) { if ($1->getType().getArraySize() == 0) { - if ($1->getType().getMaxArraySize() <= $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst()) { - if (context->arraySetMaxSize($1->getAsSymbolNode(), $1->getTypePointer(), $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst(), true, $2.line)) + if ($1->getType().getMaxArraySize() <= $3->getAsConstantUnion()->getIConst(0)) { + if (context->arraySetMaxSize($1->getAsSymbolNode(), $1->getTypePointer(), $3->getAsConstantUnion()->getIConst(0), true, $2.line)) context->recover(); } else { if (context->arraySetMaxSize($1->getAsSymbolNode(), $1->getTypePointer(), 0, false, $2.line)) context->recover(); } - } else if ( $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst() >= $1->getType().getArraySize()) { + } else if ( $3->getAsConstantUnion()->getIConst(0) >= $1->getType().getArraySize()) { std::stringstream extraInfoStream; - extraInfoStream << "array index out of range '" << $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst() << "'"; + extraInfoStream << "array index out of range '" << $3->getAsConstantUnion()->getIConst(0) << "'"; std::string extraInfo = extraInfoStream.str(); context->error($2.line, "", "[", extraInfo.c_str()); context->recover(); @@ -521,7 +524,7 @@ function_call $$->getAsAggregate()->setName(fnCandidate->getMangledName()); TQualifier qual; - for (int i = 0; i < fnCandidate->getParamCount(); ++i) { + 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())) { @@ -962,7 +965,7 @@ declaration prototype->setType(function.getReturnType()); prototype->setName(function.getName()); - for (int i = 0; i < function.getParamCount(); i++) + for (size_t i = 0; i < function.getParamCount(); i++) { const TParameter ¶m = function.getParam(i); if (param.name != 0) @@ -988,7 +991,14 @@ declaration $$ = $1.intermAggregate; } | PRECISION precision_qualifier type_specifier_no_prec SEMICOLON { - context->symbolTable.setDefaultPrecision( $3.type, $2 ); + if (($2 == EbpHigh) && (context->shaderType == SH_FRAGMENT_SHADER) && !context->fragmentPrecisionHigh) { + context->error($1.line, "precision is not supported in fragment shader", "highp"); + context->recover(); + } + if (!context->symbolTable.setDefaultPrecision( $3, $2 )) { + context->error($1.line, "illegal type argument for default precision qualifier", getBasicString($3.type)); + context->recover(); + } $$ = 0; } ; @@ -1009,7 +1019,7 @@ function_prototype context->error($2.line, "overloaded functions must have the same return type", $1->getReturnType().getBasicString()); context->recover(); } - for (int i = 0; i < prevDec->getParamCount(); ++i) { + for (size_t i = 0; i < prevDec->getParamCount(); ++i) { if (prevDec->getParam(i).type->getQualifier() != $1->getParam(i).type->getQualifier()) { context->error($2.line, "overloaded functions must have the same parameter qualifiers", $1->getParam(i).type->getQualifierString()); context->recover(); @@ -2079,7 +2089,7 @@ function_definition // knows where to find parameters. // TIntermAggregate* paramNodes = new TIntermAggregate; - for (int i = 0; i < function->getParamCount(); i++) { + 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); @@ -2139,4 +2149,3 @@ function_definition 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 index e83c7b72f2..f48a049c63 100644 --- a/src/3rdparty/angle/src/compiler/intermOut.cpp +++ b/src/3rdparty/angle/src/compiler/intermOut.cpp @@ -42,7 +42,7 @@ TString TType::getCompleteString() const if (qualifier != EvqTemporary && qualifier != EvqGlobal) stream << getQualifierString() << " " << getPrecisionString() << " "; if (array) - stream << "array of "; + stream << "array[" << getArraySize() << "] of "; if (matrix) stream << size << "X" << size << " matrix of "; else if (size > 1) diff --git a/src/3rdparty/angle/src/compiler/intermediate.h b/src/3rdparty/angle/src/compiler/intermediate.h index af78fa00ef..8e76ef921f 100644 --- a/src/3rdparty/angle/src/compiler/intermediate.h +++ b/src/3rdparty/angle/src/compiler/intermediate.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// 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. // @@ -16,6 +16,8 @@ #ifndef __INTERMEDIATE_H #define __INTERMEDIATE_H +#include "GLSLANG/ShaderLang.h" + #include "compiler/Common.h" #include "compiler/Types.h" #include "compiler/ConstantUnion.h" @@ -181,7 +183,7 @@ enum TOperator { EOpVectorTimesScalarAssign, EOpMatrixTimesScalarAssign, EOpMatrixTimesMatrixAssign, - EOpDivAssign, + EOpDivAssign }; extern const char* getOperatorString(TOperator op); @@ -257,6 +259,10 @@ public: 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; }; @@ -267,7 +273,7 @@ protected: enum TLoopType { ELoopFor, ELoopWhile, - ELoopDoWhile, + ELoopDoWhile }; class TIntermLoop : public TIntermNode { @@ -356,7 +362,10 @@ public: TIntermConstantUnion(ConstantUnion *unionPointer, const TType& t) : TIntermTyped(t), unionArrayPointer(unionPointer) { } ConstantUnion* getUnionArrayPointer() const { return unionArrayPointer; } - void setUnionArrayPointer(ConstantUnion *c) { unionArrayPointer = c; } + + 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*); @@ -389,7 +398,7 @@ protected: // class TIntermBinary : public TIntermOperator { public: - TIntermBinary(TOperator o) : TIntermOperator(o) {} + TIntermBinary(TOperator o) : TIntermOperator(o), addIndexClamp(false) {} virtual TIntermBinary* getAsBinaryNode() { return this; } virtual void traverse(TIntermTraverser*); @@ -400,9 +409,15 @@ public: 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; }; // @@ -545,6 +560,10 @@ public: void incrementDepth() {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; diff --git a/src/3rdparty/angle/src/compiler/osinclude.h b/src/3rdparty/angle/src/compiler/osinclude.h index 1d95907b79..d8bb1a797c 100644 --- a/src/3rdparty/angle/src/compiler/osinclude.h +++ b/src/3rdparty/angle/src/compiler/osinclude.h @@ -24,9 +24,7 @@ #error Unsupported platform. #endif -#if defined(ANGLE_USE_NSPR) -#include "prthread.h" -#elif defined(ANGLE_OS_WIN) +#if defined(ANGLE_OS_WIN) #define STRICT #define VC_EXTRALEAN 1 #include @@ -34,7 +32,7 @@ #include #include #include -#endif // ANGLE_USE_NSPR +#endif // ANGLE_OS_WIN #include "compiler/debug.h" @@ -42,16 +40,13 @@ // // Thread Local Storage Operations // -#if defined(ANGLE_USE_NSPR) -typedef PRUintn OS_TLSIndex; -#define OS_INVALID_TLS_INDEX 0xFFFFFFFF -#elif defined(ANGLE_OS_WIN) +#if defined(ANGLE_OS_WIN) typedef DWORD OS_TLSIndex; #define OS_INVALID_TLS_INDEX (TLS_OUT_OF_INDEXES) #elif defined(ANGLE_OS_POSIX) -typedef unsigned int OS_TLSIndex; -#define OS_INVALID_TLS_INDEX 0xFFFFFFFF -#endif // ANGLE_USE_NSPR +typedef pthread_key_t OS_TLSIndex; +#define OS_INVALID_TLS_INDEX (static_cast(-1)) +#endif // ANGLE_OS_WIN OS_TLSIndex OS_AllocTLSIndex(); bool OS_SetTLSValue(OS_TLSIndex nIndex, void *lpvValue); @@ -60,9 +55,7 @@ bool OS_FreeTLSIndex(OS_TLSIndex nIndex); inline void* OS_GetTLSValue(OS_TLSIndex nIndex) { ASSERT(nIndex != OS_INVALID_TLS_INDEX); -#if defined(ANGLE_USE_NSPR) - return PR_GetThreadPrivate(nIndex); -#elif defined(ANGLE_OS_WIN) +#if defined(ANGLE_OS_WIN) return TlsGetValue(nIndex); #elif defined(ANGLE_OS_POSIX) return pthread_getspecific(nIndex); diff --git a/src/3rdparty/angle/src/compiler/ossource_nspr.cpp b/src/3rdparty/angle/src/compiler/ossource_nspr.cpp deleted file mode 100644 index f63d81e5d5..0000000000 --- a/src/3rdparty/angle/src/compiler/ossource_nspr.cpp +++ /dev/null @@ -1,43 +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 nspr specific functions -// -#include "compiler/osinclude.h" - -// -// Thread Local Storage Operations -// -OS_TLSIndex OS_AllocTLSIndex() -{ - PRUintn index; - PRStatus status = PR_NewThreadPrivateIndex(&index, NULL); - - if (status) { - assert(0 && "OS_AllocTLSIndex(): Unable to allocate Thread Local Storage"); - return OS_INVALID_TLS_INDEX; - } - - return index; -} - -bool OS_SetTLSValue(OS_TLSIndex nIndex, void *lpvValue) -{ - if (nIndex == OS_INVALID_TLS_INDEX) { - assert(0 && "OS_SetTLSValue(): Invalid TLS Index"); - return false; - } - - return PR_SetThreadPrivate(nIndex, lpvValue) == 0; -} - -bool OS_FreeTLSIndex(OS_TLSIndex nIndex) -{ - // Can't delete TLS keys with nspr - return true; -} - diff --git a/src/3rdparty/angle/src/compiler/parseConst.cpp b/src/3rdparty/angle/src/compiler/parseConst.cpp index 9a8a50c31c..421d31f586 100644 --- a/src/3rdparty/angle/src/compiler/parseConst.cpp +++ b/src/3rdparty/angle/src/compiler/parseConst.cpp @@ -151,6 +151,13 @@ bool TConstTraverser::visitSelection(Visit visit, TIntermSelection* node) 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; int instanceSize = type.getObjectSize(); diff --git a/src/3rdparty/angle/src/compiler/preprocessor/DiagnosticsBase.cpp b/src/3rdparty/angle/src/compiler/preprocessor/DiagnosticsBase.cpp new file mode 100644 index 0000000000..3e22e1f1c5 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/preprocessor/DiagnosticsBase.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 "DiagnosticsBase.h" + +#include + +namespace pp +{ + +Diagnostics::~Diagnostics() +{ +} + +void Diagnostics::report(ID id, + const SourceLocation& loc, + const std::string& text) +{ + // TODO(alokp): Keep a count of errors and warnings. + print(id, loc, text); +} + +Diagnostics::Severity Diagnostics::severity(ID id) +{ + if ((id > ERROR_BEGIN) && (id < ERROR_END)) + return ERROR; + + if ((id > WARNING_BEGIN) && (id < WARNING_END)) + return WARNING; + + assert(false); + return ERROR; +} + +std::string Diagnostics::message(ID id) +{ + switch (id) + { + // Errors begin. + case INTERNAL_ERROR: + return "internal error"; + case OUT_OF_MEMORY: + return "out of memory"; + case INVALID_CHARACTER: + return "invalid character"; + case INVALID_NUMBER: + return "invalid number"; + case INTEGER_OVERFLOW: + return "integer overflow"; + case FLOAT_OVERFLOW: + return "float overflow"; + case TOKEN_TOO_LONG: + return "token too long"; + case INVALID_EXPRESSION: + return "invalid expression"; + case DIVISION_BY_ZERO: + return "division by zero"; + case EOF_IN_COMMENT: + return "unexpected end of file found in comment"; + case UNEXPECTED_TOKEN: + return "unexpected token"; + case DIRECTIVE_INVALID_NAME: + return "invalid directive name"; + case MACRO_NAME_RESERVED: + return "macro name is reserved"; + case MACRO_REDEFINED: + return "macro redefined"; + case MACRO_PREDEFINED_REDEFINED: + return "predefined macro redefined"; + case MACRO_PREDEFINED_UNDEFINED: + return "predefined macro undefined"; + case MACRO_UNTERMINATED_INVOCATION: + return "unterminated macro invocation"; + case MACRO_TOO_FEW_ARGS: + return "Not enough arguments for macro"; + case MACRO_TOO_MANY_ARGS: + return "Too many arguments for macro"; + case CONDITIONAL_ENDIF_WITHOUT_IF: + return "unexpected #endif found without a matching #if"; + case CONDITIONAL_ELSE_WITHOUT_IF: + return "unexpected #else found without a matching #if"; + case CONDITIONAL_ELSE_AFTER_ELSE: + return "unexpected #else found after another #else"; + case CONDITIONAL_ELIF_WITHOUT_IF: + return "unexpected #elif found without a matching #if"; + case CONDITIONAL_ELIF_AFTER_ELSE: + return "unexpected #elif found after #else"; + case CONDITIONAL_UNTERMINATED: + return "unexpected end of file found in conditional block"; + case INVALID_EXTENSION_NAME: + return "invalid extension name"; + case INVALID_EXTENSION_BEHAVIOR: + return "invalid extension behavior"; + case INVALID_EXTENSION_DIRECTIVE: + return "invalid extension directive"; + case INVALID_VERSION_NUMBER: + return "invalid version number"; + case INVALID_VERSION_DIRECTIVE: + return "invalid version directive"; + case VERSION_NOT_FIRST_STATEMENT: + return "#version directive must occur before anything else, " + "except for comments and white space"; + case INVALID_LINE_NUMBER: + return "invalid line number"; + case INVALID_FILE_NUMBER: + return "invalid file number"; + case INVALID_LINE_DIRECTIVE: + return "invalid line directive"; + // Errors end. + // Warnings begin. + case EOF_IN_DIRECTIVE: + return "unexpected end of file found in directive"; + case CONDITIONAL_UNEXPECTED_TOKEN: + return "unexpected token after conditional expression"; + case UNRECOGNIZED_PRAGMA: + return "unrecognized pragma"; + // Warnings end. + default: + assert(false); + return ""; + } +} + +} // namespace pp diff --git a/src/3rdparty/angle/src/compiler/preprocessor/DiagnosticsBase.h b/src/3rdparty/angle/src/compiler/preprocessor/DiagnosticsBase.h new file mode 100644 index 0000000000..07bc411846 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/preprocessor/DiagnosticsBase.h @@ -0,0 +1,87 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_PREPROCESSOR_DIAGNOSTICS_H_ +#define COMPILER_PREPROCESSOR_DIAGNOSTICS_H_ + +#include + +namespace pp +{ + +struct SourceLocation; + +// Base class for reporting diagnostic messages. +// Derived classes are responsible for formatting and printing the messages. +class Diagnostics +{ + public: + enum Severity + { + ERROR, + WARNING + }; + enum ID + { + ERROR_BEGIN, + INTERNAL_ERROR, + OUT_OF_MEMORY, + INVALID_CHARACTER, + INVALID_NUMBER, + INTEGER_OVERFLOW, + FLOAT_OVERFLOW, + TOKEN_TOO_LONG, + INVALID_EXPRESSION, + DIVISION_BY_ZERO, + EOF_IN_COMMENT, + UNEXPECTED_TOKEN, + DIRECTIVE_INVALID_NAME, + MACRO_NAME_RESERVED, + MACRO_REDEFINED, + MACRO_PREDEFINED_REDEFINED, + MACRO_PREDEFINED_UNDEFINED, + MACRO_UNTERMINATED_INVOCATION, + MACRO_TOO_FEW_ARGS, + MACRO_TOO_MANY_ARGS, + CONDITIONAL_ENDIF_WITHOUT_IF, + CONDITIONAL_ELSE_WITHOUT_IF, + CONDITIONAL_ELSE_AFTER_ELSE, + CONDITIONAL_ELIF_WITHOUT_IF, + CONDITIONAL_ELIF_AFTER_ELSE, + CONDITIONAL_UNTERMINATED, + INVALID_EXTENSION_NAME, + INVALID_EXTENSION_BEHAVIOR, + INVALID_EXTENSION_DIRECTIVE, + INVALID_VERSION_NUMBER, + INVALID_VERSION_DIRECTIVE, + VERSION_NOT_FIRST_STATEMENT, + INVALID_LINE_NUMBER, + INVALID_FILE_NUMBER, + INVALID_LINE_DIRECTIVE, + ERROR_END, + + WARNING_BEGIN, + EOF_IN_DIRECTIVE, + CONDITIONAL_UNEXPECTED_TOKEN, + UNRECOGNIZED_PRAGMA, + WARNING_END + }; + + virtual ~Diagnostics(); + + void report(ID id, const SourceLocation& loc, const std::string& text); + + protected: + Severity severity(ID id); + std::string message(ID id); + + virtual void print(ID id, + const SourceLocation& loc, + const std::string& text) = 0; +}; + +} // namespace pp +#endif // COMPILER_PREPROCESSOR_DIAGNOSTICS_H_ diff --git a/src/3rdparty/angle/src/compiler/preprocessor/DirectiveHandlerBase.cpp b/src/3rdparty/angle/src/compiler/preprocessor/DirectiveHandlerBase.cpp new file mode 100644 index 0000000000..ef35c6ed50 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/preprocessor/DirectiveHandlerBase.cpp @@ -0,0 +1,16 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "DirectiveHandlerBase.h" + +namespace pp +{ + +DirectiveHandler::~DirectiveHandler() +{ +} + +} // namespace pp diff --git a/src/3rdparty/angle/src/compiler/preprocessor/DirectiveHandlerBase.h b/src/3rdparty/angle/src/compiler/preprocessor/DirectiveHandlerBase.h new file mode 100644 index 0000000000..2aaeec2818 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/preprocessor/DirectiveHandlerBase.h @@ -0,0 +1,43 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_PREPROCESSOR_DIRECTIVE_HANDLER_H_ +#define COMPILER_PREPROCESSOR_DIRECTIVE_HANDLER_H_ + +#include + +namespace pp +{ + +struct SourceLocation; + +// Base class for handling directives. +// Preprocessor uses this class to notify the clients about certain +// preprocessor directives. Derived classes are responsible for +// handling them in an appropriate manner. +class DirectiveHandler +{ + public: + virtual ~DirectiveHandler(); + + virtual void handleError(const SourceLocation& loc, + const std::string& msg) = 0; + + // Handle pragma of form: #pragma name[(value)] + virtual void handlePragma(const SourceLocation& loc, + const std::string& name, + const std::string& value) = 0; + + virtual void handleExtension(const SourceLocation& loc, + const std::string& name, + const std::string& behavior) = 0; + + virtual void handleVersion(const SourceLocation& loc, + int version) = 0; +}; + +} // namespace pp +#endif // COMPILER_PREPROCESSOR_DIRECTIVE_HANDLER_H_ diff --git a/src/3rdparty/angle/src/compiler/preprocessor/DirectiveParser.cpp b/src/3rdparty/angle/src/compiler/preprocessor/DirectiveParser.cpp new file mode 100644 index 0000000000..94dfdf513d --- /dev/null +++ b/src/3rdparty/angle/src/compiler/preprocessor/DirectiveParser.cpp @@ -0,0 +1,932 @@ +// +// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "DirectiveParser.h" + +#include +#include +#include + +#include "DiagnosticsBase.h" +#include "DirectiveHandlerBase.h" +#include "ExpressionParser.h" +#include "MacroExpander.h" +#include "Token.h" +#include "Tokenizer.h" + +namespace { +enum DirectiveType +{ + DIRECTIVE_NONE, + DIRECTIVE_DEFINE, + DIRECTIVE_UNDEF, + DIRECTIVE_IF, + DIRECTIVE_IFDEF, + DIRECTIVE_IFNDEF, + DIRECTIVE_ELSE, + DIRECTIVE_ELIF, + DIRECTIVE_ENDIF, + DIRECTIVE_ERROR, + DIRECTIVE_PRAGMA, + DIRECTIVE_EXTENSION, + DIRECTIVE_VERSION, + DIRECTIVE_LINE +}; +} // namespace + +static DirectiveType getDirective(const pp::Token* token) +{ + static const std::string kDirectiveDefine("define"); + static const std::string kDirectiveUndef("undef"); + static const std::string kDirectiveIf("if"); + static const std::string kDirectiveIfdef("ifdef"); + static const std::string kDirectiveIfndef("ifndef"); + static const std::string kDirectiveElse("else"); + static const std::string kDirectiveElif("elif"); + static const std::string kDirectiveEndif("endif"); + static const std::string kDirectiveError("error"); + static const std::string kDirectivePragma("pragma"); + static const std::string kDirectiveExtension("extension"); + static const std::string kDirectiveVersion("version"); + static const std::string kDirectiveLine("line"); + + if (token->type != pp::Token::IDENTIFIER) + return DIRECTIVE_NONE; + + if (token->text == kDirectiveDefine) + return DIRECTIVE_DEFINE; + else if (token->text == kDirectiveUndef) + return DIRECTIVE_UNDEF; + else if (token->text == kDirectiveIf) + return DIRECTIVE_IF; + else if (token->text == kDirectiveIfdef) + return DIRECTIVE_IFDEF; + else if (token->text == kDirectiveIfndef) + return DIRECTIVE_IFNDEF; + else if (token->text == kDirectiveElse) + return DIRECTIVE_ELSE; + else if (token->text == kDirectiveElif) + return DIRECTIVE_ELIF; + else if (token->text == kDirectiveEndif) + return DIRECTIVE_ENDIF; + else if (token->text == kDirectiveError) + return DIRECTIVE_ERROR; + else if (token->text == kDirectivePragma) + return DIRECTIVE_PRAGMA; + else if (token->text == kDirectiveExtension) + return DIRECTIVE_EXTENSION; + else if (token->text == kDirectiveVersion) + return DIRECTIVE_VERSION; + else if (token->text == kDirectiveLine) + return DIRECTIVE_LINE; + + return DIRECTIVE_NONE; +} + +static bool isConditionalDirective(DirectiveType directive) +{ + switch (directive) + { + case DIRECTIVE_IF: + case DIRECTIVE_IFDEF: + case DIRECTIVE_IFNDEF: + case DIRECTIVE_ELSE: + case DIRECTIVE_ELIF: + case DIRECTIVE_ENDIF: + return true; + default: + return false; + } +} + +// Returns true if the token represents End Of Directive. +static bool isEOD(const pp::Token* token) +{ + return (token->type == '\n') || (token->type == pp::Token::LAST); +} + +static void skipUntilEOD(pp::Lexer* lexer, pp::Token* token) +{ + while(!isEOD(token)) + { + lexer->lex(token); + } +} + +static bool isMacroNameReserved(const std::string& name) +{ + // Names prefixed with "GL_" are reserved. + if (name.substr(0, 3) == "GL_") + return true; + + // Names containing two consecutive underscores are reserved. + if (name.find("__") != std::string::npos) + return true; + + return false; +} + +static bool isMacroPredefined(const std::string& name, + const pp::MacroSet& macroSet) +{ + pp::MacroSet::const_iterator iter = macroSet.find(name); + return iter != macroSet.end() ? iter->second.predefined : false; +} + +namespace pp +{ + +class DefinedParser : public Lexer +{ + public: + DefinedParser(Lexer* lexer, + const MacroSet* macroSet, + Diagnostics* diagnostics) : + mLexer(lexer), + mMacroSet(macroSet), + mDiagnostics(diagnostics) + { + } + + protected: + virtual void lex(Token* token) + { + static const std::string kDefined("defined"); + + mLexer->lex(token); + if (token->type != Token::IDENTIFIER) + return; + if (token->text != kDefined) + return; + + bool paren = false; + mLexer->lex(token); + if (token->type == '(') + { + paren = true; + mLexer->lex(token); + } + + if (token->type != Token::IDENTIFIER) + { + mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, + token->location, token->text); + skipUntilEOD(mLexer, token); + return; + } + MacroSet::const_iterator iter = mMacroSet->find(token->text); + std::string expression = iter != mMacroSet->end() ? "1" : "0"; + + if (paren) + { + mLexer->lex(token); + if (token->type != ')') + { + mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, + token->location, token->text); + skipUntilEOD(mLexer, token); + return; + } + } + + // We have a valid defined operator. + // Convert the current token into a CONST_INT token. + token->type = Token::CONST_INT; + token->text = expression; + } + + private: + Lexer* mLexer; + const MacroSet* mMacroSet; + Diagnostics* mDiagnostics; +}; + +DirectiveParser::DirectiveParser(Tokenizer* tokenizer, + MacroSet* macroSet, + Diagnostics* diagnostics, + DirectiveHandler* directiveHandler) : + mPastFirstStatement(false), + mTokenizer(tokenizer), + mMacroSet(macroSet), + mDiagnostics(diagnostics), + mDirectiveHandler(directiveHandler) +{ +} + +void DirectiveParser::lex(Token* token) +{ + do + { + mTokenizer->lex(token); + + if (token->type == Token::PP_HASH) + { + parseDirective(token); + mPastFirstStatement = true; + } + + if (token->type == Token::LAST) + { + if (!mConditionalStack.empty()) + { + const ConditionalBlock& block = mConditionalStack.back(); + mDiagnostics->report(Diagnostics::CONDITIONAL_UNTERMINATED, + block.location, block.type); + } + break; + } + + } while (skipping() || (token->type == '\n')); + + mPastFirstStatement = true; +} + +void DirectiveParser::parseDirective(Token* token) +{ + assert(token->type == Token::PP_HASH); + + mTokenizer->lex(token); + if (isEOD(token)) + { + // Empty Directive. + return; + } + + DirectiveType directive = getDirective(token); + + // While in an excluded conditional block/group, + // we only parse conditional directives. + if (skipping() && !isConditionalDirective(directive)) + { + skipUntilEOD(mTokenizer, token); + return; + } + + switch(directive) + { + case DIRECTIVE_NONE: + mDiagnostics->report(Diagnostics::DIRECTIVE_INVALID_NAME, + token->location, token->text); + skipUntilEOD(mTokenizer, token); + break; + case DIRECTIVE_DEFINE: + parseDefine(token); + break; + case DIRECTIVE_UNDEF: + parseUndef(token); + break; + case DIRECTIVE_IF: + parseIf(token); + break; + case DIRECTIVE_IFDEF: + parseIfdef(token); + break; + case DIRECTIVE_IFNDEF: + parseIfndef(token); + break; + case DIRECTIVE_ELSE: + parseElse(token); + break; + case DIRECTIVE_ELIF: + parseElif(token); + break; + case DIRECTIVE_ENDIF: + parseEndif(token); + break; + case DIRECTIVE_ERROR: + parseError(token); + break; + case DIRECTIVE_PRAGMA: + parsePragma(token); + break; + case DIRECTIVE_EXTENSION: + parseExtension(token); + break; + case DIRECTIVE_VERSION: + parseVersion(token); + break; + case DIRECTIVE_LINE: + parseLine(token); + break; + default: + assert(false); + break; + } + + skipUntilEOD(mTokenizer, token); + if (token->type == Token::LAST) + { + mDiagnostics->report(Diagnostics::EOF_IN_DIRECTIVE, + token->location, token->text); + } +} + +void DirectiveParser::parseDefine(Token* token) +{ + assert(getDirective(token) == DIRECTIVE_DEFINE); + + mTokenizer->lex(token); + if (token->type != Token::IDENTIFIER) + { + mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, + token->location, token->text); + return; + } + if (isMacroPredefined(token->text, *mMacroSet)) + { + mDiagnostics->report(Diagnostics::MACRO_PREDEFINED_REDEFINED, + token->location, token->text); + return; + } + if (isMacroNameReserved(token->text)) + { + mDiagnostics->report(Diagnostics::MACRO_NAME_RESERVED, + token->location, token->text); + return; + } + + Macro macro; + macro.type = Macro::kTypeObj; + macro.name = token->text; + + mTokenizer->lex(token); + if (token->type == '(' && !token->hasLeadingSpace()) + { + // Function-like macro. Collect arguments. + macro.type = Macro::kTypeFunc; + do { + mTokenizer->lex(token); + if (token->type != Token::IDENTIFIER) + break; + macro.parameters.push_back(token->text); + + mTokenizer->lex(token); // Get ','. + } while (token->type == ','); + + if (token->type != ')') + { + mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, + token->location, + token->text); + return; + } + mTokenizer->lex(token); // Get ')'. + } + + while ((token->type != '\n') && (token->type != Token::LAST)) + { + // Reset the token location because it is unnecessary in replacement + // list. Resetting it also allows us to reuse Token::equals() to + // compare macros. + token->location = SourceLocation(); + macro.replacements.push_back(*token); + mTokenizer->lex(token); + } + if (!macro.replacements.empty()) + { + // Whitespace preceding the replacement list is not considered part of + // the replacement list for either form of macro. + macro.replacements.front().setHasLeadingSpace(false); + } + + // Check for macro redefinition. + MacroSet::const_iterator iter = mMacroSet->find(macro.name); + if (iter != mMacroSet->end() && !macro.equals(iter->second)) + { + mDiagnostics->report(Diagnostics::MACRO_REDEFINED, + token->location, + macro.name); + return; + } + mMacroSet->insert(std::make_pair(macro.name, macro)); +} + +void DirectiveParser::parseUndef(Token* token) +{ + assert(getDirective(token) == DIRECTIVE_UNDEF); + + mTokenizer->lex(token); + if (token->type != Token::IDENTIFIER) + { + mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, + token->location, token->text); + return; + } + + MacroSet::iterator iter = mMacroSet->find(token->text); + if (iter != mMacroSet->end()) + { + if (iter->second.predefined) + { + mDiagnostics->report(Diagnostics::MACRO_PREDEFINED_UNDEFINED, + token->location, token->text); + } + else + { + mMacroSet->erase(iter); + } + } + + mTokenizer->lex(token); +} + +void DirectiveParser::parseIf(Token* token) +{ + assert(getDirective(token) == DIRECTIVE_IF); + parseConditionalIf(token); +} + +void DirectiveParser::parseIfdef(Token* token) +{ + assert(getDirective(token) == DIRECTIVE_IFDEF); + parseConditionalIf(token); +} + +void DirectiveParser::parseIfndef(Token* token) +{ + assert(getDirective(token) == DIRECTIVE_IFNDEF); + parseConditionalIf(token); +} + +void DirectiveParser::parseElse(Token* token) +{ + assert(getDirective(token) == DIRECTIVE_ELSE); + + if (mConditionalStack.empty()) + { + mDiagnostics->report(Diagnostics::CONDITIONAL_ELSE_WITHOUT_IF, + token->location, token->text); + skipUntilEOD(mTokenizer, token); + return; + } + + ConditionalBlock& block = mConditionalStack.back(); + if (block.skipBlock) + { + // No diagnostics. Just skip the whole line. + skipUntilEOD(mTokenizer, token); + return; + } + if (block.foundElseGroup) + { + mDiagnostics->report(Diagnostics::CONDITIONAL_ELSE_AFTER_ELSE, + token->location, token->text); + skipUntilEOD(mTokenizer, token); + return; + } + + block.foundElseGroup = true; + block.skipGroup = block.foundValidGroup; + block.foundValidGroup = true; + + // Warn if there are extra tokens after #else. + mTokenizer->lex(token); + if (!isEOD(token)) + { + mDiagnostics->report(Diagnostics::CONDITIONAL_UNEXPECTED_TOKEN, + token->location, token->text); + skipUntilEOD(mTokenizer, token); + } +} + +void DirectiveParser::parseElif(Token* token) +{ + assert(getDirective(token) == DIRECTIVE_ELIF); + + if (mConditionalStack.empty()) + { + mDiagnostics->report(Diagnostics::CONDITIONAL_ELIF_WITHOUT_IF, + token->location, token->text); + skipUntilEOD(mTokenizer, token); + return; + } + + ConditionalBlock& block = mConditionalStack.back(); + if (block.skipBlock) + { + // No diagnostics. Just skip the whole line. + skipUntilEOD(mTokenizer, token); + return; + } + if (block.foundElseGroup) + { + mDiagnostics->report(Diagnostics::CONDITIONAL_ELIF_AFTER_ELSE, + token->location, token->text); + skipUntilEOD(mTokenizer, token); + return; + } + if (block.foundValidGroup) + { + // Do not parse the expression. + // Also be careful not to emit a diagnostic. + block.skipGroup = true; + skipUntilEOD(mTokenizer, token); + return; + } + + int expression = parseExpressionIf(token); + block.skipGroup = expression == 0; + block.foundValidGroup = expression != 0; +} + +void DirectiveParser::parseEndif(Token* token) +{ + assert(getDirective(token) == DIRECTIVE_ENDIF); + + if (mConditionalStack.empty()) + { + mDiagnostics->report(Diagnostics::CONDITIONAL_ENDIF_WITHOUT_IF, + token->location, token->text); + skipUntilEOD(mTokenizer, token); + return; + } + + mConditionalStack.pop_back(); + + // Warn if there are tokens after #endif. + mTokenizer->lex(token); + if (!isEOD(token)) + { + mDiagnostics->report(Diagnostics::CONDITIONAL_UNEXPECTED_TOKEN, + token->location, token->text); + skipUntilEOD(mTokenizer, token); + } +} + +void DirectiveParser::parseError(Token* token) +{ + assert(getDirective(token) == DIRECTIVE_ERROR); + + std::ostringstream stream; + mTokenizer->lex(token); + while ((token->type != '\n') && (token->type != Token::LAST)) + { + stream << *token; + mTokenizer->lex(token); + } + mDirectiveHandler->handleError(token->location, stream.str()); +} + +// Parses pragma of form: #pragma name[(value)]. +void DirectiveParser::parsePragma(Token* token) +{ + assert(getDirective(token) == DIRECTIVE_PRAGMA); + + enum State + { + PRAGMA_NAME, + LEFT_PAREN, + PRAGMA_VALUE, + RIGHT_PAREN + }; + + bool valid = true; + std::string name, value; + int state = PRAGMA_NAME; + + mTokenizer->lex(token); + while ((token->type != '\n') && (token->type != Token::LAST)) + { + switch(state++) + { + case PRAGMA_NAME: + name = token->text; + valid = valid && (token->type == Token::IDENTIFIER); + break; + case LEFT_PAREN: + valid = valid && (token->type == '('); + break; + case PRAGMA_VALUE: + value = token->text; + valid = valid && (token->type == Token::IDENTIFIER); + break; + case RIGHT_PAREN: + valid = valid && (token->type == ')'); + break; + default: + valid = false; + break; + } + mTokenizer->lex(token); + } + + valid = valid && ((state == PRAGMA_NAME) || // Empty pragma. + (state == LEFT_PAREN) || // Without value. + (state == RIGHT_PAREN + 1)); // With value. + if (!valid) + { + mDiagnostics->report(Diagnostics::UNRECOGNIZED_PRAGMA, + token->location, name); + } + else if (state > PRAGMA_NAME) // Do not notify for empty pragma. + { + mDirectiveHandler->handlePragma(token->location, name, value); + } +} + +void DirectiveParser::parseExtension(Token* token) +{ + assert(getDirective(token) == DIRECTIVE_EXTENSION); + + enum State + { + EXT_NAME, + COLON, + EXT_BEHAVIOR + }; + + bool valid = true; + std::string name, behavior; + int state = EXT_NAME; + + mTokenizer->lex(token); + while ((token->type != '\n') && (token->type != Token::LAST)) + { + switch (state++) + { + case EXT_NAME: + if (valid && (token->type != Token::IDENTIFIER)) + { + mDiagnostics->report(Diagnostics::INVALID_EXTENSION_NAME, + token->location, token->text); + valid = false; + } + if (valid) name = token->text; + break; + case COLON: + if (valid && (token->type != ':')) + { + mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, + token->location, token->text); + valid = false; + } + break; + case EXT_BEHAVIOR: + if (valid && (token->type != Token::IDENTIFIER)) + { + mDiagnostics->report(Diagnostics::INVALID_EXTENSION_BEHAVIOR, + token->location, token->text); + valid = false; + } + if (valid) behavior = token->text; + break; + default: + if (valid) + { + mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, + token->location, token->text); + valid = false; + } + break; + } + mTokenizer->lex(token); + } + if (valid && (state != EXT_BEHAVIOR + 1)) + { + mDiagnostics->report(Diagnostics::INVALID_EXTENSION_DIRECTIVE, + token->location, token->text); + valid = false; + } + if (valid) + mDirectiveHandler->handleExtension(token->location, name, behavior); +} + +void DirectiveParser::parseVersion(Token* token) +{ + assert(getDirective(token) == DIRECTIVE_VERSION); + + if (mPastFirstStatement) + { + mDiagnostics->report(Diagnostics::VERSION_NOT_FIRST_STATEMENT, + token->location, token->text); + skipUntilEOD(mTokenizer, token); + return; + } + + enum State + { + VERSION_NUMBER + }; + + bool valid = true; + int version = 0; + int state = VERSION_NUMBER; + + mTokenizer->lex(token); + while ((token->type != '\n') && (token->type != Token::LAST)) + { + switch (state++) + { + case VERSION_NUMBER: + if (valid && (token->type != Token::CONST_INT)) + { + mDiagnostics->report(Diagnostics::INVALID_VERSION_NUMBER, + token->location, token->text); + valid = false; + } + if (valid && !token->iValue(&version)) + { + mDiagnostics->report(Diagnostics::INTEGER_OVERFLOW, + token->location, token->text); + valid = false; + } + break; + default: + if (valid) + { + mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, + token->location, token->text); + valid = false; + } + break; + } + mTokenizer->lex(token); + } + if (valid && (state != VERSION_NUMBER + 1)) + { + mDiagnostics->report(Diagnostics::INVALID_VERSION_DIRECTIVE, + token->location, token->text); + valid = false; + } + if (valid) + mDirectiveHandler->handleVersion(token->location, version); +} + +void DirectiveParser::parseLine(Token* token) +{ + assert(getDirective(token) == DIRECTIVE_LINE); + + enum State + { + LINE_NUMBER, + FILE_NUMBER + }; + + bool valid = true; + int line = 0, file = 0; + int state = LINE_NUMBER; + + MacroExpander macroExpander(mTokenizer, mMacroSet, mDiagnostics); + macroExpander.lex(token); + while ((token->type != '\n') && (token->type != Token::LAST)) + { + switch (state++) + { + case LINE_NUMBER: + if (valid && (token->type != Token::CONST_INT)) + { + mDiagnostics->report(Diagnostics::INVALID_LINE_NUMBER, + token->location, token->text); + valid = false; + } + if (valid && !token->iValue(&line)) + { + mDiagnostics->report(Diagnostics::INTEGER_OVERFLOW, + token->location, token->text); + valid = false; + } + break; + case FILE_NUMBER: + if (valid && (token->type != Token::CONST_INT)) + { + mDiagnostics->report(Diagnostics::INVALID_FILE_NUMBER, + token->location, token->text); + valid = false; + } + if (valid && !token->iValue(&file)) + { + mDiagnostics->report(Diagnostics::INTEGER_OVERFLOW, + token->location, token->text); + valid = false; + } + break; + default: + if (valid) + { + mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, + token->location, token->text); + valid = false; + } + break; + } + macroExpander.lex(token); + } + + if (valid && (state != FILE_NUMBER) && (state != FILE_NUMBER + 1)) + { + mDiagnostics->report(Diagnostics::INVALID_LINE_DIRECTIVE, + token->location, token->text); + valid = false; + } + if (valid) + { + mTokenizer->setLineNumber(line); + if (state == FILE_NUMBER + 1) mTokenizer->setFileNumber(file); + } +} + +bool DirectiveParser::skipping() const +{ + if (mConditionalStack.empty()) return false; + + const ConditionalBlock& block = mConditionalStack.back(); + return block.skipBlock || block.skipGroup; +} + +void DirectiveParser::parseConditionalIf(Token* token) +{ + ConditionalBlock block; + block.type = token->text; + block.location = token->location; + + if (skipping()) + { + // This conditional block is inside another conditional group + // which is skipped. As a consequence this whole block is skipped. + // Be careful not to parse the conditional expression that might + // emit a diagnostic. + skipUntilEOD(mTokenizer, token); + block.skipBlock = true; + } + else + { + DirectiveType directive = getDirective(token); + + int expression = 0; + switch (directive) + { + case DIRECTIVE_IF: + expression = parseExpressionIf(token); + break; + case DIRECTIVE_IFDEF: + expression = parseExpressionIfdef(token); + break; + case DIRECTIVE_IFNDEF: + expression = parseExpressionIfdef(token) == 0 ? 1 : 0; + break; + default: + assert(false); + break; + } + block.skipGroup = expression == 0; + block.foundValidGroup = expression != 0; + } + mConditionalStack.push_back(block); +} + +int DirectiveParser::parseExpressionIf(Token* token) +{ + assert((getDirective(token) == DIRECTIVE_IF) || + (getDirective(token) == DIRECTIVE_ELIF)); + + DefinedParser definedParser(mTokenizer, mMacroSet, mDiagnostics); + MacroExpander macroExpander(&definedParser, mMacroSet, mDiagnostics); + ExpressionParser expressionParser(¯oExpander, mDiagnostics); + + int expression = 0; + macroExpander.lex(token); + expressionParser.parse(token, &expression); + + // Warn if there are tokens after #if expression. + if (!isEOD(token)) + { + mDiagnostics->report(Diagnostics::CONDITIONAL_UNEXPECTED_TOKEN, + token->location, token->text); + skipUntilEOD(mTokenizer, token); + } + + return expression; +} + +int DirectiveParser::parseExpressionIfdef(Token* token) +{ + assert((getDirective(token) == DIRECTIVE_IFDEF) || + (getDirective(token) == DIRECTIVE_IFNDEF)); + + mTokenizer->lex(token); + if (token->type != Token::IDENTIFIER) + { + mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, + token->location, token->text); + skipUntilEOD(mTokenizer, token); + return 0; + } + + MacroSet::const_iterator iter = mMacroSet->find(token->text); + int expression = iter != mMacroSet->end() ? 1 : 0; + + // Warn if there are tokens after #ifdef expression. + mTokenizer->lex(token); + if (!isEOD(token)) + { + mDiagnostics->report(Diagnostics::CONDITIONAL_UNEXPECTED_TOKEN, + token->location, token->text); + skipUntilEOD(mTokenizer, token); + } + return expression; +} + +} // namespace pp diff --git a/src/3rdparty/angle/src/compiler/preprocessor/DirectiveParser.h b/src/3rdparty/angle/src/compiler/preprocessor/DirectiveParser.h new file mode 100644 index 0000000000..8a7f0072ba --- /dev/null +++ b/src/3rdparty/angle/src/compiler/preprocessor/DirectiveParser.h @@ -0,0 +1,82 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_PREPROCESSOR_DIRECTIVE_PARSER_H_ +#define COMPILER_PREPROCESSOR_DIRECTIVE_PARSER_H_ + +#include "Lexer.h" +#include "Macro.h" +#include "pp_utils.h" +#include "SourceLocation.h" + +namespace pp +{ + +class Diagnostics; +class DirectiveHandler; +class Tokenizer; + +class DirectiveParser : public Lexer +{ + public: + DirectiveParser(Tokenizer* tokenizer, + MacroSet* macroSet, + Diagnostics* diagnostics, + DirectiveHandler* directiveHandler); + + virtual void lex(Token* token); + + private: + PP_DISALLOW_COPY_AND_ASSIGN(DirectiveParser); + + void parseDirective(Token* token); + void parseDefine(Token* token); + void parseUndef(Token* token); + void parseIf(Token* token); + void parseIfdef(Token* token); + void parseIfndef(Token* token); + void parseElse(Token* token); + void parseElif(Token* token); + void parseEndif(Token* token); + void parseError(Token* token); + void parsePragma(Token* token); + void parseExtension(Token* token); + void parseVersion(Token* token); + void parseLine(Token* token); + + bool skipping() const; + void parseConditionalIf(Token* token); + int parseExpressionIf(Token* token); + int parseExpressionIfdef(Token* token); + + struct ConditionalBlock + { + std::string type; + SourceLocation location; + bool skipBlock; + bool skipGroup; + bool foundValidGroup; + bool foundElseGroup; + + ConditionalBlock() : + skipBlock(false), + skipGroup(false), + foundValidGroup(false), + foundElseGroup(false) + { + } + }; + bool mPastFirstStatement; + std::vector mConditionalStack; + Tokenizer* mTokenizer; + MacroSet* mMacroSet; + Diagnostics* mDiagnostics; + DirectiveHandler* mDirectiveHandler; +}; + +} // namespace pp +#endif // COMPILER_PREPROCESSOR_DIRECTIVE_PARSER_H_ + diff --git a/src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.h b/src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.h new file mode 100644 index 0000000000..092d059413 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.h @@ -0,0 +1,34 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_PREPROCESSOR_EXPRESSION_PARSER_H_ +#define COMPILER_PREPROCESSOR_EXPRESSION_PARSER_H_ + +#include "pp_utils.h" + +namespace pp +{ + +class Diagnostics; +class Lexer; +struct Token; + +class ExpressionParser +{ + public: + ExpressionParser(Lexer* lexer, Diagnostics* diagnostics); + + bool parse(Token* token, int* result); + + private: + PP_DISALLOW_COPY_AND_ASSIGN(ExpressionParser); + + Lexer* mLexer; + Diagnostics* mDiagnostics; +}; + +} // namespace pp +#endif // COMPILER_PREPROCESSOR_EXPRESSION_PARSER_H_ diff --git a/src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.y b/src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.y new file mode 100644 index 0000000000..b6d3143e60 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.y @@ -0,0 +1,285 @@ +/* +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +This file contains the Yacc grammar for GLSL ES preprocessor expression. + +IF YOU MODIFY THIS FILE YOU ALSO NEED TO RUN generate_parser.sh, +WHICH GENERATES THE GLSL ES preprocessor expression parser. +*/ + +%{ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// This file is auto-generated by generate_parser.sh. DO NOT EDIT! + +#if defined(__GNUC__) +// Triggered by the auto-generated pplval variable. +#if !defined(__clang__) && ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)) +#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" +#else +#pragma GCC diagnostic ignored "-Wuninitialized" +#endif +#elif defined(_MSC_VER) +#pragma warning(disable: 4065 4701) +#endif + +#include "ExpressionParser.h" + +#include +#include + +#include "DiagnosticsBase.h" +#include "Lexer.h" +#include "Token.h" + +#if defined(_MSC_VER) +typedef __int64 YYSTYPE; +#else +#include +typedef intmax_t YYSTYPE; +#endif // _MSC_VER +#define YYENABLE_NLS 0 +#define YYLTYPE_IS_TRIVIAL 1 +#define YYSTYPE_IS_TRIVIAL 1 +#define YYSTYPE_IS_DECLARED 1 + +namespace { +struct Context +{ + pp::Diagnostics* diagnostics; + pp::Lexer* lexer; + pp::Token* token; + int* result; +}; +} // namespace +%} + +%pure-parser +%name-prefix="pp" +%parse-param {Context *context} +%lex-param {Context *context} + +%{ +static int yylex(YYSTYPE* lvalp, Context* context); +static void yyerror(Context* context, const char* reason); +%} + +%token TOK_CONST_INT +%left TOK_OP_OR +%left TOK_OP_AND +%left '|' +%left '^' +%left '&' +%left TOK_OP_EQ TOK_OP_NE +%left '<' '>' TOK_OP_LE TOK_OP_GE +%left TOK_OP_LEFT TOK_OP_RIGHT +%left '+' '-' +%left '*' '/' '%' +%right TOK_UNARY + +%% + +input + : expression { + *(context->result) = static_cast($1); + YYACCEPT; + } +; + +expression + : TOK_CONST_INT + | expression TOK_OP_OR expression { + $$ = $1 || $3; + } + | expression TOK_OP_AND expression { + $$ = $1 && $3; + } + | expression '|' expression { + $$ = $1 | $3; + } + | expression '^' expression { + $$ = $1 ^ $3; + } + | expression '&' expression { + $$ = $1 & $3; + } + | expression TOK_OP_NE expression { + $$ = $1 != $3; + } + | expression TOK_OP_EQ expression { + $$ = $1 == $3; + } + | expression TOK_OP_GE expression { + $$ = $1 >= $3; + } + | expression TOK_OP_LE expression { + $$ = $1 <= $3; + } + | expression '>' expression { + $$ = $1 > $3; + } + | expression '<' expression { + $$ = $1 < $3; + } + | expression TOK_OP_RIGHT expression { + $$ = $1 >> $3; + } + | expression TOK_OP_LEFT expression { + $$ = $1 << $3; + } + | expression '-' expression { + $$ = $1 - $3; + } + | expression '+' expression { + $$ = $1 + $3; + } + | expression '%' expression { + if ($3 == 0) { + std::ostringstream stream; + stream << $1 << " % " << $3; + std::string text = stream.str(); + context->diagnostics->report(pp::Diagnostics::DIVISION_BY_ZERO, + context->token->location, + text.c_str()); + YYABORT; + } else { + $$ = $1 % $3; + } + } + | expression '/' expression { + if ($3 == 0) { + std::ostringstream stream; + stream << $1 << " / " << $3; + std::string text = stream.str(); + context->diagnostics->report(pp::Diagnostics::DIVISION_BY_ZERO, + context->token->location, + text.c_str()); + YYABORT; + } else { + $$ = $1 / $3; + } + } + | expression '*' expression { + $$ = $1 * $3; + } + | '!' expression %prec TOK_UNARY { + $$ = ! $2; + } + | '~' expression %prec TOK_UNARY { + $$ = ~ $2; + } + | '-' expression %prec TOK_UNARY { + $$ = - $2; + } + | '+' expression %prec TOK_UNARY { + $$ = + $2; + } + | '(' expression ')' { + $$ = $2; + } +; + +%% + +int yylex(YYSTYPE* lvalp, Context* context) +{ + int type = 0; + + pp::Token* token = context->token; + switch (token->type) + { + case pp::Token::CONST_INT: + { + unsigned int val = 0; + if (!token->uValue(&val)) + { + context->diagnostics->report(pp::Diagnostics::INTEGER_OVERFLOW, + token->location, token->text); + } + *lvalp = static_cast(val); + type = TOK_CONST_INT; + break; + } + case pp::Token::OP_OR: type = TOK_OP_OR; break; + case pp::Token::OP_AND: type = TOK_OP_AND; break; + case pp::Token::OP_NE: type = TOK_OP_NE; break; + case pp::Token::OP_EQ: type = TOK_OP_EQ; break; + case pp::Token::OP_GE: type = TOK_OP_GE; break; + case pp::Token::OP_LE: type = TOK_OP_LE; break; + case pp::Token::OP_RIGHT: type = TOK_OP_RIGHT; break; + case pp::Token::OP_LEFT: type = TOK_OP_LEFT; break; + case '|': type = '|'; break; + case '^': type = '^'; break; + case '&': type = '&'; break; + case '>': type = '>'; break; + case '<': type = '<'; break; + case '-': type = '-'; break; + case '+': type = '+'; break; + case '%': type = '%'; break; + case '/': type = '/'; break; + case '*': type = '*'; break; + case '!': type = '!'; break; + case '~': type = '~'; break; + case '(': type = '('; break; + case ')': type = ')'; break; + + default: break; + } + + // Advance to the next token if the current one is valid. + if (type != 0) context->lexer->lex(token); + + return type; +} + +void yyerror(Context* context, const char* reason) +{ + context->diagnostics->report(pp::Diagnostics::INVALID_EXPRESSION, + context->token->location, + reason); +} + +namespace pp { + +ExpressionParser::ExpressionParser(Lexer* lexer, Diagnostics* diagnostics) : + mLexer(lexer), + mDiagnostics(diagnostics) +{ +} + +bool ExpressionParser::parse(Token* token, int* result) +{ + Context context; + context.diagnostics = mDiagnostics; + context.lexer = mLexer; + context.token = token; + context.result = result; + int ret = yyparse(&context); + switch (ret) + { + case 0: + case 1: + break; + + case 2: + mDiagnostics->report(Diagnostics::OUT_OF_MEMORY, token->location, ""); + break; + + default: + assert(false); + mDiagnostics->report(Diagnostics::INTERNAL_ERROR, token->location, ""); + break; + } + + return ret == 0; +} + +} // namespace pp diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Input.cpp b/src/3rdparty/angle/src/compiler/preprocessor/Input.cpp new file mode 100644 index 0000000000..b4d970a97d --- /dev/null +++ b/src/3rdparty/angle/src/compiler/preprocessor/Input.cpp @@ -0,0 +1,54 @@ +// +// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "Input.h" + +#include +#include +#include + +namespace pp +{ + +Input::Input() : mCount(0), mString(0) +{ +} + +Input::Input(size_t count, const char* const string[], const int length[]) : + mCount(count), + mString(string) +{ + mLength.reserve(mCount); + for (size_t i = 0; i < mCount; ++i) + { + int len = length ? length[i] : -1; + mLength.push_back(len < 0 ? std::strlen(mString[i]) : len); + } +} + +size_t Input::read(char* buf, size_t maxSize) +{ + size_t nRead = 0; + while ((nRead < maxSize) && (mReadLoc.sIndex < mCount)) + { + size_t size = mLength[mReadLoc.sIndex] - mReadLoc.cIndex; + size = std::min(size, maxSize); + std::memcpy(buf + nRead, mString[mReadLoc.sIndex] + mReadLoc.cIndex, size); + nRead += size; + mReadLoc.cIndex += size; + + // Advance string if we reached the end of current string. + if (mReadLoc.cIndex == mLength[mReadLoc.sIndex]) + { + ++mReadLoc.sIndex; + mReadLoc.cIndex = 0; + } + } + return nRead; +} + +} // namespace pp + diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Input.h b/src/3rdparty/angle/src/compiler/preprocessor/Input.h new file mode 100644 index 0000000000..14b7597cb4 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/preprocessor/Input.h @@ -0,0 +1,49 @@ +// +// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_PREPROCESSOR_INPUT_H_ +#define COMPILER_PREPROCESSOR_INPUT_H_ + +#include +#include + +namespace pp +{ + +// Holds and reads input for Lexer. +class Input +{ + public: + Input(); + Input(size_t count, const char* const string[], const int length[]); + + size_t count() const { return mCount; } + const char* string(size_t index) const { return mString[index]; } + size_t length(size_t index) const { return mLength[index]; } + + size_t read(char* buf, size_t maxSize); + + struct Location + { + size_t sIndex; // String index; + size_t cIndex; // Char index. + + Location() : sIndex(0), cIndex(0) { } + }; + const Location& readLoc() const { return mReadLoc; } + + private: + // Input. + size_t mCount; + const char* const* mString; + std::vector mLength; + + Location mReadLoc; +}; + +} // namespace pp +#endif // COMPILER_PREPROCESSOR_INPUT_H_ + diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Lexer.cpp b/src/3rdparty/angle/src/compiler/preprocessor/Lexer.cpp new file mode 100644 index 0000000000..7c663ee761 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/preprocessor/Lexer.cpp @@ -0,0 +1,16 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "Lexer.h" + +namespace pp +{ + +Lexer::~Lexer() +{ +} + +} // namespace pp diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Lexer.h b/src/3rdparty/angle/src/compiler/preprocessor/Lexer.h new file mode 100644 index 0000000000..eb85cea873 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/preprocessor/Lexer.h @@ -0,0 +1,25 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_PREPROCESSOR_LEXER_H_ +#define COMPILER_PREPROCESSOR_LEXER_H_ + +namespace pp +{ + +struct Token; + +class Lexer +{ + public: + virtual ~Lexer(); + + virtual void lex(Token* token) = 0; +}; + +} // namespace pp +#endif // COMPILER_PREPROCESSOR_LEXER_H_ + diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Macro.cpp b/src/3rdparty/angle/src/compiler/preprocessor/Macro.cpp new file mode 100644 index 0000000000..b2e3088e32 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/preprocessor/Macro.cpp @@ -0,0 +1,23 @@ +// +// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "Macro.h" + +#include "Token.h" + +namespace pp +{ + +bool Macro::equals(const Macro& other) const +{ + return (type == other.type) && + (name == other.name) && + (parameters == other.parameters) && + (replacements == other.replacements); +} + +} // namespace pp + diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Macro.h b/src/3rdparty/angle/src/compiler/preprocessor/Macro.h new file mode 100644 index 0000000000..7ec0149116 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/preprocessor/Macro.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_PREPROCESSOR_MACRO_H_ +#define COMPILER_PREPROCESSOR_MACRO_H_ + +#include +#include +#include + +namespace pp +{ + +struct Token; + +struct Macro +{ + enum Type + { + kTypeObj, + kTypeFunc + }; + typedef std::vector Parameters; + typedef std::vector Replacements; + + Macro() : predefined(false), disabled(false), type(kTypeObj) { } + bool equals(const Macro& other) const; + + bool predefined; + mutable bool disabled; + + Type type; + std::string name; + Parameters parameters; + Replacements replacements; +}; + +typedef std::map MacroSet; + +} // namespace pp +#endif // COMPILER_PREPROCESSOR_MACRO_H_ diff --git a/src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.cpp b/src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.cpp new file mode 100644 index 0000000000..1116c516ff --- /dev/null +++ b/src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.cpp @@ -0,0 +1,370 @@ +// +// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "MacroExpander.h" + +#include +#include + +#include "DiagnosticsBase.h" +#include "Token.h" + +namespace pp +{ + +class TokenLexer : public Lexer +{ + public: + typedef std::vector TokenVector; + + TokenLexer(TokenVector* tokens) + { + tokens->swap(mTokens); + mIter = mTokens.begin(); + } + + virtual void lex(Token* token) + { + if (mIter == mTokens.end()) + { + token->reset(); + token->type = Token::LAST; + } + else + { + *token = *mIter++; + } + } + + private: + PP_DISALLOW_COPY_AND_ASSIGN(TokenLexer); + + TokenVector mTokens; + TokenVector::const_iterator mIter; +}; + +MacroExpander::MacroExpander(Lexer* lexer, + MacroSet* macroSet, + Diagnostics* diagnostics) : + mLexer(lexer), + mMacroSet(macroSet), + mDiagnostics(diagnostics) +{ +} + +MacroExpander::~MacroExpander() +{ + for (std::size_t i = 0; i < mContextStack.size(); ++i) + { + delete mContextStack[i]; + } +} + +void MacroExpander::lex(Token* token) +{ + while (true) + { + getToken(token); + + if (token->type != Token::IDENTIFIER) + break; + + if (token->expansionDisabled()) + break; + + MacroSet::const_iterator iter = mMacroSet->find(token->text); + if (iter == mMacroSet->end()) + break; + + const Macro& macro = iter->second; + if (macro.disabled) + { + // If a particular token is not expanded, it is never expanded. + token->setExpansionDisabled(true); + break; + } + if ((macro.type == Macro::kTypeFunc) && !isNextTokenLeftParen()) + { + // If the token immediately after the macro name is not a '(', + // this macro should not be expanded. + break; + } + + pushMacro(macro, *token); + } +} + +void MacroExpander::getToken(Token* token) +{ + if (mReserveToken.get()) + { + *token = *mReserveToken; + mReserveToken.reset(); + return; + } + + // First pop all empty macro contexts. + while (!mContextStack.empty() && mContextStack.back()->empty()) + { + popMacro(); + } + + if (!mContextStack.empty()) + { + *token = mContextStack.back()->get(); + } + else + { + mLexer->lex(token); + } +} + +void MacroExpander::ungetToken(const Token& token) +{ + if (!mContextStack.empty()) + { + MacroContext* context = mContextStack.back(); + context->unget(); + assert(context->replacements[context->index] == token); + } + else + { + assert(!mReserveToken.get()); + mReserveToken.reset(new Token(token)); + } +} + +bool MacroExpander::isNextTokenLeftParen() +{ + Token token; + getToken(&token); + + bool lparen = token.type == '('; + ungetToken(token); + + return lparen; +} + +bool MacroExpander::pushMacro(const Macro& macro, const Token& identifier) +{ + assert(!macro.disabled); + assert(!identifier.expansionDisabled()); + assert(identifier.type == Token::IDENTIFIER); + assert(identifier.text == macro.name); + + std::vector replacements; + if (!expandMacro(macro, identifier, &replacements)) + return false; + + // Macro is disabled for expansion until it is popped off the stack. + macro.disabled = true; + + MacroContext* context = new MacroContext; + context->macro = ¯o; + context->replacements.swap(replacements); + mContextStack.push_back(context); + return true; +} + +void MacroExpander::popMacro() +{ + assert(!mContextStack.empty()); + + MacroContext* context = mContextStack.back(); + mContextStack.pop_back(); + + assert(context->empty()); + assert(context->macro->disabled); + context->macro->disabled = false; + delete context; +} + +bool MacroExpander::expandMacro(const Macro& macro, + const Token& identifier, + std::vector* replacements) +{ + replacements->clear(); + if (macro.type == Macro::kTypeObj) + { + replacements->assign(macro.replacements.begin(), + macro.replacements.end()); + + if (macro.predefined) + { + static const std::string kLine = "__LINE__"; + static const std::string kFile = "__FILE__"; + + assert(replacements->size() == 1); + Token& repl = replacements->front(); + if (macro.name == kLine) + { + std::ostringstream stream; + stream << identifier.location.line; + repl.text = stream.str(); + } + else if (macro.name == kFile) + { + std::ostringstream stream; + stream << identifier.location.file; + repl.text = stream.str(); + } + } + } + else + { + assert(macro.type == Macro::kTypeFunc); + std::vector args; + args.reserve(macro.parameters.size()); + if (!collectMacroArgs(macro, identifier, &args)) + return false; + + replaceMacroParams(macro, args, replacements); + } + + for (std::size_t i = 0; i < replacements->size(); ++i) + { + Token& repl = replacements->at(i); + if (i == 0) + { + // The first token in the replacement list inherits the padding + // properties of the identifier token. + repl.setAtStartOfLine(identifier.atStartOfLine()); + repl.setHasLeadingSpace(identifier.hasLeadingSpace()); + } + repl.location = identifier.location; + } + return true; +} + +bool MacroExpander::collectMacroArgs(const Macro& macro, + const Token& identifier, + std::vector* args) +{ + Token token; + getToken(&token); + assert(token.type == '('); + + args->push_back(MacroArg()); + for (int openParens = 1; openParens != 0; ) + { + getToken(&token); + + if (token.type == Token::LAST) + { + mDiagnostics->report(Diagnostics::MACRO_UNTERMINATED_INVOCATION, + identifier.location, identifier.text); + // Do not lose EOF token. + ungetToken(token); + return false; + } + + bool isArg = false; // True if token is part of the current argument. + switch (token.type) + { + case '(': + ++openParens; + isArg = true; + break; + case ')': + --openParens; + isArg = openParens != 0; + break; + case ',': + // The individual arguments are separated by comma tokens, but + // the comma tokens between matching inner parentheses do not + // seperate arguments. + if (openParens == 1) args->push_back(MacroArg()); + isArg = openParens != 1; + break; + default: + isArg = true; + break; + } + if (isArg) + { + MacroArg& arg = args->back(); + // Initial whitespace is not part of the argument. + if (arg.empty()) token.setHasLeadingSpace(false); + arg.push_back(token); + } + } + + const Macro::Parameters& params = macro.parameters; + // If there is only one empty argument, it is equivalent to no argument. + if (params.empty() && (args->size() == 1) && args->front().empty()) + { + args->clear(); + } + // Validate the number of arguments. + if (args->size() != params.size()) + { + Diagnostics::ID id = args->size() < macro.parameters.size() ? + Diagnostics::MACRO_TOO_FEW_ARGS : + Diagnostics::MACRO_TOO_MANY_ARGS; + mDiagnostics->report(id, identifier.location, identifier.text); + return false; + } + + // Pre-expand each argument before substitution. + // This step expands each argument individually before they are + // inserted into the macro body. + for (std::size_t i = 0; i < args->size(); ++i) + { + MacroArg& arg = args->at(i); + TokenLexer lexer(&arg); + MacroExpander expander(&lexer, mMacroSet, mDiagnostics); + + arg.clear(); + expander.lex(&token); + while (token.type != Token::LAST) + { + arg.push_back(token); + expander.lex(&token); + } + } + return true; +} + +void MacroExpander::replaceMacroParams(const Macro& macro, + const std::vector& args, + std::vector* replacements) +{ + for (std::size_t i = 0; i < macro.replacements.size(); ++i) + { + const Token& repl = macro.replacements[i]; + if (repl.type != Token::IDENTIFIER) + { + replacements->push_back(repl); + continue; + } + + // TODO(alokp): Optimize this. + // There is no need to search for macro params every time. + // The param index can be cached with the replacement token. + Macro::Parameters::const_iterator iter = std::find( + macro.parameters.begin(), macro.parameters.end(), repl.text); + if (iter == macro.parameters.end()) + { + replacements->push_back(repl); + continue; + } + + std::size_t iArg = std::distance(macro.parameters.begin(), iter); + const MacroArg& arg = args[iArg]; + if (arg.empty()) + { + continue; + } + std::size_t iRepl = replacements->size(); + replacements->insert(replacements->end(), arg.begin(), arg.end()); + // The replacement token inherits padding properties from + // macro replacement token. + replacements->at(iRepl).setHasLeadingSpace(repl.hasLeadingSpace()); + } +} + +} // namespace pp + diff --git a/src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.h b/src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.h new file mode 100644 index 0000000000..21b67571f1 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.h @@ -0,0 +1,75 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_PREPROCESSOR_MACRO_EXPANDER_H_ +#define COMPILER_PREPROCESSOR_MACRO_EXPANDER_H_ + +#include +#include +#include + +#include "Lexer.h" +#include "Macro.h" +#include "pp_utils.h" + +namespace pp +{ + +class Diagnostics; + +class MacroExpander : public Lexer +{ + public: + MacroExpander(Lexer* lexer, MacroSet* macroSet, Diagnostics* diagnostics); + virtual ~MacroExpander(); + + virtual void lex(Token* token); + + private: + PP_DISALLOW_COPY_AND_ASSIGN(MacroExpander); + + void getToken(Token* token); + void ungetToken(const Token& token); + bool isNextTokenLeftParen(); + + bool pushMacro(const Macro& macro, const Token& identifier); + void popMacro(); + + bool expandMacro(const Macro& macro, + const Token& identifier, + std::vector* replacements); + + typedef std::vector MacroArg; + bool collectMacroArgs(const Macro& macro, + const Token& identifier, + std::vector* args); + void replaceMacroParams(const Macro& macro, + const std::vector& args, + std::vector* replacements); + + struct MacroContext + { + const Macro* macro; + std::size_t index; + std::vector replacements; + + MacroContext() : macro(0), index(0) { } + bool empty() const { return index == replacements.size(); } + const Token& get() { return replacements[index++]; } + void unget() { assert(index > 0); --index; } + }; + + Lexer* mLexer; + MacroSet* mMacroSet; + Diagnostics* mDiagnostics; + + std::auto_ptr mReserveToken; + std::vector mContextStack; +}; + +} // namespace pp +#endif // COMPILER_PREPROCESSOR_MACRO_EXPANDER_H_ + diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.cpp b/src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.cpp new file mode 100644 index 0000000000..5ffc6420bc --- /dev/null +++ b/src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.cpp @@ -0,0 +1,142 @@ +// +// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "Preprocessor.h" + +#include +#include + +#include "DiagnosticsBase.h" +#include "DirectiveParser.h" +#include "Macro.h" +#include "MacroExpander.h" +#include "Token.h" +#include "Tokenizer.h" + +namespace pp +{ + +struct PreprocessorImpl +{ + Diagnostics* diagnostics; + MacroSet macroSet; + Tokenizer tokenizer; + DirectiveParser directiveParser; + MacroExpander macroExpander; + + PreprocessorImpl(Diagnostics* diag, + DirectiveHandler* directiveHandler) : + diagnostics(diag), + tokenizer(diag), + directiveParser(&tokenizer, ¯oSet, diag, directiveHandler), + macroExpander(&directiveParser, ¯oSet, diag) + { + } +}; + +Preprocessor::Preprocessor(Diagnostics* diagnostics, + DirectiveHandler* directiveHandler) +{ + mImpl = new PreprocessorImpl(diagnostics, directiveHandler); +} + +Preprocessor::~Preprocessor() +{ + delete mImpl; +} + +bool Preprocessor::init(size_t count, + const char* const string[], + const int length[]) +{ + static const int kGLSLVersion = 100; + + // Add standard pre-defined macros. + predefineMacro("__LINE__", 0); + predefineMacro("__FILE__", 0); + predefineMacro("__VERSION__", kGLSLVersion); + predefineMacro("GL_ES", 1); + + return mImpl->tokenizer.init(count, string, length); +} + +void Preprocessor::predefineMacro(const char* name, int value) +{ + std::ostringstream stream; + stream << value; + + Token token; + token.type = Token::CONST_INT; + token.text = stream.str(); + + Macro macro; + macro.predefined = true; + macro.type = Macro::kTypeObj; + macro.name = name; + macro.replacements.push_back(token); + + mImpl->macroSet[name] = macro; +} + +void Preprocessor::lex(Token* token) +{ + bool validToken = false; + while (!validToken) + { + mImpl->macroExpander.lex(token); + switch (token->type) + { + // We should not be returning internal preprocessing tokens. + // Convert preprocessing tokens to compiler tokens or report + // diagnostics. + case Token::PP_HASH: + assert(false); + break; + case Token::CONST_INT: + { + int val = 0; + if (!token->iValue(&val)) + { + // Do not mark the token as invalid. + // Just emit the diagnostic and reset value to 0. + mImpl->diagnostics->report(Diagnostics::INTEGER_OVERFLOW, + token->location, token->text); + token->text.assign("0"); + } + validToken = true; + break; + } + case Token::CONST_FLOAT: + { + float val = 0; + if (!token->fValue(&val)) + { + // Do not mark the token as invalid. + // Just emit the diagnostic and reset value to 0.0. + mImpl->diagnostics->report(Diagnostics::FLOAT_OVERFLOW, + token->location, token->text); + token->text.assign("0.0"); + } + validToken = true; + break; + } + case Token::PP_NUMBER: + mImpl->diagnostics->report(Diagnostics::INVALID_NUMBER, + token->location, token->text); + break; + case Token::PP_OTHER: + mImpl->diagnostics->report(Diagnostics::INVALID_CHARACTER, + token->location, token->text); + break; + default: + validToken = true; + break; + } + } +} + +} // namespace pp + diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.h b/src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.h new file mode 100644 index 0000000000..7b70180fc8 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.h @@ -0,0 +1,51 @@ +// +// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_PREPROCESSOR_PREPROCESSOR_H_ +#define COMPILER_PREPROCESSOR_PREPROCESSOR_H_ + +#include + +#include "pp_utils.h" + +namespace pp +{ + +class Diagnostics; +class DirectiveHandler; +struct PreprocessorImpl; +struct Token; + +class Preprocessor +{ + public: + Preprocessor(Diagnostics* diagnostics, DirectiveHandler* directiveHandler); + ~Preprocessor(); + + // count: specifies the number of elements in the string and length arrays. + // string: specifies an array of pointers to strings. + // length: specifies an array of string lengths. + // If length is NULL, each string is assumed to be null terminated. + // If length is a value other than NULL, it points to an array containing + // a string length for each of the corresponding elements of string. + // Each element in the length array may contain the length of the + // corresponding string or a value less than 0 to indicate that the string + // is null terminated. + bool init(size_t count, const char* const string[], const int length[]); + // Adds a pre-defined macro. + void predefineMacro(const char* name, int value); + + void lex(Token* token); + + private: + PP_DISALLOW_COPY_AND_ASSIGN(Preprocessor); + + PreprocessorImpl* mImpl; +}; + +} // namespace pp +#endif // COMPILER_PREPROCESSOR_PREPROCESSOR_H_ + diff --git a/src/3rdparty/angle/src/compiler/preprocessor/SourceLocation.h b/src/3rdparty/angle/src/compiler/preprocessor/SourceLocation.h new file mode 100644 index 0000000000..6982613ac7 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/preprocessor/SourceLocation.h @@ -0,0 +1,38 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_PREPROCESSOR_SOURCE_LOCATION_H_ +#define COMPILER_PREPROCESSOR_SOURCE_LOCATION_H_ + +namespace pp +{ + +struct SourceLocation +{ + SourceLocation() : file(0), line(0) { } + SourceLocation(int f, int l) : file(f), line(l) { } + + bool equals(const SourceLocation& other) const + { + return (file == other.file) && (line == other.line); + } + + int file; + int line; +}; + +inline bool operator==(const SourceLocation& lhs, const SourceLocation& rhs) +{ + return lhs.equals(rhs); +} + +inline bool operator!=(const SourceLocation& lhs, const SourceLocation& rhs) +{ + return !lhs.equals(rhs); +} + +} // namespace pp +#endif // COMPILER_PREPROCESSOR_SOURCE_LOCATION_H_ diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Token.cpp b/src/3rdparty/angle/src/compiler/preprocessor/Token.cpp new file mode 100644 index 0000000000..67f50aa32c --- /dev/null +++ b/src/3rdparty/angle/src/compiler/preprocessor/Token.cpp @@ -0,0 +1,83 @@ +// +// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "Token.h" + +#include + +#include "numeric_lex.h" + +namespace pp +{ + +void Token::reset() +{ + type = 0; + flags = 0; + location = SourceLocation(); + text.clear(); +} + +bool Token::equals(const Token& other) const +{ + return (type == other.type) && + (flags == other.flags) && + (location == other.location) && + (text == other.text); +} + +void Token::setAtStartOfLine(bool start) +{ + if (start) + flags |= AT_START_OF_LINE; + else + flags &= ~AT_START_OF_LINE; +} + +void Token::setHasLeadingSpace(bool space) +{ + if (space) + flags |= HAS_LEADING_SPACE; + else + flags &= ~HAS_LEADING_SPACE; +} + +void Token::setExpansionDisabled(bool disable) +{ + if (disable) + flags |= EXPANSION_DISABLED; + else + flags &= ~EXPANSION_DISABLED; +} + +bool Token::iValue(int* value) const +{ + assert(type == CONST_INT); + return numeric_lex_int(text, value); +} + +bool Token::uValue(unsigned int* value) const +{ + assert(type == CONST_INT); + return numeric_lex_int(text, value); +} + +bool Token::fValue(float* value) const +{ + assert(type == CONST_FLOAT); + return numeric_lex_float(text, value); +} + +std::ostream& operator<<(std::ostream& out, const Token& token) +{ + if (token.hasLeadingSpace()) + out << " "; + + out << token.text; + return out; +} + +} // namespace pp diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Token.h b/src/3rdparty/angle/src/compiler/preprocessor/Token.h new file mode 100644 index 0000000000..8b553aecb6 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/preprocessor/Token.h @@ -0,0 +1,106 @@ +// +// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_PREPROCESSOR_TOKEN_H_ +#define COMPILER_PREPROCESSOR_TOKEN_H_ + +#include +#include + +#include "SourceLocation.h" + +namespace pp +{ + +struct Token +{ + enum Type + { + LAST = 0, // EOF. + + IDENTIFIER = 258, + + CONST_INT, + CONST_FLOAT, + + OP_INC, + OP_DEC, + OP_LEFT, + OP_RIGHT, + OP_LE, + OP_GE, + OP_EQ, + OP_NE, + OP_AND, + OP_XOR, + OP_OR, + OP_ADD_ASSIGN, + OP_SUB_ASSIGN, + OP_MUL_ASSIGN, + OP_DIV_ASSIGN, + OP_MOD_ASSIGN, + OP_LEFT_ASSIGN, + OP_RIGHT_ASSIGN, + OP_AND_ASSIGN, + OP_XOR_ASSIGN, + OP_OR_ASSIGN, + + // Preprocessing token types. + // These types are used by the preprocessor internally. + // Preprocessor clients must not depend or check for them. + PP_HASH, + PP_NUMBER, + PP_OTHER + }; + enum Flags + { + AT_START_OF_LINE = 1 << 0, + HAS_LEADING_SPACE = 1 << 1, + EXPANSION_DISABLED = 1 << 2 + }; + + Token() : type(0), flags(0) { } + + void reset(); + bool equals(const Token& other) const; + + // Returns true if this is the first token on line. + // It disregards any leading whitespace. + bool atStartOfLine() const { return (flags & AT_START_OF_LINE) != 0; } + void setAtStartOfLine(bool start); + + bool hasLeadingSpace() const { return (flags & HAS_LEADING_SPACE) != 0; } + void setHasLeadingSpace(bool space); + + bool expansionDisabled() const { return (flags & EXPANSION_DISABLED) != 0; } + void setExpansionDisabled(bool disable); + + // Converts text into numeric value for CONST_INT and CONST_FLOAT token. + // Returns false if the parsed value cannot fit into an int or float. + bool iValue(int* value) const; + bool uValue(unsigned int* value) const; + bool fValue(float* value) const; + + int type; + unsigned int flags; + SourceLocation location; + std::string text; +}; + +inline bool operator==(const Token& lhs, const Token& rhs) +{ + return lhs.equals(rhs); +} + +inline bool operator!=(const Token& lhs, const Token& rhs) +{ + return !lhs.equals(rhs); +} + +extern std::ostream& operator<<(std::ostream& out, const Token& token); + +} // namepsace pp +#endif // COMPILER_PREPROCESSOR_TOKEN_H_ diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.h b/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.h new file mode 100644 index 0000000000..7a6fa87b04 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.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. +// + +#ifndef COMPILER_PREPROCESSOR_TOKENIZER_H_ +#define COMPILER_PREPROCESSOR_TOKENIZER_H_ + +#include "Input.h" +#include "Lexer.h" +#include "pp_utils.h" + +namespace pp +{ + +class Diagnostics; + +class Tokenizer : public Lexer +{ + public: + struct Context + { + Diagnostics* diagnostics; + + Input input; + // The location where yytext points to. Token location should track + // scanLoc instead of Input::mReadLoc because they may not be the same + // if text is buffered up in the scanner input buffer. + Input::Location scanLoc; + + bool leadingSpace; + bool lineStart; + }; + static const std::size_t kMaxTokenLength; + + Tokenizer(Diagnostics* diagnostics); + ~Tokenizer(); + + bool init(size_t count, const char* const string[], const int length[]); + + void setFileNumber(int file); + void setLineNumber(int line); + + virtual void lex(Token* token); + + private: + PP_DISALLOW_COPY_AND_ASSIGN(Tokenizer); + bool initScanner(); + void destroyScanner(); + + void* mHandle; // Scanner handle. + Context mContext; // Scanner extra. +}; + +} // namespace pp +#endif // COMPILER_PREPROCESSOR_TOKENIZER_H_ + diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.l b/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.l new file mode 100644 index 0000000000..fc81d84f37 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.l @@ -0,0 +1,342 @@ +/* +// +// 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 Lex specification for GLSL ES preprocessor. +Based on Microsoft Visual Studio 2010 Preprocessor Grammar: +http://msdn.microsoft.com/en-us/library/2scxys89.aspx + +IF YOU MODIFY THIS FILE YOU ALSO NEED TO RUN generate_parser.sh. +*/ + +%top{ +// +// Copyright (c) 2011-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 is auto-generated by generate_parser.sh. DO NOT EDIT! +} + +%{ +#include "Tokenizer.h" + +#include "DiagnosticsBase.h" +#include "Token.h" + +#if defined(__GNUC__) +// Triggered by the auto-generated yy_fatal_error function. +#pragma GCC diagnostic ignored "-Wmissing-noreturn" +#endif + +typedef std::string YYSTYPE; +typedef pp::SourceLocation YYLTYPE; + +// Use the unused yycolumn variable to track file (string) number. +#define yyfileno yycolumn + +#define YY_USER_INIT \ + do { \ + yyfileno = 0; \ + yylineno = 1; \ + yyextra->leadingSpace = false; \ + yyextra->lineStart = true; \ + } while(0); + +#define YY_USER_ACTION \ + do \ + { \ + pp::Input* input = &yyextra->input; \ + pp::Input::Location* scanLoc = &yyextra->scanLoc; \ + while ((scanLoc->sIndex < input->count()) && \ + (scanLoc->cIndex >= input->length(scanLoc->sIndex))) \ + { \ + scanLoc->cIndex -= input->length(scanLoc->sIndex++); \ + ++yyfileno; yylineno = 1; \ + } \ + yylloc->file = yyfileno; \ + yylloc->line = yylineno; \ + scanLoc->cIndex += yyleng; \ + } while(0); + +#define YY_INPUT(buf, result, maxSize) \ + result = yyextra->input.read(buf, maxSize); + +%} + +%option noyywrap nounput never-interactive +%option reentrant bison-bridge bison-locations +%option prefix="pp" +%option extra-type="pp::Tokenizer::Context*" +%x COMMENT + +NEWLINE \n|\r|\r\n +IDENTIFIER [_a-zA-Z][_a-zA-Z0-9]* +PUNCTUATOR [][<>(){}.+-/*%^|&~=!:;,?] + +DECIMAL_CONSTANT [1-9][0-9]* +OCTAL_CONSTANT 0[0-7]* +HEXADECIMAL_CONSTANT 0[xX][0-9a-fA-F]+ + +DIGIT [0-9] +EXPONENT_PART [eE][+-]?{DIGIT}+ +FRACTIONAL_CONSTANT ({DIGIT}*"."{DIGIT}+)|({DIGIT}+".") + +%% + + /* Line comment */ +"//"[^\r\n]* + + /* Block comment */ + /* Line breaks are just counted - not returned. */ + /* The comment is replaced by a single space. */ +"/*" { BEGIN(COMMENT); } +[^*\r\n]+ +"*" +{NEWLINE} { ++yylineno; } +"*/" { + yyextra->leadingSpace = true; + BEGIN(INITIAL); +} + +# { + // # is only valid at start of line for preprocessor directives. + yylval->assign(1, yytext[0]); + return yyextra->lineStart ? pp::Token::PP_HASH : pp::Token::PP_OTHER; +} + +{IDENTIFIER} { + yylval->assign(yytext, yyleng); + return pp::Token::IDENTIFIER; +} + +{DECIMAL_CONSTANT}|{OCTAL_CONSTANT}|{HEXADECIMAL_CONSTANT} { + yylval->assign(yytext, yyleng); + return pp::Token::CONST_INT; +} + +({DIGIT}+{EXPONENT_PART})|({FRACTIONAL_CONSTANT}{EXPONENT_PART}?) { + yylval->assign(yytext, yyleng); + return pp::Token::CONST_FLOAT; +} + + /* Anything that starts with a {DIGIT} or .{DIGIT} must be a number. */ + /* Rule to catch all invalid integers and floats. */ +({DIGIT}+[_a-zA-Z0-9.]*)|("."{DIGIT}+[_a-zA-Z0-9.]*) { + yylval->assign(yytext, yyleng); + return pp::Token::PP_NUMBER; +} + +"++" { + yylval->assign(yytext, yyleng); + return pp::Token::OP_INC; +} +"--" { + yylval->assign(yytext, yyleng); + return pp::Token::OP_DEC; +} +"<<" { + yylval->assign(yytext, yyleng); + return pp::Token::OP_LEFT; +} +">>" { + yylval->assign(yytext, yyleng); + return pp::Token::OP_RIGHT; +} +"<=" { + yylval->assign(yytext, yyleng); + return pp::Token::OP_LE; +} +">=" { + yylval->assign(yytext, yyleng); + return pp::Token::OP_GE; +} +"==" { + yylval->assign(yytext, yyleng); + return pp::Token::OP_EQ; +} +"!=" { + yylval->assign(yytext, yyleng); + return pp::Token::OP_NE; +} +"&&" { + yylval->assign(yytext, yyleng); + return pp::Token::OP_AND; +} +"^^" { + yylval->assign(yytext, yyleng); + return pp::Token::OP_XOR; +} +"||" { + yylval->assign(yytext, yyleng); + return pp::Token::OP_OR; +} +"+=" { + yylval->assign(yytext, yyleng); + return pp::Token::OP_ADD_ASSIGN; +} +"-=" { + yylval->assign(yytext, yyleng); + return pp::Token::OP_SUB_ASSIGN; +} +"*=" { + yylval->assign(yytext, yyleng); + return pp::Token::OP_MUL_ASSIGN; +} +"/=" { + yylval->assign(yytext, yyleng); + return pp::Token::OP_DIV_ASSIGN; +} +"%=" { + yylval->assign(yytext, yyleng); + return pp::Token::OP_MOD_ASSIGN; +} +"<<=" { + yylval->assign(yytext, yyleng); + return pp::Token::OP_LEFT_ASSIGN; +} +">>=" { + yylval->assign(yytext, yyleng); + return pp::Token::OP_RIGHT_ASSIGN; +} +"&=" { + yylval->assign(yytext, yyleng); + return pp::Token::OP_AND_ASSIGN; +} +"^=" { + yylval->assign(yytext, yyleng); + return pp::Token::OP_XOR_ASSIGN; +} +"|=" { + yylval->assign(yytext, yyleng); + return pp::Token::OP_OR_ASSIGN; +} + +{PUNCTUATOR} { + yylval->assign(1, yytext[0]); + return yytext[0]; +} + +[ \t\v\f]+ { yyextra->leadingSpace = true; } + +{NEWLINE} { + ++yylineno; + yylval->assign(1, '\n'); + return '\n'; +} + +\\{NEWLINE} { ++yylineno; } + +. { + yylval->assign(1, yytext[0]); + return pp::Token::PP_OTHER; +} + +<*><> { + // YY_USER_ACTION is not invoked for handling EOF. + // Set the location for EOF token manually. + pp::Input* input = &yyextra->input; + pp::Input::Location* scanLoc = &yyextra->scanLoc; + yy_size_t sIndexMax = input->count() ? input->count() - 1 : 0; + if (scanLoc->sIndex != sIndexMax) + { + // We can only reach here if there are empty strings at the + // end of the input. + scanLoc->sIndex = sIndexMax; scanLoc->cIndex = 0; + // FIXME: this is not 64-bit clean. + yyfileno = static_cast(sIndexMax); yylineno = 1; + } + yylloc->file = yyfileno; + yylloc->line = yylineno; + yylval->clear(); + + if (YY_START == COMMENT) + { + yyextra->diagnostics->report(pp::Diagnostics::EOF_IN_COMMENT, + pp::SourceLocation(yyfileno, yylineno), + ""); + } + yyterminate(); +} + +%% + +namespace pp { + +// TODO(alokp): Maximum token length should ideally be specified by +// the preprocessor client, i.e., the compiler. +const size_t Tokenizer::kMaxTokenLength = 256; + +Tokenizer::Tokenizer(Diagnostics* diagnostics) : mHandle(0) +{ + mContext.diagnostics = diagnostics; +} + +Tokenizer::~Tokenizer() +{ + destroyScanner(); +} + +bool Tokenizer::init(size_t count, const char* const string[], const int length[]) +{ + if ((count > 0) && (string == 0)) return false; + + mContext.input = Input(count, string, length); + return initScanner(); +} + +void Tokenizer::setFileNumber(int file) +{ + // We use column number as file number. + // See macro yyfileno. + yyset_column(file, mHandle); +} + +void Tokenizer::setLineNumber(int line) +{ + yyset_lineno(line, mHandle); +} + +void Tokenizer::lex(Token* token) +{ + token->type = yylex(&token->text, &token->location, mHandle); + if (token->text.size() > kMaxTokenLength) + { + mContext.diagnostics->report(Diagnostics::TOKEN_TOO_LONG, + token->location, token->text); + token->text.erase(kMaxTokenLength); + } + + token->flags = 0; + + token->setAtStartOfLine(mContext.lineStart); + mContext.lineStart = token->type == '\n'; + + token->setHasLeadingSpace(mContext.leadingSpace); + mContext.leadingSpace = false; +} + +bool Tokenizer::initScanner() +{ + if ((mHandle == NULL) && yylex_init_extra(&mContext, &mHandle)) + return false; + + yyrestart(0, mHandle); + return true; +} + +void Tokenizer::destroyScanner() +{ + if (mHandle == NULL) + return; + + yylex_destroy(mHandle); + mHandle = NULL; +} + +} // namespace pp + diff --git a/src/3rdparty/angle/src/compiler/preprocessor/atom.c b/src/3rdparty/angle/src/compiler/preprocessor/atom.c deleted file mode 100644 index 39158d2fa1..0000000000 --- a/src/3rdparty/angle/src/compiler/preprocessor/atom.c +++ /dev/null @@ -1,737 +0,0 @@ -/****************************************************************************\ -Copyright (c) 2002, NVIDIA Corporation. - -NVIDIA Corporation("NVIDIA") supplies this software to you in -consideration of your agreement to the following terms, and your use, -installation, modification or redistribution of this NVIDIA software -constitutes acceptance of these terms. If you do not agree with these -terms, please do not use, install, modify or redistribute this NVIDIA -software. - -In consideration of your agreement to abide by the following terms, and -subject to these terms, NVIDIA grants you a personal, non-exclusive -license, under NVIDIA's copyrights in this original NVIDIA software (the -"NVIDIA Software"), to use, reproduce, modify and redistribute the -NVIDIA Software, with or without modifications, in source and/or binary -forms; provided that if you redistribute the NVIDIA Software, you must -retain the copyright notice of NVIDIA, this notice and the following -text and disclaimers in all such redistributions of the NVIDIA Software. -Neither the name, trademarks, service marks nor logos of NVIDIA -Corporation may be used to endorse or promote products derived from the -NVIDIA Software without specific prior written permission from NVIDIA. -Except as expressly stated in this notice, no other rights or licenses -express or implied, are granted by NVIDIA herein, including but not -limited to any patent rights that may be infringed by your derivative -works or by other works in which the NVIDIA Software may be -incorporated. No hardware is licensed hereunder. - -THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT -WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, -INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, -NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR -ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER -PRODUCTS. - -IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, -INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF -USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY -OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE -NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, -TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF -NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -\****************************************************************************/ - -// -// atom.c -// - -#include -#include -#include - -#include "common/angleutils.h" -#include "compiler/debug.h" -#include "compiler/preprocessor/slglobals.h" - -#undef malloc -#undef realloc -#undef free - -/////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////// String table: ////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////// - -static const struct { - int val; - const char *str; -} tokens[] = { - { CPP_AND_OP, "&&" }, - { CPP_AND_ASSIGN, "&=" }, - { CPP_SUB_ASSIGN, "-=" }, - { CPP_MOD_ASSIGN, "%=" }, - { CPP_ADD_ASSIGN, "+=" }, - { CPP_DIV_ASSIGN, "/=" }, - { CPP_MUL_ASSIGN, "*=" }, - { CPP_RIGHT_BRACKET, ":>" }, - { CPP_EQ_OP, "==" }, - { CPP_XOR_OP, "^^" }, - { CPP_XOR_ASSIGN, "^=" }, - { CPP_FLOATCONSTANT, "" }, - { CPP_GE_OP, ">=" }, - { CPP_RIGHT_OP, ">>" }, - { CPP_RIGHT_ASSIGN, ">>=" }, - { CPP_IDENTIFIER, "" }, - { CPP_INTCONSTANT, "" }, - { CPP_LE_OP, "<=" }, - { CPP_LEFT_OP, "<<" }, - { CPP_LEFT_ASSIGN, "<<=" }, - { CPP_LEFT_BRACKET, "<:" }, - { CPP_LEFT_BRACE, "<%" }, - { CPP_DEC_OP, "--" }, - { CPP_RIGHT_BRACE, "%>" }, - { CPP_NE_OP, "!=" }, - { CPP_OR_OP, "||" }, - { CPP_OR_ASSIGN, "|=" }, - { CPP_INC_OP, "++" }, - { CPP_STRCONSTANT, "" }, - { CPP_TYPEIDENTIFIER, "" }, -}; - -/////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////// String table: ////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////// - -#define INIT_STRING_TABLE_SIZE 16384 - -typedef struct StringTable_Rec { - char *strings; - int nextFree; - int size; -} StringTable; - -/* - * InitStringTable() - Initialize the string table. - * - */ - -static int InitStringTable(StringTable *stable) -{ - stable->strings = (char *) malloc(INIT_STRING_TABLE_SIZE); - if (!stable->strings) - return 0; - // Zero-th offset means "empty" so don't use it. - stable->nextFree = 1; - stable->size = INIT_STRING_TABLE_SIZE; - return 1; -} // InitStringTable - -/* - * FreeStringTable() - Free the string table. - * - */ - -static void FreeStringTable(StringTable *stable) -{ - if (stable->strings) - free(stable->strings); - stable->strings = NULL; - stable->nextFree = 0; - stable->size = 0; -} // FreeStringTable - -/* - * HashString() - Hash a string with the base hash function. - * - */ - -static int HashString(const char *s) -{ - int hval = 0; - - while (*s) { - hval = (hval*13507 + *s*197) ^ (hval >> 2); - s++; - } - return hval & 0x7fffffff; -} // HashString - -/* - * HashString2() - Hash a string with the incrimenting hash function. - * - */ - -static int HashString2(const char *s) -{ - int hval = 0; - - while (*s) { - hval = (hval*729 + *s*37) ^ (hval >> 1); - s++; - } - return hval; -} // HashString2 - -/* - * AddString() - Add a string to a string table. Return it's offset. - * - */ - -static int AddString(StringTable *stable, const char *s) -{ - int len, loc; - char *str; - - len = (int) strlen(s); - while (stable->nextFree + len + 1 >= stable->size) { - assert(stable->size < 1000000); - str = (char *) malloc(stable->size*2); - memcpy(str, stable->strings, stable->size); - free(stable->strings); - stable->strings = str; - stable->size = stable->size*2; - } - loc = stable->nextFree; - strcpy(&stable->strings[loc], s); - stable->nextFree += len + 1; - return loc; -} // AddString - -/////////////////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////// Hash table: /////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////// - -#define INIT_HASH_TABLE_SIZE 2047 -#define HASH_TABLE_MAX_COLLISIONS 3 - -typedef struct HashEntry_Rec { - int index; // String table offset of string representation - int value; // Atom (symbol) value -} HashEntry; - -typedef struct HashTable_Rec { - HashEntry *entry; - int size; - int entries; - int counts[HASH_TABLE_MAX_COLLISIONS + 1]; -} HashTable; - -/* - * InitHashTable() - Initialize the hash table. - * - */ - -static int InitHashTable(HashTable *htable, int fsize) -{ - int ii; - - htable->entry = (HashEntry *) malloc(sizeof(HashEntry)*fsize); - if (!htable->entry) - return 0; - htable->size = fsize; - for (ii = 0; ii < fsize; ii++) { - htable->entry[ii].index = 0; - htable->entry[ii].value = 0; - } - htable->entries = 0; - for (ii = 0; ii <= HASH_TABLE_MAX_COLLISIONS; ii++) - htable->counts[ii] = 0; - return 1; -} // InitHashTable - -/* - * FreeHashTable() - Free the hash table. - * - */ - -static void FreeHashTable(HashTable *htable) -{ - if (htable->entry) - free(htable->entry); - htable->entry = NULL; - htable->size = 0; - htable->entries = 0; -} // FreeHashTable - -/* - * Empty() - See if a hash table entry is empty. - * - */ - -static int Empty(HashTable *htable, int hashloc) -{ - assert(hashloc >= 0 && hashloc < htable->size); - if (htable->entry[hashloc].index == 0) { - return 1; - } else { - return 0; - } -} // Empty - -/* - * Match() - See if a hash table entry is matches a string. - * - */ - -static int Match(HashTable *htable, StringTable *stable, const char *s, int hashloc) -{ - int strloc; - - strloc = htable->entry[hashloc].index; - if (!strcmp(s, &stable->strings[strloc])) { - return 1; - } else { - return 0; - } -} // Match - -/////////////////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////// Atom table: /////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////// - -#define INIT_ATOM_TABLE_SIZE 1024 - - -struct AtomTable_Rec { - StringTable stable; // String table. - HashTable htable; // Hashes string to atom number and token value. Multiple strings can - // have the same token value but each unique string is a unique atom. - int *amap; // Maps atom value to offset in string table. Atoms all map to unique - // strings except for some undefined values in the lower, fixed part - // of the atom table that map to "". The lowest 256 atoms - // correspond to single character ASCII values except for alphanumeric - // characters and '_', which can be other tokens. Next come the - // language tokens with their atom values equal to the token value. - // Then come predefined atoms, followed by user specified identifiers. - int *arev; // Reversed atom for symbol table use. - int nextFree; - int size; -}; - -static AtomTable latable = { { NULL, 0, 0 }, { NULL, 0, 0, {0} }, NULL, NULL, 0, 0 }; -AtomTable *atable = &latable; - -static int AddAtomFixed(AtomTable *atable, const char *s, int atom); - -/* - * GrowAtomTable() - Grow the atom table to at least "size" if it's smaller. - * - */ - -static int GrowAtomTable(AtomTable *atable, int size) -{ - int *newmap, *newrev; - - if (atable->size < size) { - if (atable->amap) { - newmap = realloc(atable->amap, sizeof(int)*size); - newrev = realloc(atable->arev, sizeof(int)*size); - } else { - newmap = malloc(sizeof(int)*size); - newrev = malloc(sizeof(int)*size); - atable->size = 0; - } - if (!newmap || !newrev) { - /* failed to grow -- error */ - if (newmap) - atable->amap = newmap; - if (newrev) - atable->arev = newrev; - return -1; - } - memset(&newmap[atable->size], 0, (size - atable->size) * sizeof(int)); - memset(&newrev[atable->size], 0, (size - atable->size) * sizeof(int)); - atable->amap = newmap; - atable->arev = newrev; - atable->size = size; - } - return 0; -} // GrowAtomTable - -/* - * lReverse() - Reverse the bottom 20 bits of a 32 bit int. - * - */ - -static int lReverse(int fval) -{ - unsigned int in = fval; - int result = 0, cnt = 0; - - while(in) { - result <<= 1; - result |= in&1; - in >>= 1; - cnt++; - } - - // Don't use all 31 bits. One million atoms is plenty and sometimes the - // upper bits are used for other things. - - if (cnt < 20) - result <<= 20 - cnt; - return result; -} // lReverse - -/* - * AllocateAtom() - Allocate a new atom. Associated with the "undefined" value of -1. - * - */ - -static int AllocateAtom(AtomTable *atable) -{ - if (atable->nextFree >= atable->size) - GrowAtomTable(atable, atable->nextFree*2); - atable->amap[atable->nextFree] = -1; - atable->arev[atable->nextFree] = lReverse(atable->nextFree); - atable->nextFree++; - return atable->nextFree - 1; -} // AllocateAtom - -/* - * SetAtomValue() - Allocate a new atom associated with "hashindex". - * - */ - -static void SetAtomValue(AtomTable *atable, int atomnumber, int hashindex) -{ - atable->amap[atomnumber] = atable->htable.entry[hashindex].index; - atable->htable.entry[hashindex].value = atomnumber; -} // SetAtomValue - -/* - * FindHashLoc() - Find the hash location for this string. Return -1 it hash table is full. - * - */ - -static int FindHashLoc(AtomTable *atable, const char *s) -{ - int hashloc, hashdelta, count; - int FoundEmptySlot = 0; - int collision[HASH_TABLE_MAX_COLLISIONS + 1]; - - hashloc = HashString(s) % atable->htable.size; - if (!Empty(&atable->htable, hashloc)) { - if (Match(&atable->htable, &atable->stable, s, hashloc)) - return hashloc; - collision[0] = hashloc; - hashdelta = HashString2(s); - count = 0; - while (count < HASH_TABLE_MAX_COLLISIONS) { - hashloc = ((hashloc + hashdelta) & 0x7fffffff) % atable->htable.size; - if (!Empty(&atable->htable, hashloc)) { - if (Match(&atable->htable, &atable->stable, s, hashloc)) { - return hashloc; - } - } else { - FoundEmptySlot = 1; - break; - } - count++; - collision[count] = hashloc; - } - - if (!FoundEmptySlot) { - if (cpp->options.DumpAtomTable) { - int ii; - char str[200]; - snprintf(str, sizeof(str), "*** Hash failed with more than %d collisions. Must increase hash table size. ***", - HASH_TABLE_MAX_COLLISIONS); - CPPShInfoLogMsg(str); - - snprintf(str, sizeof(str), "*** New string \"%s\", hash=%04x, delta=%04x", s, collision[0], hashdelta); - CPPShInfoLogMsg(str); - for (ii = 0; ii <= HASH_TABLE_MAX_COLLISIONS; ii++) { - snprintf(str, sizeof(str), "*** Collides on try %d at hash entry %04x with \"%s\"", - ii + 1, collision[ii], GetAtomString(atable, atable->htable.entry[collision[ii]].value)); - CPPShInfoLogMsg(str); - } - } - return -1; - } else { - atable->htable.counts[count]++; - } - } - return hashloc; -} // FindHashLoc - -/* - * IncreaseHashTableSize() - * - */ - -static int IncreaseHashTableSize(AtomTable *atable) -{ - int ii, strloc, oldhashloc, value, size; - AtomTable oldtable; - char *s; - - // Save the old atom table and create a new one: - - oldtable = *atable; - size = oldtable.htable.size*2 + 1; - if (!InitAtomTable(atable, size)) - return 0; - - // Add all the existing values to the new atom table preserving their atom values: - - for (ii = atable->nextFree; ii < oldtable.nextFree; ii++) { - strloc = oldtable.amap[ii]; - s = &oldtable.stable.strings[strloc]; - oldhashloc = FindHashLoc(&oldtable, s); - assert(oldhashloc >= 0); - value = oldtable.htable.entry[oldhashloc].value; - AddAtomFixed(atable, s, value); - } - FreeAtomTable(&oldtable); - return 1; -} // IncreaseHashTableSize - -/* - * LookUpAddStringHash() - Lookup a string in the hash table. If it's not there, add it and - * initialize the atom value in the hash table to 0. Return the hash table index. - */ - -static int LookUpAddStringHash(AtomTable *atable, const char *s) -{ - int hashloc, strloc; - - while(1) { - hashloc = FindHashLoc(atable, s); - if (hashloc >= 0) - break; - IncreaseHashTableSize(atable); - } - - if (Empty(&atable->htable, hashloc)) { - atable->htable.entries++; - strloc = AddString(&atable->stable, s); - atable->htable.entry[hashloc].index = strloc; - atable->htable.entry[hashloc].value = 0; - } - return hashloc; -} // LookUpAddStringHash - -/* - * LookUpAddString() - Lookup a string in the hash table. If it's not there, add it and - * initialize the atom value in the hash table to the next atom number. - * Return the atom value of string. - */ - -int LookUpAddString(AtomTable *atable, const char *s) -{ - int hashindex, atom; - - hashindex = LookUpAddStringHash(atable, s); - atom = atable->htable.entry[hashindex].value; - if (atom == 0) { - atom = AllocateAtom(atable); - SetAtomValue(atable, atom, hashindex); - } - return atom; -} // LookUpAddString - -/* - * GetAtomString() - * - */ - -const char *GetAtomString(AtomTable *atable, int atom) -{ - int soffset; - - if (atom > 0 && atom < atable->nextFree) { - soffset = atable->amap[atom]; - if (soffset > 0 && soffset < atable->stable.nextFree) { - return &atable->stable.strings[soffset]; - } else { - return ""; - } - } else { - if (atom == 0) { - return ""; - } else { - if (atom == EOF) { - return ""; - } else { - return ""; - } - } - } -} // GetAtomString - -/* - * GetReversedAtom() - * - */ - -int GetReversedAtom(AtomTable *atable, int atom) -{ - if (atom > 0 && atom < atable->nextFree) { - return atable->arev[atom]; - } else { - return 0; - } -} // GetReversedAtom - -/* - * AddAtom() - Add a string to the atom, hash and string tables if it isn't already there. - * Return it's atom index. - */ - -int AddAtom(AtomTable *atable, const char *s) -{ - int atom; - - atom = LookUpAddString(atable, s); - return atom; -} // AddAtom - -/* - * AddAtomFixed() - Add an atom to the hash and string tables if it isn't already there. - * Assign it the atom value of "atom". - */ - -static int AddAtomFixed(AtomTable *atable, const char *s, int atom) -{ - int hashindex, lsize; - - hashindex = LookUpAddStringHash(atable, s); - if (atable->nextFree >= atable->size || atom >= atable->size) { - lsize = atable->size*2; - if (lsize <= atom) - lsize = atom + 1; - GrowAtomTable(atable, lsize); - } - atable->amap[atom] = atable->htable.entry[hashindex].index; - atable->htable.entry[hashindex].value = atom; - //if (atom >= atable->nextFree) - // atable->nextFree = atom + 1; - while (atom >= atable->nextFree) { - atable->arev[atable->nextFree] = lReverse(atable->nextFree); - atable->nextFree++; - } - return atom; -} // AddAtomFixed - -/* - * InitAtomTable() - Initialize the atom table. - * - */ - -int InitAtomTable(AtomTable *atable, int htsize) -{ - unsigned int ii; - - htsize = htsize <= 0 ? INIT_HASH_TABLE_SIZE : htsize; - if (!InitStringTable(&atable->stable)) - return 0; - if (!InitHashTable(&atable->htable, htsize)) - return 0; - - atable->nextFree = 0; - atable->amap = NULL; - atable->size = 0; - GrowAtomTable(atable, INIT_ATOM_TABLE_SIZE); - if (!atable->amap) - return 0; - - // Initialize lower part of atom table to "" atom: - - AddAtomFixed(atable, "", 0); - for (ii = 0; ii < FIRST_USER_TOKEN_SY; ii++) - atable->amap[ii] = atable->amap[0]; - - // Add single character tokens to the atom table: - - { - const char *s = "~!%^&*()-+=|,.<>/?;:[]{}#"; - char t[2]; - - t[1] = '\0'; - while (*s) { - t[0] = *s; - AddAtomFixed(atable, t, s[0]); - s++; - } - } - - // Add multiple character scanner tokens : - - for (ii = 0; ii < sizeof(tokens)/sizeof(tokens[0]); ii++) - AddAtomFixed(atable, tokens[ii].str, tokens[ii].val); - - // Add error symbol if running in error mode: - - if (cpp->options.ErrorMode) - AddAtomFixed(atable, "error", ERROR_SY); - - AddAtom(atable, "<*** end fixed atoms ***>"); - - return 1; -} // InitAtomTable - -/////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////// Debug Printing Functions: ////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////// - -/* - * PrintAtomTable() - * - */ - -void PrintAtomTable(AtomTable *atable) -{ - int ii; - char str[200]; - - for (ii = 0; ii < atable->nextFree; ii++) { - snprintf(str, sizeof(str), "%d: \"%s\"", ii, &atable->stable.strings[atable->amap[ii]]); - CPPDebugLogMsg(str); - } - snprintf(str, sizeof(str), "Hash table: size=%d, entries=%d, collisions=", - atable->htable.size, atable->htable.entries); - CPPDebugLogMsg(str); - for (ii = 0; ii < HASH_TABLE_MAX_COLLISIONS; ii++) { - snprintf(str, sizeof(str), " %d", atable->htable.counts[ii]); - CPPDebugLogMsg(str); - } - -} // PrintAtomTable - - -/* - * GetStringOfAtom() - * - */ - -char* GetStringOfAtom(AtomTable *atable, int atom) -{ - char* chr_str; - chr_str=&atable->stable.strings[atable->amap[atom]]; - return chr_str; -} // GetStringOfAtom - -/* - * FreeAtomTable() - Free the atom table and associated memory - * - */ - -void FreeAtomTable(AtomTable *atable) -{ - FreeStringTable(&atable->stable); - FreeHashTable(&atable->htable); - if (atable->amap) - free(atable->amap); - if (atable->arev) - free(atable->arev); - atable->amap = NULL; - atable->arev = NULL; - atable->nextFree = 0; - atable->size = 0; -} // FreeAtomTable - -/////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////// End of atom.c /////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////// - diff --git a/src/3rdparty/angle/src/compiler/preprocessor/atom.h b/src/3rdparty/angle/src/compiler/preprocessor/atom.h deleted file mode 100644 index 1d84c32515..0000000000 --- a/src/3rdparty/angle/src/compiler/preprocessor/atom.h +++ /dev/null @@ -1,63 +0,0 @@ -/****************************************************************************\ -Copyright (c) 2002, NVIDIA Corporation. - -NVIDIA Corporation("NVIDIA") supplies this software to you in -consideration of your agreement to the following terms, and your use, -installation, modification or redistribution of this NVIDIA software -constitutes acceptance of these terms. If you do not agree with these -terms, please do not use, install, modify or redistribute this NVIDIA -software. - -In consideration of your agreement to abide by the following terms, and -subject to these terms, NVIDIA grants you a personal, non-exclusive -license, under NVIDIA's copyrights in this original NVIDIA software (the -"NVIDIA Software"), to use, reproduce, modify and redistribute the -NVIDIA Software, with or without modifications, in source and/or binary -forms; provided that if you redistribute the NVIDIA Software, you must -retain the copyright notice of NVIDIA, this notice and the following -text and disclaimers in all such redistributions of the NVIDIA Software. -Neither the name, trademarks, service marks nor logos of NVIDIA -Corporation may be used to endorse or promote products derived from the -NVIDIA Software without specific prior written permission from NVIDIA. -Except as expressly stated in this notice, no other rights or licenses -express or implied, are granted by NVIDIA herein, including but not -limited to any patent rights that may be infringed by your derivative -works or by other works in which the NVIDIA Software may be -incorporated. No hardware is licensed hereunder. - -THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT -WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, -INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, -NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR -ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER -PRODUCTS. - -IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, -INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF -USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY -OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE -NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, -TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF -NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -\****************************************************************************/ -// -// atom.h -// - -#if !defined(__ATOM_H) -#define __ATOM_H 1 - -typedef struct AtomTable_Rec AtomTable; - -extern AtomTable *atable; - -int InitAtomTable(AtomTable *atable, int htsize); -void FreeAtomTable(AtomTable *atable); -int AddAtom(AtomTable *atable, const char *s); -void PrintAtomTable(AtomTable *atable); -int LookUpAddString(AtomTable *atable, const char *s); -const char *GetAtomString(AtomTable *atable, int atom); -int GetReversedAtom(AtomTable *atable, int atom); -char* GetStringOfAtom(AtomTable *atable, int atom); -#endif // !defined(__ATOM_H) diff --git a/src/3rdparty/angle/src/compiler/preprocessor/compile.h b/src/3rdparty/angle/src/compiler/preprocessor/compile.h deleted file mode 100644 index 11808531cc..0000000000 --- a/src/3rdparty/angle/src/compiler/preprocessor/compile.h +++ /dev/null @@ -1,100 +0,0 @@ -/****************************************************************************\ -Copyright (c) 2002, NVIDIA Corporation. - -NVIDIA Corporation("NVIDIA") supplies this software to you in -consideration of your agreement to the following terms, and your use, -installation, modification or redistribution of this NVIDIA software -constitutes acceptance of these terms. If you do not agree with these -terms, please do not use, install, modify or redistribute this NVIDIA -software. - -In consideration of your agreement to abide by the following terms, and -subject to these terms, NVIDIA grants you a personal, non-exclusive -license, under NVIDIA's copyrights in this original NVIDIA software (the -"NVIDIA Software"), to use, reproduce, modify and redistribute the -NVIDIA Software, with or without modifications, in source and/or binary -forms; provided that if you redistribute the NVIDIA Software, you must -retain the copyright notice of NVIDIA, this notice and the following -text and disclaimers in all such redistributions of the NVIDIA Software. -Neither the name, trademarks, service marks nor logos of NVIDIA -Corporation may be used to endorse or promote products derived from the -NVIDIA Software without specific prior written permission from NVIDIA. -Except as expressly stated in this notice, no other rights or licenses -express or implied, are granted by NVIDIA herein, including but not -limited to any patent rights that may be infringed by your derivative -works or by other works in which the NVIDIA Software may be -incorporated. No hardware is licensed hereunder. - -THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT -WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, -INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, -NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR -ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER -PRODUCTS. - -IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, -INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF -USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY -OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE -NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, -TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF -NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -\****************************************************************************/ -// -// compile.h -// - -#if !defined(__COMPILE_H) -#define __COMPILE_H 1 - -int InitCPPStruct(void); - -typedef struct Options_Rec{ - const char *profileString; - int ErrorMode; - int Quiet; - - // Debug The Compiler options: - int DumpAtomTable; -} Options; - -#define MAX_IF_NESTING 64 -struct CPPStruct_Rec { - // Public members - SourceLoc *pLastSourceLoc; // Set at the start of each statement by the tree walkers - Options options; // Compile options and parameters - - // Private members - SourceLoc lastSourceLoc; - - // Scanner data: - - SourceLoc *tokenLoc; // Source location of most recent token seen by the scanner - int mostRecentToken; // Most recent token seen by the scanner - InputSrc *currentInput; - int previous_token; - int pastFirstStatement; // used to make sure that #version is the first statement seen in the file, if present - - void *pC; // storing the parseContext of the compile object in cpp. - - // Private members: - SourceLoc ltokenLoc; - int ifdepth; //current #if-#else-#endif nesting in the cpp.c file (pre-processor) - int elsedepth[MAX_IF_NESTING];//Keep a track of #if depth..Max allowed is 64. - int elsetracker; //#if-#else and #endif constructs...Counter. - const char *ErrMsg; - int CompileError; //Indicate compile error when #error, #else,#elif mismatch. - - // - // Globals used to communicate between PaParseStrings() and yy_input()and - // also across the files.(gen_glslang.cpp and scanner.c) - // - int PaWhichStr; // which string we're parsing - const int* PaStrLen; // array of lengths of the PaArgv strings - int PaArgc; // count of strings in the array - const char* const* PaArgv; // our array of strings to parse - unsigned int tokensBeforeEOF : 1; -}; - -#endif // !defined(__COMPILE_H) diff --git a/src/3rdparty/angle/src/compiler/preprocessor/cpp.c b/src/3rdparty/angle/src/compiler/preprocessor/cpp.c deleted file mode 100644 index 8a1076b9df..0000000000 --- a/src/3rdparty/angle/src/compiler/preprocessor/cpp.c +++ /dev/null @@ -1,1118 +0,0 @@ -/****************************************************************************\ -Copyright (c) 2002, NVIDIA Corporation. - -NVIDIA Corporation("NVIDIA") supplies this software to you in -consideration of your agreement to the following terms, and your use, -installation, modification or redistribution of this NVIDIA software -constitutes acceptance of these terms. If you do not agree with these -terms, please do not use, install, modify or redistribute this NVIDIA -software. - -In consideration of your agreement to abide by the following terms, and -subject to these terms, NVIDIA grants you a personal, non-exclusive -license, under NVIDIA's copyrights in this original NVIDIA software (the -"NVIDIA Software"), to use, reproduce, modify and redistribute the -NVIDIA Software, with or without modifications, in source and/or binary -forms; provided that if you redistribute the NVIDIA Software, you must -retain the copyright notice of NVIDIA, this notice and the following -text and disclaimers in all such redistributions of the NVIDIA Software. -Neither the name, trademarks, service marks nor logos of NVIDIA -Corporation may be used to endorse or promote products derived from the -NVIDIA Software without specific prior written permission from NVIDIA. -Except as expressly stated in this notice, no other rights or licenses -express or implied, are granted by NVIDIA herein, including but not -limited to any patent rights that may be infringed by your derivative -works or by other works in which the NVIDIA Software may be -incorporated. No hardware is licensed hereunder. - -THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT -WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, -INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, -NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR -ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER -PRODUCTS. - -IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, -INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF -USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY -OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE -NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, -TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF -NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -\****************************************************************************/ -// -// cpp.c -// - -#include -#include -#include -#include -#include - -#include "common/angleutils.h" -#include "compiler/preprocessor/slglobals.h" - -#if defined(_MSC_VER) -#pragma warning(disable: 4054) -#pragma warning(disable: 4152) -#pragma warning(disable: 4706) -#endif - -static int CPPif(yystypepp * yylvalpp); - -/* Don't use memory.c's replacements, as we clean up properly here */ -#undef malloc -#undef free - -static int bindAtom = 0; -static int constAtom = 0; -static int defaultAtom = 0; -static int defineAtom = 0; -static int definedAtom = 0; -static int elseAtom = 0; -static int elifAtom = 0; -static int endifAtom = 0; -static int ifAtom = 0; -static int ifdefAtom = 0; -static int ifndefAtom = 0; -static int includeAtom = 0; -static int lineAtom = 0; -static int pragmaAtom = 0; -static int texunitAtom = 0; -static int undefAtom = 0; -static int errorAtom = 0; -static int __LINE__Atom = 0; -static int __FILE__Atom = 0; -static int __VERSION__Atom = 0; -static int versionAtom = 0; -static int extensionAtom = 0; - -static Scope *macros = 0; -#define MAX_MACRO_ARGS 64 - -static SourceLoc ifloc; /* outermost #if */ - -int InitCPP(void) -{ - char buffer[64], *t; - const char *f; - - // Add various atoms needed by the CPP line scanner: - bindAtom = LookUpAddString(atable, "bind"); - constAtom = LookUpAddString(atable, "const"); - defaultAtom = LookUpAddString(atable, "default"); - defineAtom = LookUpAddString(atable, "define"); - definedAtom = LookUpAddString(atable, "defined"); - elifAtom = LookUpAddString(atable, "elif"); - elseAtom = LookUpAddString(atable, "else"); - endifAtom = LookUpAddString(atable, "endif"); - ifAtom = LookUpAddString(atable, "if"); - ifdefAtom = LookUpAddString(atable, "ifdef"); - ifndefAtom = LookUpAddString(atable, "ifndef"); - includeAtom = LookUpAddString(atable, "include"); - lineAtom = LookUpAddString(atable, "line"); - pragmaAtom = LookUpAddString(atable, "pragma"); - texunitAtom = LookUpAddString(atable, "texunit"); - undefAtom = LookUpAddString(atable, "undef"); - errorAtom = LookUpAddString(atable, "error"); - __LINE__Atom = LookUpAddString(atable, "__LINE__"); - __FILE__Atom = LookUpAddString(atable, "__FILE__"); - __VERSION__Atom = LookUpAddString(atable, "__VERSION__"); - versionAtom = LookUpAddString(atable, "version"); - extensionAtom = LookUpAddString(atable, "extension"); - macros = NewScopeInPool(mem_CreatePool(0, 0)); - strcpy(buffer, "PROFILE_"); - t = buffer + strlen(buffer); - f = cpp->options.profileString; - while ((isalnum(*f) || *f == '_') && t < buffer + sizeof(buffer) - 1) - *t++ = toupper(*f++); - *t = 0; - - PredefineIntMacro("GL_ES", 1); - PredefineIntMacro("GL_FRAGMENT_PRECISION_HIGH", 1); - - return 1; -} // InitCPP - -int FreeCPP(void) -{ - if (macros) - { - mem_FreePool(macros->pool); - macros = 0; - } - - return 1; -} - -int FinalCPP(void) -{ - if (cpp->ifdepth) - CPPErrorToInfoLog("#if mismatch"); - return 1; -} - -static int CPPdefine(yystypepp * yylvalpp) -{ - int token, name, args[MAX_MACRO_ARGS], argc; - const char *message; - MacroSymbol mac; - Symbol *symb; - SourceLoc dummyLoc; - memset(&mac, 0, sizeof(mac)); - token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); - if (token != CPP_IDENTIFIER) { - CPPErrorToInfoLog("#define"); - return token; - } - name = yylvalpp->sc_ident; - token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); - if (token == '(' && !yylvalpp->sc_int) { - // gather arguments - argc = 0; - do { - token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); - if (argc == 0 && token == ')') break; - if (token != CPP_IDENTIFIER) { - CPPErrorToInfoLog("#define"); - return token; - } - if (argc < MAX_MACRO_ARGS) - args[argc++] = yylvalpp->sc_ident; - token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); - } while (token == ','); - if (token != ')') { - CPPErrorToInfoLog("#define"); - return token; - } - mac.argc = argc; - mac.args = mem_Alloc(macros->pool, argc * sizeof(int)); - memcpy(mac.args, args, argc * sizeof(int)); - token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); - } - mac.body = NewTokenStream(GetAtomString(atable, name), macros->pool); - while (token != '\n') { - if (token == '\\') { - CPPErrorToInfoLog("The line continuation character (\\) is not part of the OpenGL ES Shading Language"); - return token; - } else if (token <= 0) { // EOF or error - CPPErrorToInfoLog("unexpected end of input in #define preprocessor directive - expected a newline"); - return 0; - } - RecordToken(mac.body, token, yylvalpp); - token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); - }; - - symb = LookUpSymbol(macros, name); - if (symb) { - if (!symb->details.mac.undef) { - // already defined -- need to make sure they are identical - if (symb->details.mac.argc != mac.argc) goto error; - for (argc=0; argc < mac.argc; argc++) - if (symb->details.mac.args[argc] != mac.args[argc]) - goto error; - RewindTokenStream(symb->details.mac.body); - RewindTokenStream(mac.body); - do { - int old_lval, old_token; - old_token = ReadToken(symb->details.mac.body, yylvalpp); - old_lval = yylvalpp->sc_int; - token = ReadToken(mac.body, yylvalpp); - if (token != old_token || yylvalpp->sc_int != old_lval) { - error: - StoreStr("Macro Redefined"); - StoreStr(GetStringOfAtom(atable,name)); - message=GetStrfromTStr(); - DecLineNumber(); - CPPShInfoLogMsg(message); - IncLineNumber(); - ResetTString(); - break; } - } while (token > 0); - } - //FreeMacro(&symb->details.mac); - } else { - dummyLoc.file = 0; - dummyLoc.line = 0; - symb = AddSymbol(&dummyLoc, macros, name, MACRO_S); - } - symb->details.mac = mac; - return '\n'; -} // CPPdefine - -static int CPPundef(yystypepp * yylvalpp) -{ - int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); - Symbol *symb; - if(token == '\n'){ - CPPErrorToInfoLog("#undef"); - return token; - } - if (token != CPP_IDENTIFIER) - goto error; - symb = LookUpSymbol(macros, yylvalpp->sc_ident); - if (symb) { - symb->details.mac.undef = 1; - } - token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); - if (token != '\n') { - error: - CPPErrorToInfoLog("#undef"); - } - return token; -} // CPPundef - -/* CPPelse -- skip forward to appropriate spot. This is actually used -** to skip to and #endif after seeing an #else, AND to skip to a #else, -** #elif, or #endif after a #if/#ifdef/#ifndef/#elif test was false -*/ - -static int CPPelse(int matchelse, yystypepp * yylvalpp) -{ - int atom,depth=0; - int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); - - while (token > 0) { - if (token != '#') { - while (token != '\n') { - token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); - if (token <= 0) { // EOF or error - CPPErrorToInfoLog("unexpected end of input in #else preprocessor directive - expected a newline"); - return 0; - } - } - token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); - continue; - } - if ((token = cpp->currentInput->scan(cpp->currentInput, yylvalpp)) != CPP_IDENTIFIER) - continue; - atom = yylvalpp->sc_ident; - if (atom == ifAtom || atom == ifdefAtom || atom == ifndefAtom){ - depth++; cpp->ifdepth++; cpp->elsetracker++; - if (cpp->ifdepth > MAX_IF_NESTING) { - CPPErrorToInfoLog("max #if nesting depth exceeded"); - cpp->CompileError = 1; - return 0; - } - // sanity check elsetracker - if (cpp->elsetracker < 0 || cpp->elsetracker >= MAX_IF_NESTING) { - CPPErrorToInfoLog("mismatched #if/#endif statements"); - cpp->CompileError = 1; - return 0; - } - cpp->elsedepth[cpp->elsetracker] = 0; - } - else if (atom == endifAtom) { - if(--depth<0){ - if (cpp->elsetracker) - --cpp->elsetracker; - if (cpp->ifdepth) - --cpp->ifdepth; - break; - } - --cpp->elsetracker; - --cpp->ifdepth; - } - else if (((int)(matchelse) != 0)&& depth==0) { - if (atom == elseAtom ) { - token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); - if (token != '\n') { - CPPWarningToInfoLog("unexpected tokens following #else preprocessor directive - expected a newline"); - while (token != '\n') { - token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); - if (token <= 0) { // EOF or error - CPPErrorToInfoLog("unexpected end of input following #else preprocessor directive - expected a newline"); - return 0; - } - } - } - break; - } - else if (atom == elifAtom) { - /* we decrement cpp->ifdepth here, because CPPif will increment - * it and we really want to leave it alone */ - if (cpp->ifdepth){ - --cpp->ifdepth; - --cpp->elsetracker; - } - return CPPif(yylvalpp); - } - } - else if((atom==elseAtom) && (!ChkCorrectElseNesting())){ - CPPErrorToInfoLog("#else after a #else"); - cpp->CompileError=1; - return 0; - } - }; - return token; -} - -enum eval_prec { - MIN_PREC, - COND, LOGOR, LOGAND, OR, XOR, AND, EQUAL, RELATION, SHIFT, ADD, MUL, UNARY, - MAX_PREC -}; - -static int op_logor(int a, int b) { return a || b; } -static int op_logand(int a, int b) { return a && b; } -static int op_or(int a, int b) { return a | b; } -static int op_xor(int a, int b) { return a ^ b; } -static int op_and(int a, int b) { return a & b; } -static int op_eq(int a, int b) { return a == b; } -static int op_ne(int a, int b) { return a != b; } -static int op_ge(int a, int b) { return a >= b; } -static int op_le(int a, int b) { return a <= b; } -static int op_gt(int a, int b) { return a > b; } -static int op_lt(int a, int b) { return a < b; } -static int op_shl(int a, int b) { return a << b; } -static int op_shr(int a, int b) { return a >> b; } -static int op_add(int a, int b) { return a + b; } -static int op_sub(int a, int b) { return a - b; } -static int op_mul(int a, int b) { return a * b; } -static int op_div(int a, int b) { return a / b; } -static int op_mod(int a, int b) { return a % b; } -static int op_pos(int a) { return a; } -static int op_neg(int a) { return -a; } -static int op_cmpl(int a) { return ~a; } -static int op_not(int a) { return !a; } - -struct { - int token, prec, (*op)(int, int); -} binop[] = { - { CPP_OR_OP, LOGOR, op_logor }, - { CPP_AND_OP, LOGAND, op_logand }, - { '|', OR, op_or }, - { '^', XOR, op_xor }, - { '&', AND, op_and }, - { CPP_EQ_OP, EQUAL, op_eq }, - { CPP_NE_OP, EQUAL, op_ne }, - { '>', RELATION, op_gt }, - { CPP_GE_OP, RELATION, op_ge }, - { '<', RELATION, op_lt }, - { CPP_LE_OP, RELATION, op_le }, - { CPP_LEFT_OP, SHIFT, op_shl }, - { CPP_RIGHT_OP, SHIFT, op_shr }, - { '+', ADD, op_add }, - { '-', ADD, op_sub }, - { '*', MUL, op_mul }, - { '/', MUL, op_div }, - { '%', MUL, op_mod }, -}; - -struct { - int token, (*op)(int); -} unop[] = { - { '+', op_pos }, - { '-', op_neg }, - { '~', op_cmpl }, - { '!', op_not }, -}; - -#define ALEN(A) (sizeof(A)/sizeof(A[0])) - -static int eval(int token, int prec, int *res, int *err, yystypepp * yylvalpp) -{ - int i, val; - Symbol *s; - if (token == CPP_IDENTIFIER) { - if (yylvalpp->sc_ident == definedAtom) { - int needclose = 0; - token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); - if (token == '(') { - needclose = 1; - token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); - } - if (token != CPP_IDENTIFIER) - goto error; - *res = (s = LookUpSymbol(macros, yylvalpp->sc_ident)) - ? !s->details.mac.undef : 0; - token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); - if (needclose) { - if (token != ')') - goto error; - token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); - } - } else if (MacroExpand(yylvalpp->sc_ident, yylvalpp)) { - token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); - return eval(token, prec, res, err, yylvalpp); - } else { - goto error; - } - } else if (token == CPP_INTCONSTANT) { - *res = yylvalpp->sc_int; - token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); - } else if (token == '(') { - token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); - token = eval(token, MIN_PREC, res, err, yylvalpp); - if (!*err) { - if (token != ')') - goto error; - token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); - } - } else { - for (i = ALEN(unop) - 1; i >= 0; i--) { - if (unop[i].token == token) - break; - } - if (i >= 0) { - token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); - token = eval(token, UNARY, res, err, yylvalpp); - *res = unop[i].op(*res); - } else { - goto error; - } - } - while (!*err) { - if (token == ')' || token == '\n') break; - for (i = ALEN(binop) - 1; i >= 0; i--) { - if (binop[i].token == token) - break; - } - if (i < 0 || binop[i].prec <= prec) - break; - val = *res; - token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); - token = eval(token, binop[i].prec, res, err, yylvalpp); - - if (binop[i].op == op_div || binop[i].op == op_mod) - { - if (*res == 0) - { - CPPErrorToInfoLog("preprocessor divide or modulo by zero"); - *err = 1; - return token; - } - } - - *res = binop[i].op(val, *res); - } - return token; -error: - CPPErrorToInfoLog("incorrect preprocessor directive"); - *err = 1; - *res = 0; - return token; -} // eval - -static int CPPif(yystypepp * yylvalpp) { - int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); - int res = 0, err = 0; - - if (!cpp->ifdepth++) - ifloc = *cpp->tokenLoc; - if(cpp->ifdepth > MAX_IF_NESTING){ - CPPErrorToInfoLog("max #if nesting depth exceeded"); - cpp->CompileError = 1; - return 0; - } - cpp->elsetracker++; - // sanity check elsetracker - if (cpp->elsetracker < 0 || cpp->elsetracker >= MAX_IF_NESTING) { - CPPErrorToInfoLog("mismatched #if/#endif statements"); - cpp->CompileError = 1; - return 0; - } - cpp->elsedepth[cpp->elsetracker] = 0; - - token = eval(token, MIN_PREC, &res, &err, yylvalpp); - if (token != '\n') { - CPPWarningToInfoLog("unexpected tokens following #if preprocessor directive - expected a newline"); - while (token != '\n') { - token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); - if (token <= 0) { // EOF or error - CPPErrorToInfoLog("unexpected end of input in #if preprocessor directive - expected a newline"); - return 0; - } - } - } - if (!res && !err) { - token = CPPelse(1, yylvalpp); - } - - return token; -} // CPPif - -static int CPPifdef(int defined, yystypepp * yylvalpp) -{ - int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); - int name = yylvalpp->sc_ident; - if(++cpp->ifdepth > MAX_IF_NESTING){ - CPPErrorToInfoLog("max #if nesting depth exceeded"); - cpp->CompileError = 1; - return 0; - } - cpp->elsetracker++; - // sanity check elsetracker - if (cpp->elsetracker < 0 || cpp->elsetracker >= MAX_IF_NESTING) { - CPPErrorToInfoLog("mismatched #if/#endif statements"); - cpp->CompileError = 1; - return 0; - } - cpp->elsedepth[cpp->elsetracker] = 0; - - if (token != CPP_IDENTIFIER) { - defined ? CPPErrorToInfoLog("ifdef"):CPPErrorToInfoLog("ifndef"); - } else { - Symbol *s = LookUpSymbol(macros, name); - token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); - if (token != '\n') { - CPPWarningToInfoLog("unexpected tokens following #ifdef preprocessor directive - expected a newline"); - while (token != '\n') { - token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); - if (token <= 0) { // EOF or error - CPPErrorToInfoLog("unexpected end of input in #ifdef preprocessor directive - expected a newline"); - return 0; - } - } - } - if (((s && !s->details.mac.undef) ? 1 : 0) != defined) - token = CPPelse(1, yylvalpp); - } - return token; -} // CPPifdef - -static int CPPline(yystypepp * yylvalpp) -{ - int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); - if(token=='\n'){ - DecLineNumber(); - CPPErrorToInfoLog("#line"); - IncLineNumber(); - return token; - } - else if (token == CPP_INTCONSTANT) { - yylvalpp->sc_int=atoi(yylvalpp->symbol_name); - SetLineNumber(yylvalpp->sc_int); - token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); - - if (token == CPP_INTCONSTANT) { - yylvalpp->sc_int=atoi(yylvalpp->symbol_name); - SetStringNumber(yylvalpp->sc_int); - token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); - if(token!='\n') - CPPErrorToInfoLog("#line"); - } - else if (token == '\n'){ - return token; - } - else{ - CPPErrorToInfoLog("#line"); - } - } - else{ - CPPErrorToInfoLog("#line"); - } - return token; -} - -static int CPPerror(yystypepp * yylvalpp) { - - int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); - const char *message; - - while (token != '\n') { - if (token <= 0){ - CPPErrorToInfoLog("unexpected end of input in #error preprocessor directive - expected a newline"); - return 0; - }else if (token == CPP_FLOATCONSTANT || token == CPP_INTCONSTANT){ - StoreStr(yylvalpp->symbol_name); - }else if(token == CPP_IDENTIFIER || token == CPP_STRCONSTANT){ - StoreStr(GetStringOfAtom(atable,yylvalpp->sc_ident)); - }else { - StoreStr(GetStringOfAtom(atable,token)); - } - token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); - } - DecLineNumber(); - //store this msg into the shader's information log..set the Compile Error flag!!!! - message=GetStrfromTStr(); - CPPShInfoLogMsg(message); - ResetTString(); - cpp->CompileError=1; - IncLineNumber(); - return '\n'; -}//CPPerror - -static int CPPpragma(yystypepp * yylvalpp) -{ - char SrcStrName[2]; - char** allTokens; - int tokenCount = 0; - int maxTokenCount = 10; - const char* SrcStr; - int i; - - int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); - - if (token=='\n') { - DecLineNumber(); - CPPErrorToInfoLog("#pragma"); - IncLineNumber(); - return token; - } - - allTokens = (char**)malloc(sizeof(char*) * maxTokenCount); - - while (token != '\n') { - if (tokenCount >= maxTokenCount) { - maxTokenCount *= 2; - allTokens = (char**)realloc((char**)allTokens, sizeof(char*) * maxTokenCount); - } - switch (token) { - case CPP_IDENTIFIER: - SrcStr = GetAtomString(atable, yylvalpp->sc_ident); - allTokens[tokenCount] = (char*)malloc(strlen(SrcStr) + 1); - strcpy(allTokens[tokenCount++], SrcStr); - break; - case CPP_INTCONSTANT: - SrcStr = yylvalpp->symbol_name; - allTokens[tokenCount] = (char*)malloc(strlen(SrcStr) + 1); - strcpy(allTokens[tokenCount++], SrcStr); - break; - case CPP_FLOATCONSTANT: - SrcStr = yylvalpp->symbol_name; - allTokens[tokenCount] = (char*)malloc(strlen(SrcStr) + 1); - strcpy(allTokens[tokenCount++], SrcStr); - break; - case -1: - // EOF - CPPShInfoLogMsg("#pragma directive must end with a newline"); - goto freeMemoryAndReturnToken; - default: - SrcStrName[0] = token; - SrcStrName[1] = '\0'; - allTokens[tokenCount] = (char*)malloc(2); - strcpy(allTokens[tokenCount++], SrcStrName); - } - token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); - } - - HandlePragma((const char**)allTokens, tokenCount); - -freeMemoryAndReturnToken: - for (i = 0; i < tokenCount; ++i) { - free (allTokens[i]); - } - free (allTokens); - - return token; -} // CPPpragma - -#define ESSL_VERSION_NUMBER 100 -#define ESSL_VERSION_STRING "100" - -static int CPPversion(yystypepp * yylvalpp) -{ - - int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); - - if (cpp->pastFirstStatement == 1) - CPPShInfoLogMsg("#version must occur before any other statement in the program"); - - if(token=='\n'){ - DecLineNumber(); - CPPErrorToInfoLog("#version"); - IncLineNumber(); - return token; - } - if (token != CPP_INTCONSTANT) - CPPErrorToInfoLog("#version"); - - yylvalpp->sc_int=atoi(yylvalpp->symbol_name); - //SetVersionNumber(yylvalpp->sc_int); - - if (yylvalpp->sc_int != ESSL_VERSION_NUMBER) - CPPShInfoLogMsg("Version number not supported by ESSL"); - - token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); - - if (token == '\n'){ - return token; - } - else{ - CPPErrorToInfoLog("#version"); - } - return token; -} // CPPversion - -static int CPPextension(yystypepp * yylvalpp) -{ - - int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); - char extensionName[MAX_SYMBOL_NAME_LEN + 1]; - - if(token=='\n'){ - DecLineNumber(); - CPPShInfoLogMsg("extension name not specified"); - IncLineNumber(); - return token; - } - - if (token != CPP_IDENTIFIER) - CPPErrorToInfoLog("#extension"); - - strncpy(extensionName, GetAtomString(atable, yylvalpp->sc_ident), MAX_SYMBOL_NAME_LEN); - extensionName[MAX_SYMBOL_NAME_LEN] = '\0'; - - token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); - if (token != ':') { - CPPShInfoLogMsg("':' missing after extension name"); - return token; - } - - token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); - if (token != CPP_IDENTIFIER) { - CPPShInfoLogMsg("behavior for extension not specified"); - return token; - } - - updateExtensionBehavior(extensionName, GetAtomString(atable, yylvalpp->sc_ident)); - - token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); - if (token == '\n'){ - return token; - } - else{ - CPPErrorToInfoLog("#extension"); - } - return token; -} // CPPextension - -int readCPPline(yystypepp * yylvalpp) -{ - int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); - const char *message; - - if (token == CPP_IDENTIFIER) { - if (yylvalpp->sc_ident == defineAtom) { - token = CPPdefine(yylvalpp); - } else if (yylvalpp->sc_ident == elseAtom) { - if(ChkCorrectElseNesting()){ - if (!cpp->ifdepth ){ - CPPErrorToInfoLog("#else mismatch"); - cpp->CompileError=1; - return 0; - } - token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); - if (token != '\n') { - CPPWarningToInfoLog("unexpected tokens following #else preprocessor directive - expected a newline"); - while (token != '\n') { - token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); - if (token <= 0) { // EOF or error - CPPErrorToInfoLog("unexpected end of input in #ifdef preprocessor directive - expected a newline"); - return 0; - } - } - } - token = CPPelse(0, yylvalpp); - }else{ - CPPErrorToInfoLog("#else after a #else"); - cpp->ifdepth = 0; - cpp->elsetracker = 0; - cpp->pastFirstStatement = 1; - cpp->CompileError = 1; - return 0; - } - } else if (yylvalpp->sc_ident == elifAtom) { - if (!cpp->ifdepth){ - CPPErrorToInfoLog("#elif mismatch"); - cpp->CompileError=1; - return 0; - } - // this token is really a dont care, but we still need to eat the tokens - token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); - while (token != '\n') { - token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); - if (token <= 0) { // EOF or error - CPPErrorToInfoLog("unexpect tokens following #elif preprocessor directive - expected a newline"); - cpp->CompileError = 1; - return 0; - } - } - token = CPPelse(0, yylvalpp); - } else if (yylvalpp->sc_ident == endifAtom) { - if (!cpp->ifdepth){ - CPPErrorToInfoLog("#endif mismatch"); - cpp->CompileError=1; - return 0; - } - else - --cpp->ifdepth; - - if (cpp->elsetracker) - --cpp->elsetracker; - - } else if (yylvalpp->sc_ident == ifAtom) { - token = CPPif(yylvalpp); - } else if (yylvalpp->sc_ident == ifdefAtom) { - token = CPPifdef(1, yylvalpp); - } else if (yylvalpp->sc_ident == ifndefAtom) { - token = CPPifdef(0, yylvalpp); - } else if (yylvalpp->sc_ident == lineAtom) { - token = CPPline(yylvalpp); - } else if (yylvalpp->sc_ident == pragmaAtom) { - token = CPPpragma(yylvalpp); - } else if (yylvalpp->sc_ident == undefAtom) { - token = CPPundef(yylvalpp); - } else if (yylvalpp->sc_ident == errorAtom) { - token = CPPerror(yylvalpp); - } else if (yylvalpp->sc_ident == versionAtom) { - token = CPPversion(yylvalpp); - } else if (yylvalpp->sc_ident == extensionAtom) { - token = CPPextension(yylvalpp); - } else { - StoreStr("Invalid Directive"); - StoreStr(GetStringOfAtom(atable,yylvalpp->sc_ident)); - message=GetStrfromTStr(); - CPPShInfoLogMsg(message); - ResetTString(); - } - } - while (token != '\n' && token != 0 && token != EOF) { - token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); - } - - cpp->pastFirstStatement = 1; - - return token; -} // readCPPline - -void FreeMacro(MacroSymbol *s) { - DeleteTokenStream(s->body); -} - -void PredefineIntMacro(const char *name, int value) { - SourceLoc location = {0, 0}; - Symbol *symbol = NULL; - MacroSymbol macro = {0, NULL, NULL, 0, 0}; - yystypepp val = {0, 0.0, 0, {0}}; - int atom = 0; - - macro.body = NewTokenStream(name, macros->pool); - val.sc_int = value; - snprintf(val.symbol_name, MAX_SYMBOL_NAME_LEN+1, "%d", value); - RecordToken(macro.body, CPP_INTCONSTANT, &val); - atom = LookUpAddString(atable, name); - symbol = AddSymbol(&location, macros, atom, MACRO_S); - symbol->details.mac = macro; -} - -static int eof_scan(InputSrc *in, yystypepp * yylvalpp) { return -1; } -static void noop(InputSrc *in, int ch, yystypepp * yylvalpp) { } - -static void PushEofSrc() { - InputSrc *in = malloc(sizeof(InputSrc)); - memset(in, 0, sizeof(InputSrc)); - in->scan = eof_scan; - in->getch = eof_scan; - in->ungetch = noop; - in->prev = cpp->currentInput; - cpp->currentInput = in; -} - -static void PopEofSrc() { - if (cpp->currentInput->scan == eof_scan) { - InputSrc *in = cpp->currentInput; - cpp->currentInput = in->prev; - free(in); - } -} - -static TokenStream *PrescanMacroArg(TokenStream *a, yystypepp * yylvalpp) { - int token; - TokenStream *n; - RewindTokenStream(a); - do { - token = ReadToken(a, yylvalpp); - if (token == CPP_IDENTIFIER && LookUpSymbol(macros, yylvalpp->sc_ident)) - break; - } while (token > 0); - if (token <= 0) return a; - n = NewTokenStream("macro arg", 0); - PushEofSrc(); - ReadFromTokenStream(a, 0, 0); - while ((token = cpp->currentInput->scan(cpp->currentInput, yylvalpp)) > 0) { - if (token == CPP_IDENTIFIER && MacroExpand(yylvalpp->sc_ident, yylvalpp)) - continue; - RecordToken(n, token, yylvalpp); - } - PopEofSrc(); - DeleteTokenStream(a); - return n; -} // PrescanMacroArg - -typedef struct MacroInputSrc { - InputSrc base; - MacroSymbol *mac; - TokenStream **args; -} MacroInputSrc; - -/* macro_scan --- -** return the next token for a macro expanion, handling macro args -*/ -static int macro_scan(MacroInputSrc *in, yystypepp * yylvalpp) { - int i; - int token = ReadToken(in->mac->body, yylvalpp); - if (token == CPP_IDENTIFIER) { - for (i = in->mac->argc-1; i>=0; i--) - if (in->mac->args[i] == yylvalpp->sc_ident) break; - if (i >= 0) { - ReadFromTokenStream(in->args[i], yylvalpp->sc_ident, 0); - return cpp->currentInput->scan(cpp->currentInput, yylvalpp); - } - } - if (token > 0) return token; - in->mac->busy = 0; - cpp->currentInput = in->base.prev; - if (in->args) { - for (i=in->mac->argc-1; i>=0; i--) - DeleteTokenStream(in->args[i]); - free(in->args); - } - free(in); - return cpp->currentInput->scan(cpp->currentInput, yylvalpp); -} // macro_scan - -/* MacroExpand -** check an identifier (atom) to see if it a macro that should be expanded. -** If it is, push an InputSrc that will produce the appropriate expansion -** and return TRUE. If not, return FALSE. -*/ - -int MacroExpand(int atom, yystypepp * yylvalpp) -{ - Symbol *sym = LookUpSymbol(macros, atom); - MacroInputSrc *in; - int i,j, token, depth=0; - const char *message; - if (atom == __LINE__Atom) { - yylvalpp->sc_int = GetLineNumber(); - snprintf(yylvalpp->symbol_name, MAX_SYMBOL_NAME_LEN+1, "%d", yylvalpp->sc_int); - UngetToken(CPP_INTCONSTANT, yylvalpp); - return 1; - } - if (atom == __FILE__Atom) { - yylvalpp->sc_int = GetStringNumber(); - snprintf(yylvalpp->symbol_name, MAX_SYMBOL_NAME_LEN+1, "%d", yylvalpp->sc_int); - UngetToken(CPP_INTCONSTANT, yylvalpp); - return 1; - } - if (atom == __VERSION__Atom) { - strcpy(yylvalpp->symbol_name,ESSL_VERSION_STRING); - yylvalpp->sc_int = atoi(yylvalpp->symbol_name); - UngetToken(CPP_INTCONSTANT, yylvalpp); - return 1; - } - if (!sym || sym->details.mac.undef) return 0; - if (sym->details.mac.busy) return 0; // no recursive expansions - in = malloc(sizeof(*in)); - memset(in, 0, sizeof(*in)); - in->base.scan = (void *)macro_scan; - in->base.line = cpp->currentInput->line; - in->base.name = cpp->currentInput->name; - in->mac = &sym->details.mac; - if (sym->details.mac.args) { - token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); - if (token != '(') { - UngetToken(token, yylvalpp); - yylvalpp->sc_ident = atom; - return 0; - } - in->args = malloc(in->mac->argc * sizeof(TokenStream *)); - for (i=0; imac->argc; i++) - in->args[i] = NewTokenStream("macro arg", 0); - i=0;j=0; - do{ - depth = 0; - while(1) { - token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); - if (token <= 0) { - StoreStr("EOF in Macro "); - StoreStr(GetStringOfAtom(atable,atom)); - message=GetStrfromTStr(); - CPPShInfoLogMsg(message); - ResetTString(); - return 1; - } - if((in->mac->argc==0) && (token!=')')) break; - if (depth == 0 && (token == ',' || token == ')')) break; - if (token == '(') depth++; - if (token == ')') depth--; - RecordToken(in->args[i], token, yylvalpp); - j=1; - } - if (token == ')') { - if((in->mac->argc==1) &&j==0) - break; - i++; - break; - } - i++; - }while(i < in->mac->argc); - - if (i < in->mac->argc) { - StoreStr("Too few args in Macro "); - StoreStr(GetStringOfAtom(atable,atom)); - message=GetStrfromTStr(); - CPPShInfoLogMsg(message); - ResetTString(); - } else if (token != ')') { - depth=0; - while (token >= 0 && (depth > 0 || token != ')')) { - if (token == ')') depth--; - token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); - if (token == '(') depth++; - } - - if (token <= 0) { - StoreStr("EOF in Macro "); - StoreStr(GetStringOfAtom(atable,atom)); - message=GetStrfromTStr(); - CPPShInfoLogMsg(message); - ResetTString(); - return 1; - } - StoreStr("Too many args in Macro "); - StoreStr(GetStringOfAtom(atable,atom)); - message=GetStrfromTStr(); - CPPShInfoLogMsg(message); - ResetTString(); - } - for (i=0; imac->argc; i++) { - in->args[i] = PrescanMacroArg(in->args[i], yylvalpp); - } - } -#if 0 - printf(" <%s:%d>found macro %s\n", GetAtomString(atable, loc.file), - loc.line, GetAtomString(atable, atom)); - for (i=0; imac->argc; i++) { - printf("\targ %s = '", GetAtomString(atable, in->mac->args[i])); - DumpTokenStream(stdout, in->args[i]); - printf("'\n"); - } -#endif - /*retain the input source*/ - in->base.prev = cpp->currentInput; - sym->details.mac.busy = 1; - RewindTokenStream(sym->details.mac.body); - cpp->currentInput = &in->base; - return 1; -} // MacroExpand - -int ChkCorrectElseNesting(void) -{ - // sanity check to make sure elsetracker is in a valid range - if (cpp->elsetracker < 0 || cpp->elsetracker >= MAX_IF_NESTING) { - return 0; - } - - if (cpp->elsedepth[cpp->elsetracker] == 0) { - cpp->elsedepth[cpp->elsetracker] = 1; - return 1; - } - return 0; -} - - diff --git a/src/3rdparty/angle/src/compiler/preprocessor/cpp.h b/src/3rdparty/angle/src/compiler/preprocessor/cpp.h deleted file mode 100644 index 802e23ef07..0000000000 --- a/src/3rdparty/angle/src/compiler/preprocessor/cpp.h +++ /dev/null @@ -1,86 +0,0 @@ -/****************************************************************************\ -Copyright (c) 2002, NVIDIA Corporation. - -NVIDIA Corporation("NVIDIA") supplies this software to you in -consideration of your agreement to the following terms, and your use, -installation, modification or redistribution of this NVIDIA software -constitutes acceptance of these terms. If you do not agree with these -terms, please do not use, install, modify or redistribute this NVIDIA -software. - -In consideration of your agreement to abide by the following terms, and -subject to these terms, NVIDIA grants you a personal, non-exclusive -license, under NVIDIA's copyrights in this original NVIDIA software (the -"NVIDIA Software"), to use, reproduce, modify and redistribute the -NVIDIA Software, with or without modifications, in source and/or binary -forms; provided that if you redistribute the NVIDIA Software, you must -retain the copyright notice of NVIDIA, this notice and the following -text and disclaimers in all such redistributions of the NVIDIA Software. -Neither the name, trademarks, service marks nor logos of NVIDIA -Corporation may be used to endorse or promote products derived from the -NVIDIA Software without specific prior written permission from NVIDIA. -Except as expressly stated in this notice, no other rights or licenses -express or implied, are granted by NVIDIA herein, including but not -limited to any patent rights that may be infringed by your derivative -works or by other works in which the NVIDIA Software may be -incorporated. No hardware is licensed hereunder. - -THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT -WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, -INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, -NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR -ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER -PRODUCTS. - -IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, -INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF -USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY -OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE -NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, -TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF -NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -\****************************************************************************/ -// -// cpp.h -// - -#if !defined(__CPP_H) -#define __CPP_H 1 - -#include "compiler/preprocessor/parser.h" -#include "compiler/preprocessor/tokens.h" - -int InitCPP(void); -int FinalCPP(void); -int readCPPline(yystypepp * yylvalpp); -int MacroExpand(int atom, yystypepp * yylvalpp); -int ChkCorrectElseNesting(void); - -typedef struct MacroSymbol { - int argc; - int *args; - TokenStream *body; - unsigned busy:1; - unsigned undef:1; -} MacroSymbol; - -void FreeMacro(MacroSymbol *); -void PredefineIntMacro(const char *name, int value); - -void CPPDebugLogMsg(const char *msg); // Prints information into debug log -void CPPShInfoLogMsg(const char*); // Store cpp Err Msg into Sh.Info.Log -void CPPWarningToInfoLog(const char *msg); // Prints warning messages into info log -void HandlePragma(const char**, int numTokens); // #pragma directive container. -void ResetTString(void); // #error Message as TString. -void CPPErrorToInfoLog(const char*); // Stick all cpp errors into Sh.Info.log. -void StoreStr(const char*); // Store the TString in Parse Context. -void SetLineNumber(int); // Set line number. -void SetStringNumber(int); // Set string number. -int GetLineNumber(void); // Get the current String Number. -int GetStringNumber(void); // Get the current String Number. -const char* GetStrfromTStr(void); // Convert TString to String. -void updateExtensionBehavior(const char* extName, const char* behavior); -int FreeCPP(void); - -#endif // !(defined(__CPP_H) diff --git a/src/3rdparty/angle/src/compiler/preprocessor/cppstruct.c b/src/3rdparty/angle/src/compiler/preprocessor/cppstruct.c deleted file mode 100644 index 58cff31091..0000000000 --- a/src/3rdparty/angle/src/compiler/preprocessor/cppstruct.c +++ /dev/null @@ -1,152 +0,0 @@ -/****************************************************************************\ -Copyright (c) 2002, NVIDIA Corporation. - -NVIDIA Corporation("NVIDIA") supplies this software to you in -consideration of your agreement to the following terms, and your use, -installation, modification or redistribution of this NVIDIA software -constitutes acceptance of these terms. If you do not agree with these -terms, please do not use, install, modify or redistribute this NVIDIA -software. - -In consideration of your agreement to abide by the following terms, and -subject to these terms, NVIDIA grants you a personal, non-exclusive -license, under NVIDIA's copyrights in this original NVIDIA software (the -"NVIDIA Software"), to use, reproduce, modify and redistribute the -NVIDIA Software, with or without modifications, in source and/or binary -forms; provided that if you redistribute the NVIDIA Software, you must -retain the copyright notice of NVIDIA, this notice and the following -text and disclaimers in all such redistributions of the NVIDIA Software. -Neither the name, trademarks, service marks nor logos of NVIDIA -Corporation may be used to endorse or promote products derived from the -NVIDIA Software without specific prior written permission from NVIDIA. -Except as expressly stated in this notice, no other rights or licenses -express or implied, are granted by NVIDIA herein, including but not -limited to any patent rights that may be infringed by your derivative -works or by other works in which the NVIDIA Software may be -incorporated. No hardware is licensed hereunder. - -THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT -WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, -INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, -NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR -ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER -PRODUCTS. - -IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, -INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF -USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY -OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE -NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, -TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF -NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -\****************************************************************************/ -// -// cppstruct.c -// - -#include -#include - -#include "compiler/preprocessor/slglobals.h" - -CPPStruct *cpp = NULL; -static int refCount = 0; - -int InitPreprocessor(void); -int ResetPreprocessor(void); -int FreeCPPStruct(void); -int FinalizePreprocessor(void); - -/* - * InitCPPStruct() - Initilaize the CPP structure. - * - */ - -int InitCPPStruct(void) -{ - int len; - char *p; - - cpp = (CPPStruct *) malloc(sizeof(CPPStruct)); - if (cpp == NULL) - return 0; - - refCount++; - - // Initialize public members: - cpp->pLastSourceLoc = &cpp->lastSourceLoc; - - p = (char *) &cpp->options; - len = sizeof(cpp->options); - while (--len >= 0) - p[len] = 0; - - ResetPreprocessor(); - return 1; -} // InitCPPStruct - -int ResetPreprocessor(void) -{ - // Initialize private members: - - cpp->lastSourceLoc.file = 0; - cpp->lastSourceLoc.line = 0; - cpp->pC = 0; - cpp->CompileError = 0; - cpp->ifdepth = 0; - for(cpp->elsetracker = 0; cpp->elsetracker < MAX_IF_NESTING; cpp->elsetracker++) - cpp->elsedepth[cpp->elsetracker] = 0; - cpp->elsetracker = 0; - cpp->tokensBeforeEOF = 0; - return 1; -} - -//Intializing the Preprocessor. - -int InitPreprocessor(void) -{ - # define CPP_STUFF true - # ifdef CPP_STUFF - FreeCPPStruct(); - InitCPPStruct(); - cpp->options.Quiet = 1; - cpp->options.profileString = "generic"; - if (!InitAtomTable(atable, 0)) - return 1; - if (!InitScanner(cpp)) - return 1; - # endif - return 0; -} - -//FreeCPPStruct() - Free the CPP structure. - -int FreeCPPStruct(void) -{ - if (refCount) - { - free(cpp); - refCount--; - } - - return 1; -} - -//Finalizing the Preprocessor. - -int FinalizePreprocessor(void) -{ - # define CPP_STUFF true - # ifdef CPP_STUFF - FreeAtomTable(atable); - FreeCPPStruct(); - FreeScanner(); - # endif - return 0; -} - - -/////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////// End of cppstruct.c ////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/3rdparty/angle/src/compiler/preprocessor/memory.c b/src/3rdparty/angle/src/compiler/preprocessor/memory.c deleted file mode 100644 index 029521a559..0000000000 --- a/src/3rdparty/angle/src/compiler/preprocessor/memory.c +++ /dev/null @@ -1,158 +0,0 @@ -/****************************************************************************\ -Copyright (c) 2002, NVIDIA Corporation. - -NVIDIA Corporation("NVIDIA") supplies this software to you in -consideration of your agreement to the following terms, and your use, -installation, modification or redistribution of this NVIDIA software -constitutes acceptance of these terms. If you do not agree with these -terms, please do not use, install, modify or redistribute this NVIDIA -software. - -In consideration of your agreement to abide by the following terms, and -subject to these terms, NVIDIA grants you a personal, non-exclusive -license, under NVIDIA's copyrights in this original NVIDIA software (the -"NVIDIA Software"), to use, reproduce, modify and redistribute the -NVIDIA Software, with or without modifications, in source and/or binary -forms; provided that if you redistribute the NVIDIA Software, you must -retain the copyright notice of NVIDIA, this notice and the following -text and disclaimers in all such redistributions of the NVIDIA Software. -Neither the name, trademarks, service marks nor logos of NVIDIA -Corporation may be used to endorse or promote products derived from the -NVIDIA Software without specific prior written permission from NVIDIA. -Except as expressly stated in this notice, no other rights or licenses -express or implied, are granted by NVIDIA herein, including but not -limited to any patent rights that may be infringed by your derivative -works or by other works in which the NVIDIA Software may be -incorporated. No hardware is licensed hereunder. - -THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT -WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, -INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, -NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR -ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER -PRODUCTS. - -IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, -INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF -USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY -OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE -NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, -TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF -NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -\****************************************************************************/ -// -#include -#include -#include - -#ifndef _MSC_VER -#include -#endif - -#include "compiler/preprocessor/memory.h" - -#if defined(_MSC_VER) -#pragma warning(disable: 4706) -#endif - -// default alignment and chunksize, if called with 0 arguments -#define CHUNKSIZE (64*1024) -#define ALIGN 8 - -// we need to call the `real' malloc and free, not our replacements -#undef malloc -#undef free - -struct chunk { - struct chunk *next; -}; - -struct cleanup { - struct cleanup *next; - void (*fn)(void *); - void *arg; -}; - -struct MemoryPool_rec { - struct chunk *next; - uintptr_t free, end; - size_t chunksize; - uintptr_t alignmask; - struct cleanup *cleanup; -}; - -MemoryPool *mem_CreatePool(size_t chunksize, unsigned int align) -{ - MemoryPool *pool; - - if (align == 0) align = ALIGN; - if (chunksize == 0) chunksize = CHUNKSIZE; - if (align & (align-1)) return 0; - if (chunksize < sizeof(MemoryPool)) return 0; - if (chunksize & (align-1)) return 0; - if (!(pool = malloc(chunksize))) return 0; - pool->next = 0; - pool->chunksize = chunksize; - pool->alignmask = (uintptr_t)(align)-1; - pool->free = ((uintptr_t)(pool + 1) + pool->alignmask) & ~pool->alignmask; - pool->end = (uintptr_t)pool + chunksize; - pool->cleanup = 0; - return pool; -} - -void mem_FreePool(MemoryPool *pool) -{ - struct cleanup *cleanup; - struct chunk *p, *next; - - for (cleanup = pool->cleanup; cleanup; cleanup = cleanup->next) { - cleanup->fn(cleanup->arg); - } - for (p = (struct chunk *)pool; p; p = next) { - next = p->next; - free(p); - } -} - -void *mem_Alloc(MemoryPool *pool, size_t size) -{ - struct chunk *ch; - void *rv = (void *)pool->free; - size = (size + pool->alignmask) & ~pool->alignmask; - if (size <= 0) size = pool->alignmask; - pool->free += size; - if (pool->free > pool->end || pool->free < (uintptr_t)rv) { - size_t minreq = (size + sizeof(struct chunk) + pool->alignmask) - & ~pool->alignmask; - pool->free = (uintptr_t)rv; - if (minreq >= pool->chunksize) { - // request size is too big for the chunksize, so allocate it as - // a single chunk of the right size - ch = malloc(minreq); - if (!ch) return 0; - } else { - ch = malloc(pool->chunksize); - if (!ch) return 0; - pool->free = (uintptr_t)ch + minreq; - pool->end = (uintptr_t)ch + pool->chunksize; - } - ch->next = pool->next; - pool->next = ch; - rv = (void *)(((uintptr_t)(ch+1) + pool->alignmask) & ~pool->alignmask); - } - return rv; -} - -int mem_AddCleanup(MemoryPool *pool, void (*fn)(void *), void *arg) { - struct cleanup *cleanup; - - pool->free = (pool->free + sizeof(void *) - 1) & ~(sizeof(void *)-1); - cleanup = mem_Alloc(pool, sizeof(struct cleanup)); - if (!cleanup) return -1; - cleanup->next = pool->cleanup; - cleanup->fn = fn; - cleanup->arg = arg; - pool->cleanup = cleanup; - return 0; -} diff --git a/src/3rdparty/angle/src/compiler/preprocessor/memory.h b/src/3rdparty/angle/src/compiler/preprocessor/memory.h deleted file mode 100644 index 5fcadb32f6..0000000000 --- a/src/3rdparty/angle/src/compiler/preprocessor/memory.h +++ /dev/null @@ -1,58 +0,0 @@ -/****************************************************************************\ -Copyright (c) 2002, NVIDIA Corporation. - -NVIDIA Corporation("NVIDIA") supplies this software to you in -consideration of your agreement to the following terms, and your use, -installation, modification or redistribution of this NVIDIA software -constitutes acceptance of these terms. If you do not agree with these -terms, please do not use, install, modify or redistribute this NVIDIA -software. - -In consideration of your agreement to abide by the following terms, and -subject to these terms, NVIDIA grants you a personal, non-exclusive -license, under NVIDIA's copyrights in this original NVIDIA software (the -"NVIDIA Software"), to use, reproduce, modify and redistribute the -NVIDIA Software, with or without modifications, in source and/or binary -forms; provided that if you redistribute the NVIDIA Software, you must -retain the copyright notice of NVIDIA, this notice and the following -text and disclaimers in all such redistributions of the NVIDIA Software. -Neither the name, trademarks, service marks nor logos of NVIDIA -Corporation may be used to endorse or promote products derived from the -NVIDIA Software without specific prior written permission from NVIDIA. -Except as expressly stated in this notice, no other rights or licenses -express or implied, are granted by NVIDIA herein, including but not -limited to any patent rights that may be infringed by your derivative -works or by other works in which the NVIDIA Software may be -incorporated. No hardware is licensed hereunder. - -THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT -WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, -INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, -NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR -ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER -PRODUCTS. - -IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, -INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF -USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY -OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE -NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, -TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF -NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -\****************************************************************************/ -// -#ifndef __MEMORY_H -#define __MEMORY_H - -#include - -typedef struct MemoryPool_rec MemoryPool; - -extern MemoryPool *mem_CreatePool(size_t chunksize, unsigned int align); -extern void mem_FreePool(MemoryPool *); -extern void *mem_Alloc(MemoryPool *p, size_t size); -extern void *mem_Realloc(MemoryPool *p, void *old, size_t oldsize, size_t newsize); -extern int mem_AddCleanup(MemoryPool *p, void (*fn)(void *), void *arg); - -#endif /* __MEMORY_H */ diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/Diagnostics.cpp b/src/3rdparty/angle/src/compiler/preprocessor/new/Diagnostics.cpp deleted file mode 100644 index 3f50dfc98a..0000000000 --- a/src/3rdparty/angle/src/compiler/preprocessor/new/Diagnostics.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 "Diagnostics.h" - -#include - -namespace pp -{ - -Diagnostics::~Diagnostics() -{ -} - -void Diagnostics::report(ID id, - const SourceLocation& loc, - const std::string& text) -{ - // TODO(alokp): Keep a count of errors and warnings. - print(id, loc, text); -} - -Diagnostics::Severity Diagnostics::severity(ID id) -{ - if ((id > ERROR_BEGIN) && (id < ERROR_END)) - return ERROR; - - if ((id > WARNING_BEGIN) && (id < WARNING_END)) - return WARNING; - - assert(false); - return ERROR; -} - -std::string Diagnostics::message(ID id) -{ - switch (id) - { - // Errors begin. - case INTERNAL_ERROR: - return "internal error"; - case OUT_OF_MEMORY: - return "out of memory"; - case INVALID_CHARACTER: - return "invalid character"; - case INVALID_NUMBER: - return "invalid number"; - case INTEGER_OVERFLOW: - return "integer overflow"; - case FLOAT_OVERFLOW: - return "float overflow"; - case TOKEN_TOO_LONG: - return "token too long"; - case INVALID_EXPRESSION: - return "invalid expression"; - case DIVISION_BY_ZERO: - return "division by zero"; - case EOF_IN_COMMENT: - return "unexpected end of file found in comment"; - case UNEXPECTED_TOKEN: - return "unexpected token"; - case DIRECTIVE_INVALID_NAME: - return "invalid directive name"; - case MACRO_NAME_RESERVED: - return "macro name is reserved"; - case MACRO_REDEFINED: - return "macro redefined"; - case MACRO_PREDEFINED_REDEFINED: - return "predefined macro redefined"; - case MACRO_PREDEFINED_UNDEFINED: - return "predefined macro undefined"; - case MACRO_UNTERMINATED_INVOCATION: - return "unterminated macro invocation"; - case MACRO_TOO_FEW_ARGS: - return "Not enough arguments for macro"; - case MACRO_TOO_MANY_ARGS: - return "Too many arguments for macro"; - case CONDITIONAL_ENDIF_WITHOUT_IF: - return "unexpected #endif found without a matching #if"; - case CONDITIONAL_ELSE_WITHOUT_IF: - return "unexpected #else found without a matching #if"; - case CONDITIONAL_ELSE_AFTER_ELSE: - return "unexpected #else found after another #else"; - case CONDITIONAL_ELIF_WITHOUT_IF: - return "unexpected #elif found without a matching #if"; - case CONDITIONAL_ELIF_AFTER_ELSE: - return "unexpected #elif found after #else"; - case CONDITIONAL_UNTERMINATED: - return "unexpected end of file found in conditional block"; - case INVALID_EXTENSION_NAME: - return "invalid extension name"; - case INVALID_EXTENSION_BEHAVIOR: - return "invalid extension behavior"; - case INVALID_EXTENSION_DIRECTIVE: - return "invalid extension directive"; - case INVALID_VERSION_NUMBER: - return "invalid version number"; - case INVALID_VERSION_DIRECTIVE: - return "invalid version directive"; - case VERSION_NOT_FIRST_STATEMENT: - return "#version directive must occur before anything else, " - "except for comments and white space"; - case INVALID_LINE_NUMBER: - return "invalid line number"; - case INVALID_FILE_NUMBER: - return "invalid file number"; - case INVALID_LINE_DIRECTIVE: - return "invalid line directive"; - // Errors end. - // Warnings begin. - case EOF_IN_DIRECTIVE: - return "unexpected end of file found in directive"; - case CONDITIONAL_UNEXPECTED_TOKEN: - return "unexpected token after conditional expression"; - case UNRECOGNIZED_PRAGMA: - return "unrecognized pragma"; - // Warnings end. - default: - assert(false); - return ""; - } -} - -} // namespace pp diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/Diagnostics.h b/src/3rdparty/angle/src/compiler/preprocessor/new/Diagnostics.h deleted file mode 100644 index 07bc411846..0000000000 --- a/src/3rdparty/angle/src/compiler/preprocessor/new/Diagnostics.h +++ /dev/null @@ -1,87 +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_PREPROCESSOR_DIAGNOSTICS_H_ -#define COMPILER_PREPROCESSOR_DIAGNOSTICS_H_ - -#include - -namespace pp -{ - -struct SourceLocation; - -// Base class for reporting diagnostic messages. -// Derived classes are responsible for formatting and printing the messages. -class Diagnostics -{ - public: - enum Severity - { - ERROR, - WARNING - }; - enum ID - { - ERROR_BEGIN, - INTERNAL_ERROR, - OUT_OF_MEMORY, - INVALID_CHARACTER, - INVALID_NUMBER, - INTEGER_OVERFLOW, - FLOAT_OVERFLOW, - TOKEN_TOO_LONG, - INVALID_EXPRESSION, - DIVISION_BY_ZERO, - EOF_IN_COMMENT, - UNEXPECTED_TOKEN, - DIRECTIVE_INVALID_NAME, - MACRO_NAME_RESERVED, - MACRO_REDEFINED, - MACRO_PREDEFINED_REDEFINED, - MACRO_PREDEFINED_UNDEFINED, - MACRO_UNTERMINATED_INVOCATION, - MACRO_TOO_FEW_ARGS, - MACRO_TOO_MANY_ARGS, - CONDITIONAL_ENDIF_WITHOUT_IF, - CONDITIONAL_ELSE_WITHOUT_IF, - CONDITIONAL_ELSE_AFTER_ELSE, - CONDITIONAL_ELIF_WITHOUT_IF, - CONDITIONAL_ELIF_AFTER_ELSE, - CONDITIONAL_UNTERMINATED, - INVALID_EXTENSION_NAME, - INVALID_EXTENSION_BEHAVIOR, - INVALID_EXTENSION_DIRECTIVE, - INVALID_VERSION_NUMBER, - INVALID_VERSION_DIRECTIVE, - VERSION_NOT_FIRST_STATEMENT, - INVALID_LINE_NUMBER, - INVALID_FILE_NUMBER, - INVALID_LINE_DIRECTIVE, - ERROR_END, - - WARNING_BEGIN, - EOF_IN_DIRECTIVE, - CONDITIONAL_UNEXPECTED_TOKEN, - UNRECOGNIZED_PRAGMA, - WARNING_END - }; - - virtual ~Diagnostics(); - - void report(ID id, const SourceLocation& loc, const std::string& text); - - protected: - Severity severity(ID id); - std::string message(ID id); - - virtual void print(ID id, - const SourceLocation& loc, - const std::string& text) = 0; -}; - -} // namespace pp -#endif // COMPILER_PREPROCESSOR_DIAGNOSTICS_H_ diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/DirectiveHandler.cpp b/src/3rdparty/angle/src/compiler/preprocessor/new/DirectiveHandler.cpp deleted file mode 100644 index ca91e1c71b..0000000000 --- a/src/3rdparty/angle/src/compiler/preprocessor/new/DirectiveHandler.cpp +++ /dev/null @@ -1,16 +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 "DirectiveHandler.h" - -namespace pp -{ - -DirectiveHandler::~DirectiveHandler() -{ -} - -} // namespace pp diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/DirectiveHandler.h b/src/3rdparty/angle/src/compiler/preprocessor/new/DirectiveHandler.h deleted file mode 100644 index 2aaeec2818..0000000000 --- a/src/3rdparty/angle/src/compiler/preprocessor/new/DirectiveHandler.h +++ /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. -// - -#ifndef COMPILER_PREPROCESSOR_DIRECTIVE_HANDLER_H_ -#define COMPILER_PREPROCESSOR_DIRECTIVE_HANDLER_H_ - -#include - -namespace pp -{ - -struct SourceLocation; - -// Base class for handling directives. -// Preprocessor uses this class to notify the clients about certain -// preprocessor directives. Derived classes are responsible for -// handling them in an appropriate manner. -class DirectiveHandler -{ - public: - virtual ~DirectiveHandler(); - - virtual void handleError(const SourceLocation& loc, - const std::string& msg) = 0; - - // Handle pragma of form: #pragma name[(value)] - virtual void handlePragma(const SourceLocation& loc, - const std::string& name, - const std::string& value) = 0; - - virtual void handleExtension(const SourceLocation& loc, - const std::string& name, - const std::string& behavior) = 0; - - virtual void handleVersion(const SourceLocation& loc, - int version) = 0; -}; - -} // namespace pp -#endif // COMPILER_PREPROCESSOR_DIRECTIVE_HANDLER_H_ diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/DirectiveParser.cpp b/src/3rdparty/angle/src/compiler/preprocessor/new/DirectiveParser.cpp deleted file mode 100644 index f2e42d06bf..0000000000 --- a/src/3rdparty/angle/src/compiler/preprocessor/new/DirectiveParser.cpp +++ /dev/null @@ -1,932 +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 "DirectiveParser.h" - -#include -#include -#include - -#include "Diagnostics.h" -#include "DirectiveHandler.h" -#include "ExpressionParser.h" -#include "MacroExpander.h" -#include "Token.h" -#include "Tokenizer.h" - -namespace { -enum DirectiveType -{ - DIRECTIVE_NONE, - DIRECTIVE_DEFINE, - DIRECTIVE_UNDEF, - DIRECTIVE_IF, - DIRECTIVE_IFDEF, - DIRECTIVE_IFNDEF, - DIRECTIVE_ELSE, - DIRECTIVE_ELIF, - DIRECTIVE_ENDIF, - DIRECTIVE_ERROR, - DIRECTIVE_PRAGMA, - DIRECTIVE_EXTENSION, - DIRECTIVE_VERSION, - DIRECTIVE_LINE -}; -} // namespace - -static DirectiveType getDirective(const pp::Token* token) -{ - static const std::string kDirectiveDefine("define"); - static const std::string kDirectiveUndef("undef"); - static const std::string kDirectiveIf("if"); - static const std::string kDirectiveIfdef("ifdef"); - static const std::string kDirectiveIfndef("ifndef"); - static const std::string kDirectiveElse("else"); - static const std::string kDirectiveElif("elif"); - static const std::string kDirectiveEndif("endif"); - static const std::string kDirectiveError("error"); - static const std::string kDirectivePragma("pragma"); - static const std::string kDirectiveExtension("extension"); - static const std::string kDirectiveVersion("version"); - static const std::string kDirectiveLine("line"); - - if (token->type != pp::Token::IDENTIFIER) - return DIRECTIVE_NONE; - - if (token->text == kDirectiveDefine) - return DIRECTIVE_DEFINE; - else if (token->text == kDirectiveUndef) - return DIRECTIVE_UNDEF; - else if (token->text == kDirectiveIf) - return DIRECTIVE_IF; - else if (token->text == kDirectiveIfdef) - return DIRECTIVE_IFDEF; - else if (token->text == kDirectiveIfndef) - return DIRECTIVE_IFNDEF; - else if (token->text == kDirectiveElse) - return DIRECTIVE_ELSE; - else if (token->text == kDirectiveElif) - return DIRECTIVE_ELIF; - else if (token->text == kDirectiveEndif) - return DIRECTIVE_ENDIF; - else if (token->text == kDirectiveError) - return DIRECTIVE_ERROR; - else if (token->text == kDirectivePragma) - return DIRECTIVE_PRAGMA; - else if (token->text == kDirectiveExtension) - return DIRECTIVE_EXTENSION; - else if (token->text == kDirectiveVersion) - return DIRECTIVE_VERSION; - else if (token->text == kDirectiveLine) - return DIRECTIVE_LINE; - - return DIRECTIVE_NONE; -} - -static bool isConditionalDirective(DirectiveType directive) -{ - switch (directive) - { - case DIRECTIVE_IF: - case DIRECTIVE_IFDEF: - case DIRECTIVE_IFNDEF: - case DIRECTIVE_ELSE: - case DIRECTIVE_ELIF: - case DIRECTIVE_ENDIF: - return true; - default: - return false; - } -} - -// Returns true if the token represents End Of Directive. -static bool isEOD(const pp::Token* token) -{ - return (token->type == '\n') || (token->type == pp::Token::LAST); -} - -static void skipUntilEOD(pp::Lexer* lexer, pp::Token* token) -{ - while(!isEOD(token)) - { - lexer->lex(token); - } -} - -static bool isMacroNameReserved(const std::string& name) -{ - // Names prefixed with "GL_" are reserved. - if (name.substr(0, 3) == "GL_") - return true; - - // Names containing two consecutive underscores are reserved. - if (name.find("__") != std::string::npos) - return true; - - return false; -} - -static bool isMacroPredefined(const std::string& name, - const pp::MacroSet& macroSet) -{ - pp::MacroSet::const_iterator iter = macroSet.find(name); - return iter != macroSet.end() ? iter->second.predefined : false; -} - -namespace pp -{ - -class DefinedParser : public Lexer -{ - public: - DefinedParser(Lexer* lexer, - const MacroSet* macroSet, - Diagnostics* diagnostics) : - mLexer(lexer), - mMacroSet(macroSet), - mDiagnostics(diagnostics) - { - } - - protected: - virtual void lex(Token* token) - { - static const std::string kDefined("defined"); - - mLexer->lex(token); - if (token->type != Token::IDENTIFIER) - return; - if (token->text != kDefined) - return; - - bool paren = false; - mLexer->lex(token); - if (token->type == '(') - { - paren = true; - mLexer->lex(token); - } - - if (token->type != Token::IDENTIFIER) - { - mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, - token->location, token->text); - skipUntilEOD(mLexer, token); - return; - } - MacroSet::const_iterator iter = mMacroSet->find(token->text); - std::string expression = iter != mMacroSet->end() ? "1" : "0"; - - if (paren) - { - mLexer->lex(token); - if (token->type != ')') - { - mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, - token->location, token->text); - skipUntilEOD(mLexer, token); - return; - } - } - - // We have a valid defined operator. - // Convert the current token into a CONST_INT token. - token->type = Token::CONST_INT; - token->text = expression; - } - - private: - Lexer* mLexer; - const MacroSet* mMacroSet; - Diagnostics* mDiagnostics; -}; - -DirectiveParser::DirectiveParser(Tokenizer* tokenizer, - MacroSet* macroSet, - Diagnostics* diagnostics, - DirectiveHandler* directiveHandler) : - mPastFirstStatement(false), - mTokenizer(tokenizer), - mMacroSet(macroSet), - mDiagnostics(diagnostics), - mDirectiveHandler(directiveHandler) -{ -} - -void DirectiveParser::lex(Token* token) -{ - do - { - mTokenizer->lex(token); - - if (token->type == Token::PP_HASH) - { - parseDirective(token); - mPastFirstStatement = true; - } - - if (token->type == Token::LAST) - { - if (!mConditionalStack.empty()) - { - const ConditionalBlock& block = mConditionalStack.back(); - mDiagnostics->report(Diagnostics::CONDITIONAL_UNTERMINATED, - block.location, block.type); - } - break; - } - - } while (skipping() || (token->type == '\n')); - - mPastFirstStatement = true; -} - -void DirectiveParser::parseDirective(Token* token) -{ - assert(token->type == Token::PP_HASH); - - mTokenizer->lex(token); - if (isEOD(token)) - { - // Empty Directive. - return; - } - - DirectiveType directive = getDirective(token); - - // While in an excluded conditional block/group, - // we only parse conditional directives. - if (skipping() && !isConditionalDirective(directive)) - { - skipUntilEOD(mTokenizer, token); - return; - } - - switch(directive) - { - case DIRECTIVE_NONE: - mDiagnostics->report(Diagnostics::DIRECTIVE_INVALID_NAME, - token->location, token->text); - skipUntilEOD(mTokenizer, token); - break; - case DIRECTIVE_DEFINE: - parseDefine(token); - break; - case DIRECTIVE_UNDEF: - parseUndef(token); - break; - case DIRECTIVE_IF: - parseIf(token); - break; - case DIRECTIVE_IFDEF: - parseIfdef(token); - break; - case DIRECTIVE_IFNDEF: - parseIfndef(token); - break; - case DIRECTIVE_ELSE: - parseElse(token); - break; - case DIRECTIVE_ELIF: - parseElif(token); - break; - case DIRECTIVE_ENDIF: - parseEndif(token); - break; - case DIRECTIVE_ERROR: - parseError(token); - break; - case DIRECTIVE_PRAGMA: - parsePragma(token); - break; - case DIRECTIVE_EXTENSION: - parseExtension(token); - break; - case DIRECTIVE_VERSION: - parseVersion(token); - break; - case DIRECTIVE_LINE: - parseLine(token); - break; - default: - assert(false); - break; - } - - skipUntilEOD(mTokenizer, token); - if (token->type == Token::LAST) - { - mDiagnostics->report(Diagnostics::EOF_IN_DIRECTIVE, - token->location, token->text); - } -} - -void DirectiveParser::parseDefine(Token* token) -{ - assert(getDirective(token) == DIRECTIVE_DEFINE); - - mTokenizer->lex(token); - if (token->type != Token::IDENTIFIER) - { - mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, - token->location, token->text); - return; - } - if (isMacroPredefined(token->text, *mMacroSet)) - { - mDiagnostics->report(Diagnostics::MACRO_PREDEFINED_REDEFINED, - token->location, token->text); - return; - } - if (isMacroNameReserved(token->text)) - { - mDiagnostics->report(Diagnostics::MACRO_NAME_RESERVED, - token->location, token->text); - return; - } - - Macro macro; - macro.type = Macro::kTypeObj; - macro.name = token->text; - - mTokenizer->lex(token); - if (token->type == '(' && !token->hasLeadingSpace()) - { - // Function-like macro. Collect arguments. - macro.type = Macro::kTypeFunc; - do { - mTokenizer->lex(token); - if (token->type != Token::IDENTIFIER) - break; - macro.parameters.push_back(token->text); - - mTokenizer->lex(token); // Get ','. - } while (token->type == ','); - - if (token->type != ')') - { - mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, - token->location, - token->text); - return; - } - mTokenizer->lex(token); // Get ')'. - } - - while ((token->type != '\n') && (token->type != Token::LAST)) - { - // Reset the token location because it is unnecessary in replacement - // list. Resetting it also allows us to reuse Token::equals() to - // compare macros. - token->location = SourceLocation(); - macro.replacements.push_back(*token); - mTokenizer->lex(token); - } - if (!macro.replacements.empty()) - { - // Whitespace preceding the replacement list is not considered part of - // the replacement list for either form of macro. - macro.replacements.front().setHasLeadingSpace(false); - } - - // Check for macro redefinition. - MacroSet::const_iterator iter = mMacroSet->find(macro.name); - if (iter != mMacroSet->end() && !macro.equals(iter->second)) - { - mDiagnostics->report(Diagnostics::MACRO_REDEFINED, - token->location, - macro.name); - return; - } - mMacroSet->insert(std::make_pair(macro.name, macro)); -} - -void DirectiveParser::parseUndef(Token* token) -{ - assert(getDirective(token) == DIRECTIVE_UNDEF); - - mTokenizer->lex(token); - if (token->type != Token::IDENTIFIER) - { - mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, - token->location, token->text); - return; - } - - MacroSet::iterator iter = mMacroSet->find(token->text); - if (iter != mMacroSet->end()) - { - if (iter->second.predefined) - { - mDiagnostics->report(Diagnostics::MACRO_PREDEFINED_UNDEFINED, - token->location, token->text); - } - else - { - mMacroSet->erase(iter); - } - } - - mTokenizer->lex(token); -} - -void DirectiveParser::parseIf(Token* token) -{ - assert(getDirective(token) == DIRECTIVE_IF); - parseConditionalIf(token); -} - -void DirectiveParser::parseIfdef(Token* token) -{ - assert(getDirective(token) == DIRECTIVE_IFDEF); - parseConditionalIf(token); -} - -void DirectiveParser::parseIfndef(Token* token) -{ - assert(getDirective(token) == DIRECTIVE_IFNDEF); - parseConditionalIf(token); -} - -void DirectiveParser::parseElse(Token* token) -{ - assert(getDirective(token) == DIRECTIVE_ELSE); - - if (mConditionalStack.empty()) - { - mDiagnostics->report(Diagnostics::CONDITIONAL_ELSE_WITHOUT_IF, - token->location, token->text); - skipUntilEOD(mTokenizer, token); - return; - } - - ConditionalBlock& block = mConditionalStack.back(); - if (block.skipBlock) - { - // No diagnostics. Just skip the whole line. - skipUntilEOD(mTokenizer, token); - return; - } - if (block.foundElseGroup) - { - mDiagnostics->report(Diagnostics::CONDITIONAL_ELSE_AFTER_ELSE, - token->location, token->text); - skipUntilEOD(mTokenizer, token); - return; - } - - block.foundElseGroup = true; - block.skipGroup = block.foundValidGroup; - block.foundValidGroup = true; - - // Warn if there are extra tokens after #else. - mTokenizer->lex(token); - if (!isEOD(token)) - { - mDiagnostics->report(Diagnostics::CONDITIONAL_UNEXPECTED_TOKEN, - token->location, token->text); - skipUntilEOD(mTokenizer, token); - } -} - -void DirectiveParser::parseElif(Token* token) -{ - assert(getDirective(token) == DIRECTIVE_ELIF); - - if (mConditionalStack.empty()) - { - mDiagnostics->report(Diagnostics::CONDITIONAL_ELIF_WITHOUT_IF, - token->location, token->text); - skipUntilEOD(mTokenizer, token); - return; - } - - ConditionalBlock& block = mConditionalStack.back(); - if (block.skipBlock) - { - // No diagnostics. Just skip the whole line. - skipUntilEOD(mTokenizer, token); - return; - } - if (block.foundElseGroup) - { - mDiagnostics->report(Diagnostics::CONDITIONAL_ELIF_AFTER_ELSE, - token->location, token->text); - skipUntilEOD(mTokenizer, token); - return; - } - if (block.foundValidGroup) - { - // Do not parse the expression. - // Also be careful not to emit a diagnostic. - block.skipGroup = true; - skipUntilEOD(mTokenizer, token); - return; - } - - int expression = parseExpressionIf(token); - block.skipGroup = expression == 0; - block.foundValidGroup = expression != 0; -} - -void DirectiveParser::parseEndif(Token* token) -{ - assert(getDirective(token) == DIRECTIVE_ENDIF); - - if (mConditionalStack.empty()) - { - mDiagnostics->report(Diagnostics::CONDITIONAL_ENDIF_WITHOUT_IF, - token->location, token->text); - skipUntilEOD(mTokenizer, token); - return; - } - - mConditionalStack.pop_back(); - - // Warn if there are tokens after #endif. - mTokenizer->lex(token); - if (!isEOD(token)) - { - mDiagnostics->report(Diagnostics::CONDITIONAL_UNEXPECTED_TOKEN, - token->location, token->text); - skipUntilEOD(mTokenizer, token); - } -} - -void DirectiveParser::parseError(Token* token) -{ - assert(getDirective(token) == DIRECTIVE_ERROR); - - std::ostringstream stream; - mTokenizer->lex(token); - while ((token->type != '\n') && (token->type != Token::LAST)) - { - stream << *token; - mTokenizer->lex(token); - } - mDirectiveHandler->handleError(token->location, stream.str()); -} - -// Parses pragma of form: #pragma name[(value)]. -void DirectiveParser::parsePragma(Token* token) -{ - assert(getDirective(token) == DIRECTIVE_PRAGMA); - - enum State - { - PRAGMA_NAME, - LEFT_PAREN, - PRAGMA_VALUE, - RIGHT_PAREN - }; - - bool valid = true; - std::string name, value; - int state = PRAGMA_NAME; - - mTokenizer->lex(token); - while ((token->type != '\n') && (token->type != Token::LAST)) - { - switch(state++) - { - case PRAGMA_NAME: - name = token->text; - valid = valid && (token->type == Token::IDENTIFIER); - break; - case LEFT_PAREN: - valid = valid && (token->type == '('); - break; - case PRAGMA_VALUE: - value = token->text; - valid = valid && (token->type == Token::IDENTIFIER); - break; - case RIGHT_PAREN: - valid = valid && (token->type == ')'); - break; - default: - valid = false; - break; - } - mTokenizer->lex(token); - } - - valid = valid && ((state == PRAGMA_NAME) || // Empty pragma. - (state == LEFT_PAREN) || // Without value. - (state == RIGHT_PAREN + 1)); // With value. - if (!valid) - { - mDiagnostics->report(Diagnostics::UNRECOGNIZED_PRAGMA, - token->location, name); - } - else if (state > PRAGMA_NAME) // Do not notify for empty pragma. - { - mDirectiveHandler->handlePragma(token->location, name, value); - } -} - -void DirectiveParser::parseExtension(Token* token) -{ - assert(getDirective(token) == DIRECTIVE_EXTENSION); - - enum State - { - EXT_NAME, - COLON, - EXT_BEHAVIOR - }; - - bool valid = true; - std::string name, behavior; - int state = EXT_NAME; - - mTokenizer->lex(token); - while ((token->type != '\n') && (token->type != Token::LAST)) - { - switch (state++) - { - case EXT_NAME: - if (valid && (token->type != Token::IDENTIFIER)) - { - mDiagnostics->report(Diagnostics::INVALID_EXTENSION_NAME, - token->location, token->text); - valid = false; - } - if (valid) name = token->text; - break; - case COLON: - if (valid && (token->type != ':')) - { - mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, - token->location, token->text); - valid = false; - } - break; - case EXT_BEHAVIOR: - if (valid && (token->type != Token::IDENTIFIER)) - { - mDiagnostics->report(Diagnostics::INVALID_EXTENSION_BEHAVIOR, - token->location, token->text); - valid = false; - } - if (valid) behavior = token->text; - break; - default: - if (valid) - { - mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, - token->location, token->text); - valid = false; - } - break; - } - mTokenizer->lex(token); - } - if (valid && (state != EXT_BEHAVIOR + 1)) - { - mDiagnostics->report(Diagnostics::INVALID_EXTENSION_DIRECTIVE, - token->location, token->text); - valid = false; - } - if (valid) - mDirectiveHandler->handleExtension(token->location, name, behavior); -} - -void DirectiveParser::parseVersion(Token* token) -{ - assert(getDirective(token) == DIRECTIVE_VERSION); - - if (mPastFirstStatement) - { - mDiagnostics->report(Diagnostics::VERSION_NOT_FIRST_STATEMENT, - token->location, token->text); - skipUntilEOD(mTokenizer, token); - return; - } - - enum State - { - VERSION_NUMBER - }; - - bool valid = true; - int version = 0; - int state = VERSION_NUMBER; - - mTokenizer->lex(token); - while ((token->type != '\n') && (token->type != Token::LAST)) - { - switch (state++) - { - case VERSION_NUMBER: - if (valid && (token->type != Token::CONST_INT)) - { - mDiagnostics->report(Diagnostics::INVALID_VERSION_NUMBER, - token->location, token->text); - valid = false; - } - if (valid && !token->iValue(&version)) - { - mDiagnostics->report(Diagnostics::INTEGER_OVERFLOW, - token->location, token->text); - valid = false; - } - break; - default: - if (valid) - { - mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, - token->location, token->text); - valid = false; - } - break; - } - mTokenizer->lex(token); - } - if (valid && (state != VERSION_NUMBER + 1)) - { - mDiagnostics->report(Diagnostics::INVALID_VERSION_DIRECTIVE, - token->location, token->text); - valid = false; - } - if (valid) - mDirectiveHandler->handleVersion(token->location, version); -} - -void DirectiveParser::parseLine(Token* token) -{ - assert(getDirective(token) == DIRECTIVE_LINE); - - enum State - { - LINE_NUMBER, - FILE_NUMBER - }; - - bool valid = true; - int line = 0, file = 0; - int state = LINE_NUMBER; - - MacroExpander macroExpander(mTokenizer, mMacroSet, mDiagnostics); - macroExpander.lex(token); - while ((token->type != '\n') && (token->type != Token::LAST)) - { - switch (state++) - { - case LINE_NUMBER: - if (valid && (token->type != Token::CONST_INT)) - { - mDiagnostics->report(Diagnostics::INVALID_LINE_NUMBER, - token->location, token->text); - valid = false; - } - if (valid && !token->iValue(&line)) - { - mDiagnostics->report(Diagnostics::INTEGER_OVERFLOW, - token->location, token->text); - valid = false; - } - break; - case FILE_NUMBER: - if (valid && (token->type != Token::CONST_INT)) - { - mDiagnostics->report(Diagnostics::INVALID_FILE_NUMBER, - token->location, token->text); - valid = false; - } - if (valid && !token->iValue(&file)) - { - mDiagnostics->report(Diagnostics::INTEGER_OVERFLOW, - token->location, token->text); - valid = false; - } - break; - default: - if (valid) - { - mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, - token->location, token->text); - valid = false; - } - break; - } - macroExpander.lex(token); - } - - if (valid && (state != FILE_NUMBER) && (state != FILE_NUMBER + 1)) - { - mDiagnostics->report(Diagnostics::INVALID_LINE_DIRECTIVE, - token->location, token->text); - valid = false; - } - if (valid) - { - mTokenizer->setLineNumber(line); - if (state == FILE_NUMBER + 1) mTokenizer->setFileNumber(file); - } -} - -bool DirectiveParser::skipping() const -{ - if (mConditionalStack.empty()) return false; - - const ConditionalBlock& block = mConditionalStack.back(); - return block.skipBlock || block.skipGroup; -} - -void DirectiveParser::parseConditionalIf(Token* token) -{ - ConditionalBlock block; - block.type = token->text; - block.location = token->location; - - if (skipping()) - { - // This conditional block is inside another conditional group - // which is skipped. As a consequence this whole block is skipped. - // Be careful not to parse the conditional expression that might - // emit a diagnostic. - skipUntilEOD(mTokenizer, token); - block.skipBlock = true; - } - else - { - DirectiveType directive = getDirective(token); - - int expression = 0; - switch (directive) - { - case DIRECTIVE_IF: - expression = parseExpressionIf(token); - break; - case DIRECTIVE_IFDEF: - expression = parseExpressionIfdef(token); - break; - case DIRECTIVE_IFNDEF: - expression = parseExpressionIfdef(token) == 0 ? 1 : 0; - break; - default: - assert(false); - break; - } - block.skipGroup = expression == 0; - block.foundValidGroup = expression != 0; - } - mConditionalStack.push_back(block); -} - -int DirectiveParser::parseExpressionIf(Token* token) -{ - assert((getDirective(token) == DIRECTIVE_IF) || - (getDirective(token) == DIRECTIVE_ELIF)); - - DefinedParser definedParser(mTokenizer, mMacroSet, mDiagnostics); - MacroExpander macroExpander(&definedParser, mMacroSet, mDiagnostics); - ExpressionParser expressionParser(¯oExpander, mDiagnostics); - - int expression = 0; - macroExpander.lex(token); - expressionParser.parse(token, &expression); - - // Warn if there are tokens after #if expression. - if (!isEOD(token)) - { - mDiagnostics->report(Diagnostics::CONDITIONAL_UNEXPECTED_TOKEN, - token->location, token->text); - skipUntilEOD(mTokenizer, token); - } - - return expression; -} - -int DirectiveParser::parseExpressionIfdef(Token* token) -{ - assert((getDirective(token) == DIRECTIVE_IFDEF) || - (getDirective(token) == DIRECTIVE_IFNDEF)); - - mTokenizer->lex(token); - if (token->type != Token::IDENTIFIER) - { - mDiagnostics->report(Diagnostics::UNEXPECTED_TOKEN, - token->location, token->text); - skipUntilEOD(mTokenizer, token); - return 0; - } - - MacroSet::const_iterator iter = mMacroSet->find(token->text); - int expression = iter != mMacroSet->end() ? 1 : 0; - - // Warn if there are tokens after #ifdef expression. - mTokenizer->lex(token); - if (!isEOD(token)) - { - mDiagnostics->report(Diagnostics::CONDITIONAL_UNEXPECTED_TOKEN, - token->location, token->text); - skipUntilEOD(mTokenizer, token); - } - return expression; -} - -} // namespace pp diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/DirectiveParser.h b/src/3rdparty/angle/src/compiler/preprocessor/new/DirectiveParser.h deleted file mode 100644 index 8a7f0072ba..0000000000 --- a/src/3rdparty/angle/src/compiler/preprocessor/new/DirectiveParser.h +++ /dev/null @@ -1,82 +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_PREPROCESSOR_DIRECTIVE_PARSER_H_ -#define COMPILER_PREPROCESSOR_DIRECTIVE_PARSER_H_ - -#include "Lexer.h" -#include "Macro.h" -#include "pp_utils.h" -#include "SourceLocation.h" - -namespace pp -{ - -class Diagnostics; -class DirectiveHandler; -class Tokenizer; - -class DirectiveParser : public Lexer -{ - public: - DirectiveParser(Tokenizer* tokenizer, - MacroSet* macroSet, - Diagnostics* diagnostics, - DirectiveHandler* directiveHandler); - - virtual void lex(Token* token); - - private: - PP_DISALLOW_COPY_AND_ASSIGN(DirectiveParser); - - void parseDirective(Token* token); - void parseDefine(Token* token); - void parseUndef(Token* token); - void parseIf(Token* token); - void parseIfdef(Token* token); - void parseIfndef(Token* token); - void parseElse(Token* token); - void parseElif(Token* token); - void parseEndif(Token* token); - void parseError(Token* token); - void parsePragma(Token* token); - void parseExtension(Token* token); - void parseVersion(Token* token); - void parseLine(Token* token); - - bool skipping() const; - void parseConditionalIf(Token* token); - int parseExpressionIf(Token* token); - int parseExpressionIfdef(Token* token); - - struct ConditionalBlock - { - std::string type; - SourceLocation location; - bool skipBlock; - bool skipGroup; - bool foundValidGroup; - bool foundElseGroup; - - ConditionalBlock() : - skipBlock(false), - skipGroup(false), - foundValidGroup(false), - foundElseGroup(false) - { - } - }; - bool mPastFirstStatement; - std::vector mConditionalStack; - Tokenizer* mTokenizer; - MacroSet* mMacroSet; - Diagnostics* mDiagnostics; - DirectiveHandler* mDirectiveHandler; -}; - -} // namespace pp -#endif // COMPILER_PREPROCESSOR_DIRECTIVE_PARSER_H_ - diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/ExpressionParser.h b/src/3rdparty/angle/src/compiler/preprocessor/new/ExpressionParser.h deleted file mode 100644 index 092d059413..0000000000 --- a/src/3rdparty/angle/src/compiler/preprocessor/new/ExpressionParser.h +++ /dev/null @@ -1,34 +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_PREPROCESSOR_EXPRESSION_PARSER_H_ -#define COMPILER_PREPROCESSOR_EXPRESSION_PARSER_H_ - -#include "pp_utils.h" - -namespace pp -{ - -class Diagnostics; -class Lexer; -struct Token; - -class ExpressionParser -{ - public: - ExpressionParser(Lexer* lexer, Diagnostics* diagnostics); - - bool parse(Token* token, int* result); - - private: - PP_DISALLOW_COPY_AND_ASSIGN(ExpressionParser); - - Lexer* mLexer; - Diagnostics* mDiagnostics; -}; - -} // namespace pp -#endif // COMPILER_PREPROCESSOR_EXPRESSION_PARSER_H_ diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/ExpressionParser.y b/src/3rdparty/angle/src/compiler/preprocessor/new/ExpressionParser.y deleted file mode 100644 index 832ad4001e..0000000000 --- a/src/3rdparty/angle/src/compiler/preprocessor/new/ExpressionParser.y +++ /dev/null @@ -1,279 +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. -// - -This file contains the Yacc grammar for GLSL ES preprocessor expression. - -IF YOU MODIFY THIS FILE YOU ALSO NEED TO RUN generate_parser.sh, -WHICH GENERATES THE GLSL ES preprocessor expression parser. -*/ - -%{ -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// This file is auto-generated by generate_parser.sh. DO NOT EDIT! - -#if defined(__GNUC__) -// Triggered by the auto-generated pplval variable. -#pragma GCC diagnostic ignored "-Wuninitialized" -#elif defined(_MSC_VER) -#pragma warning(disable: 4065 4701) -#endif - -#include "ExpressionParser.h" - -#include -#include - -#include "Diagnostics.h" -#include "Lexer.h" -#include "Token.h" - -#if defined(_MSC_VER) -typedef __int64 YYSTYPE; -#else -#include -typedef intmax_t YYSTYPE; -#endif // _MSC_VER -#define YYSTYPE_IS_TRIVIAL 1 -#define YYSTYPE_IS_DECLARED 1 - -namespace { -struct Context -{ - pp::Diagnostics* diagnostics; - pp::Lexer* lexer; - pp::Token* token; - int* result; -}; -} // namespace -%} - -%pure-parser -%name-prefix="pp" -%parse-param {Context *context} -%lex-param {Context *context} - -%{ -static int yylex(YYSTYPE* lvalp, Context* context); -static void yyerror(Context* context, const char* reason); -%} - -%token TOK_CONST_INT -%left TOK_OP_OR -%left TOK_OP_AND -%left '|' -%left '^' -%left '&' -%left TOK_OP_EQ TOK_OP_NE -%left '<' '>' TOK_OP_LE TOK_OP_GE -%left TOK_OP_LEFT TOK_OP_RIGHT -%left '+' '-' -%left '*' '/' '%' -%right TOK_UNARY - -%% - -input - : expression { - *(context->result) = static_cast($1); - YYACCEPT; - } -; - -expression - : TOK_CONST_INT - | expression TOK_OP_OR expression { - $$ = $1 || $3; - } - | expression TOK_OP_AND expression { - $$ = $1 && $3; - } - | expression '|' expression { - $$ = $1 | $3; - } - | expression '^' expression { - $$ = $1 ^ $3; - } - | expression '&' expression { - $$ = $1 & $3; - } - | expression TOK_OP_NE expression { - $$ = $1 != $3; - } - | expression TOK_OP_EQ expression { - $$ = $1 == $3; - } - | expression TOK_OP_GE expression { - $$ = $1 >= $3; - } - | expression TOK_OP_LE expression { - $$ = $1 <= $3; - } - | expression '>' expression { - $$ = $1 > $3; - } - | expression '<' expression { - $$ = $1 < $3; - } - | expression TOK_OP_RIGHT expression { - $$ = $1 >> $3; - } - | expression TOK_OP_LEFT expression { - $$ = $1 << $3; - } - | expression '-' expression { - $$ = $1 - $3; - } - | expression '+' expression { - $$ = $1 + $3; - } - | expression '%' expression { - if ($3 == 0) { - std::ostringstream stream; - stream << $1 << " % " << $3; - std::string text = stream.str(); - context->diagnostics->report(pp::Diagnostics::DIVISION_BY_ZERO, - context->token->location, - text.c_str()); - YYABORT; - } else { - $$ = $1 % $3; - } - } - | expression '/' expression { - if ($3 == 0) { - std::ostringstream stream; - stream << $1 << " / " << $3; - std::string text = stream.str(); - context->diagnostics->report(pp::Diagnostics::DIVISION_BY_ZERO, - context->token->location, - text.c_str()); - YYABORT; - } else { - $$ = $1 / $3; - } - } - | expression '*' expression { - $$ = $1 * $3; - } - | '!' expression %prec TOK_UNARY { - $$ = ! $2; - } - | '~' expression %prec TOK_UNARY { - $$ = ~ $2; - } - | '-' expression %prec TOK_UNARY { - $$ = - $2; - } - | '+' expression %prec TOK_UNARY { - $$ = + $2; - } - | '(' expression ')' { - $$ = $2; - } -; - -%% - -int yylex(YYSTYPE* lvalp, Context* context) -{ - int type = 0; - - pp::Token* token = context->token; - switch (token->type) - { - case pp::Token::CONST_INT: - { - unsigned int val = 0; - if (!token->uValue(&val)) - { - context->diagnostics->report(pp::Diagnostics::INTEGER_OVERFLOW, - token->location, token->text); - } - *lvalp = static_cast(val); - type = TOK_CONST_INT; - break; - } - case pp::Token::OP_OR: type = TOK_OP_OR; break; - case pp::Token::OP_AND: type = TOK_OP_AND; break; - case pp::Token::OP_NE: type = TOK_OP_NE; break; - case pp::Token::OP_EQ: type = TOK_OP_EQ; break; - case pp::Token::OP_GE: type = TOK_OP_GE; break; - case pp::Token::OP_LE: type = TOK_OP_LE; break; - case pp::Token::OP_RIGHT: type = TOK_OP_RIGHT; break; - case pp::Token::OP_LEFT: type = TOK_OP_LEFT; break; - case '|': type = '|'; break; - case '^': type = '^'; break; - case '&': type = '&'; break; - case '>': type = '>'; break; - case '<': type = '<'; break; - case '-': type = '-'; break; - case '+': type = '+'; break; - case '%': type = '%'; break; - case '/': type = '/'; break; - case '*': type = '*'; break; - case '!': type = '!'; break; - case '~': type = '~'; break; - case '(': type = '('; break; - case ')': type = ')'; break; - - default: break; - } - - // Advance to the next token if the current one is valid. - if (type != 0) context->lexer->lex(token); - - return type; -} - -void yyerror(Context* context, const char* reason) -{ - context->diagnostics->report(pp::Diagnostics::INVALID_EXPRESSION, - context->token->location, - reason); -} - -namespace pp { - -ExpressionParser::ExpressionParser(Lexer* lexer, Diagnostics* diagnostics) : - mLexer(lexer), - mDiagnostics(diagnostics) -{ -} - -bool ExpressionParser::parse(Token* token, int* result) -{ - Context context; - context.diagnostics = mDiagnostics; - context.lexer = mLexer; - context.token = token; - context.result = result; - int ret = yyparse(&context); - switch (ret) - { - case 0: - case 1: - break; - - case 2: - mDiagnostics->report(Diagnostics::OUT_OF_MEMORY, token->location, ""); - break; - - default: - assert(false); - mDiagnostics->report(Diagnostics::INTERNAL_ERROR, token->location, ""); - break; - } - - return ret == 0; -} - -} // namespace pp diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/Input.cpp b/src/3rdparty/angle/src/compiler/preprocessor/new/Input.cpp deleted file mode 100644 index c3de95f313..0000000000 --- a/src/3rdparty/angle/src/compiler/preprocessor/new/Input.cpp +++ /dev/null @@ -1,55 +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 "Input.h" - -#include -#include -#include - -namespace pp -{ - -Input::Input() : mCount(0), mString(0) -{ -} - -Input::Input(int count, const char* const string[], const int length[]) : - mCount(count), - mString(string) -{ - assert(mCount >= 0); - mLength.reserve(mCount); - for (int i = 0; i < mCount; ++i) - { - int len = length ? length[i] : -1; - mLength.push_back(len < 0 ? strlen(mString[i]) : len); - } -} - -int Input::read(char* buf, int maxSize) -{ - int nRead = 0; - while ((nRead < maxSize) && (mReadLoc.sIndex < mCount)) - { - int size = mLength[mReadLoc.sIndex] - mReadLoc.cIndex; - size = std::min(size, maxSize); - memcpy(buf + nRead, mString[mReadLoc.sIndex] + mReadLoc.cIndex, size); - nRead += size; - mReadLoc.cIndex += size; - - // Advance string if we reached the end of current string. - if (mReadLoc.cIndex == mLength[mReadLoc.sIndex]) - { - ++mReadLoc.sIndex; - mReadLoc.cIndex = 0; - } - } - return nRead; -} - -} // namespace pp - diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/Input.h b/src/3rdparty/angle/src/compiler/preprocessor/new/Input.h deleted file mode 100644 index dac734b68d..0000000000 --- a/src/3rdparty/angle/src/compiler/preprocessor/new/Input.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. -// - -#ifndef COMPILER_PREPROCESSOR_INPUT_H_ -#define COMPILER_PREPROCESSOR_INPUT_H_ - -#include - -namespace pp -{ - -// Holds and reads input for Lexer. -class Input -{ - public: - Input(); - Input(int count, const char* const string[], const int length[]); - - int count() const { return mCount; } - const char* string(int index) const { return mString[index]; } - int length(int index) const { return mLength[index]; } - - int read(char* buf, int maxSize); - - struct Location - { - int sIndex; // String index; - int cIndex; // Char index. - - Location() : sIndex(0), cIndex(0) { } - }; - const Location& readLoc() const { return mReadLoc; } - - private: - // Input. - int mCount; - const char* const* mString; - std::vector mLength; - - Location mReadLoc; -}; - -} // namespace pp -#endif // COMPILER_PREPROCESSOR_INPUT_H_ - diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/Lexer.cpp b/src/3rdparty/angle/src/compiler/preprocessor/new/Lexer.cpp deleted file mode 100644 index 7c663ee761..0000000000 --- a/src/3rdparty/angle/src/compiler/preprocessor/new/Lexer.cpp +++ /dev/null @@ -1,16 +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 "Lexer.h" - -namespace pp -{ - -Lexer::~Lexer() -{ -} - -} // namespace pp diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/Lexer.h b/src/3rdparty/angle/src/compiler/preprocessor/new/Lexer.h deleted file mode 100644 index eb85cea873..0000000000 --- a/src/3rdparty/angle/src/compiler/preprocessor/new/Lexer.h +++ /dev/null @@ -1,25 +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_PREPROCESSOR_LEXER_H_ -#define COMPILER_PREPROCESSOR_LEXER_H_ - -namespace pp -{ - -struct Token; - -class Lexer -{ - public: - virtual ~Lexer(); - - virtual void lex(Token* token) = 0; -}; - -} // namespace pp -#endif // COMPILER_PREPROCESSOR_LEXER_H_ - diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/Macro.cpp b/src/3rdparty/angle/src/compiler/preprocessor/new/Macro.cpp deleted file mode 100644 index b2e3088e32..0000000000 --- a/src/3rdparty/angle/src/compiler/preprocessor/new/Macro.cpp +++ /dev/null @@ -1,23 +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 "Macro.h" - -#include "Token.h" - -namespace pp -{ - -bool Macro::equals(const Macro& other) const -{ - return (type == other.type) && - (name == other.name) && - (parameters == other.parameters) && - (replacements == other.replacements); -} - -} // namespace pp - diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/Macro.h b/src/3rdparty/angle/src/compiler/preprocessor/new/Macro.h deleted file mode 100644 index 7ec0149116..0000000000 --- a/src/3rdparty/angle/src/compiler/preprocessor/new/Macro.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_PREPROCESSOR_MACRO_H_ -#define COMPILER_PREPROCESSOR_MACRO_H_ - -#include -#include -#include - -namespace pp -{ - -struct Token; - -struct Macro -{ - enum Type - { - kTypeObj, - kTypeFunc - }; - typedef std::vector Parameters; - typedef std::vector Replacements; - - Macro() : predefined(false), disabled(false), type(kTypeObj) { } - bool equals(const Macro& other) const; - - bool predefined; - mutable bool disabled; - - Type type; - std::string name; - Parameters parameters; - Replacements replacements; -}; - -typedef std::map MacroSet; - -} // namespace pp -#endif // COMPILER_PREPROCESSOR_MACRO_H_ diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/MacroExpander.cpp b/src/3rdparty/angle/src/compiler/preprocessor/new/MacroExpander.cpp deleted file mode 100644 index 701cec9a4b..0000000000 --- a/src/3rdparty/angle/src/compiler/preprocessor/new/MacroExpander.cpp +++ /dev/null @@ -1,370 +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 "MacroExpander.h" - -#include -#include - -#include "Diagnostics.h" -#include "Token.h" - -namespace pp -{ - -class TokenLexer : public Lexer -{ - public: - typedef std::vector TokenVector; - - TokenLexer(TokenVector* tokens) - { - tokens->swap(mTokens); - mIter = mTokens.begin(); - } - - virtual void lex(Token* token) - { - if (mIter == mTokens.end()) - { - token->reset(); - token->type = Token::LAST; - } - else - { - *token = *mIter++; - } - } - - private: - PP_DISALLOW_COPY_AND_ASSIGN(TokenLexer); - - TokenVector mTokens; - TokenVector::const_iterator mIter; -}; - -MacroExpander::MacroExpander(Lexer* lexer, - MacroSet* macroSet, - Diagnostics* diagnostics) : - mLexer(lexer), - mMacroSet(macroSet), - mDiagnostics(diagnostics) -{ -} - -MacroExpander::~MacroExpander() -{ - for (size_t i = 0; i < mContextStack.size(); ++i) - { - delete mContextStack[i]; - } -} - -void MacroExpander::lex(Token* token) -{ - while (true) - { - getToken(token); - - if (token->type != Token::IDENTIFIER) - break; - - if (token->expansionDisabled()) - break; - - MacroSet::const_iterator iter = mMacroSet->find(token->text); - if (iter == mMacroSet->end()) - break; - - const Macro& macro = iter->second; - if (macro.disabled) - { - // If a particular token is not expanded, it is never expanded. - token->setExpansionDisabled(true); - break; - } - if ((macro.type == Macro::kTypeFunc) && !isNextTokenLeftParen()) - { - // If the token immediately after the macro name is not a '(', - // this macro should not be expanded. - break; - } - - pushMacro(macro, *token); - } -} - -void MacroExpander::getToken(Token* token) -{ - if (mReserveToken.get()) - { - *token = *mReserveToken; - mReserveToken.reset(); - return; - } - - // First pop all empty macro contexts. - while (!mContextStack.empty() && mContextStack.back()->empty()) - { - popMacro(); - } - - if (!mContextStack.empty()) - { - *token = mContextStack.back()->get(); - } - else - { - mLexer->lex(token); - } -} - -void MacroExpander::ungetToken(const Token& token) -{ - if (!mContextStack.empty()) - { - MacroContext* context = mContextStack.back(); - context->unget(); - assert(context->replacements[context->index] == token); - } - else - { - assert(!mReserveToken.get()); - mReserveToken.reset(new Token(token)); - } -} - -bool MacroExpander::isNextTokenLeftParen() -{ - Token token; - getToken(&token); - - bool lparen = token.type == '('; - ungetToken(token); - - return lparen; -} - -bool MacroExpander::pushMacro(const Macro& macro, const Token& identifier) -{ - assert(!macro.disabled); - assert(!identifier.expansionDisabled()); - assert(identifier.type == Token::IDENTIFIER); - assert(identifier.text == macro.name); - - std::vector replacements; - if (!expandMacro(macro, identifier, &replacements)) - return false; - - // Macro is disabled for expansion until it is popped off the stack. - macro.disabled = true; - - MacroContext* context = new MacroContext; - context->macro = ¯o; - context->replacements.swap(replacements); - mContextStack.push_back(context); - return true; -} - -void MacroExpander::popMacro() -{ - assert(!mContextStack.empty()); - - MacroContext* context = mContextStack.back(); - mContextStack.pop_back(); - - assert(context->empty()); - assert(context->macro->disabled); - context->macro->disabled = false; - delete context; -} - -bool MacroExpander::expandMacro(const Macro& macro, - const Token& identifier, - std::vector* replacements) -{ - replacements->clear(); - if (macro.type == Macro::kTypeObj) - { - replacements->assign(macro.replacements.begin(), - macro.replacements.end()); - - if (macro.predefined) - { - static const std::string kLine = "__LINE__"; - static const std::string kFile = "__FILE__"; - - assert(replacements->size() == 1); - Token& repl = replacements->front(); - if (macro.name == kLine) - { - std::ostringstream stream; - stream << identifier.location.line; - repl.text = stream.str(); - } - else if (macro.name == kFile) - { - std::ostringstream stream; - stream << identifier.location.file; - repl.text = stream.str(); - } - } - } - else - { - assert(macro.type == Macro::kTypeFunc); - std::vector args; - args.reserve(macro.parameters.size()); - if (!collectMacroArgs(macro, identifier, &args)) - return false; - - replaceMacroParams(macro, args, replacements); - } - - for (size_t i = 0; i < replacements->size(); ++i) - { - Token& repl = replacements->at(i); - if (i == 0) - { - // The first token in the replacement list inherits the padding - // properties of the identifier token. - repl.setAtStartOfLine(identifier.atStartOfLine()); - repl.setHasLeadingSpace(identifier.hasLeadingSpace()); - } - repl.location = identifier.location; - } - return true; -} - -bool MacroExpander::collectMacroArgs(const Macro& macro, - const Token& identifier, - std::vector* args) -{ - Token token; - getToken(&token); - assert(token.type == '('); - - args->push_back(MacroArg()); - for (int openParens = 1; openParens != 0; ) - { - getToken(&token); - - if (token.type == Token::LAST) - { - mDiagnostics->report(Diagnostics::MACRO_UNTERMINATED_INVOCATION, - identifier.location, identifier.text); - // Do not lose EOF token. - ungetToken(token); - return false; - } - - bool isArg = false; // True if token is part of the current argument. - switch (token.type) - { - case '(': - ++openParens; - isArg = true; - break; - case ')': - --openParens; - isArg = openParens != 0; - break; - case ',': - // The individual arguments are separated by comma tokens, but - // the comma tokens between matching inner parentheses do not - // seperate arguments. - if (openParens == 1) args->push_back(MacroArg()); - isArg = openParens != 1; - break; - default: - isArg = true; - break; - } - if (isArg) - { - MacroArg& arg = args->back(); - // Initial whitespace is not part of the argument. - if (arg.empty()) token.setHasLeadingSpace(false); - arg.push_back(token); - } - } - - const Macro::Parameters& params = macro.parameters; - // If there is only one empty argument, it is equivalent to no argument. - if (params.empty() && (args->size() == 1) && args->front().empty()) - { - args->clear(); - } - // Validate the number of arguments. - if (args->size() != params.size()) - { - Diagnostics::ID id = args->size() < macro.parameters.size() ? - Diagnostics::MACRO_TOO_FEW_ARGS : - Diagnostics::MACRO_TOO_MANY_ARGS; - mDiagnostics->report(id, identifier.location, identifier.text); - return false; - } - - // Pre-expand each argument before substitution. - // This step expands each argument individually before they are - // inserted into the macro body. - for (size_t i = 0; i < args->size(); ++i) - { - MacroArg& arg = args->at(i); - TokenLexer lexer(&arg); - MacroExpander expander(&lexer, mMacroSet, mDiagnostics); - - arg.clear(); - expander.lex(&token); - while (token.type != Token::LAST) - { - arg.push_back(token); - expander.lex(&token); - } - } - return true; -} - -void MacroExpander::replaceMacroParams(const Macro& macro, - const std::vector& args, - std::vector* replacements) -{ - for (size_t i = 0; i < macro.replacements.size(); ++i) - { - const Token& repl = macro.replacements[i]; - if (repl.type != Token::IDENTIFIER) - { - replacements->push_back(repl); - continue; - } - - // TODO(alokp): Optimize this. - // There is no need to search for macro params every time. - // The param index can be cached with the replacement token. - Macro::Parameters::const_iterator iter = std::find( - macro.parameters.begin(), macro.parameters.end(), repl.text); - if (iter == macro.parameters.end()) - { - replacements->push_back(repl); - continue; - } - - size_t iArg = std::distance(macro.parameters.begin(), iter); - const MacroArg& arg = args[iArg]; - if (arg.empty()) - { - continue; - } - size_t iRepl = replacements->size(); - replacements->insert(replacements->end(), arg.begin(), arg.end()); - // The replacement token inherits padding properties from - // macro replacement token. - replacements->at(iRepl).setHasLeadingSpace(repl.hasLeadingSpace()); - } -} - -} // namespace pp - diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/MacroExpander.h b/src/3rdparty/angle/src/compiler/preprocessor/new/MacroExpander.h deleted file mode 100644 index 7c5c543871..0000000000 --- a/src/3rdparty/angle/src/compiler/preprocessor/new/MacroExpander.h +++ /dev/null @@ -1,75 +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_PREPROCESSOR_MACRO_EXPANDER_H_ -#define COMPILER_PREPROCESSOR_MACRO_EXPANDER_H_ - -#include -#include -#include - -#include "Lexer.h" -#include "Macro.h" -#include "pp_utils.h" - -namespace pp -{ - -class Diagnostics; - -class MacroExpander : public Lexer -{ - public: - MacroExpander(Lexer* lexer, MacroSet* macroSet, Diagnostics* diagnostics); - virtual ~MacroExpander(); - - virtual void lex(Token* token); - - private: - PP_DISALLOW_COPY_AND_ASSIGN(MacroExpander); - - void getToken(Token* token); - void ungetToken(const Token& token); - bool isNextTokenLeftParen(); - - bool pushMacro(const Macro& macro, const Token& identifier); - void popMacro(); - - bool expandMacro(const Macro& macro, - const Token& identifier, - std::vector* replacements); - - typedef std::vector MacroArg; - bool collectMacroArgs(const Macro& macro, - const Token& identifier, - std::vector* args); - void replaceMacroParams(const Macro& macro, - const std::vector& args, - std::vector* replacements); - - struct MacroContext - { - const Macro* macro; - size_t index; - std::vector replacements; - - MacroContext() : macro(0), index(0) { } - bool empty() const { return index == replacements.size(); } - const Token& get() { return replacements[index++]; } - void unget() { assert(index > 0); --index; } - }; - - Lexer* mLexer; - MacroSet* mMacroSet; - Diagnostics* mDiagnostics; - - std::auto_ptr mReserveToken; - std::vector mContextStack; -}; - -} // namespace pp -#endif // COMPILER_PREPROCESSOR_MACRO_EXPANDER_H_ - diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/Preprocessor.cpp b/src/3rdparty/angle/src/compiler/preprocessor/new/Preprocessor.cpp deleted file mode 100644 index ffa7225a8f..0000000000 --- a/src/3rdparty/angle/src/compiler/preprocessor/new/Preprocessor.cpp +++ /dev/null @@ -1,142 +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 "Preprocessor.h" - -#include -#include - -#include "Diagnostics.h" -#include "DirectiveParser.h" -#include "Macro.h" -#include "MacroExpander.h" -#include "Token.h" -#include "Tokenizer.h" - -namespace pp -{ - -struct PreprocessorImpl -{ - Diagnostics* diagnostics; - MacroSet macroSet; - Tokenizer tokenizer; - DirectiveParser directiveParser; - MacroExpander macroExpander; - - PreprocessorImpl(Diagnostics* diag, - DirectiveHandler* directiveHandler) : - diagnostics(diag), - tokenizer(diag), - directiveParser(&tokenizer, ¯oSet, diag, directiveHandler), - macroExpander(&directiveParser, ¯oSet, diag) - { - } -}; - -Preprocessor::Preprocessor(Diagnostics* diagnostics, - DirectiveHandler* directiveHandler) -{ - mImpl = new PreprocessorImpl(diagnostics, directiveHandler); -} - -Preprocessor::~Preprocessor() -{ - delete mImpl; -} - -bool Preprocessor::init(int count, - const char* const string[], - const int length[]) -{ - static const int kGLSLVersion = 100; - - // Add standard pre-defined macros. - predefineMacro("__LINE__", 0); - predefineMacro("__FILE__", 0); - predefineMacro("__VERSION__", kGLSLVersion); - predefineMacro("GL_ES", 1); - - return mImpl->tokenizer.init(count, string, length); -} - -void Preprocessor::predefineMacro(const char* name, int value) -{ - std::ostringstream stream; - stream << value; - - Token token; - token.type = Token::CONST_INT; - token.text = stream.str(); - - Macro macro; - macro.predefined = true; - macro.type = Macro::kTypeObj; - macro.name = name; - macro.replacements.push_back(token); - - mImpl->macroSet[name] = macro; -} - -void Preprocessor::lex(Token* token) -{ - bool validToken = false; - while (!validToken) - { - mImpl->macroExpander.lex(token); - switch (token->type) - { - // We should not be returning internal preprocessing tokens. - // Convert preprocessing tokens to compiler tokens or report - // diagnostics. - case Token::PP_HASH: - assert(false); - break; - case Token::CONST_INT: - { - int val = 0; - if (!token->iValue(&val)) - { - // Do not mark the token as invalid. - // Just emit the diagnostic and reset value to 0. - mImpl->diagnostics->report(Diagnostics::INTEGER_OVERFLOW, - token->location, token->text); - token->text.assign("0"); - } - validToken = true; - break; - } - case Token::CONST_FLOAT: - { - float val = 0; - if (!token->fValue(&val)) - { - // Do not mark the token as invalid. - // Just emit the diagnostic and reset value to 0.0. - mImpl->diagnostics->report(Diagnostics::FLOAT_OVERFLOW, - token->location, token->text); - token->text.assign("0.0"); - } - validToken = true; - break; - } - case Token::PP_NUMBER: - mImpl->diagnostics->report(Diagnostics::INVALID_NUMBER, - token->location, token->text); - break; - case Token::PP_OTHER: - mImpl->diagnostics->report(Diagnostics::INVALID_CHARACTER, - token->location, token->text); - break; - default: - validToken = true; - break; - } - } -} - -} // namespace pp - diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/Preprocessor.h b/src/3rdparty/angle/src/compiler/preprocessor/new/Preprocessor.h deleted file mode 100644 index 5fe35b27bd..0000000000 --- a/src/3rdparty/angle/src/compiler/preprocessor/new/Preprocessor.h +++ /dev/null @@ -1,49 +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 COMPILER_PREPROCESSOR_PREPROCESSOR_H_ -#define COMPILER_PREPROCESSOR_PREPROCESSOR_H_ - -#include "pp_utils.h" - -namespace pp -{ - -class Diagnostics; -class DirectiveHandler; -struct PreprocessorImpl; -struct Token; - -class Preprocessor -{ - public: - Preprocessor(Diagnostics* diagnostics, DirectiveHandler* directiveHandler); - ~Preprocessor(); - - // count: specifies the number of elements in the string and length arrays. - // string: specifies an array of pointers to strings. - // length: specifies an array of string lengths. - // If length is NULL, each string is assumed to be null terminated. - // If length is a value other than NULL, it points to an array containing - // a string length for each of the corresponding elements of string. - // Each element in the length array may contain the length of the - // corresponding string or a value less than 0 to indicate that the string - // is null terminated. - bool init(int count, const char* const string[], const int length[]); - // Adds a pre-defined macro. - void predefineMacro(const char* name, int value); - - void lex(Token* token); - - private: - PP_DISALLOW_COPY_AND_ASSIGN(Preprocessor); - - PreprocessorImpl* mImpl; -}; - -} // namespace pp -#endif // COMPILER_PREPROCESSOR_PREPROCESSOR_H_ - diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/SourceLocation.h b/src/3rdparty/angle/src/compiler/preprocessor/new/SourceLocation.h deleted file mode 100644 index 6982613ac7..0000000000 --- a/src/3rdparty/angle/src/compiler/preprocessor/new/SourceLocation.h +++ /dev/null @@ -1,38 +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_PREPROCESSOR_SOURCE_LOCATION_H_ -#define COMPILER_PREPROCESSOR_SOURCE_LOCATION_H_ - -namespace pp -{ - -struct SourceLocation -{ - SourceLocation() : file(0), line(0) { } - SourceLocation(int f, int l) : file(f), line(l) { } - - bool equals(const SourceLocation& other) const - { - return (file == other.file) && (line == other.line); - } - - int file; - int line; -}; - -inline bool operator==(const SourceLocation& lhs, const SourceLocation& rhs) -{ - return lhs.equals(rhs); -} - -inline bool operator!=(const SourceLocation& lhs, const SourceLocation& rhs) -{ - return !lhs.equals(rhs); -} - -} // namespace pp -#endif // COMPILER_PREPROCESSOR_SOURCE_LOCATION_H_ diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/Token.cpp b/src/3rdparty/angle/src/compiler/preprocessor/new/Token.cpp deleted file mode 100644 index 67f50aa32c..0000000000 --- a/src/3rdparty/angle/src/compiler/preprocessor/new/Token.cpp +++ /dev/null @@ -1,83 +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 "Token.h" - -#include - -#include "numeric_lex.h" - -namespace pp -{ - -void Token::reset() -{ - type = 0; - flags = 0; - location = SourceLocation(); - text.clear(); -} - -bool Token::equals(const Token& other) const -{ - return (type == other.type) && - (flags == other.flags) && - (location == other.location) && - (text == other.text); -} - -void Token::setAtStartOfLine(bool start) -{ - if (start) - flags |= AT_START_OF_LINE; - else - flags &= ~AT_START_OF_LINE; -} - -void Token::setHasLeadingSpace(bool space) -{ - if (space) - flags |= HAS_LEADING_SPACE; - else - flags &= ~HAS_LEADING_SPACE; -} - -void Token::setExpansionDisabled(bool disable) -{ - if (disable) - flags |= EXPANSION_DISABLED; - else - flags &= ~EXPANSION_DISABLED; -} - -bool Token::iValue(int* value) const -{ - assert(type == CONST_INT); - return numeric_lex_int(text, value); -} - -bool Token::uValue(unsigned int* value) const -{ - assert(type == CONST_INT); - return numeric_lex_int(text, value); -} - -bool Token::fValue(float* value) const -{ - assert(type == CONST_FLOAT); - return numeric_lex_float(text, value); -} - -std::ostream& operator<<(std::ostream& out, const Token& token) -{ - if (token.hasLeadingSpace()) - out << " "; - - out << token.text; - return out; -} - -} // namespace pp diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/Token.h b/src/3rdparty/angle/src/compiler/preprocessor/new/Token.h deleted file mode 100644 index 8b553aecb6..0000000000 --- a/src/3rdparty/angle/src/compiler/preprocessor/new/Token.h +++ /dev/null @@ -1,106 +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 COMPILER_PREPROCESSOR_TOKEN_H_ -#define COMPILER_PREPROCESSOR_TOKEN_H_ - -#include -#include - -#include "SourceLocation.h" - -namespace pp -{ - -struct Token -{ - enum Type - { - LAST = 0, // EOF. - - IDENTIFIER = 258, - - CONST_INT, - CONST_FLOAT, - - OP_INC, - OP_DEC, - OP_LEFT, - OP_RIGHT, - OP_LE, - OP_GE, - OP_EQ, - OP_NE, - OP_AND, - OP_XOR, - OP_OR, - OP_ADD_ASSIGN, - OP_SUB_ASSIGN, - OP_MUL_ASSIGN, - OP_DIV_ASSIGN, - OP_MOD_ASSIGN, - OP_LEFT_ASSIGN, - OP_RIGHT_ASSIGN, - OP_AND_ASSIGN, - OP_XOR_ASSIGN, - OP_OR_ASSIGN, - - // Preprocessing token types. - // These types are used by the preprocessor internally. - // Preprocessor clients must not depend or check for them. - PP_HASH, - PP_NUMBER, - PP_OTHER - }; - enum Flags - { - AT_START_OF_LINE = 1 << 0, - HAS_LEADING_SPACE = 1 << 1, - EXPANSION_DISABLED = 1 << 2 - }; - - Token() : type(0), flags(0) { } - - void reset(); - bool equals(const Token& other) const; - - // Returns true if this is the first token on line. - // It disregards any leading whitespace. - bool atStartOfLine() const { return (flags & AT_START_OF_LINE) != 0; } - void setAtStartOfLine(bool start); - - bool hasLeadingSpace() const { return (flags & HAS_LEADING_SPACE) != 0; } - void setHasLeadingSpace(bool space); - - bool expansionDisabled() const { return (flags & EXPANSION_DISABLED) != 0; } - void setExpansionDisabled(bool disable); - - // Converts text into numeric value for CONST_INT and CONST_FLOAT token. - // Returns false if the parsed value cannot fit into an int or float. - bool iValue(int* value) const; - bool uValue(unsigned int* value) const; - bool fValue(float* value) const; - - int type; - unsigned int flags; - SourceLocation location; - std::string text; -}; - -inline bool operator==(const Token& lhs, const Token& rhs) -{ - return lhs.equals(rhs); -} - -inline bool operator!=(const Token& lhs, const Token& rhs) -{ - return !lhs.equals(rhs); -} - -extern std::ostream& operator<<(std::ostream& out, const Token& token); - -} // namepsace pp -#endif // COMPILER_PREPROCESSOR_TOKEN_H_ diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/Tokenizer.h b/src/3rdparty/angle/src/compiler/preprocessor/new/Tokenizer.h deleted file mode 100644 index a594d2d865..0000000000 --- a/src/3rdparty/angle/src/compiler/preprocessor/new/Tokenizer.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. -// - -#ifndef COMPILER_PREPROCESSOR_TOKENIZER_H_ -#define COMPILER_PREPROCESSOR_TOKENIZER_H_ - -#include "Input.h" -#include "Lexer.h" -#include "pp_utils.h" - -namespace pp -{ - -class Diagnostics; - -class Tokenizer : public Lexer -{ - public: - struct Context - { - Diagnostics* diagnostics; - - Input input; - // The location where yytext points to. Token location should track - // scanLoc instead of Input::mReadLoc because they may not be the same - // if text is buffered up in the scanner input buffer. - Input::Location scanLoc; - - bool leadingSpace; - bool lineStart; - }; - static const size_t kMaxTokenLength; - - Tokenizer(Diagnostics* diagnostics); - ~Tokenizer(); - - bool init(int count, const char* const string[], const int length[]); - - void setFileNumber(int file); - void setLineNumber(int line); - - virtual void lex(Token* token); - - private: - PP_DISALLOW_COPY_AND_ASSIGN(Tokenizer); - bool initScanner(); - void destroyScanner(); - - void* mHandle; // Scanner handle. - Context mContext; // Scanner extra. -}; - -} // namespace pp -#endif // COMPILER_PREPROCESSOR_TOKENIZER_H_ - diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/Tokenizer.l b/src/3rdparty/angle/src/compiler/preprocessor/new/Tokenizer.l deleted file mode 100644 index 9762988350..0000000000 --- a/src/3rdparty/angle/src/compiler/preprocessor/new/Tokenizer.l +++ /dev/null @@ -1,340 +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. -// - -This file contains the Lex specification for GLSL ES preprocessor. -Based on Microsoft Visual Studio 2010 Preprocessor Grammar: -http://msdn.microsoft.com/en-us/library/2scxys89.aspx - -IF YOU MODIFY THIS FILE YOU ALSO NEED TO RUN generate_parser.sh. -*/ - -%top{ -// -// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// This file is auto-generated by generate_parser.sh. DO NOT EDIT! -} - -%{ -#include "Tokenizer.h" - -#include "Diagnostics.h" -#include "Token.h" - -#if defined(__GNUC__) -// Triggered by the auto-generated yy_fatal_error function. -#pragma GCC diagnostic ignored "-Wmissing-noreturn" -#endif - -typedef std::string YYSTYPE; -typedef pp::SourceLocation YYLTYPE; - -// Use the unused yycolumn variable to track file (string) number. -#define yyfileno yycolumn - -#define YY_USER_INIT \ - do { \ - yyfileno = 0; \ - yylineno = 1; \ - yyextra->leadingSpace = false; \ - yyextra->lineStart = true; \ - } while(0); - -#define YY_USER_ACTION \ - do \ - { \ - pp::Input* input = &yyextra->input; \ - pp::Input::Location* scanLoc = &yyextra->scanLoc; \ - while ((scanLoc->sIndex < input->count()) && \ - (scanLoc->cIndex >= input->length(scanLoc->sIndex))) \ - { \ - scanLoc->cIndex -= input->length(scanLoc->sIndex++); \ - ++yyfileno; yylineno = 1; \ - } \ - yylloc->file = yyfileno; \ - yylloc->line = yylineno; \ - scanLoc->cIndex += yyleng; \ - } while(0); - -#define YY_INPUT(buf, result, maxSize) \ - result = yyextra->input.read(buf, maxSize); - -%} - -%option noyywrap nounput never-interactive -%option reentrant bison-bridge bison-locations -%option prefix="pp" -%option extra-type="pp::Tokenizer::Context*" -%x COMMENT - -NEWLINE \n|\r|\r\n -IDENTIFIER [_a-zA-Z][_a-zA-Z0-9]* -PUNCTUATOR [][<>(){}.+-/*%^|&~=!:;,?] - -DECIMAL_CONSTANT [1-9][0-9]* -OCTAL_CONSTANT 0[0-7]* -HEXADECIMAL_CONSTANT 0[xX][0-9a-fA-F]+ - -DIGIT [0-9] -EXPONENT_PART [eE][+-]?{DIGIT}+ -FRACTIONAL_CONSTANT ({DIGIT}*"."{DIGIT}+)|({DIGIT}+".") - -%% - - /* Line comment */ -"//"[^\r\n]* - - /* Block comment */ - /* Line breaks are just counted - not returned. */ - /* The comment is replaced by a single space. */ -"/*" { BEGIN(COMMENT); } -[^*\r\n]+ -"*" -{NEWLINE} { ++yylineno; } -"*/" { - yyextra->leadingSpace = true; - BEGIN(INITIAL); -} - -# { - // # is only valid at start of line for preprocessor directives. - yylval->assign(1, yytext[0]); - return yyextra->lineStart ? pp::Token::PP_HASH : pp::Token::PP_OTHER; -} - -{IDENTIFIER} { - yylval->assign(yytext, yyleng); - return pp::Token::IDENTIFIER; -} - -{DECIMAL_CONSTANT}|{OCTAL_CONSTANT}|{HEXADECIMAL_CONSTANT} { - yylval->assign(yytext, yyleng); - return pp::Token::CONST_INT; -} - -({DIGIT}+{EXPONENT_PART})|({FRACTIONAL_CONSTANT}{EXPONENT_PART}?) { - yylval->assign(yytext, yyleng); - return pp::Token::CONST_FLOAT; -} - - /* Anything that starts with a {DIGIT} or .{DIGIT} must be a number. */ - /* Rule to catch all invalid integers and floats. */ -({DIGIT}+[_a-zA-Z0-9.]*)|("."{DIGIT}+[_a-zA-Z0-9.]*) { - yylval->assign(yytext, yyleng); - return pp::Token::PP_NUMBER; -} - -"++" { - yylval->assign(yytext, yyleng); - return pp::Token::OP_INC; -} -"--" { - yylval->assign(yytext, yyleng); - return pp::Token::OP_DEC; -} -"<<" { - yylval->assign(yytext, yyleng); - return pp::Token::OP_LEFT; -} -">>" { - yylval->assign(yytext, yyleng); - return pp::Token::OP_RIGHT; -} -"<=" { - yylval->assign(yytext, yyleng); - return pp::Token::OP_LE; -} -">=" { - yylval->assign(yytext, yyleng); - return pp::Token::OP_GE; -} -"==" { - yylval->assign(yytext, yyleng); - return pp::Token::OP_EQ; -} -"!=" { - yylval->assign(yytext, yyleng); - return pp::Token::OP_NE; -} -"&&" { - yylval->assign(yytext, yyleng); - return pp::Token::OP_AND; -} -"^^" { - yylval->assign(yytext, yyleng); - return pp::Token::OP_XOR; -} -"||" { - yylval->assign(yytext, yyleng); - return pp::Token::OP_OR; -} -"+=" { - yylval->assign(yytext, yyleng); - return pp::Token::OP_ADD_ASSIGN; -} -"-=" { - yylval->assign(yytext, yyleng); - return pp::Token::OP_SUB_ASSIGN; -} -"*=" { - yylval->assign(yytext, yyleng); - return pp::Token::OP_MUL_ASSIGN; -} -"/=" { - yylval->assign(yytext, yyleng); - return pp::Token::OP_DIV_ASSIGN; -} -"%=" { - yylval->assign(yytext, yyleng); - return pp::Token::OP_MOD_ASSIGN; -} -"<<=" { - yylval->assign(yytext, yyleng); - return pp::Token::OP_LEFT_ASSIGN; -} -">>=" { - yylval->assign(yytext, yyleng); - return pp::Token::OP_RIGHT_ASSIGN; -} -"&=" { - yylval->assign(yytext, yyleng); - return pp::Token::OP_AND_ASSIGN; -} -"^=" { - yylval->assign(yytext, yyleng); - return pp::Token::OP_XOR_ASSIGN; -} -"|=" { - yylval->assign(yytext, yyleng); - return pp::Token::OP_OR_ASSIGN; -} - -{PUNCTUATOR} { - yylval->assign(1, yytext[0]); - return yytext[0]; -} - -[ \t\v\f]+ { yyextra->leadingSpace = true; } - -{NEWLINE} { - ++yylineno; - yylval->assign(1, '\n'); - return '\n'; -} - -. { - yylval->assign(1, yytext[0]); - return pp::Token::PP_OTHER; -} - -<*><> { - // YY_USER_ACTION is not invoked for handling EOF. - // Set the location for EOF token manually. - pp::Input* input = &yyextra->input; - pp::Input::Location* scanLoc = &yyextra->scanLoc; - int sIndexMax = std::max(0, input->count() - 1); - if (scanLoc->sIndex != sIndexMax) - { - // We can only reach here if there are empty strings at the - // end of the input. - scanLoc->sIndex = sIndexMax; scanLoc->cIndex = 0; - yyfileno = sIndexMax; yylineno = 1; - } - yylloc->file = yyfileno; - yylloc->line = yylineno; - yylval->clear(); - - if (YY_START == COMMENT) - { - yyextra->diagnostics->report(pp::Diagnostics::EOF_IN_COMMENT, - pp::SourceLocation(yyfileno, yylineno), - ""); - } - yyterminate(); -} - -%% - -namespace pp { - -// TODO(alokp): Maximum token length should ideally be specified by -// the preprocessor client, i.e., the compiler. -const size_t Tokenizer::kMaxTokenLength = 256; - -Tokenizer::Tokenizer(Diagnostics* diagnostics) : mHandle(0) -{ - mContext.diagnostics = diagnostics; -} - -Tokenizer::~Tokenizer() -{ - destroyScanner(); -} - -bool Tokenizer::init(int count, const char* const string[], const int length[]) -{ - if (count < 0) return false; - if ((count > 0) && (string == 0)) return false; - - mContext.input = Input(count, string, length); - return initScanner(); -} - -void Tokenizer::setFileNumber(int file) -{ - // We use column number as file number. - // See macro yyfileno. - yyset_column(file, mHandle); -} - -void Tokenizer::setLineNumber(int line) -{ - yyset_lineno(line, mHandle); -} - -void Tokenizer::lex(Token* token) -{ - token->type = yylex(&token->text, &token->location, mHandle); - if (token->text.size() > kMaxTokenLength) - { - mContext.diagnostics->report(Diagnostics::TOKEN_TOO_LONG, - token->location, token->text); - token->text.erase(kMaxTokenLength); - } - - token->flags = 0; - - token->setAtStartOfLine(mContext.lineStart); - mContext.lineStart = token->type == '\n'; - - token->setHasLeadingSpace(mContext.leadingSpace); - mContext.leadingSpace = false; -} - -bool Tokenizer::initScanner() -{ - if ((mHandle == NULL) && yylex_init_extra(&mContext, &mHandle)) - return false; - - yyrestart(0, mHandle); - return true; -} - -void Tokenizer::destroyScanner() -{ - if (mHandle == NULL) - return; - - yylex_destroy(mHandle); - mHandle = NULL; -} - -} // namespace pp - diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/numeric_lex.h b/src/3rdparty/angle/src/compiler/preprocessor/new/numeric_lex.h deleted file mode 100644 index b04125d230..0000000000 --- a/src/3rdparty/angle/src/compiler/preprocessor/new/numeric_lex.h +++ /dev/null @@ -1,61 +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. -// - -// numeric_lex.h: Functions to extract numeric values from string. - -#ifndef COMPILER_PREPROCESSOR_NUMERIC_LEX_H_ -#define COMPILER_PREPROCESSOR_NUMERIC_LEX_H_ - -#include - -namespace pp { - -inline std::ios::fmtflags numeric_base_int(const std::string& str) -{ - if ((str.size() >= 2) && - (str[0] == '0') && - (str[1] == 'x' || str[1] == 'X')) - { - return std::ios::hex; - } - else if ((str.size() >= 1) && (str[0] == '0')) - { - return std::ios::oct; - } - return std::ios::dec; -} - -// The following functions parse the given string to extract a numerical -// value of the given type. These functions assume that the string is -// of the correct form. They can only fail if the parsed value is too big, -// in which case false is returned. - -template -bool numeric_lex_int(const std::string& str, IntType* value) -{ - std::istringstream stream(str); - // This should not be necessary, but MSVS has a buggy implementation. - // It returns incorrect results if the base is not specified. - stream.setf(numeric_base_int(str), std::ios::basefield); - - stream >> (*value); - return !stream.fail(); -} - -template -bool numeric_lex_float(const std::string& str, FloatType* value) -{ - std::istringstream stream(str); - // Force "C" locale so that decimal character is always '.', and - // not dependent on the current locale. - stream.imbue(std::locale::classic()); - - stream >> (*value); - return !stream.fail(); -} - -} // namespace pp. -#endif // COMPILER_PREPROCESSOR_NUMERIC_LEX_H_ diff --git a/src/3rdparty/angle/src/compiler/preprocessor/new/pp_utils.h b/src/3rdparty/angle/src/compiler/preprocessor/new/pp_utils.h deleted file mode 100644 index 17164ea8b0..0000000000 --- a/src/3rdparty/angle/src/compiler/preprocessor/new/pp_utils.h +++ /dev/null @@ -1,18 +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. -// - -// pp_utils.h: Common preprocessor utilities - -#ifndef COMPILER_PREPROCESSOR_PPUTILS_H_ -#define COMPILER_PREPROCESSOR_PPUTILS_H_ - -// A macro to disallow the copy constructor and operator= functions -// This must be used in the private: declarations for a class. -#define PP_DISALLOW_COPY_AND_ASSIGN(TypeName) \ - TypeName(const TypeName&); \ - void operator=(const TypeName&) - -#endif // COMPILER_PREPROCESSOR_PPUTILS_H_ diff --git a/src/3rdparty/angle/src/compiler/preprocessor/numeric_lex.h b/src/3rdparty/angle/src/compiler/preprocessor/numeric_lex.h new file mode 100644 index 0000000000..b04125d230 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/preprocessor/numeric_lex.h @@ -0,0 +1,61 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// numeric_lex.h: Functions to extract numeric values from string. + +#ifndef COMPILER_PREPROCESSOR_NUMERIC_LEX_H_ +#define COMPILER_PREPROCESSOR_NUMERIC_LEX_H_ + +#include + +namespace pp { + +inline std::ios::fmtflags numeric_base_int(const std::string& str) +{ + if ((str.size() >= 2) && + (str[0] == '0') && + (str[1] == 'x' || str[1] == 'X')) + { + return std::ios::hex; + } + else if ((str.size() >= 1) && (str[0] == '0')) + { + return std::ios::oct; + } + return std::ios::dec; +} + +// The following functions parse the given string to extract a numerical +// value of the given type. These functions assume that the string is +// of the correct form. They can only fail if the parsed value is too big, +// in which case false is returned. + +template +bool numeric_lex_int(const std::string& str, IntType* value) +{ + std::istringstream stream(str); + // This should not be necessary, but MSVS has a buggy implementation. + // It returns incorrect results if the base is not specified. + stream.setf(numeric_base_int(str), std::ios::basefield); + + stream >> (*value); + return !stream.fail(); +} + +template +bool numeric_lex_float(const std::string& str, FloatType* value) +{ + std::istringstream stream(str); + // Force "C" locale so that decimal character is always '.', and + // not dependent on the current locale. + stream.imbue(std::locale::classic()); + + stream >> (*value); + return !stream.fail(); +} + +} // namespace pp. +#endif // COMPILER_PREPROCESSOR_NUMERIC_LEX_H_ diff --git a/src/3rdparty/angle/src/compiler/preprocessor/parser.h b/src/3rdparty/angle/src/compiler/preprocessor/parser.h deleted file mode 100644 index f67342b670..0000000000 --- a/src/3rdparty/angle/src/compiler/preprocessor/parser.h +++ /dev/null @@ -1,93 +0,0 @@ -/****************************************************************************\ -Copyright (c) 2002, NVIDIA Corporation. - -NVIDIA Corporation("NVIDIA") supplies this software to you in -consideration of your agreement to the following terms, and your use, -installation, modification or redistribution of this NVIDIA software -constitutes acceptance of these terms. If you do not agree with these -terms, please do not use, install, modify or redistribute this NVIDIA -software. - -In consideration of your agreement to abide by the following terms, and -subject to these terms, NVIDIA grants you a personal, non-exclusive -license, under NVIDIA's copyrights in this original NVIDIA software (the -"NVIDIA Software"), to use, reproduce, modify and redistribute the -NVIDIA Software, with or without modifications, in source and/or binary -forms; provided that if you redistribute the NVIDIA Software, you must -retain the copyright notice of NVIDIA, this notice and the following -text and disclaimers in all such redistributions of the NVIDIA Software. -Neither the name, trademarks, service marks nor logos of NVIDIA -Corporation may be used to endorse or promote products derived from the -NVIDIA Software without specific prior written permission from NVIDIA. -Except as expressly stated in this notice, no other rights or licenses -express or implied, are granted by NVIDIA herein, including but not -limited to any patent rights that may be infringed by your derivative -works or by other works in which the NVIDIA Software may be -incorporated. No hardware is licensed hereunder. - -THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT -WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, -INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, -NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR -ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER -PRODUCTS. - -IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, -INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF -USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY -OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE -NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, -TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF -NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -\****************************************************************************/ - -#ifndef BISON_PARSER_H -# define BISON_PARSER_H - -#ifndef yystypepp -typedef struct { - int sc_int; - float sc_fval; - int sc_ident; - char symbol_name[MAX_SYMBOL_NAME_LEN+1]; -} yystypepp; - -# define YYSTYPE_IS_TRIVIAL 1 -#endif -# define CPP_AND_OP 257 -# define CPP_SUB_ASSIGN 259 -# define CPP_MOD_ASSIGN 260 -# define CPP_ADD_ASSIGN 261 -# define CPP_DIV_ASSIGN 262 -# define CPP_MUL_ASSIGN 263 -# define CPP_EQ_OP 264 -# define CPP_XOR_OP 265 -# define ERROR_SY 266 -# define CPP_FLOATCONSTANT 267 -# define CPP_GE_OP 268 -# define CPP_RIGHT_OP 269 -# define CPP_IDENTIFIER 270 -# define CPP_INTCONSTANT 271 -# define CPP_LE_OP 272 -# define CPP_LEFT_OP 273 -# define CPP_DEC_OP 274 -# define CPP_NE_OP 275 -# define CPP_OR_OP 276 -# define CPP_INC_OP 277 -# define CPP_STRCONSTANT 278 -# define CPP_TYPEIDENTIFIER 279 - -# define FIRST_USER_TOKEN_SY 289 - -# define CPP_RIGHT_ASSIGN 280 -# define CPP_LEFT_ASSIGN 281 -# define CPP_AND_ASSIGN 282 -# define CPP_OR_ASSIGN 283 -# define CPP_XOR_ASSIGN 284 -# define CPP_LEFT_BRACKET 285 -# define CPP_RIGHT_BRACKET 286 -# define CPP_LEFT_BRACE 287 -# define CPP_RIGHT_BRACE 288 - -#endif /* not BISON_PARSER_H */ diff --git a/src/3rdparty/angle/src/compiler/preprocessor/pp_utils.h b/src/3rdparty/angle/src/compiler/preprocessor/pp_utils.h new file mode 100644 index 0000000000..17164ea8b0 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/preprocessor/pp_utils.h @@ -0,0 +1,18 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// pp_utils.h: Common preprocessor utilities + +#ifndef COMPILER_PREPROCESSOR_PPUTILS_H_ +#define COMPILER_PREPROCESSOR_PPUTILS_H_ + +// A macro to disallow the copy constructor and operator= functions +// This must be used in the private: declarations for a class. +#define PP_DISALLOW_COPY_AND_ASSIGN(TypeName) \ + TypeName(const TypeName&); \ + void operator=(const TypeName&) + +#endif // COMPILER_PREPROCESSOR_PPUTILS_H_ diff --git a/src/3rdparty/angle/src/compiler/preprocessor/preprocess.h b/src/3rdparty/angle/src/compiler/preprocessor/preprocess.h deleted file mode 100644 index 15056da2c9..0000000000 --- a/src/3rdparty/angle/src/compiler/preprocessor/preprocess.h +++ /dev/null @@ -1,50 +0,0 @@ -/****************************************************************************\ -Copyright (c) 2002, NVIDIA Corporation. - -NVIDIA Corporation("NVIDIA") supplies this software to you in -consideration of your agreement to the following terms, and your use, -installation, modification or redistribution of this NVIDIA software -constitutes acceptance of these terms. If you do not agree with these -terms, please do not use, install, modify or redistribute this NVIDIA -software. - -In consideration of your agreement to abide by the following terms, and -subject to these terms, NVIDIA grants you a personal, non-exclusive -license, under NVIDIA's copyrights in this original NVIDIA software (the -"NVIDIA Software"), to use, reproduce, modify and redistribute the -NVIDIA Software, with or without modifications, in source and/or binary -forms; provided that if you redistribute the NVIDIA Software, you must -retain the copyright notice of NVIDIA, this notice and the following -text and disclaimers in all such redistributions of the NVIDIA Software. -Neither the name, trademarks, service marks nor logos of NVIDIA -Corporation may be used to endorse or promote products derived from the -NVIDIA Software without specific prior written permission from NVIDIA. -Except as expressly stated in this notice, no other rights or licenses -express or implied, are granted by NVIDIA herein, including but not -limited to any patent rights that may be infringed by your derivative -works or by other works in which the NVIDIA Software may be -incorporated. No hardware is licensed hereunder. - -THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT -WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, -INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, -NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR -ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER -PRODUCTS. - -IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, -INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF -USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY -OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE -NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, -TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF -NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -\****************************************************************************/ - -#include "compiler/preprocessor/slglobals.h" -extern CPPStruct *cpp; -int InitCPPStruct(void); -int InitScanner(CPPStruct *cpp); -int InitAtomTable(AtomTable *atable, int htsize); -char* GetStringOfAtom(AtomTable *atable, int atom); diff --git a/src/3rdparty/angle/src/compiler/preprocessor/scanner.c b/src/3rdparty/angle/src/compiler/preprocessor/scanner.c deleted file mode 100644 index fde853c1e0..0000000000 --- a/src/3rdparty/angle/src/compiler/preprocessor/scanner.c +++ /dev/null @@ -1,698 +0,0 @@ -/****************************************************************************\ -Copyright (c) 2002, NVIDIA Corporation. - -NVIDIA Corporation("NVIDIA") supplies this software to you in -consideration of your agreement to the following terms, and your use, -installation, modification or redistribution of this NVIDIA software -constitutes acceptance of these terms. If you do not agree with these -terms, please do not use, install, modify or redistribute this NVIDIA -software. - -In consideration of your agreement to abide by the following terms, and -subject to these terms, NVIDIA grants you a personal, non-exclusive -license, under NVIDIA's copyrights in this original NVIDIA software (the -"NVIDIA Software"), to use, reproduce, modify and redistribute the -NVIDIA Software, with or without modifications, in source and/or binary -forms; provided that if you redistribute the NVIDIA Software, you must -retain the copyright notice of NVIDIA, this notice and the following -text and disclaimers in all such redistributions of the NVIDIA Software. -Neither the name, trademarks, service marks nor logos of NVIDIA -Corporation may be used to endorse or promote products derived from the -NVIDIA Software without specific prior written permission from NVIDIA. -Except as expressly stated in this notice, no other rights or licenses -express or implied, are granted by NVIDIA herein, including but not -limited to any patent rights that may be infringed by your derivative -works or by other works in which the NVIDIA Software may be -incorporated. No hardware is licensed hereunder. - -THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT -WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, -INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, -NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR -ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER -PRODUCTS. - -IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, -INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF -USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY -OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE -NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, -TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF -NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -\****************************************************************************/ -// -// scanner.c -// - -#include -#include -#include -#include -#include - -#if 0 - #include -#else - #define isinff(x) (((*(int *)&(x) & 0x7f800000L)==0x7f800000L) && \ - ((*(int *)&(x) & 0x007fffffL)==0000000000L)) -#endif - -#include "compiler/preprocessor/slglobals.h" -#include "compiler/util.h" - -typedef struct StringInputSrc { - InputSrc base; - char *p; -} StringInputSrc; - -static int ScanFromString(const char *s); - -static int eof_scan(InputSrc *is, yystypepp * yylvalpp) -{ - return EOF; -} // eof_scan - -static void noop(InputSrc *in, int ch, yystypepp * yylvalpp) {} - -static InputSrc eof_inputsrc = { 0, &eof_scan, &eof_scan, &noop, 0, 0 }; - -static int byte_scan(InputSrc *, yystypepp * yylvalpp); - -#define EOL_SY '\n' - -#if defined(_MSC_VER) - #define DBG_BREAKPOINT() __asm int 3 -#elif defined(_M_AMD64) - #define DBG_BREAKPOINT() assert(!"Dbg_Breakpoint"); -#else - #define DBG_BREAKPOINT() -#endif - -#if defined(_MSC_VER) && !defined(_M_AMD64) - __int64 RDTSC ( void ) { - - __int64 v; - - __asm __emit 0x0f - __asm __emit 0x31 - __asm mov dword ptr v, eax - __asm mov dword ptr v+4, edx - - return v; - } -#endif - - -int InitScanner(CPPStruct *cpp) -{ - // Add various atoms needed by the CPP line scanner: - if (!InitCPP()) - return 0; - - cpp->mostRecentToken = 0; - cpp->tokenLoc = &cpp->ltokenLoc; - - cpp->ltokenLoc.file = 0; - cpp->ltokenLoc.line = 0; - - cpp->currentInput = &eof_inputsrc; - cpp->previous_token = '\n'; - cpp->pastFirstStatement = 0; - - return 1; -} // InitScanner - -int FreeScanner(void) -{ - return (FreeCPP()); -} - -int InitScannerInput(CPPStruct *cpp, int count, const char* const string[], const int length[]) -{ - cpp->PaWhichStr = 0; - cpp->PaArgv = string; - cpp->PaArgc = count; - cpp->PaStrLen = length; - ScanFromString(string[0]); - return 0; -} - -/* - * str_getch() - * takes care of reading from multiple strings. - * returns the next-char from the input stream. - * returns EOF when the complete shader is parsed. - */ -static int str_getch(StringInputSrc *in) -{ - for(;;){ - if (*in->p){ - if (*in->p == '\n') { - in->base.line++; - IncLineNumber(); - } - return *in->p++; - } - if(++(cpp->PaWhichStr) < cpp->PaArgc){ - free(in); - SetStringNumber(cpp->PaWhichStr); - SetLineNumber(1); - ScanFromString(cpp->PaArgv[cpp->PaWhichStr]); - in=(StringInputSrc*)cpp->currentInput; - continue; - } - else{ - cpp->currentInput = in->base.prev; - cpp->PaWhichStr=0; - free(in); - return EOF; - } - } -} // str_getch - -static void str_ungetch(StringInputSrc *in, int ch, yystypepp *type) { - if (in->p[-1] == ch)in->p--; - else { - *(in->p)='\0'; //this would take care of shifting to the previous string. - cpp->PaWhichStr--; - } - if (ch == '\n') { - in->base.line--; - DecLineNumber(); - } -} // str_ungetch - -int ScanFromString(const char *s) -{ - - StringInputSrc *in = malloc(sizeof(StringInputSrc)); - memset(in, 0, sizeof(StringInputSrc)); - in->p = (char*) s; - in->base.line = 1; - in->base.scan = byte_scan; - in->base.getch = (int (*)(InputSrc *, yystypepp *))str_getch; - in->base.ungetch = (void (*)(InputSrc *, int, yystypepp *))str_ungetch; - in->base.prev = cpp->currentInput; - cpp->currentInput = &in->base; - - return 1; -} // ScanFromString; - - -/////////////////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////// Floating point constants: ///////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////// - -#define APPEND_CHAR_S(ch, str, len, max_len) \ - if (len < max_len) { \ - str[len++] = ch; \ - } else if (!alreadyComplained) { \ - CPPErrorToInfoLog("BUFFER OVERFLOW"); \ - alreadyComplained = 1; \ - } - -/* - * lFloatConst() - Scan a floating point constant. Assumes that the scanner - * has seen at least one digit, followed by either a decimal '.' or the - * letter 'e'. - * ch - '.' or 'e' - * len - length of string already copied into yylvalpp->symbol_name. - */ - -static int lFloatConst(int ch, int len, yystypepp * yylvalpp) -{ - int alreadyComplained = 0; - assert((ch == '.') || (ch == 'e') || (ch == 'E')); - - if (ch == '.') { - do { - APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN); - ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); - } while (ch >= '0' && ch <= '9'); - } - - // Exponent: - if (ch == 'e' || ch == 'E') { - APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN); - ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); - if (ch == '+') { - APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN); - ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); - } else if (ch == '-') { - APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN); - ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); - } - if (ch >= '0' && ch <= '9') { - while (ch >= '0' && ch <= '9') { - APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN); - ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); - } - } else { - CPPErrorToInfoLog("EXPONENT INVALID"); - } - } - cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); - - assert(len <= MAX_SYMBOL_NAME_LEN); - yylvalpp->symbol_name[len] = '\0'; - yylvalpp->sc_fval = (float) atof_dot(yylvalpp->symbol_name); - if (isinff(yylvalpp->sc_fval)) { - CPPErrorToInfoLog("FLOAT CONSTANT OVERFLOW"); - } - return CPP_FLOATCONSTANT; -} // lFloatConst - -/////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////// Normal Scanner ////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////// - -static int byte_scan(InputSrc *in, yystypepp * yylvalpp) -{ - char string_val[MAX_STRING_LEN + 1]; - int alreadyComplained = 0; - int len, ch, ii, ival = 0; - - for (;;) { - yylvalpp->sc_int = 0; - ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); - - while (ch == ' ' || ch == '\t' || ch == '\r') { - yylvalpp->sc_int = 1; - ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); - } - - cpp->ltokenLoc.file = cpp->currentInput->name; - cpp->ltokenLoc.line = cpp->currentInput->line; - alreadyComplained = 0; - len = 0; - switch (ch) { - default: - return ch; // Single character token - case EOF: - return -1; - case 'A': case 'B': case 'C': case 'D': case 'E': - case 'F': case 'G': case 'H': case 'I': case 'J': - case 'K': case 'L': case 'M': case 'N': case 'O': - case 'P': case 'Q': case 'R': case 'S': case 'T': - case 'U': case 'V': case 'W': case 'X': case 'Y': - case 'Z': case '_': - case 'a': case 'b': case 'c': case 'd': case 'e': - case 'f': case 'g': case 'h': case 'i': case 'j': - case 'k': case 'l': case 'm': case 'n': case 'o': - case 'p': case 'q': case 'r': case 's': case 't': - case 'u': case 'v': case 'w': case 'x': case 'y': - case 'z': - do { - APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN); - ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); - } while ((ch >= 'a' && ch <= 'z') || - (ch >= 'A' && ch <= 'Z') || - (ch >= '0' && ch <= '9') || - ch == '_'); - assert(len <= MAX_SYMBOL_NAME_LEN); - yylvalpp->symbol_name[len] = '\0'; - cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); - yylvalpp->sc_ident = LookUpAddString(atable, yylvalpp->symbol_name); - return CPP_IDENTIFIER; - break; - case '0': - APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN); - ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); - if (ch == 'x' || ch == 'X') { // hexadecimal integer constants - APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN); - ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); - if ((ch >= '0' && ch <= '9') || - (ch >= 'A' && ch <= 'F') || - (ch >= 'a' && ch <= 'f')) - { - ival = 0; - do { - if ((ival <= 0x0fffffff) && (len < MAX_SYMBOL_NAME_LEN)) { - yylvalpp->symbol_name[len++] = ch; - if (ch >= '0' && ch <= '9') { - ii = ch - '0'; - } else if (ch >= 'A' && ch <= 'F') { - ii = ch - 'A' + 10; - } else { - ii = ch - 'a' + 10; - } - ival = (ival << 4) | ii; - } else if (!alreadyComplained) { - CPPErrorToInfoLog("HEX CONSTANT OVERFLOW"); - alreadyComplained = 1; - } - ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); - } while ((ch >= '0' && ch <= '9') || - (ch >= 'A' && ch <= 'F') || - (ch >= 'a' && ch <= 'f')); - } else { - CPPErrorToInfoLog("HEX CONSTANT INVALID"); - } - assert(len <= MAX_SYMBOL_NAME_LEN); - yylvalpp->symbol_name[len] = '\0'; - cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); - yylvalpp->sc_int = ival; - return CPP_INTCONSTANT; - } else if (ch >= '0' && ch <= '7') { // octal integer constants - ival = 0; - do { - if ((ival <= 0x1fffffff) && (len < MAX_SYMBOL_NAME_LEN)) { - yylvalpp->symbol_name[len++] = ch; - ii = ch - '0'; - ival = (ival << 3) | ii; - } else if (!alreadyComplained) { - CPPErrorToInfoLog("OCT CONSTANT OVERFLOW"); - alreadyComplained = 1; - } - ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); - } while (ch >= '0' && ch <= '7'); - if (ch == '.' || ch == 'e' || ch == 'f' || ch == 'h' || ch == 'x'|| ch == 'E') - return lFloatConst(ch, len, yylvalpp); - assert(len <= MAX_SYMBOL_NAME_LEN); - yylvalpp->symbol_name[len] = '\0'; - cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); - yylvalpp->sc_int = ival; - return CPP_INTCONSTANT; - } else { - cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); - ch = '0'; - } - // Fall through... - case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - do { - APPEND_CHAR_S(ch, yylvalpp->symbol_name, len, MAX_SYMBOL_NAME_LEN); - ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); - } while (ch >= '0' && ch <= '9'); - if (ch == '.' || ch == 'e' || ch == 'E') { - return lFloatConst(ch, len, yylvalpp); - } else { - assert(len <= MAX_SYMBOL_NAME_LEN); - yylvalpp->symbol_name[len] = '\0'; - cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); - ival = 0; - for (ii = 0; ii < len; ii++) { - ch = yylvalpp->symbol_name[ii] - '0'; - ival = ival*10 + ch; - if ((ival > 214748364) || (ival == 214748364 && ch >= 8)) { - CPPErrorToInfoLog("INTEGER CONSTANT OVERFLOW"); - break; - } - } - yylvalpp->sc_int = ival; - if(ival==0) - strcpy(yylvalpp->symbol_name,"0"); - return CPP_INTCONSTANT; - } - break; - case '-': - ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); - if (ch == '-') { - return CPP_DEC_OP; - } else if (ch == '=') { - return CPP_SUB_ASSIGN; - } else { - cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); - return '-'; - } - case '+': - ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); - if (ch == '+') { - return CPP_INC_OP; - } else if (ch == '=') { - return CPP_ADD_ASSIGN; - } else { - cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); - return '+'; - } - case '*': - ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); - if (ch == '=') { - return CPP_MUL_ASSIGN; - } else { - cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); - return '*'; - } - case '%': - ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); - if (ch == '=') { - return CPP_MOD_ASSIGN; - } else if (ch == '>'){ - return CPP_RIGHT_BRACE; - } else { - cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); - return '%'; - } - case ':': - ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); - if (ch == '>') { - return CPP_RIGHT_BRACKET; - } else { - cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); - return ':'; - } - case '^': - ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); - if (ch == '^') { - return CPP_XOR_OP; - } else { - if (ch == '=') - return CPP_XOR_ASSIGN; - else{ - cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); - return '^'; - } - } - - case '=': - ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); - if (ch == '=') { - return CPP_EQ_OP; - } else { - cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); - return '='; - } - case '!': - ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); - if (ch == '=') { - return CPP_NE_OP; - } else { - cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); - return '!'; - } - case '|': - ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); - if (ch == '|') { - return CPP_OR_OP; - } else { - if (ch == '=') - return CPP_OR_ASSIGN; - else{ - cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); - return '|'; - } - } - case '&': - ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); - if (ch == '&') { - return CPP_AND_OP; - } else { - if (ch == '=') - return CPP_AND_ASSIGN; - else{ - cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); - return '&'; - } - } - case '<': - ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); - if (ch == '<') { - ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); - if(ch == '=') - return CPP_LEFT_ASSIGN; - else{ - cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); - return CPP_LEFT_OP; - } - } else { - if (ch == '=') { - return CPP_LE_OP; - } else { - if (ch == '%') - return CPP_LEFT_BRACE; - else if (ch == ':') - return CPP_LEFT_BRACKET; - else{ - cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); - return '<'; - } - } - } - case '>': - ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); - if (ch == '>') { - ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); - if(ch == '=') - return CPP_RIGHT_ASSIGN; - else{ - cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); - return CPP_RIGHT_OP; - } - } else { - if (ch == '=') { - return CPP_GE_OP; - } else { - cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); - return '>'; - } - } - case '.': - ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); - if (ch >= '0' && ch <= '9') { - cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); - return lFloatConst('.', 0, yylvalpp); - } else { - if (ch == '.') { - return -1; // Special EOF hack - } else { - cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); - return '.'; - } - } - case '/': - ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); - if (ch == '/') { - do { - ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); - } while (ch != '\n' && ch != EOF); - if (ch == EOF) - return -1; - return '\n'; - } else if (ch == '*') { - ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); - do { - while (ch != '*') { - if (ch == EOF) { - CPPErrorToInfoLog("EOF IN COMMENT"); - return -1; - } - ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); - } - ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); - if (ch == EOF) { - CPPErrorToInfoLog("EOF IN COMMENT"); - return -1; - } - } while (ch != '/'); - // Go try it again... - } else if (ch == '=') { - return CPP_DIV_ASSIGN; - } else { - cpp->currentInput->ungetch(cpp->currentInput, ch, yylvalpp); - return '/'; - } - break; - case '"': - ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); - while (ch != '"' && ch != '\n' && ch != EOF) { - if (ch == '\\') { - CPPErrorToInfoLog("The line continuation character (\\) is not part of the OpenGL ES Shading Language"); - return -1; - } - APPEND_CHAR_S(ch, string_val, len, MAX_STRING_LEN); - ch = cpp->currentInput->getch(cpp->currentInput, yylvalpp); - }; - assert(len <= MAX_STRING_LEN); - string_val[len] = '\0'; - if (ch == '"') { - yylvalpp->sc_ident = LookUpAddString(atable, string_val); - return CPP_STRCONSTANT; - } else { - CPPErrorToInfoLog("EOL IN STRING"); - return ERROR_SY; - } - break; - } - } -} // byte_scan - -int yylex_CPP(char* buf, int maxSize) -{ - yystypepp yylvalpp; - int token = '\n'; - - for(;;) { - - char* tokenString = 0; - token = cpp->currentInput->scan(cpp->currentInput, &yylvalpp); - if(check_EOF(token)) - return 0; - if (token < 0) { - // This check may need to be improved to support UTF-8 - // characters in comments. - CPPErrorToInfoLog("preprocessor encountered non-ASCII character in shader source"); - return 0; - } - if (token == '#') { - if (cpp->previous_token == '\n'|| cpp->previous_token == 0) { - token = readCPPline(&yylvalpp); - if(check_EOF(token)) - return 0; - continue; - } else { - CPPErrorToInfoLog("preprocessor command must not be preceded by any other statement in that line"); - return 0; - } - } - cpp->previous_token = token; - // expand macros - if (token == CPP_IDENTIFIER && MacroExpand(yylvalpp.sc_ident, &yylvalpp)) { - cpp->pastFirstStatement = 1; - continue; - } - - if (token == '\n') - continue; - cpp->pastFirstStatement = 1; - - if (token == CPP_IDENTIFIER) { - tokenString = GetStringOfAtom(atable,yylvalpp.sc_ident); - } else if (token == CPP_FLOATCONSTANT || token == CPP_INTCONSTANT){ - tokenString = yylvalpp.symbol_name; - } else { - tokenString = GetStringOfAtom(atable,token); - } - - if (tokenString) { - int len = strlen(tokenString); - cpp->tokensBeforeEOF = 1; - if (len >= maxSize) { - return maxSize; - } else if (len > 0) { - strcpy(buf, tokenString); - return len; - } - - return 0; - } - } -} // yylex - -//Checks if the token just read is EOF or not. -int check_EOF(int token) -{ - if(token==-1){ - if(cpp->ifdepth >0){ - CPPErrorToInfoLog("#endif missing!! Compilation stopped"); - cpp->CompileError=1; - } - return 1; - } - return 0; -} - -/////////////////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////// End of scanner.c ////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////// - diff --git a/src/3rdparty/angle/src/compiler/preprocessor/scanner.h b/src/3rdparty/angle/src/compiler/preprocessor/scanner.h deleted file mode 100644 index b67c1d644e..0000000000 --- a/src/3rdparty/angle/src/compiler/preprocessor/scanner.h +++ /dev/null @@ -1,81 +0,0 @@ -/****************************************************************************\ -Copyright (c) 2002, NVIDIA Corporation. - -NVIDIA Corporation("NVIDIA") supplies this software to you in -consideration of your agreement to the following terms, and your use, -installation, modification or redistribution of this NVIDIA software -constitutes acceptance of these terms. If you do not agree with these -terms, please do not use, install, modify or redistribute this NVIDIA -software. - -In consideration of your agreement to abide by the following terms, and -subject to these terms, NVIDIA grants you a personal, non-exclusive -license, under NVIDIA's copyrights in this original NVIDIA software (the -"NVIDIA Software"), to use, reproduce, modify and redistribute the -NVIDIA Software, with or without modifications, in source and/or binary -forms; provided that if you redistribute the NVIDIA Software, you must -retain the copyright notice of NVIDIA, this notice and the following -text and disclaimers in all such redistributions of the NVIDIA Software. -Neither the name, trademarks, service marks nor logos of NVIDIA -Corporation may be used to endorse or promote products derived from the -NVIDIA Software without specific prior written permission from NVIDIA. -Except as expressly stated in this notice, no other rights or licenses -express or implied, are granted by NVIDIA herein, including but not -limited to any patent rights that may be infringed by your derivative -works or by other works in which the NVIDIA Software may be -incorporated. No hardware is licensed hereunder. - -THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT -WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, -INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, -NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR -ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER -PRODUCTS. - -IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, -INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF -USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY -OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE -NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, -TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF -NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -\****************************************************************************/ -// -// scanner.h -// - -#if !defined(__SCANNER_H) -#define __SCANNER_H 1 - -#include "compiler/preprocessor/length_limits.h" -#include "compiler/preprocessor/parser.h" - -// Not really atom table stuff but needed first... - -typedef struct SourceLoc_Rec { - unsigned short file, line; -} SourceLoc; - -int yylex_CPP(char* buf, int maxSize); - -typedef struct InputSrc { - struct InputSrc *prev; - int (*scan)(struct InputSrc *, yystypepp *); - int (*getch)(struct InputSrc *, yystypepp *); - void (*ungetch)(struct InputSrc *, int, yystypepp *); - int name; /* atom */ - int line; -} InputSrc; - -int InitScanner(CPPStruct *cpp); // Intialise the cpp scanner. -int InitScannerInput(CPPStruct *cpp, int count, const char* const string[], const int length[]); -int check_EOF(int); // check if we hit a EOF abruptly -void CPPErrorToInfoLog(const char *); // sticking the msg,line into the Shader's.Info.log -void SetLineNumber(int); -void SetStringNumber(int); -void IncLineNumber(void); -void DecLineNumber(void); -int FreeScanner(void); // Free the cpp scanner -#endif // !(defined(__SCANNER_H) - diff --git a/src/3rdparty/angle/src/compiler/preprocessor/slglobals.h b/src/3rdparty/angle/src/compiler/preprocessor/slglobals.h deleted file mode 100644 index 4634626643..0000000000 --- a/src/3rdparty/angle/src/compiler/preprocessor/slglobals.h +++ /dev/null @@ -1,82 +0,0 @@ -/****************************************************************************\ -Copyright (c) 2002, NVIDIA Corporation. - -NVIDIA Corporation("NVIDIA") supplies this software to you in -consideration of your agreement to the following terms, and your use, -installation, modification or redistribution of this NVIDIA software -constitutes acceptance of these terms. If you do not agree with these -terms, please do not use, install, modify or redistribute this NVIDIA -software. - -In consideration of your agreement to abide by the following terms, and -subject to these terms, NVIDIA grants you a personal, non-exclusive -license, under NVIDIA's copyrights in this original NVIDIA software (the -"NVIDIA Software"), to use, reproduce, modify and redistribute the -NVIDIA Software, with or without modifications, in source and/or binary -forms; provided that if you redistribute the NVIDIA Software, you must -retain the copyright notice of NVIDIA, this notice and the following -text and disclaimers in all such redistributions of the NVIDIA Software. -Neither the name, trademarks, service marks nor logos of NVIDIA -Corporation may be used to endorse or promote products derived from the -NVIDIA Software without specific prior written permission from NVIDIA. -Except as expressly stated in this notice, no other rights or licenses -express or implied, are granted by NVIDIA herein, including but not -limited to any patent rights that may be infringed by your derivative -works or by other works in which the NVIDIA Software may be -incorporated. No hardware is licensed hereunder. - -THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT -WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, -INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, -NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR -ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER -PRODUCTS. - -IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, -INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF -USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY -OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE -NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, -TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF -NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -\****************************************************************************/ -// -// slglobals.h -// - -#if !defined(__SLGLOBALS_H) -#define __SLGLOBALS_H 1 - -typedef struct CPPStruct_Rec CPPStruct; - -extern CPPStruct *cpp; - -#undef CPPC_DEBUG_THE_COMPILER -#if defined(_DEBUG) -#define CPPC_DEBUG_THE_COMPILER 1 -#endif - -#undef CPPC_ENABLE_TOOLS -#define CPPC_ENABLE_TOOLS 1 - -#include "compiler/preprocessor/memory.h" -#include "compiler/preprocessor/atom.h" -#include "compiler/preprocessor/scanner.h" -#include "compiler/preprocessor/cpp.h" -#include "compiler/preprocessor/tokens.h" -#include "compiler/preprocessor/symbols.h" -#include "compiler/preprocessor/compile.h" -#if !defined(NO_PARSER) -#include "compiler/preprocessor/parser.h" -#endif - -#if !defined(NULL) -#define NULL 0 -#endif - -#endif // !(defined(__SLGLOBALS_H) - - - - diff --git a/src/3rdparty/angle/src/compiler/preprocessor/symbols.c b/src/3rdparty/angle/src/compiler/preprocessor/symbols.c deleted file mode 100644 index f18b2569b3..0000000000 --- a/src/3rdparty/angle/src/compiler/preprocessor/symbols.c +++ /dev/null @@ -1,288 +0,0 @@ -/****************************************************************************\ -Copyright (c) 2002, NVIDIA Corporation. - -NVIDIA Corporation("NVIDIA") supplies this software to you in -consideration of your agreement to the following terms, and your use, -installation, modification or redistribution of this NVIDIA software -constitutes acceptance of these terms. If you do not agree with these -terms, please do not use, install, modify or redistribute this NVIDIA -software. - -In consideration of your agreement to abide by the following terms, and -subject to these terms, NVIDIA grants you a personal, non-exclusive -license, under NVIDIA's copyrights in this original NVIDIA software (the -"NVIDIA Software"), to use, reproduce, modify and redistribute the -NVIDIA Software, with or without modifications, in source and/or binary -forms; provided that if you redistribute the NVIDIA Software, you must -retain the copyright notice of NVIDIA, this notice and the following -text and disclaimers in all such redistributions of the NVIDIA Software. -Neither the name, trademarks, service marks nor logos of NVIDIA -Corporation may be used to endorse or promote products derived from the -NVIDIA Software without specific prior written permission from NVIDIA. -Except as expressly stated in this notice, no other rights or licenses -express or implied, are granted by NVIDIA herein, including but not -limited to any patent rights that may be infringed by your derivative -works or by other works in which the NVIDIA Software may be -incorporated. No hardware is licensed hereunder. - -THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT -WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, -INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, -NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR -ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER -PRODUCTS. - -IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, -INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF -USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY -OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE -NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, -TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF -NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -\****************************************************************************/ -// -// symbols.c -// - -#include -#include -#include - -#include "compiler/preprocessor/slglobals.h" - -#if defined(_MSC_VER) -#pragma warning(disable: 4706) -#endif - -/////////////////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////// Symbol Table Variables: /////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////// - -Scope *ScopeList = NULL; -Scope *CurrentScope = NULL; -Scope *GlobalScope = NULL; - -static void unlinkScope(void *_scope) { - Scope *scope = _scope; - - if (scope->next) - scope->next->prev = scope->prev; - if (scope->prev) - scope->prev->next = scope->next; - else - ScopeList = scope->next; -} - -/* - * NewScope() - * - */ -Scope *NewScopeInPool(MemoryPool *pool) -{ - Scope *lScope; - - lScope = mem_Alloc(pool, sizeof(Scope)); - lScope->pool = pool; - lScope->parent = NULL; - lScope->funScope = NULL; - lScope->symbols = NULL; - - lScope->level = 0; - - lScope->programs = NULL; - if ((lScope->next = ScopeList)) - ScopeList->prev = lScope; - lScope->prev = 0; - ScopeList = lScope; - mem_AddCleanup(pool, unlinkScope, lScope); - return lScope; -} // NewScope - -/* - * PushScope() - * - */ - -void PushScope(Scope *fScope) -{ - Scope *lScope; - - if (CurrentScope) { - fScope->level = CurrentScope->level + 1; - if (fScope->level == 1) { - if (!GlobalScope) { - /* HACK - CTD -- if GlobalScope==NULL and level==1, we're - * defining a function in the superglobal scope. Things - * will break if we leave the level as 1, so we arbitrarily - * set it to 2 */ - fScope->level = 2; - } - } - if (fScope->level >= 2) { - lScope = fScope; - while (lScope->level > 2) - lScope = lScope->next; - fScope->funScope = lScope; - } - } else { - fScope->level = 0; - } - fScope->parent = CurrentScope; - CurrentScope = fScope; -} // PushScope - -/* - * PopScope() - * - */ - -Scope *PopScope(void) -{ - Scope *lScope; - - lScope = CurrentScope; - if (CurrentScope) - CurrentScope = CurrentScope->parent; - return lScope; -} // PopScope - -/* - * NewSymbol() - Allocate a new symbol node; - * - */ - -Symbol *NewSymbol(SourceLoc *loc, Scope *fScope, int name, symbolkind kind) -{ - Symbol *lSymb; - char *pch; - unsigned int ii; - - lSymb = (Symbol *) mem_Alloc(fScope->pool, sizeof(Symbol)); - lSymb->left = NULL; - lSymb->right = NULL; - lSymb->next = NULL; - lSymb->name = name; - lSymb->loc = *loc; - lSymb->kind = kind; - - // Clear union area: - - pch = (char *) &lSymb->details; - for (ii = 0; ii < sizeof(lSymb->details); ii++) - *pch++ = 0; - return lSymb; -} // NewSymbol - -/* - * lAddToTree() - Using a binary tree is not a good idea for basic atom values because they - * are generated in order. We'll fix this later (by reversing the bit pattern). - */ - -static void lAddToTree(Symbol **fSymbols, Symbol *fSymb) -{ - Symbol *lSymb; - int lrev, frev; - - lSymb = *fSymbols; - if (lSymb) { - frev = GetReversedAtom(atable, fSymb->name); - while (lSymb) { - lrev = GetReversedAtom(atable, lSymb->name); - if (lrev == frev) { - CPPErrorToInfoLog("GetAtomString(atable, fSymb->name)"); - break; - } else { - if (lrev > frev) { - if (lSymb->left) { - lSymb = lSymb->left; - } else { - lSymb->left = fSymb; - break; - } - } else { - if (lSymb->right) { - lSymb = lSymb->right; - } else { - lSymb->right = fSymb; - break; - } - } - } - } - } else { - *fSymbols = fSymb; - } -} // lAddToTree - - -/* - * AddSymbol() - Add a variable, type, or function name to a scope. - * - */ - -Symbol *AddSymbol(SourceLoc *loc, Scope *fScope, int atom, symbolkind kind) -{ - Symbol *lSymb; - - if (!fScope) - fScope = CurrentScope; - lSymb = NewSymbol(loc, fScope, atom, kind); - lAddToTree(&fScope->symbols, lSymb); - return lSymb; -} // AddSymbol - - -/*********************************************************************************************/ -/************************************ Symbol Semantic Functions ******************************/ -/*********************************************************************************************/ - -/* - * LookUpLocalSymbol() - * - */ - -Symbol *LookUpLocalSymbol(Scope *fScope, int atom) -{ - Symbol *lSymb; - int rname, ratom; - - ratom = GetReversedAtom(atable, atom); - if (!fScope) - fScope = CurrentScope; - lSymb = fScope->symbols; - while (lSymb) { - rname = GetReversedAtom(atable, lSymb->name); - if (rname == ratom) { - return lSymb; - } else { - if (rname > ratom) { - lSymb = lSymb->left; - } else { - lSymb = lSymb->right; - } - } - } - return NULL; -} // LookUpLocalSymbol - -/* - * LookUpSymbol() - * - */ - -Symbol *LookUpSymbol(Scope *fScope, int atom) -{ - Symbol *lSymb; - - if (!fScope) - fScope = CurrentScope; - while (fScope) { - lSymb = LookUpLocalSymbol(fScope, atom); - if (lSymb) - return lSymb; - fScope = fScope->parent; - } - return NULL; -} // LookUpSymbol - diff --git a/src/3rdparty/angle/src/compiler/preprocessor/symbols.h b/src/3rdparty/angle/src/compiler/preprocessor/symbols.h deleted file mode 100644 index e7d0b075fa..0000000000 --- a/src/3rdparty/angle/src/compiler/preprocessor/symbols.h +++ /dev/null @@ -1,111 +0,0 @@ -/****************************************************************************\ -Copyright (c) 2002, NVIDIA Corporation. - -NVIDIA Corporation("NVIDIA") supplies this software to you in -consideration of your agreement to the following terms, and your use, -installation, modification or redistribution of this NVIDIA software -constitutes acceptance of these terms. If you do not agree with these -terms, please do not use, install, modify or redistribute this NVIDIA -software. - -In consideration of your agreement to abide by the following terms, and -subject to these terms, NVIDIA grants you a personal, non-exclusive -license, under NVIDIA's copyrights in this original NVIDIA software (the -"NVIDIA Software"), to use, reproduce, modify and redistribute the -NVIDIA Software, with or without modifications, in source and/or binary -forms; provided that if you redistribute the NVIDIA Software, you must -retain the copyright notice of NVIDIA, this notice and the following -text and disclaimers in all such redistributions of the NVIDIA Software. -Neither the name, trademarks, service marks nor logos of NVIDIA -Corporation may be used to endorse or promote products derived from the -NVIDIA Software without specific prior written permission from NVIDIA. -Except as expressly stated in this notice, no other rights or licenses -express or implied, are granted by NVIDIA herein, including but not -limited to any patent rights that may be infringed by your derivative -works or by other works in which the NVIDIA Software may be -incorporated. No hardware is licensed hereunder. - -THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT -WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, -INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, -NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR -ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER -PRODUCTS. - -IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, -INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF -USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY -OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE -NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, -TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF -NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -\****************************************************************************/ -// -// symbols.h -// - -#if !defined(__SYMBOLS_H) -#define __SYMBOLS_H 1 - -#include "compiler/preprocessor/memory.h" - -typedef enum symbolkind { - MACRO_S -} symbolkind; - -// Typedefs for things defined here in "symbols.h": - -typedef struct Scope_Rec Scope; -typedef struct Symbol_Rec Symbol; - -typedef struct SymbolList_Rec { - struct SymbolList_Rec *next; - Symbol *symb; -} SymbolList; - -struct Scope_Rec { - Scope *next, *prev; // doubly-linked list of all scopes - Scope *parent; - Scope *funScope; // Points to base scope of enclosing function - MemoryPool *pool; // pool used for allocation in this scope - Symbol *symbols; - - int level; // 0 = super globals, 1 = globals, etc. - - // Only used at global scope (level 1): - SymbolList *programs; // List of programs for this compilation. -}; - - -// Symbol table is a simple binary tree. - -#include "compiler/preprocessor/cpp.h" // to get MacroSymbol def - -struct Symbol_Rec { - Symbol *left, *right; - Symbol *next; - int name; // Name atom - SourceLoc loc; - symbolkind kind; - union { - MacroSymbol mac; - } details; -}; - -extern Scope *CurrentScope; -extern Scope *GlobalScope; -extern Scope *ScopeList; - -Scope *NewScopeInPool(MemoryPool *); -#define NewScope() NewScopeInPool(CurrentScope->pool) -void PushScope(Scope *fScope); -Scope *PopScope(void); -Symbol *NewSymbol(SourceLoc *loc, Scope *fScope, int name, symbolkind kind); -Symbol *AddSymbol(SourceLoc *loc, Scope *fScope, int atom, symbolkind kind); -Symbol *LookUpLocalSymbol(Scope *fScope, int atom); -Symbol *LookUpSymbol(Scope *fScope, int atom); - - -#endif // !defined(__SYMBOLS_H) - diff --git a/src/3rdparty/angle/src/compiler/preprocessor/tokens.c b/src/3rdparty/angle/src/compiler/preprocessor/tokens.c deleted file mode 100644 index b94c05ebd4..0000000000 --- a/src/3rdparty/angle/src/compiler/preprocessor/tokens.c +++ /dev/null @@ -1,467 +0,0 @@ -/****************************************************************************\ -Copyright (c) 2002, NVIDIA Corporation. - -NVIDIA Corporation("NVIDIA") supplies this software to you in -consideration of your agreement to the following terms, and your use, -installation, modification or redistribution of this NVIDIA software -constitutes acceptance of these terms. If you do not agree with these -terms, please do not use, install, modify or redistribute this NVIDIA -software. - -In consideration of your agreement to abide by the following terms, and -subject to these terms, NVIDIA grants you a personal, non-exclusive -license, under NVIDIA's copyrights in this original NVIDIA software (the -"NVIDIA Software"), to use, reproduce, modify and redistribute the -NVIDIA Software, with or without modifications, in source and/or binary -forms; provided that if you redistribute the NVIDIA Software, you must -retain the copyright notice of NVIDIA, this notice and the following -text and disclaimers in all such redistributions of the NVIDIA Software. -Neither the name, trademarks, service marks nor logos of NVIDIA -Corporation may be used to endorse or promote products derived from the -NVIDIA Software without specific prior written permission from NVIDIA. -Except as expressly stated in this notice, no other rights or licenses -express or implied, are granted by NVIDIA herein, including but not -limited to any patent rights that may be infringed by your derivative -works or by other works in which the NVIDIA Software may be -incorporated. No hardware is licensed hereunder. - -THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT -WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, -INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, -NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR -ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER -PRODUCTS. - -IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, -INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF -USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY -OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE -NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, -TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF -NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -\****************************************************************************/ -// -// tokens.c -// - -#include -#include -#include -#include - -#include "common/angleutils.h" -#include "compiler/debug.h" -#include "compiler/preprocessor/slglobals.h" -#include "compiler/util.h" - -#if defined(_MSC_VER) -#pragma warning(disable: 4054) -#pragma warning(disable: 4152) -#endif - -/////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////////// Preprocessor and Token Recorder and Playback: //////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////// - -/* - * idstr() - * Copy a string to a malloc'ed block and convert it into something suitable - * for an ID - * - */ - -static char *idstr(const char *fstr, MemoryPool *pool) -{ - size_t len; - char *str, *t; - const char *f; - - len = strlen(fstr); - if (!pool) - str = (char *) malloc(len + 1); - else - str = (char *) mem_Alloc(pool, len + 1); - - for (f=fstr, t=str; *f; f++) { - if (isalnum(*f)) *t++ = *f; - else if (*f == '.' || *f == '/') *t++ = '_'; - } - *t = 0; - return str; -} // idstr - - -/* - * lNewBlock() - * - */ - -static TokenBlock *lNewBlock(TokenStream *fTok, MemoryPool *pool) -{ - TokenBlock *lBlock; - - if (!pool) - lBlock = (TokenBlock *) malloc(sizeof(TokenBlock) + 256); - else - lBlock = (TokenBlock *) mem_Alloc(pool, sizeof(TokenBlock) + 256); - lBlock->count = 0; - lBlock->current = 0; - lBlock->data = (unsigned char *) lBlock + sizeof(TokenBlock); - lBlock->max = 256; - lBlock->next = NULL; - if (fTok->head) { - fTok->current->next = lBlock; - } else { - fTok->head = lBlock; - } - fTok->current = lBlock; - return lBlock; -} // lNewBlock - -/* - * lAddByte() - * - */ - -static void lAddByte(TokenStream *fTok, unsigned char fVal) -{ - TokenBlock *lBlock; - lBlock = fTok->current; - if (lBlock->count >= lBlock->max) - lBlock = lNewBlock(fTok, 0); - lBlock->data[lBlock->count++] = fVal; -} // lAddByte - - - -/* - * lReadByte() - Get the next byte from a stream. - * - */ - -static int lReadByte(TokenStream *pTok) -{ - TokenBlock *lBlock; - int lval = -1; - - lBlock = pTok->current; - if (lBlock) { - if (lBlock->current >= lBlock->count) { - lBlock = lBlock->next; - if (lBlock) - lBlock->current = 0; - pTok->current = lBlock; - } - if (lBlock) - lval = lBlock->data[lBlock->current++]; - } - return lval; -} // lReadByte - -/////////////////////////////////////// Global Functions:////////////////////////////////////// - -/* - * NewTokenStream() - * - */ - -TokenStream *NewTokenStream(const char *name, MemoryPool *pool) -{ - TokenStream *pTok; - - if (!pool) - pTok = (TokenStream *) malloc(sizeof(TokenStream)); - else - pTok = (TokenStream*)mem_Alloc(pool, sizeof(TokenStream)); - pTok->next = NULL; - pTok->name = idstr(name, pool); - pTok->head = NULL; - pTok->current = NULL; - lNewBlock(pTok, pool); - return pTok; -} // NewTokenStream - -/* - * DeleteTokenStream() - * - */ - -void DeleteTokenStream(TokenStream *pTok) -{ - TokenBlock *pBlock, *nBlock; - - if (pTok) { - pBlock = pTok->head; - while (pBlock) { - nBlock = pBlock->next; - free(pBlock); - pBlock = nBlock; - } - if (pTok->name) - free(pTok->name); - free(pTok); - } -} // DeleteTokenStream - -/* - * RecordToken() - Add a token to the end of a list for later playback or printout. - * - */ - -void RecordToken(TokenStream *pTok, int token, yystypepp * yylvalpp) -{ - const char *s; - char *str=NULL; - - if (token > 256) - lAddByte(pTok, (unsigned char)((token & 0x7f) + 0x80)); - else - lAddByte(pTok, (unsigned char)(token & 0x7f)); - switch (token) { - case CPP_IDENTIFIER: - case CPP_TYPEIDENTIFIER: - case CPP_STRCONSTANT: - s = GetAtomString(atable, yylvalpp->sc_ident); - while (*s) - lAddByte(pTok, (unsigned char) *s++); - lAddByte(pTok, 0); - break; - case CPP_FLOATCONSTANT: - case CPP_INTCONSTANT: - str=yylvalpp->symbol_name; - while (*str){ - lAddByte(pTok, (unsigned char) *str++); - } - lAddByte(pTok, 0); - break; - case '(': - lAddByte(pTok, (unsigned char)(yylvalpp->sc_int ? 1 : 0)); - default: - break; - } -} // RecordToken - -/* - * RewindTokenStream() - Reset a token stream in preperation for reading. - * - */ - -void RewindTokenStream(TokenStream *pTok) -{ - if (pTok->head) { - pTok->current = pTok->head; - pTok->current->current = 0; - } -} // RewindTokenStream - -/* - * ReadToken() - Read the next token from a stream. - * - */ - -int ReadToken(TokenStream *pTok, yystypepp * yylvalpp) -{ - char symbol_name[MAX_SYMBOL_NAME_LEN + 1]; - char string_val[MAX_STRING_LEN + 1]; - int ltoken, len; - char ch; - int base, accum; - char ch_val; - - ltoken = lReadByte(pTok); - if (ltoken >= 0) { - if (ltoken > 127) - ltoken += 128; - switch (ltoken) { - case CPP_IDENTIFIER: - case CPP_TYPEIDENTIFIER: - len = 0; - ch = lReadByte(pTok); - while ((ch >= 'a' && ch <= 'z') || - (ch >= 'A' && ch <= 'Z') || - (ch >= '0' && ch <= '9') || - ch == '_') - { - if (len < MAX_SYMBOL_NAME_LEN) { - symbol_name[len++] = ch; - ch = lReadByte(pTok); - } - } - symbol_name[len] = '\0'; - assert(ch == '\0'); - yylvalpp->sc_ident = LookUpAddString(atable, symbol_name); - return CPP_IDENTIFIER; - break; - case CPP_STRCONSTANT: - len = 0; - while ((ch = lReadByte(pTok)) != 0) - if (len < MAX_STRING_LEN) - string_val[len++] = ch; - string_val[len] = '\0'; - yylvalpp->sc_ident = LookUpAddString(atable, string_val); - break; - case CPP_FLOATCONSTANT: - len = 0; - ch = lReadByte(pTok); - while ((ch >= '0' && ch <= '9')||(ch=='e'||ch=='E'||ch=='.')||(ch=='+'||ch=='-')) - { - if (len < MAX_SYMBOL_NAME_LEN) { - symbol_name[len++] = ch; - ch = lReadByte(pTok); - } - } - symbol_name[len] = '\0'; - assert(ch == '\0'); - strcpy(yylvalpp->symbol_name,symbol_name); - yylvalpp->sc_fval=(float)atof_dot(yylvalpp->symbol_name); - break; - case CPP_INTCONSTANT: - len = 0; - accum = 0; - ch = lReadByte(pTok); - if (ch == '0') { - symbol_name[len++] = ch; - ch = lReadByte(pTok); - if (ch == 'x' || ch == 'X') { - symbol_name[len++] = ch; - base = 16; - ch = lReadByte(pTok); - } else { - base = 8; - } - } else { - base = 10; - } - - while (len < MAX_SYMBOL_NAME_LEN) - { - ch_val = -1; - if (isdigit(ch)) - ch_val = ch - '0'; - else if (isxdigit(ch)) - ch_val = tolower(ch) - 'a' + 10; - - if (ch_val < 0 || ch_val >= base) - break; - - symbol_name[len++] = ch; - accum = accum * base + ch_val; - ch = lReadByte(pTok); - } - symbol_name[len] = '\0'; - assert(ch == '\0'); - strcpy(yylvalpp->symbol_name, symbol_name); - yylvalpp->sc_int = accum; - break; - case '(': - yylvalpp->sc_int = lReadByte(pTok); - break; - } - return ltoken; - } - return EOF_SY; -} // ReadToken - -typedef struct TokenInputSrc { - InputSrc base; - TokenStream *tokens; - int (*final)(CPPStruct *); -} TokenInputSrc; - -static int scan_token(TokenInputSrc *in, yystypepp * yylvalpp) -{ - int token = ReadToken(in->tokens, yylvalpp); - int (*final)(CPPStruct *); - cpp->tokenLoc->file = cpp->currentInput->name; - cpp->tokenLoc->line = cpp->currentInput->line; - if (token == '\n') { - in->base.line++; - return token; - } - if (token > 0) return token; - cpp->currentInput = in->base.prev; - final = in->final; - free(in); - if (final && !final(cpp)) return -1; - return cpp->currentInput->scan(cpp->currentInput, yylvalpp); -} - -int ReadFromTokenStream(TokenStream *ts, int name, int (*final)(CPPStruct *)) -{ - TokenInputSrc *in = malloc(sizeof(TokenInputSrc)); - memset(in, 0, sizeof(TokenInputSrc)); - in->base.name = name; - in->base.prev = cpp->currentInput; - in->base.scan = (int (*)(InputSrc *, yystypepp *))scan_token; - in->base.line = 1; - in->tokens = ts; - in->final = final; - RewindTokenStream(ts); - cpp->currentInput = &in->base; - return 1; -} - -typedef struct UngotToken { - InputSrc base; - int token; - yystypepp lval; -} UngotToken; - -static int reget_token(UngotToken *t, yystypepp * yylvalpp) -{ - int token = t->token; - *yylvalpp = t->lval; - cpp->currentInput = t->base.prev; - free(t); - return token; -} - -void UngetToken(int token, yystypepp * yylvalpp) { - UngotToken *t = malloc(sizeof(UngotToken)); - memset(t, 0, sizeof(UngotToken)); - t->token = token; - t->lval = *yylvalpp; - t->base.scan = (void *)reget_token; - t->base.prev = cpp->currentInput; - t->base.name = cpp->currentInput->name; - t->base.line = cpp->currentInput->line; - cpp->currentInput = &t->base; -} - - -void DumpTokenStream(FILE *fp, TokenStream *s, yystypepp * yylvalpp) { - int token; - char str[100]; - - if (fp == 0) fp = stdout; - RewindTokenStream(s); - while ((token = ReadToken(s, yylvalpp)) > 0) { - switch (token) { - case CPP_IDENTIFIER: - case CPP_TYPEIDENTIFIER: - snprintf(str, sizeof(str), "%s ", GetAtomString(atable, yylvalpp->sc_ident)); - break; - case CPP_STRCONSTANT: - snprintf(str, sizeof(str), "\"%s\"", GetAtomString(atable, yylvalpp->sc_ident)); - break; - case CPP_FLOATCONSTANT: - //printf("%g9.6 ", yylvalpp->sc_fval); - break; - case CPP_INTCONSTANT: - //printf("%d ", yylvalpp->sc_int); - break; - default: - if (token >= 127) - snprintf(str, sizeof(str), "%s ", GetAtomString(atable, token)); - else - snprintf(str, sizeof(str), "%c", token); - break; - } - CPPDebugLogMsg(str); - } -} - -/////////////////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////// End of tokens.c /////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/3rdparty/angle/src/compiler/preprocessor/tokens.h b/src/3rdparty/angle/src/compiler/preprocessor/tokens.h deleted file mode 100644 index dbf4a2ccfe..0000000000 --- a/src/3rdparty/angle/src/compiler/preprocessor/tokens.h +++ /dev/null @@ -1,90 +0,0 @@ -/****************************************************************************\ -Copyright (c) 2002, NVIDIA Corporation. - -NVIDIA Corporation("NVIDIA") supplies this software to you in -consideration of your agreement to the following terms, and your use, -installation, modification or redistribution of this NVIDIA software -constitutes acceptance of these terms. If you do not agree with these -terms, please do not use, install, modify or redistribute this NVIDIA -software. - -In consideration of your agreement to abide by the following terms, and -subject to these terms, NVIDIA grants you a personal, non-exclusive -license, under NVIDIA's copyrights in this original NVIDIA software (the -"NVIDIA Software"), to use, reproduce, modify and redistribute the -NVIDIA Software, with or without modifications, in source and/or binary -forms; provided that if you redistribute the NVIDIA Software, you must -retain the copyright notice of NVIDIA, this notice and the following -text and disclaimers in all such redistributions of the NVIDIA Software. -Neither the name, trademarks, service marks nor logos of NVIDIA -Corporation may be used to endorse or promote products derived from the -NVIDIA Software without specific prior written permission from NVIDIA. -Except as expressly stated in this notice, no other rights or licenses -express or implied, are granted by NVIDIA herein, including but not -limited to any patent rights that may be infringed by your derivative -works or by other works in which the NVIDIA Software may be -incorporated. No hardware is licensed hereunder. - -THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT -WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, -INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, -NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR -ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER -PRODUCTS. - -IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, -INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF -USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY -OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE -NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, -TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF -NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -\****************************************************************************/ -// -// tokens.h -// - -#if !defined(__TOKENS_H) -#define __TOKENS_H 1 - -#include -#include "compiler/preprocessor/parser.h" - -#define EOF_SY (-1) - -typedef struct TokenBlock_Rec TokenBlock; - -typedef struct TokenStream_Rec { - struct TokenStream_Rec *next; - char *name; - TokenBlock *head; - TokenBlock *current; -} TokenStream; - -struct TokenBlock_Rec { - TokenBlock *next; - int current; - int count; - int max; - unsigned char *data; -}; - -extern TokenStream stdlib_cpp_stream; - - -TokenStream *NewTokenStream(const char *name, MemoryPool *pool); -void DeleteTokenStream(TokenStream *pTok); -void RecordToken(TokenStream *pTok, int token, yystypepp * yylvalpp); -void RewindTokenStream(TokenStream *pTok); -int ReadToken(TokenStream *pTok, yystypepp * yylvalpp); -int ReadFromTokenStream(TokenStream *pTok, int name, int (*final)(CPPStruct *)); -void UngetToken(int, yystypepp * yylvalpp); - -#if defined(CPPC_ENABLE_TOOLS) - -void DumpTokenStream(FILE *, TokenStream *, yystypepp * yylvalpp); - -#endif // defined(CPPC_ENABLE_TOOLS) - -#endif // !defined(__TOKENS_H) diff --git a/src/3rdparty/angle/src/libEGL/Config.cpp b/src/3rdparty/angle/src/libEGL/Config.cpp index 89bc8d89f4..5488cb6f4f 100644 --- a/src/3rdparty/angle/src/libEGL/Config.cpp +++ b/src/3rdparty/angle/src/libEGL/Config.cpp @@ -13,76 +13,30 @@ #include #include +#include +#include + #include "common/debug.h" using namespace std; namespace egl { -Config::Config(D3DDISPLAYMODE displayMode, EGLint minInterval, EGLint maxInterval, D3DFORMAT renderTargetFormat, D3DFORMAT depthStencilFormat, EGLint multiSample, EGLint texWidth, EGLint texHeight) - : mDisplayMode(displayMode), mRenderTargetFormat(renderTargetFormat), mDepthStencilFormat(depthStencilFormat), mMultiSample(multiSample) -{ - set(displayMode, minInterval, maxInterval, renderTargetFormat, depthStencilFormat, multiSample, texWidth, texHeight); -} - -void Config::setDefaults() -{ - mBufferSize = 0; - mRedSize = 0; - mGreenSize = 0; - mBlueSize = 0; - mLuminanceSize = 0; - mAlphaSize = 0; - mAlphaMaskSize = 0; - mBindToTextureRGB = EGL_DONT_CARE; - mBindToTextureRGBA = EGL_DONT_CARE; - mColorBufferType = EGL_RGB_BUFFER; - mConfigCaveat = EGL_DONT_CARE; - mConfigID = EGL_DONT_CARE; - mConformant = 0; - mDepthSize = 0; - mLevel = 0; - mMatchNativePixmap = EGL_NONE; - mMaxPBufferWidth = 0; - mMaxPBufferHeight = 0; - mMaxPBufferPixels = 0; - mMaxSwapInterval = EGL_DONT_CARE; - mMinSwapInterval = EGL_DONT_CARE; - mNativeRenderable = EGL_DONT_CARE; - mNativeVisualID = 0; - mNativeVisualType = EGL_DONT_CARE; - mRenderableType = EGL_OPENGL_ES_BIT; - mSampleBuffers = 0; - mSamples = 0; - mStencilSize = 0; - mSurfaceType = EGL_WINDOW_BIT; - mTransparentType = EGL_NONE; - mTransparentRedValue = EGL_DONT_CARE; - mTransparentGreenValue = EGL_DONT_CARE; - mTransparentBlueValue = EGL_DONT_CARE; -} - -void Config::set(D3DDISPLAYMODE displayMode, EGLint minInterval, EGLint maxInterval, D3DFORMAT renderTargetFormat, D3DFORMAT depthStencilFormat, EGLint multiSample, EGLint texWidth, EGLint texHeight) +Config::Config(rx::ConfigDesc desc, EGLint minInterval, EGLint maxInterval, EGLint texWidth, EGLint texHeight) + : mRenderTargetFormat(desc.renderTargetFormat), mDepthStencilFormat(desc.depthStencilFormat), mMultiSample(desc.multiSample) { mBindToTextureRGB = EGL_FALSE; mBindToTextureRGBA = EGL_FALSE; - switch (renderTargetFormat) + switch (desc.renderTargetFormat) { - case D3DFMT_A1R5G5B5: + case GL_RGB5_A1: mBufferSize = 16; mRedSize = 5; mGreenSize = 5; mBlueSize = 5; mAlphaSize = 1; break; - case D3DFMT_A2R10G10B10: - mBufferSize = 32; - mRedSize = 10; - mGreenSize = 10; - mBlueSize = 10; - mAlphaSize = 2; - break; - case D3DFMT_A8R8G8B8: + case GL_RGBA8_OES: mBufferSize = 32; mRedSize = 8; mGreenSize = 8; @@ -90,14 +44,14 @@ void Config::set(D3DDISPLAYMODE displayMode, EGLint minInterval, EGLint maxInter mAlphaSize = 8; mBindToTextureRGBA = true; break; - case D3DFMT_R5G6B5: + case GL_RGB565: mBufferSize = 16; mRedSize = 5; mGreenSize = 6; mBlueSize = 5; mAlphaSize = 0; break; - case D3DFMT_X8R8G8B8: + case GL_RGB8_OES: mBufferSize = 32; mRedSize = 8; mGreenSize = 8; @@ -105,6 +59,14 @@ void Config::set(D3DDISPLAYMODE displayMode, EGLint minInterval, EGLint maxInter mAlphaSize = 0; mBindToTextureRGB = true; break; + case GL_BGRA8_EXT: + mBufferSize = 32; + mRedSize = 8; + mGreenSize = 8; + mBlueSize = 8; + mAlphaSize = 8; + mBindToTextureRGBA = true; + break; default: UNREACHABLE(); // Other formats should not be valid } @@ -112,52 +74,32 @@ void Config::set(D3DDISPLAYMODE displayMode, EGLint minInterval, EGLint maxInter mLuminanceSize = 0; mAlphaMaskSize = 0; mColorBufferType = EGL_RGB_BUFFER; - mConfigCaveat = (displayMode.Format == renderTargetFormat) ? EGL_NONE : EGL_SLOW_CONFIG; + mConfigCaveat = (desc.fastConfig) ? EGL_NONE : EGL_SLOW_CONFIG; mConfigID = 0; mConformant = EGL_OPENGL_ES2_BIT; - switch (depthStencilFormat) + switch (desc.depthStencilFormat) { - case D3DFMT_UNKNOWN: + case GL_NONE: mDepthSize = 0; mStencilSize = 0; break; -// case D3DFMT_D16_LOCKABLE: -// mDepthSize = 16; -// mStencilSize = 0; -// break; - case D3DFMT_D32: + case GL_DEPTH_COMPONENT32_OES: mDepthSize = 32; mStencilSize = 0; break; - case D3DFMT_D15S1: - mDepthSize = 15; - mStencilSize = 1; - break; - case D3DFMT_D24S8: + case GL_DEPTH24_STENCIL8_OES: mDepthSize = 24; mStencilSize = 8; break; - case D3DFMT_D24X8: + case GL_DEPTH_COMPONENT24_OES: mDepthSize = 24; mStencilSize = 0; break; - case D3DFMT_D24X4S4: - mDepthSize = 24; - mStencilSize = 4; - break; - case D3DFMT_D16: + case GL_DEPTH_COMPONENT16: mDepthSize = 16; mStencilSize = 0; break; -// case D3DFMT_D32F_LOCKABLE: -// mDepthSize = 32; -// mStencilSize = 0; -// break; -// case D3DFMT_D24FS8: -// mDepthSize = 24; -// mStencilSize = 8; -// break; default: UNREACHABLE(); } @@ -173,8 +115,8 @@ void Config::set(D3DDISPLAYMODE displayMode, EGLint minInterval, EGLint maxInter mNativeVisualID = 0; mNativeVisualType = 0; mRenderableType = EGL_OPENGL_ES2_BIT; - mSampleBuffers = multiSample ? 1 : 0; - mSamples = multiSample; + mSampleBuffers = desc.multiSample ? 1 : 0; + mSamples = desc.multiSample; mSurfaceType = EGL_PBUFFER_BIT | EGL_WINDOW_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT; mTransparentType = EGL_NONE; mTransparentRedValue = 0; @@ -288,10 +230,9 @@ ConfigSet::ConfigSet() { } -void ConfigSet::add(D3DDISPLAYMODE displayMode, EGLint minSwapInterval, EGLint maxSwapInterval, D3DFORMAT renderTargetFormat, D3DFORMAT depthStencilFormat, EGLint multiSample, EGLint texWidth, EGLint texHeight) +void ConfigSet::add(rx::ConfigDesc desc, EGLint minSwapInterval, EGLint maxSwapInterval, EGLint texWidth, EGLint texHeight) { - Config config(displayMode, minSwapInterval, maxSwapInterval, renderTargetFormat, depthStencilFormat, multiSample, texWidth, texHeight); - + Config config(desc, minSwapInterval, maxSwapInterval, texWidth, texHeight); mSet.insert(config); } diff --git a/src/3rdparty/angle/src/libEGL/Config.h b/src/3rdparty/angle/src/libEGL/Config.h index 95626ed1ad..680337b700 100644 --- a/src/3rdparty/angle/src/libEGL/Config.h +++ b/src/3rdparty/angle/src/libEGL/Config.h @@ -13,10 +13,10 @@ #define EGLAPI #include -#include #include +#include "libGLESv2/renderer/Renderer.h" #include "common/angleutils.h" namespace egl @@ -26,16 +26,13 @@ class Display; class Config { public: - Config(D3DDISPLAYMODE displayMode, EGLint minSwapInterval, EGLint maxSwapInterval, D3DFORMAT renderTargetFormat, D3DFORMAT depthStencilFormat, EGLint multiSample, EGLint texWidth, EGLint texHeight); + Config(rx::ConfigDesc desc, EGLint minSwapInterval, EGLint maxSwapInterval, EGLint texWidth, EGLint texHeight); - void setDefaults(); - void set(D3DDISPLAYMODE displayMode, EGLint minSwapInterval, EGLint maxSwapInterval, D3DFORMAT renderTargetFormat, D3DFORMAT depthStencilFormat, EGLint multiSample, EGLint texWidth, EGLint texHeight); EGLConfig getHandle() const; - const D3DDISPLAYMODE mDisplayMode; - const D3DFORMAT mRenderTargetFormat; - const D3DFORMAT mDepthStencilFormat; - const EGLint mMultiSample; + const GLenum mRenderTargetFormat; + const GLenum mDepthStencilFormat; + const GLint mMultiSample; EGLint mBufferSize; // Depth of the color buffer EGLint mRedSize; // Bits of Red in the color buffer @@ -99,7 +96,7 @@ class ConfigSet public: ConfigSet(); - void add(D3DDISPLAYMODE displayMode, EGLint minSwapInterval, EGLint maxSwapInterval, D3DFORMAT renderTargetFormat, D3DFORMAT depthStencilFormat, EGLint multiSample, EGLint texWidth, EGLint texHeight); + void add(rx::ConfigDesc desc, EGLint minSwapInterval, EGLint maxSwapInterval, EGLint texWidth, EGLint texHeight); size_t size() const; bool getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig); const egl::Config *get(EGLConfig configHandle); diff --git a/src/3rdparty/angle/src/libEGL/Display.cpp b/src/3rdparty/angle/src/libEGL/Display.cpp index a2dee6d964..d5d0f0f831 100644 --- a/src/3rdparty/angle/src/libEGL/Display.cpp +++ b/src/3rdparty/angle/src/libEGL/Display.cpp @@ -16,20 +16,12 @@ #include "common/debug.h" #include "libGLESv2/mathutil.h" -#include "libGLESv2/utilities.h" +#include "libGLESv2/main.h" +#include "libGLESv2/Context.h" +#include "libGLESv2/renderer/SwapChain.h" #include "libEGL/main.h" - -// Can also be enabled by defining FORCE_REF_RAST in the project's predefined macros -#define REF_RAST 0 - -// The "Debug This Pixel..." feature in PIX often fails when using the -// D3D9Ex interfaces. In order to get debug pixel to work on a Vista/Win 7 -// machine, define "ANGLE_ENABLE_D3D9EX=0" in your project file. -#if !defined(ANGLE_ENABLE_D3D9EX) -// Enables use of the IDirect3D9Ex interface, when available -#define ANGLE_ENABLE_D3D9EX 1 -#endif // !defined(ANGLE_ENABLE_D3D9EX) +#include "libEGL/Surface.h" namespace egl { @@ -69,27 +61,10 @@ egl::Display *Display::getDisplay(EGLNativeDisplayType displayId) Display::Display(EGLNativeDisplayType displayId, HDC deviceContext, bool software) : mDc(deviceContext) { - mD3d9Module = NULL; - - mD3d9 = NULL; - mD3d9Ex = NULL; - mDevice = NULL; - mDeviceEx = NULL; - mDeviceWindow = NULL; - - mAdapter = D3DADAPTER_DEFAULT; - - #if REF_RAST == 1 || defined(FORCE_REF_RAST) - mDeviceType = D3DDEVTYPE_REF; - #else - mDeviceType = D3DDEVTYPE_HAL; - #endif - - mMinSwapInterval = 1; - mMaxSwapInterval = 1; + mSoftwareDevice = software; mDisplayId = displayId; - mDeviceLost = false; + mRenderer = NULL; } Display::~Display() @@ -100,7 +75,7 @@ Display::~Display() if (thisDisplay != displays.end()) { - displays.erase(thisDisplay); + displays.erase(thisDisplay); } } @@ -111,197 +86,48 @@ bool Display::initialize() return true; } - if (mSoftwareDevice) - { - mD3d9Module = GetModuleHandle(TEXT("swiftshader_d3d9.dll")); - } - else - { - mD3d9Module = GetModuleHandle(TEXT("d3d9.dll")); - } - if (mD3d9Module == NULL) + mRenderer = glCreateRenderer(this, mDc, mSoftwareDevice); + + if (!mRenderer) { terminate(); - return false; - } - - 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))) - { - ASSERT(mD3d9Ex); - mD3d9Ex->QueryInterface(IID_IDirect3D9, reinterpret_cast(&mD3d9)); - ASSERT(mD3d9); - } - else - { - mD3d9 = Direct3DCreate9(D3D_SDK_VERSION); + return error(EGL_NOT_INITIALIZED, false); } - if (mD3d9) - { - if (mDc != NULL) - { - // UNIMPLEMENTED(); // FIXME: Determine which adapter index the device context corresponds to - } - - HRESULT result; - - // Give up on getting device caps after about one second. - for (int i = 0; i < 10; ++i) - { - result = mD3d9->GetDeviceCaps(mAdapter, mDeviceType, &mDeviceCaps); - - if (SUCCEEDED(result)) - { - break; - } - else if (result == D3DERR_NOTAVAILABLE) - { - Sleep(100); // Give the driver some time to initialize/recover - } - else if (FAILED(result)) // D3DERR_OUTOFVIDEOMEMORY, E_OUTOFMEMORY, D3DERR_INVALIDDEVICE, or another error we can't recover from - { - terminate(); - return error(EGL_BAD_ALLOC, false); - } - } - - if (mDeviceCaps.PixelShaderVersion < D3DPS_VERSION(2, 0)) - { - terminate(); - return error(EGL_NOT_INITIALIZED, false); - } - - // When DirectX9 is running with an older DirectX8 driver, a StretchRect from a regular texture to a render target texture is not supported. - // This is required by Texture2D::convertToRenderTarget. - if ((mDeviceCaps.DevCaps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES) == 0) - { - terminate(); - return error(EGL_NOT_INITIALIZED, false); - } - - mMinSwapInterval = 4; - mMaxSwapInterval = 0; - - if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE) {mMinSwapInterval = std::min(mMinSwapInterval, 0); mMaxSwapInterval = std::max(mMaxSwapInterval, 0);} - if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_ONE) {mMinSwapInterval = std::min(mMinSwapInterval, 1); mMaxSwapInterval = std::max(mMaxSwapInterval, 1);} - if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_TWO) {mMinSwapInterval = std::min(mMinSwapInterval, 2); mMaxSwapInterval = std::max(mMaxSwapInterval, 2);} - if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_THREE) {mMinSwapInterval = std::min(mMinSwapInterval, 3); mMaxSwapInterval = std::max(mMaxSwapInterval, 3);} - if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_FOUR) {mMinSwapInterval = std::min(mMinSwapInterval, 4); mMaxSwapInterval = std::max(mMaxSwapInterval, 4);} - - mD3d9->GetAdapterIdentifier(mAdapter, 0, &mAdapterIdentifier); + EGLint minSwapInterval = mRenderer->getMinSwapInterval(); + EGLint maxSwapInterval = mRenderer->getMaxSwapInterval(); + EGLint maxTextureWidth = mRenderer->getMaxTextureWidth(); + EGLint maxTextureHeight = mRenderer->getMaxTextureHeight(); - // ATI cards on XP have problems with non-power-of-two textures. - mSupportsNonPower2Textures = !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_POW2) && - !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2) && - !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL) && - !(getComparableOSVersion() < versionWindowsVista && mAdapterIdentifier.VendorId == VENDOR_ID_AMD); - - const D3DFORMAT renderTargetFormats[] = - { - D3DFMT_A1R5G5B5, - // D3DFMT_A2R10G10B10, // The color_ramp conformance test uses ReadPixels with UNSIGNED_BYTE causing it to think that rendering skipped a colour value. - D3DFMT_A8R8G8B8, - D3DFMT_R5G6B5, - // D3DFMT_X1R5G5B5, // Has no compatible OpenGL ES renderbuffer format - D3DFMT_X8R8G8B8 - }; - - const D3DFORMAT depthStencilFormats[] = - { - D3DFMT_UNKNOWN, - // D3DFMT_D16_LOCKABLE, - D3DFMT_D32, - // D3DFMT_D15S1, - D3DFMT_D24S8, - D3DFMT_D24X8, - // D3DFMT_D24X4S4, - D3DFMT_D16, - // D3DFMT_D32F_LOCKABLE, - // D3DFMT_D24FS8 - }; - - D3DDISPLAYMODE currentDisplayMode; - mD3d9->GetAdapterDisplayMode(mAdapter, ¤tDisplayMode); - - ConfigSet configSet; - - for (int formatIndex = 0; formatIndex < sizeof(renderTargetFormats) / sizeof(D3DFORMAT); formatIndex++) - { - D3DFORMAT renderTargetFormat = renderTargetFormats[formatIndex]; + rx::ConfigDesc *descList; + int numConfigs = mRenderer->generateConfigs(&descList); + ConfigSet configSet; - HRESULT result = mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, renderTargetFormat); + for (int i = 0; i < numConfigs; ++i) + configSet.add(descList[i], minSwapInterval, maxSwapInterval, + maxTextureWidth, maxTextureHeight); - if (SUCCEEDED(result)) - { - for (int depthStencilIndex = 0; depthStencilIndex < sizeof(depthStencilFormats) / sizeof(D3DFORMAT); depthStencilIndex++) - { - D3DFORMAT depthStencilFormat = depthStencilFormats[depthStencilIndex]; - HRESULT result = D3D_OK; - - if(depthStencilFormat != D3DFMT_UNKNOWN) - { - result = mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, depthStencilFormat); - } - - if (SUCCEEDED(result)) - { - if(depthStencilFormat != D3DFMT_UNKNOWN) - { - result = mD3d9->CheckDepthStencilMatch(mAdapter, mDeviceType, currentDisplayMode.Format, renderTargetFormat, depthStencilFormat); - } - - if (SUCCEEDED(result)) - { - // FIXME: enumerate multi-sampling - - configSet.add(currentDisplayMode, mMinSwapInterval, mMaxSwapInterval, renderTargetFormat, depthStencilFormat, 0, - mDeviceCaps.MaxTextureWidth, mDeviceCaps.MaxTextureHeight); - } - } - } - } - } - - // Give the sorted configs a unique ID and store them internally - EGLint index = 1; - for (ConfigSet::Iterator config = configSet.mSet.begin(); config != configSet.mSet.end(); config++) - { - Config configuration = *config; - configuration.mConfigID = index; - index++; - - mConfigSet.mSet.insert(configuration); - } - } - - if (!isInitialized()) + // Give the sorted configs a unique ID and store them internally + EGLint index = 1; + for (ConfigSet::Iterator config = configSet.mSet.begin(); config != configSet.mSet.end(); config++) { - terminate(); + Config configuration = *config; + configuration.mConfigID = index; + index++; - return false; + mConfigSet.mSet.insert(configuration); } - initExtensionString(); - - static const TCHAR windowName[] = TEXT("AngleHiddenWindow"); - static const TCHAR className[] = TEXT("STATIC"); - - mDeviceWindow = CreateWindowEx(WS_EX_NOACTIVATE, className, windowName, WS_DISABLED | WS_POPUP, 0, 0, 1, 1, HWND_MESSAGE, NULL, GetModuleHandle(NULL), NULL); + mRenderer->deleteConfigs(descList); + descList = NULL; - if (!createDevice()) + if (!isInitialized()) { terminate(); return false; } - mVertexShaderCache.initialize(mDevice); - mPixelShaderCache.initialize(mDevice); + initExtensionString(); return true; } @@ -318,79 +144,8 @@ void Display::terminate() destroyContext(*mContextSet.begin()); } - while (!mEventQueryPool.empty()) - { - mEventQueryPool.back()->Release(); - mEventQueryPool.pop_back(); - } - - mVertexShaderCache.clear(); - mPixelShaderCache.clear(); - - if (mDevice) - { - // If the device is lost, reset it first to prevent leaving the driver in an unstable state - if (testDeviceLost()) - { - resetDevice(); - } - - mDevice->Release(); - mDevice = NULL; - } - - if (mDeviceEx) - { - mDeviceEx->Release(); - mDeviceEx = NULL; - } - - if (mD3d9) - { - mD3d9->Release(); - mD3d9 = NULL; - } - - if (mDeviceWindow) - { - DestroyWindow(mDeviceWindow); - mDeviceWindow = NULL; - } - - if (mD3d9Ex) - { - mD3d9Ex->Release(); - mD3d9Ex = NULL; - } - - if (mD3d9Module) - { - mD3d9Module = NULL; - } -} - -void Display::startScene() -{ - if (!mSceneStarted) - { - long result = mDevice->BeginScene(); - if (SUCCEEDED(result)) { - // This is defensive checking against the device being - // lost at unexpected times. - mSceneStarted = true; - } - } -} - -void Display::endScene() -{ - if (mSceneStarted) - { - // EndScene can fail if the device was lost, for example due - // to a TDR during a draw call. - mDevice->EndScene(); - mSceneStarted = false; - } + glDestroyRenderer(mRenderer); + mRenderer = NULL; } bool Display::getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig) @@ -443,107 +198,7 @@ bool Display::getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value) return true; } -bool Display::createDevice() -{ - D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters(); - DWORD behaviorFlags = D3DCREATE_FPU_PRESERVE | D3DCREATE_NOWINDOWCHANGES; - - HRESULT result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE, &presentParameters, &mDevice); - - if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DEVICELOST) - { - return error(EGL_BAD_ALLOC, false); - } - - if (FAILED(result)) - { - result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_SOFTWARE_VERTEXPROCESSING, &presentParameters, &mDevice); - - if (FAILED(result)) - { - ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_NOTAVAILABLE || result == D3DERR_DEVICELOST); - return error(EGL_BAD_ALLOC, false); - } - } - - if (mD3d9Ex) - { - result = mDevice->QueryInterface(IID_IDirect3DDevice9Ex, (void**) &mDeviceEx); - ASSERT(SUCCEEDED(result)); - } - - initializeDevice(); - - return true; -} - -// do any one-time device initialization -// NOTE: this is also needed after a device lost/reset -// to reset the scene status and ensure the default states are reset. -void Display::initializeDevice() -{ - // Permanent non-default states - mDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, TRUE); - mDevice->SetRenderState(D3DRS_LASTPIXEL, FALSE); - - if (mDeviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0)) - { - mDevice->SetRenderState(D3DRS_POINTSIZE_MAX, (DWORD&)mDeviceCaps.MaxPointSize); - } - else - { - mDevice->SetRenderState(D3DRS_POINTSIZE_MAX, 0x3F800000); // 1.0f - } - - mSceneStarted = false; -} - -bool Display::resetDevice() -{ - D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters(); - - HRESULT result = D3D_OK; - bool lost = testDeviceLost(); - int attempts = 3; - - while (lost && attempts > 0) - { - if (mDeviceEx) - { - Sleep(500); // Give the graphics driver some CPU time - result = mDeviceEx->ResetEx(&presentParameters, NULL); - } - else - { - result = mDevice->TestCooperativeLevel(); - - while (result == D3DERR_DEVICELOST) - { - Sleep(100); // Give the graphics driver some CPU time - result = mDevice->TestCooperativeLevel(); - } - - if (result == D3DERR_DEVICENOTRESET) - { - result = mDevice->Reset(&presentParameters); - } - } - - lost = testDeviceLost(); - attempts --; - } - - if (FAILED(result)) - { - ERR("Reset/ResetEx failed multiple times: 0x%08X", result); - return error(EGL_BAD_ALLOC, false); - } - - // reset device defaults - initializeDevice(); - return true; -} EGLSurface Display::createWindowSurface(HWND window, EGLConfig config, const EGLint *attribList) { @@ -587,7 +242,7 @@ EGLSurface Display::createWindowSurface(HWND window, EGLConfig config, const EGL return error(EGL_BAD_ALLOC, EGL_NO_SURFACE); } - if (testDeviceLost()) + if (mRenderer->testDeviceLost(false)) { if (!restoreLostDevice()) return EGL_NO_SURFACE; @@ -678,7 +333,7 @@ EGLSurface Display::createOffscreenSurface(EGLConfig config, HANDLE shareHandle, return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE); } - if (textureFormat != EGL_NO_TEXTURE && !getNonPower2TextureSupport() && (!gl::isPow2(width) || !gl::isPow2(height))) + if (textureFormat != EGL_NO_TEXTURE && !mRenderer->getNonPower2TextureSupport() && (!gl::isPow2(width) || !gl::isPow2(height))) { return error(EGL_BAD_MATCH, EGL_NO_SURFACE); } @@ -700,7 +355,7 @@ EGLSurface Display::createOffscreenSurface(EGLConfig config, HANDLE shareHandle, return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE); } - if (testDeviceLost()) + if (mRenderer->testDeviceLost(false)) { if (!restoreLostDevice()) return EGL_NO_SURFACE; @@ -721,24 +376,18 @@ EGLSurface Display::createOffscreenSurface(EGLConfig config, HANDLE shareHandle, EGLContext Display::createContext(EGLConfig configHandle, const gl::Context *shareContext, bool notifyResets, bool robustAccess) { - if (!mDevice) + if (!mRenderer) { - if (!createDevice()) - { - return NULL; - } + return NULL; } - else if (testDeviceLost()) // Lost device + else if (mRenderer->testDeviceLost(false)) // Lost device { if (!restoreLostDevice()) return NULL; } - const egl::Config *config = mConfigSet.get(configHandle); - - gl::Context *context = glCreateContext(config, shareContext, notifyResets, robustAccess); + gl::Context *context = glCreateContext(shareContext, mRenderer, notifyResets, robustAccess); mContextSet.insert(context); - mDeviceLost = false; return context; } @@ -757,18 +406,9 @@ bool Display::restoreLostDevice() (*surface)->release(); } - while (!mEventQueryPool.empty()) - { - mEventQueryPool.back()->Release(); - mEventQueryPool.pop_back(); - } - - mVertexShaderCache.clear(); - mPixelShaderCache.clear(); - - if (!resetDevice()) + if (!mRenderer->resetDevice()) { - return false; + return error(EGL_BAD_ALLOC, false); } // Restore any surfaces that may have been lost @@ -799,18 +439,20 @@ void Display::notifyDeviceLost() { (*context)->markContextLost(); } - mDeviceLost = true; - error(EGL_CONTEXT_LOST); + egl::error(EGL_CONTEXT_LOST); } -bool Display::isDeviceLost() +void Display::recreateSwapChains() { - return mDeviceLost; + for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++) + { + (*surface)->getSwapChain()->recreate(); + } } bool Display::isInitialized() const { - return mD3d9 != NULL && mConfigSet.size() > 0; + return mRenderer != NULL && mConfigSet.size() > 0; } bool Display::isValidConfig(EGLConfig config) @@ -841,352 +483,10 @@ bool Display::hasExistingWindowSurface(HWND window) return false; } -EGLint Display::getMinSwapInterval() -{ - return mMinSwapInterval; -} - -EGLint Display::getMaxSwapInterval() -{ - return mMaxSwapInterval; -} - -IDirect3DDevice9 *Display::getDevice() -{ - if (!mDevice) - { - if (!createDevice()) - { - return NULL; - } - } - - return mDevice; -} - -D3DCAPS9 Display::getDeviceCaps() -{ - return mDeviceCaps; -} - -D3DADAPTER_IDENTIFIER9 *Display::getAdapterIdentifier() -{ - return &mAdapterIdentifier; -} - -bool Display::testDeviceLost() -{ - if (mDeviceEx) - { - return FAILED(mDeviceEx->CheckDeviceState(NULL)); - } - else if (mDevice) - { - return FAILED(mDevice->TestCooperativeLevel()); - } - - return false; // No device yet, so no reset required -} - -bool Display::testDeviceResettable() -{ - HRESULT status = D3D_OK; - - if (mDeviceEx) - { - status = mDeviceEx->CheckDeviceState(NULL); - } - else if (mDevice) - { - status = mDevice->TestCooperativeLevel(); - } - - switch (status) - { - case D3DERR_DEVICENOTRESET: - case D3DERR_DEVICEHUNG: - return true; - default: - return false; - } -} - -void Display::sync(bool block) -{ - HRESULT result; - - IDirect3DQuery9* query = allocateEventQuery(); - if (!query) - { - return; - } - - result = query->Issue(D3DISSUE_END); - ASSERT(SUCCEEDED(result)); - - do - { - result = query->GetData(NULL, 0, D3DGETDATA_FLUSH); - - if(block && result == S_FALSE) - { - // Keep polling, but allow other threads to do something useful first - Sleep(0); - // explicitly check for device loss - // some drivers seem to return S_FALSE even if the device is lost - // instead of D3DERR_DEVICELOST like they should - if (testDeviceLost()) - { - result = D3DERR_DEVICELOST; - } - } - } - while(block && result == S_FALSE); - - freeEventQuery(query); - - if (isDeviceLostError(result)) - { - notifyDeviceLost(); - } -} - -IDirect3DQuery9* Display::allocateEventQuery() -{ - IDirect3DQuery9 *query = NULL; - - if (mEventQueryPool.empty()) - { - HRESULT result = mDevice->CreateQuery(D3DQUERYTYPE_EVENT, &query); - ASSERT(SUCCEEDED(result)); - } - else - { - query = mEventQueryPool.back(); - mEventQueryPool.pop_back(); - } - - return query; -} - -void Display::freeEventQuery(IDirect3DQuery9* query) -{ - if (mEventQueryPool.size() > 1000) - { - query->Release(); - } - else - { - mEventQueryPool.push_back(query); - } -} - -void Display::getMultiSampleSupport(D3DFORMAT format, bool *multiSampleArray) -{ - for (int multiSampleIndex = 0; multiSampleIndex <= D3DMULTISAMPLE_16_SAMPLES; multiSampleIndex++) - { - HRESULT result = mD3d9->CheckDeviceMultiSampleType(mAdapter, mDeviceType, format, - TRUE, (D3DMULTISAMPLE_TYPE)multiSampleIndex, NULL); - - multiSampleArray[multiSampleIndex] = SUCCEEDED(result); - } -} - -bool Display::getDXT1TextureSupport() -{ - D3DDISPLAYMODE currentDisplayMode; - mD3d9->GetAdapterDisplayMode(mAdapter, ¤tDisplayMode); - - return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT1)); -} - -bool Display::getDXT3TextureSupport() -{ - D3DDISPLAYMODE currentDisplayMode; - mD3d9->GetAdapterDisplayMode(mAdapter, ¤tDisplayMode); - - return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT3)); -} - -bool Display::getDXT5TextureSupport() -{ - D3DDISPLAYMODE currentDisplayMode; - mD3d9->GetAdapterDisplayMode(mAdapter, ¤tDisplayMode); - - return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT5)); -} - -// we use INTZ for depth textures in Direct3D9 -// we also want NULL texture support to ensure the we can make depth-only FBOs -// see http://aras-p.info/texts/D3D9GPUHacks.html -bool Display::getDepthTextureSupport() const -{ - D3DDISPLAYMODE currentDisplayMode; - mD3d9->GetAdapterDisplayMode(mAdapter, ¤tDisplayMode); - - bool intz = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, - D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_TEXTURE, D3DFMT_INTZ)); - bool null = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, - D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, D3DFMT_NULL)); - - return intz && null; -} - -bool Display::getFloat32TextureSupport(bool *filtering, bool *renderable) -{ - D3DDISPLAYMODE currentDisplayMode; - mD3d9->GetAdapterDisplayMode(mAdapter, ¤tDisplayMode); - - *filtering = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER, - D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)) && - SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER, - D3DRTYPE_CUBETEXTURE, D3DFMT_A32B32G32R32F)); - - *renderable = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET, - D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F))&& - SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET, - D3DRTYPE_CUBETEXTURE, D3DFMT_A32B32G32R32F)); - - if (!*filtering && !*renderable) - { - return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, - D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)) && - SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, - D3DRTYPE_CUBETEXTURE, D3DFMT_A32B32G32R32F)); - } - else - { - return true; - } -} - -bool Display::getFloat16TextureSupport(bool *filtering, bool *renderable) -{ - D3DDISPLAYMODE currentDisplayMode; - mD3d9->GetAdapterDisplayMode(mAdapter, ¤tDisplayMode); - - *filtering = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER, - D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F)) && - SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER, - D3DRTYPE_CUBETEXTURE, D3DFMT_A16B16G16R16F)); - - *renderable = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET, - D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F)) && - SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET, - D3DRTYPE_CUBETEXTURE, D3DFMT_A16B16G16R16F)); - - if (!*filtering && !*renderable) - { - return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, - D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F)) && - SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, - D3DRTYPE_CUBETEXTURE, D3DFMT_A16B16G16R16F)); - } - else - { - return true; - } -} - -bool Display::getLuminanceTextureSupport() -{ - D3DDISPLAYMODE currentDisplayMode; - mD3d9->GetAdapterDisplayMode(mAdapter, ¤tDisplayMode); - - return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_L8)); -} - -bool Display::getLuminanceAlphaTextureSupport() -{ - D3DDISPLAYMODE currentDisplayMode; - mD3d9->GetAdapterDisplayMode(mAdapter, ¤tDisplayMode); - - return SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_A8L8)); -} - -float Display::getTextureFilterAnisotropySupport() const -{ - // Must support a minimum of 2:1 anisotropy for max anisotropy to be considered supported, per the spec - if ((mDeviceCaps.RasterCaps & D3DPRASTERCAPS_ANISOTROPY) && (mDeviceCaps.MaxAnisotropy >= 2)) - { - return mDeviceCaps.MaxAnisotropy; - } - return 1.0f; -} - -D3DPOOL Display::getBufferPool(DWORD usage) const -{ - if (mD3d9Ex != NULL) - { - return D3DPOOL_DEFAULT; - } - else - { - if (!(usage & D3DUSAGE_DYNAMIC)) - { - return D3DPOOL_MANAGED; - } - } - - return D3DPOOL_DEFAULT; -} - -D3DPOOL Display::getTexturePool(DWORD usage) const -{ - if (mD3d9Ex != NULL) - { - return D3DPOOL_DEFAULT; - } - else - { - if (!(usage & (D3DUSAGE_DEPTHSTENCIL | D3DUSAGE_RENDERTARGET))) - { - return D3DPOOL_MANAGED; - } - } - - return D3DPOOL_DEFAULT; -} - -bool Display::getEventQuerySupport() -{ - IDirect3DQuery9 *query = allocateEventQuery(); - if (query) - { - freeEventQuery(query); - return true; - } - else - { - return false; - } -} - -D3DPRESENT_PARAMETERS Display::getDefaultPresentParameters() -{ - D3DPRESENT_PARAMETERS presentParameters = {0}; - - // The default swap chain is never actually used. Surface will create a new swap chain with the proper parameters. - presentParameters.AutoDepthStencilFormat = D3DFMT_UNKNOWN; - presentParameters.BackBufferCount = 1; - presentParameters.BackBufferFormat = D3DFMT_UNKNOWN; - presentParameters.BackBufferWidth = 1; - presentParameters.BackBufferHeight = 1; - presentParameters.EnableAutoDepthStencil = FALSE; - presentParameters.Flags = 0; - presentParameters.hDeviceWindow = mDeviceWindow; - presentParameters.MultiSampleQuality = 0; - presentParameters.MultiSampleType = D3DMULTISAMPLE_NONE; - presentParameters.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; - presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD; - presentParameters.Windowed = TRUE; - - return presentParameters; -} - void Display::initExtensionString() { HMODULE swiftShader = GetModuleHandle(TEXT("swiftshader_d3d9.dll")); + bool shareHandleSupported = mRenderer->getShareHandleSupport(); mExtensionString = ""; @@ -1194,7 +494,7 @@ void Display::initExtensionString() mExtensionString += "EGL_EXT_create_context_robustness "; // ANGLE-specific extensions - if (shareHandleSupported()) + if (shareHandleSupported) { mExtensionString += "EGL_ANGLE_d3d_share_handle_client_buffer "; } @@ -1206,12 +506,15 @@ void Display::initExtensionString() mExtensionString += "EGL_ANGLE_software_display "; } - if (shareHandleSupported()) + if (shareHandleSupported) { mExtensionString += "EGL_ANGLE_surface_d3d_texture_2d_share_handle "; } - mExtensionString += "EGL_NV_post_sub_buffer"; + if (mRenderer->getPostSubBufferSupport()) + { + mExtensionString += "EGL_NV_post_sub_buffer"; + } std::string::size_type end = mExtensionString.find_last_not_of(' '); if (end != std::string::npos) @@ -1225,68 +528,5 @@ const char *Display::getExtensionString() const return mExtensionString.c_str(); } -bool Display::shareHandleSupported() const -{ - // PIX doesn't seem to support using share handles, so disable them. - return isD3d9ExDevice() && !gl::perfActive(); -} - -IDirect3DVertexShader9 *Display::createVertexShader(const DWORD *function, size_t length) -{ - return mVertexShaderCache.create(function, length); -} - -IDirect3DPixelShader9 *Display::createPixelShader(const DWORD *function, size_t length) -{ - return mPixelShaderCache.create(function, length); -} - -// Only Direct3D 10 ready devices support all the necessary vertex texture formats. -// We test this using D3D9 by checking support for the R16F format. -bool Display::getVertexTextureSupport() const -{ - if (!isInitialized() || mDeviceCaps.PixelShaderVersion < D3DPS_VERSION(3, 0)) - { - return false; - } - - D3DDISPLAYMODE currentDisplayMode; - mD3d9->GetAdapterDisplayMode(mAdapter, ¤tDisplayMode); - - HRESULT result = mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_VERTEXTEXTURE, D3DRTYPE_TEXTURE, D3DFMT_R16F); - - return SUCCEEDED(result); -} - -bool Display::getNonPower2TextureSupport() const -{ - return mSupportsNonPower2Textures; -} - -bool Display::getOcclusionQuerySupport() const -{ - if (!isInitialized()) - { - return false; - } - - IDirect3DQuery9 *query = NULL; - HRESULT result = mDevice->CreateQuery(D3DQUERYTYPE_OCCLUSION, &query); - - if (SUCCEEDED(result) && query) - { - query->Release(); - return true; - } - else - { - return false; - } -} - -bool Display::getInstancingSupport() const -{ - return mDeviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0); -} } diff --git a/src/3rdparty/angle/src/libEGL/Display.h b/src/3rdparty/angle/src/libEGL/Display.h index 23b57b74c6..8c71e51b7a 100644 --- a/src/3rdparty/angle/src/libEGL/Display.h +++ b/src/3rdparty/angle/src/libEGL/Display.h @@ -11,36 +11,22 @@ #ifndef LIBEGL_DISPLAY_H_ #define LIBEGL_DISPLAY_H_ -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif -#include -#include +#include "common/system.h" #include #include -#include "libGLESv2/Context.h" - #include "libEGL/Config.h" -#include "libEGL/ShaderCache.h" -#include "libEGL/Surface.h" - -const int versionWindowsVista = MAKEWORD(0x00, 0x06); -const int versionWindows7 = MAKEWORD(0x01, 0x06); -// Return the version of the operating system in a format suitable for ordering -// comparison. -inline int getComparableOSVersion() +namespace gl { - DWORD version = GetVersion(); - int majorVersion = LOBYTE(LOWORD(version)); - int minorVersion = HIBYTE(LOWORD(version)); - return MAKEWORD(minorVersion, majorVersion); +class Context; } namespace egl { +class Surface; + class Display { public: @@ -49,9 +35,6 @@ class Display bool initialize(); void terminate(); - virtual void startScene(); - virtual void endScene(); - static egl::Display *getDisplay(EGLNativeDisplayType displayId); bool getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig); @@ -70,81 +53,25 @@ class Display bool isValidSurface(egl::Surface *surface); bool hasExistingWindowSurface(HWND window); - EGLint getMinSwapInterval(); - EGLint getMaxSwapInterval(); - - virtual IDirect3DDevice9 *getDevice(); - virtual D3DCAPS9 getDeviceCaps(); - virtual D3DADAPTER_IDENTIFIER9 *getAdapterIdentifier(); - virtual bool testDeviceLost(); - virtual bool testDeviceResettable(); - virtual void sync(bool block); - virtual IDirect3DQuery9* allocateEventQuery(); - virtual void freeEventQuery(IDirect3DQuery9* query); - virtual void getMultiSampleSupport(D3DFORMAT format, bool *multiSampleArray); - virtual bool getDXT1TextureSupport(); - virtual bool getDXT3TextureSupport(); - virtual bool getDXT5TextureSupport(); - virtual bool getEventQuerySupport(); - virtual bool getFloat32TextureSupport(bool *filtering, bool *renderable); - virtual bool getFloat16TextureSupport(bool *filtering, bool *renderable); - virtual bool getLuminanceTextureSupport(); - virtual bool getLuminanceAlphaTextureSupport(); - virtual bool getVertexTextureSupport() const; - virtual bool getNonPower2TextureSupport() const; - virtual bool getDepthTextureSupport() const; - virtual bool getOcclusionQuerySupport() const; - virtual bool getInstancingSupport() const; - virtual float getTextureFilterAnisotropySupport() const; - virtual D3DPOOL getBufferPool(DWORD usage) const; - virtual D3DPOOL getTexturePool(DWORD usage) const; + rx::Renderer *getRenderer() { return mRenderer; }; + // exported methods must be virtual virtual void notifyDeviceLost(); - bool isDeviceLost(); + virtual void recreateSwapChains(); - bool isD3d9ExDevice() const { return mD3d9Ex != NULL; } const char *getExtensionString() const; - bool shareHandleSupported() const; - - virtual IDirect3DVertexShader9 *createVertexShader(const DWORD *function, size_t length); - virtual IDirect3DPixelShader9 *createPixelShader(const DWORD *function, size_t length); private: DISALLOW_COPY_AND_ASSIGN(Display); Display(EGLNativeDisplayType displayId, HDC deviceContext, bool software); - D3DPRESENT_PARAMETERS getDefaultPresentParameters(); - bool restoreLostDevice(); EGLNativeDisplayType mDisplayId; const HDC mDc; - HMODULE mD3d9Module; - - UINT mAdapter; - D3DDEVTYPE mDeviceType; - IDirect3D9 *mD3d9; // Always valid after successful initialization. - IDirect3D9Ex *mD3d9Ex; // Might be null if D3D9Ex is not supported. - IDirect3DDevice9 *mDevice; - IDirect3DDevice9Ex *mDeviceEx; // Might be null if D3D9Ex is not supported. - - // A pool of event queries that are currently unused. - std::vector mEventQueryPool; - - VertexShaderCache mVertexShaderCache; - PixelShaderCache mPixelShaderCache; - - D3DCAPS9 mDeviceCaps; - D3DADAPTER_IDENTIFIER9 mAdapterIdentifier; - HWND mDeviceWindow; - - bool mSceneStarted; - EGLint mMaxSwapInterval; - EGLint mMinSwapInterval; bool mSoftwareDevice; - bool mSupportsNonPower2Textures; typedef std::set SurfaceSet; SurfaceSet mSurfaceSet; @@ -153,11 +80,8 @@ class Display typedef std::set ContextSet; ContextSet mContextSet; - bool mDeviceLost; - bool createDevice(); - void initializeDevice(); - bool resetDevice(); + rx::Renderer *mRenderer; void initExtensionString(); std::string mExtensionString; diff --git a/src/3rdparty/angle/src/libEGL/ShaderCache.h b/src/3rdparty/angle/src/libEGL/ShaderCache.h deleted file mode 100644 index cfe523ba09..0000000000 --- a/src/3rdparty/angle/src/libEGL/ShaderCache.h +++ /dev/null @@ -1,116 +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. -// - -// Display.h: Defines egl::ShaderCache, a cache of Direct3D shader objects -// keyed by their byte code. - -#ifndef LIBEGL_SHADER_CACHE_H_ -#define LIBEGL_SHADER_CACHE_H_ - -#include - -#ifdef _MSC_VER -#include -#else -#include -#endif - -namespace egl -{ -template -class ShaderCache -{ - public: - ShaderCache() : mDevice(NULL) - { - } - - ~ShaderCache() - { - // Call clear while the device is still valid. - ASSERT(mMap.empty()); - } - - void initialize(IDirect3DDevice9* device) - { - mDevice = device; - } - - ShaderObject *create(const DWORD *function, size_t length) - { - std::string key(reinterpret_cast(function), length); - typename Map::iterator it = mMap.find(key); - if (it != mMap.end()) - { - it->second->AddRef(); - return it->second; - } - - ShaderObject *shader; - HRESULT result = createShader(function, &shader); - if (FAILED(result)) - { - return NULL; - } - - // Random eviction policy. - if (mMap.size() >= kMaxMapSize) - { - mMap.begin()->second->Release(); - mMap.erase(mMap.begin()); - } - - shader->AddRef(); - mMap[key] = shader; - - return shader; - } - - void clear() - { - for (typename Map::iterator it = mMap.begin(); it != mMap.end(); ++it) - { - it->second->Release(); - } - - mMap.clear(); - } - - private: - DISALLOW_COPY_AND_ASSIGN(ShaderCache); - - const static size_t kMaxMapSize = 100; - - HRESULT createShader(const DWORD *function, IDirect3DVertexShader9 **shader) - { - return mDevice->CreateVertexShader(function, shader); - } - - HRESULT createShader(const DWORD *function, IDirect3DPixelShader9 **shader) - { - return mDevice->CreatePixelShader(function, shader); - } - -#ifndef HASH_MAP -# ifdef _MSC_VER -# define HASH_MAP stdext::hash_map -# else -# define HASH_MAP std::unordered_map -# endif -#endif - - typedef HASH_MAP Map; - Map mMap; - - IDirect3DDevice9 *mDevice; -}; - -typedef ShaderCache VertexShaderCache; -typedef ShaderCache PixelShaderCache; - -} - -#endif // LIBEGL_SHADER_CACHE_H_ diff --git a/src/3rdparty/angle/src/libEGL/Surface.cpp b/src/3rdparty/angle/src/libEGL/Surface.cpp index d9e1887e85..5a62142b45 100644 --- a/src/3rdparty/angle/src/libEGL/Surface.cpp +++ b/src/3rdparty/angle/src/libEGL/Surface.cpp @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// 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. // @@ -14,6 +14,8 @@ #include "common/debug.h" #include "libGLESv2/Texture.h" +#include "libGLESv2/renderer/SwapChain.h" +#include "libGLESv2/main.h" #include "libEGL/main.h" #include "libEGL/Display.h" @@ -23,14 +25,11 @@ namespace egl { -Surface::Surface(Display *display, const Config *config, HWND window, EGLint postSubBufferSupported) +Surface::Surface(Display *display, const Config *config, HWND window, EGLint postSubBufferSupported) : mDisplay(display), mConfig(config), mWindow(window), mPostSubBufferSupported(postSubBufferSupported) { + mRenderer = mDisplay->getRenderer(); mSwapChain = NULL; - mBackBuffer = NULL; - mDepthStencil = NULL; - mRenderTarget = NULL; - mOffscreenTexture = NULL; mShareHandle = NULL; mTexture = NULL; mTextureFormat = EGL_NO_TEXTURE; @@ -40,6 +39,8 @@ Surface::Surface(Display *display, const Config *config, HWND window, EGLint pos mRenderBuffer = EGL_BACK_BUFFER; mSwapBehavior = EGL_BUFFER_PRESERVED; mSwapInterval = -1; + mWidth = -1; + mHeight = -1; setSwapInterval(1); subclassWindow(); @@ -48,11 +49,8 @@ Surface::Surface(Display *display, const Config *config, HWND window, EGLint pos Surface::Surface(Display *display, const Config *config, HANDLE shareHandle, EGLint width, EGLint height, EGLenum textureFormat, EGLenum textureType) : mDisplay(display), mWindow(NULL), mConfig(config), mShareHandle(shareHandle), mWidth(width), mHeight(height), mPostSubBufferSupported(EGL_FALSE) { + mRenderer = mDisplay->getRenderer(); mSwapChain = NULL; - mBackBuffer = NULL; - mDepthStencil = NULL; - mRenderTarget = NULL; - mOffscreenTexture = NULL; mWindowSubclassed = false; mTexture = NULL; mTextureFormat = textureFormat; @@ -76,8 +74,6 @@ bool Surface::initialize() typedef HRESULT (STDAPICALLTYPE *PtrDwmIsCompositionEnabled)(BOOL*); typedef HRESULT (STDAPICALLTYPE *PtrDwmSetPresentParameters)(HWND, DWM_PRESENT_PARAMETERS *); - ASSERT(!mSwapChain && !mOffscreenTexture && !mDepthStencil); - if (!resetSwapChain()) return false; @@ -118,260 +114,106 @@ bool Surface::initialize() void Surface::release() { - if (mSwapChain) - { - mSwapChain->Release(); - mSwapChain = NULL; - } - - if (mBackBuffer) - { - mBackBuffer->Release(); - mBackBuffer = NULL; - } - - if (mDepthStencil) - { - mDepthStencil->Release(); - mDepthStencil = NULL; - } - - if (mRenderTarget) - { - mRenderTarget->Release(); - mRenderTarget = NULL; - } - - if (mOffscreenTexture) - { - mOffscreenTexture->Release(); - mOffscreenTexture = NULL; - } + delete mSwapChain; + mSwapChain = NULL; if (mTexture) { mTexture->releaseTexImage(); mTexture = NULL; } - - mShareHandle = NULL; } bool Surface::resetSwapChain() { - if (!mWindow) - { - return resetSwapChain(mWidth, mHeight); - } - - RECT windowRect; - if (!GetClientRect(getWindowHandle(), &windowRect)) - { - ASSERT(false); + ASSERT(!mSwapChain); - ERR("Could not retrieve the window dimensions"); - return false; - } - - return resetSwapChain(windowRect.right - windowRect.left, windowRect.bottom - windowRect.top); -} + int width; + int height; -bool Surface::resetSwapChain(int backbufferWidth, int backbufferHeight) -{ - IDirect3DDevice9 *device = mDisplay->getDevice(); - - if (device == NULL) + if (mWindow) { - return false; - } - - // Evict all non-render target textures to system memory and release all resources - // before reallocating them to free up as much video memory as possible. - device->EvictManagedResources(); - - HRESULT result; + RECT windowRect; + if (!GetClientRect(getWindowHandle(), &windowRect)) + { + ASSERT(false); - // 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; - } + ERR("Could not retrieve the window dimensions"); + return error(EGL_BAD_SURFACE, false); + } - if (mBackBuffer) - { - mBackBuffer->Release(); - mBackBuffer = NULL; + width = windowRect.right - windowRect.left; + height = windowRect.bottom - windowRect.top; } - - if (mOffscreenTexture) + else { - mOffscreenTexture->Release(); - mOffscreenTexture = NULL; + // non-window surface - size is determined at creation + width = mWidth; + height = mHeight; } - if (mDepthStencil) + mSwapChain = mRenderer->createSwapChain(mWindow, mShareHandle, + mConfig->mRenderTargetFormat, + mConfig->mDepthStencilFormat); + if (!mSwapChain) { - mDepthStencil->Release(); - mDepthStencil = NULL; + return error(EGL_BAD_ALLOC, false); } - HANDLE *pShareHandle = NULL; - if (!mWindow && mDisplay->shareHandleSupported()) + if (!resetSwapChain(width, height)) { - pShareHandle = &mShareHandle; + delete mSwapChain; + mSwapChain = NULL; + return false; } - // CreateTexture will fail on zero dimensions, so just release old target - if (!backbufferWidth || !backbufferHeight) - { - if (mRenderTarget) - { - mRenderTarget->Release(); - mRenderTarget = NULL; - } + return true; +} - mWidth = backbufferWidth; - mHeight = backbufferHeight; - mPresentIntervalDirty = false; +bool Surface::resizeSwapChain(int backbufferWidth, int backbufferHeight) +{ + ASSERT(backbufferWidth >= 0 && backbufferHeight >= 0); + ASSERT(mSwapChain); - return true; - } + EGLint status = mSwapChain->resize(backbufferWidth, backbufferHeight); - result = device->CreateTexture(backbufferWidth, backbufferHeight, 1, D3DUSAGE_RENDERTARGET, - mConfig->mRenderTargetFormat, D3DPOOL_DEFAULT, &mOffscreenTexture, pShareHandle); - if (FAILED(result)) + if (status == EGL_CONTEXT_LOST) { - ERR("Could not create offscreen texture: %08lX", result); - release(); - - if(isDeviceLostError(result)) - { - mDisplay->notifyDeviceLost(); - return false; - } - else - { - return error(EGL_BAD_ALLOC, false); - } + mDisplay->notifyDeviceLost(); + return false; } - - IDirect3DSurface9 *oldRenderTarget = mRenderTarget; - - result = mOffscreenTexture->GetSurfaceLevel(0, &mRenderTarget); - ASSERT(SUCCEEDED(result)); - - if (oldRenderTarget) + else if (status != EGL_SUCCESS) { - RECT rect = - { - 0, 0, - mWidth, mHeight - }; - - if (rect.right > static_cast(backbufferWidth)) - { - rect.right = backbufferWidth; - } + return error(status, false); + } - if (rect.bottom > static_cast(backbufferHeight)) - { - rect.bottom = backbufferHeight; - } + mWidth = backbufferWidth; + mHeight = backbufferHeight; - mDisplay->endScene(); + return true; +} - result = device->StretchRect(oldRenderTarget, &rect, mRenderTarget, &rect, D3DTEXF_NONE); - ASSERT(SUCCEEDED(result)); +bool Surface::resetSwapChain(int backbufferWidth, int backbufferHeight) +{ + ASSERT(backbufferWidth >= 0 && backbufferHeight >= 0); + ASSERT(mSwapChain); - oldRenderTarget->Release(); - } + EGLint status = mSwapChain->reset(backbufferWidth, backbufferHeight, mSwapInterval); - if (mWindow) + if (status == EGL_CONTEXT_LOST) { - D3DPRESENT_PARAMETERS presentParameters = {0}; - presentParameters.AutoDepthStencilFormat = mConfig->mDepthStencilFormat; - presentParameters.BackBufferCount = 1; - presentParameters.BackBufferFormat = mConfig->mRenderTargetFormat; - presentParameters.EnableAutoDepthStencil = FALSE; - presentParameters.Flags = 0; - presentParameters.hDeviceWindow = getWindowHandle(); - presentParameters.MultiSampleQuality = 0; // FIXME: Unimplemented - presentParameters.MultiSampleType = D3DMULTISAMPLE_NONE; // FIXME: Unimplemented - presentParameters.PresentationInterval = mPresentInterval; - presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD; - presentParameters.Windowed = TRUE; - presentParameters.BackBufferWidth = backbufferWidth; - presentParameters.BackBufferHeight = backbufferHeight; - - // http://crbug.com/140239 - // http://crbug.com/143434 - // - // Some AMD/Intel switchable systems / drivers appear to round swap chain surfaces to a multiple of 64 pixels in width - // when using the integrated Intel. This rounds the width up rather than down. - // - // Some non-switchable AMD GPUs / drivers do not respect the source rectangle to Present. Therefore, when the vendor ID - // is not Intel, the back buffer width must be exactly the same width as the window or horizontal scaling will occur. - D3DADAPTER_IDENTIFIER9* adapterIdentifier = mDisplay->getAdapterIdentifier(); - if (adapterIdentifier->VendorId == VENDOR_ID_INTEL) - { - presentParameters.BackBufferWidth = (presentParameters.BackBufferWidth + 63) / 64 * 64; - } - - result = device->CreateAdditionalSwapChain(&presentParameters, &mSwapChain); - - if (FAILED(result)) - { - ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_INVALIDCALL || result == D3DERR_DEVICELOST); - - ERR("Could not create additional swap chains or offscreen surfaces: %08lX", result); - release(); - - if(isDeviceLostError(result)) - { - mDisplay->notifyDeviceLost(); - return false; - } - else - { - return error(EGL_BAD_ALLOC, false); - } - } - - result = mSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &mBackBuffer); - ASSERT(SUCCEEDED(result)); - InvalidateRect(mWindow, NULL, FALSE); + mRenderer->notifyDeviceLost(); + return false; } - - if (mConfig->mDepthStencilFormat != D3DFMT_UNKNOWN) + else if (status != EGL_SUCCESS) { - result = device->CreateDepthStencilSurface(backbufferWidth, backbufferHeight, mConfig->mDepthStencilFormat, D3DMULTISAMPLE_NONE, - 0, FALSE, &mDepthStencil, NULL); - - if (FAILED(result)) - { - ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_INVALIDCALL); - - ERR("Could not create depthstencil surface for new swap chain: 0x%08X", result); - release(); - - if(isDeviceLostError(result)) - { - mDisplay->notifyDeviceLost(); - return false; - } - else - { - return error(EGL_BAD_ALLOC, false); - } - } + return error(status, false); } mWidth = backbufferWidth; mHeight = backbufferHeight; + mSwapIntervalDirty = false; - mPresentIntervalDirty = false; return true; } @@ -397,86 +239,18 @@ bool Surface::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) return true; } - IDirect3DDevice9 *device = mDisplay->getDevice(); - - // Disable all pipeline operations - device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE); - device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); - device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); - device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); - device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); - device->SetRenderState(D3DRS_STENCILENABLE, FALSE); - device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0); - device->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA | D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_RED); - device->SetRenderState(D3DRS_SRGBWRITEENABLE, FALSE); - device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE); - device->SetPixelShader(NULL); - device->SetVertexShader(NULL); - - device->SetRenderTarget(0, mBackBuffer); - device->SetDepthStencilSurface(NULL); - - device->SetTexture(0, mOffscreenTexture); - device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); - device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); - device->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); - device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT); - device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT); - device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); - device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); - device->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1); - - D3DVIEWPORT9 viewport = {0, 0, mWidth, mHeight, 0.0f, 1.0f}; - device->SetViewport(&viewport); - - float x1 = x - 0.5f; - float y1 = (mHeight - y - height) - 0.5f; - float x2 = (x + width) - 0.5f; - float y2 = (mHeight - y) - 0.5f; - - float u1 = x / float(mWidth); - float v1 = y / float(mHeight); - float u2 = (x + width) / float(mWidth); - float v2 = (y + height) / float(mHeight); - - float quad[4][6] = {{x1, y1, 0.0f, 1.0f, u1, v2}, - {x2, y1, 0.0f, 1.0f, u2, v2}, - {x2, y2, 0.0f, 1.0f, u2, v1}, - {x1, y2, 0.0f, 1.0f, u1, v1}}; // x, y, z, rhw, u, v - - mDisplay->startScene(); - device->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, quad, 6 * sizeof(float)); - mDisplay->endScene(); - - device->SetTexture(0, NULL); - - RECT rect = - { - x, mHeight - y - height, - x + width, mHeight - y - }; - - HRESULT result = mSwapChain->Present(&rect, &rect, NULL, NULL, 0); - - gl::Context *context = static_cast(glGetCurrentContext()); - if (context) - { - context->markAllStateDirty(); - } + EGLint status = mSwapChain->swapRect(x, y, width, height); - if (isDeviceLostError(result)) + if (status == EGL_CONTEXT_LOST) { - mDisplay->notifyDeviceLost(); + mRenderer->notifyDeviceLost(); return false; } - - if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DRIVERINTERNALERROR) + else if (status != EGL_SUCCESS) { - return error(EGL_BAD_ALLOC, false); + return error(status, false); } - ASSERT(SUCCEEDED(result)); - checkForOutOfDateSwapChain(); return true; @@ -572,9 +346,17 @@ bool Surface::checkForOutOfDateSwapChain() int clientHeight = client.bottom - client.top; bool sizeDirty = clientWidth != getWidth() || clientHeight != getHeight(); - if (sizeDirty || mPresentIntervalDirty) + if (mSwapIntervalDirty) { resetSwapChain(clientWidth, clientHeight); + } + else if (sizeDirty) + { + resizeSwapChain(clientWidth, clientHeight); + } + + if (mSwapIntervalDirty || sizeDirty) + { if (static_cast(getCurrentDrawSurface()) == this) { glMakeCurrent(glGetCurrentContext(), static_cast(getCurrentDisplay()), this); @@ -582,22 +364,8 @@ bool Surface::checkForOutOfDateSwapChain() return true; } - return false; -} - -DWORD Surface::convertInterval(EGLint interval) -{ - switch(interval) - { - case 0: return D3DPRESENT_INTERVAL_IMMEDIATE; - case 1: return D3DPRESENT_INTERVAL_ONE; - case 2: return D3DPRESENT_INTERVAL_TWO; - case 3: return D3DPRESENT_INTERVAL_THREE; - case 4: return D3DPRESENT_INTERVAL_FOUR; - default: UNREACHABLE(); - } - return D3DPRESENT_INTERVAL_DEFAULT; + return false; } bool Surface::swap() @@ -631,38 +399,9 @@ EGLint Surface::isPostSubBufferSupported() const return mPostSubBufferSupported; } -// Increments refcount on surface. -// caller must Release() the returned surface -IDirect3DSurface9 *Surface::getRenderTarget() -{ - if (mRenderTarget) - { - mRenderTarget->AddRef(); - } - - return mRenderTarget; -} - -// Increments refcount on surface. -// caller must Release() the returned surface -IDirect3DSurface9 *Surface::getDepthStencil() -{ - if (mDepthStencil) - { - mDepthStencil->AddRef(); - } - - return mDepthStencil; -} - -IDirect3DTexture9 *Surface::getOffscreenTexture() +rx::SwapChain *Surface::getSwapChain() const { - if (mOffscreenTexture) - { - mOffscreenTexture->AddRef(); - } - - return mOffscreenTexture; + return mSwapChain; } void Surface::setSwapInterval(EGLint interval) @@ -673,11 +412,10 @@ void Surface::setSwapInterval(EGLint interval) } mSwapInterval = interval; - mSwapInterval = std::max(mSwapInterval, mDisplay->getMinSwapInterval()); - mSwapInterval = std::min(mSwapInterval, mDisplay->getMaxSwapInterval()); + mSwapInterval = std::max(mSwapInterval, mRenderer->getMinSwapInterval()); + mSwapInterval = std::min(mSwapInterval, mRenderer->getMaxSwapInterval()); - mPresentInterval = convertInterval(mSwapInterval); - mPresentIntervalDirty = true; + mSwapIntervalDirty = true; } EGLenum Surface::getTextureFormat() const @@ -700,7 +438,7 @@ gl::Texture2D *Surface::getBoundTexture() const return mTexture; } -D3DFORMAT Surface::getFormat() const +EGLenum Surface::getFormat() const { return mConfig->mRenderTargetFormat; } diff --git a/src/3rdparty/angle/src/libEGL/Surface.h b/src/3rdparty/angle/src/libEGL/Surface.h index 40bd7028ab..938b800cdd 100644 --- a/src/3rdparty/angle/src/libEGL/Surface.h +++ b/src/3rdparty/angle/src/libEGL/Surface.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// 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. // @@ -8,12 +8,11 @@ // such as the client area of a window, including any back buffers. // Implements EGLSurface and related functionality. [EGL 1.4] section 2.2 page 3. -#ifndef INCLUDE_SURFACE_H_ -#define INCLUDE_SURFACE_H_ +#ifndef LIBEGL_SURFACE_H_ +#define LIBEGL_SURFACE_H_ #define EGLAPI #include -#include #include "common/angleutils.h" @@ -21,6 +20,11 @@ namespace gl { class Texture2D; } +namespace rx +{ +class Renderer; +class SwapChain; +} namespace egl { @@ -48,18 +52,14 @@ class Surface virtual EGLint isPostSubBufferSupported() const; - virtual IDirect3DSurface9 *getRenderTarget(); - virtual IDirect3DSurface9 *getDepthStencil(); - virtual IDirect3DTexture9 *getOffscreenTexture(); - - HANDLE getShareHandle() { return mShareHandle; } + virtual rx::SwapChain *getSwapChain() const; void setSwapInterval(EGLint interval); bool checkForOutOfDateSwapChain(); // Returns true if swapchain changed due to resize or interval update virtual EGLenum getTextureFormat() const; virtual EGLenum getTextureTarget() const; - virtual D3DFORMAT getFormat() const; + virtual EGLenum getFormat() const; virtual void setBoundTexture(gl::Texture2D *texture); virtual gl::Texture2D *getBoundTexture() const; @@ -68,19 +68,16 @@ private: DISALLOW_COPY_AND_ASSIGN(Surface); Display *const mDisplay; - IDirect3DSwapChain9 *mSwapChain; - IDirect3DSurface9 *mBackBuffer; - IDirect3DSurface9 *mDepthStencil; - IDirect3DSurface9* mRenderTarget; - IDirect3DTexture9* mOffscreenTexture; + rx::Renderer *mRenderer; HANDLE mShareHandle; + rx::SwapChain *mSwapChain; void subclassWindow(); void unsubclassWindow(); + bool resizeSwapChain(int backbufferWidth, int backbufferHeight); bool resetSwapChain(int backbufferWidth, int backbufferHeight); bool swapRect(EGLint x, EGLint y, EGLint width, EGLint height); - static DWORD convertInterval(EGLint interval); const HWND mWindow; // Window that the surface is created for. bool mWindowSubclassed; // Indicates whether we successfully subclassed mWindow for WM_RESIZE hooking @@ -103,10 +100,9 @@ private: EGLint mSwapInterval; EGLint mPostSubBufferSupported; - DWORD mPresentInterval; - bool mPresentIntervalDirty; + bool mSwapIntervalDirty; gl::Texture2D *mTexture; }; } -#endif // INCLUDE_SURFACE_H_ +#endif // LIBEGL_SURFACE_H_ diff --git a/src/3rdparty/angle/src/libEGL/libEGL.cpp b/src/3rdparty/angle/src/libEGL/libEGL.cpp index 25df1c8c24..7fca456cf5 100644 --- a/src/3rdparty/angle/src/libEGL/libEGL.cpp +++ b/src/3rdparty/angle/src/libEGL/libEGL.cpp @@ -12,21 +12,23 @@ #include "common/version.h" #include "libGLESv2/Context.h" #include "libGLESv2/Texture.h" +#include "libGLESv2/main.h" +#include "libGLESv2/renderer/SwapChain.h" #include "libEGL/main.h" #include "libEGL/Display.h" - +#include "libEGL/Surface.h" bool validateDisplay(egl::Display *display) { if (display == EGL_NO_DISPLAY) { - return error(EGL_BAD_DISPLAY, false); + return egl::error(EGL_BAD_DISPLAY, false); } if (!display->isInitialized()) { - return error(EGL_NOT_INITIALIZED, false); + return egl::error(EGL_NOT_INITIALIZED, false); } return true; @@ -41,7 +43,7 @@ bool validateConfig(egl::Display *display, EGLConfig config) if (!display->isValidConfig(config)) { - return error(EGL_BAD_CONFIG, false); + return egl::error(EGL_BAD_CONFIG, false); } return true; @@ -56,7 +58,7 @@ bool validateContext(egl::Display *display, gl::Context *context) if (!display->isValidContext(context)) { - return error(EGL_BAD_CONTEXT, false); + return egl::error(EGL_BAD_CONTEXT, false); } return true; @@ -71,7 +73,7 @@ bool validateSurface(egl::Display *display, egl::Surface *surface) if (!display->isValidSurface(surface)) { - return error(EGL_BAD_SURFACE, false); + return egl::error(EGL_BAD_SURFACE, false); } return true; @@ -103,7 +105,7 @@ EGLDisplay __stdcall eglGetDisplay(EGLNativeDisplayType display_id) } catch(std::bad_alloc&) { - return error(EGL_BAD_ALLOC, EGL_NO_DISPLAY); + return egl::error(EGL_BAD_ALLOC, EGL_NO_DISPLAY); } } @@ -116,24 +118,24 @@ EGLBoolean __stdcall eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) { if (dpy == EGL_NO_DISPLAY) { - return error(EGL_BAD_DISPLAY, EGL_FALSE); + return egl::error(EGL_BAD_DISPLAY, EGL_FALSE); } egl::Display *display = static_cast(dpy); if (!display->initialize()) { - return error(EGL_NOT_INITIALIZED, EGL_FALSE); + return egl::error(EGL_NOT_INITIALIZED, EGL_FALSE); } if (major) *major = 1; if (minor) *minor = 4; - return success(EGL_TRUE); + return egl::success(EGL_TRUE); } catch(std::bad_alloc&) { - return error(EGL_BAD_ALLOC, EGL_FALSE); + return egl::error(EGL_BAD_ALLOC, EGL_FALSE); } } @@ -145,18 +147,18 @@ EGLBoolean __stdcall eglTerminate(EGLDisplay dpy) { if (dpy == EGL_NO_DISPLAY) { - return error(EGL_BAD_DISPLAY, EGL_FALSE); + return egl::error(EGL_BAD_DISPLAY, EGL_FALSE); } egl::Display *display = static_cast(dpy); display->terminate(); - return success(EGL_TRUE); + return egl::success(EGL_TRUE); } catch(std::bad_alloc&) { - return error(EGL_BAD_ALLOC, EGL_FALSE); + return egl::error(EGL_BAD_ALLOC, EGL_FALSE); } } @@ -176,20 +178,20 @@ const char *__stdcall eglQueryString(EGLDisplay dpy, EGLint name) switch (name) { case EGL_CLIENT_APIS: - return success("OpenGL_ES"); + return egl::success("OpenGL_ES"); case EGL_EXTENSIONS: return display->getExtensionString(); case EGL_VENDOR: - return success("Google Inc."); + return egl::success("Google Inc."); case EGL_VERSION: - return success("1.4 (ANGLE " VERSION_STRING ")"); + return egl::success("1.4 (ANGLE " VERSION_STRING ")"); } - return error(EGL_BAD_PARAMETER, (const char*)NULL); + return egl::error(EGL_BAD_PARAMETER, (const char*)NULL); } catch(std::bad_alloc&) { - return error(EGL_BAD_ALLOC, (const char*)NULL); + return egl::error(EGL_BAD_ALLOC, (const char*)NULL); } } @@ -210,21 +212,21 @@ EGLBoolean __stdcall eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint co if (!num_config) { - return error(EGL_BAD_PARAMETER, EGL_FALSE); + return egl::error(EGL_BAD_PARAMETER, EGL_FALSE); } const EGLint attribList[] = {EGL_NONE}; if (!display->getConfigs(configs, attribList, config_size, num_config)) { - return error(EGL_BAD_ATTRIBUTE, EGL_FALSE); + return egl::error(EGL_BAD_ATTRIBUTE, EGL_FALSE); } - return success(EGL_TRUE); + return egl::success(EGL_TRUE); } catch(std::bad_alloc&) { - return error(EGL_BAD_ALLOC, EGL_FALSE); + return egl::error(EGL_BAD_ALLOC, EGL_FALSE); } } @@ -245,7 +247,7 @@ EGLBoolean __stdcall eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, if (!num_config) { - return error(EGL_BAD_PARAMETER, EGL_FALSE); + return egl::error(EGL_BAD_PARAMETER, EGL_FALSE); } const EGLint attribList[] = {EGL_NONE}; @@ -257,11 +259,11 @@ EGLBoolean __stdcall eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, display->getConfigs(configs, attrib_list, config_size, num_config); - return success(EGL_TRUE); + return egl::success(EGL_TRUE); } catch(std::bad_alloc&) { - return error(EGL_BAD_ALLOC, EGL_FALSE); + return egl::error(EGL_BAD_ALLOC, EGL_FALSE); } } @@ -281,14 +283,14 @@ EGLBoolean __stdcall eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint if (!display->getConfigAttrib(config, attribute, value)) { - return error(EGL_BAD_ATTRIBUTE, EGL_FALSE); + return egl::error(EGL_BAD_ATTRIBUTE, EGL_FALSE); } - return success(EGL_TRUE); + return egl::success(EGL_TRUE); } catch(std::bad_alloc&) { - return error(EGL_BAD_ALLOC, EGL_FALSE); + return egl::error(EGL_BAD_ALLOC, EGL_FALSE); } } @@ -310,14 +312,14 @@ EGLSurface __stdcall eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EG if (!IsWindow(window)) { - return error(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); + return egl::error(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); } return display->createWindowSurface(window, config, attrib_list); } catch(std::bad_alloc&) { - return error(EGL_BAD_ALLOC, EGL_NO_SURFACE); + return egl::error(EGL_BAD_ALLOC, EGL_NO_SURFACE); } } @@ -339,7 +341,7 @@ EGLSurface __stdcall eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, c } catch(std::bad_alloc&) { - return error(EGL_BAD_ALLOC, EGL_NO_SURFACE); + return egl::error(EGL_BAD_ALLOC, EGL_NO_SURFACE); } } @@ -359,11 +361,11 @@ EGLSurface __stdcall eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EG UNIMPLEMENTED(); // FIXME - return success(EGL_NO_SURFACE); + return egl::success(EGL_NO_SURFACE); } catch(std::bad_alloc&) { - return error(EGL_BAD_ALLOC, EGL_NO_SURFACE); + return egl::error(EGL_BAD_ALLOC, EGL_NO_SURFACE); } } @@ -383,16 +385,16 @@ EGLBoolean __stdcall eglDestroySurface(EGLDisplay dpy, EGLSurface surface) if (surface == EGL_NO_SURFACE) { - return error(EGL_BAD_SURFACE, EGL_FALSE); + return egl::error(EGL_BAD_SURFACE, EGL_FALSE); } display->destroySurface((egl::Surface*)surface); - return success(EGL_TRUE); + return egl::success(EGL_TRUE); } catch(std::bad_alloc&) { - return error(EGL_BAD_ALLOC, EGL_FALSE); + return egl::error(EGL_BAD_ALLOC, EGL_FALSE); } } @@ -413,7 +415,7 @@ EGLBoolean __stdcall eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint if (surface == EGL_NO_SURFACE) { - return error(EGL_BAD_SURFACE, EGL_FALSE); + return egl::error(EGL_BAD_SURFACE, EGL_FALSE); } switch (attribute) @@ -470,14 +472,14 @@ EGLBoolean __stdcall eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint *value = eglSurface->isPostSubBufferSupported(); break; default: - return error(EGL_BAD_ATTRIBUTE, EGL_FALSE); + return egl::error(EGL_BAD_ATTRIBUTE, EGL_FALSE); } - return success(EGL_TRUE); + return egl::success(EGL_TRUE); } catch(std::bad_alloc&) { - return error(EGL_BAD_ALLOC, EGL_FALSE); + return egl::error(EGL_BAD_ALLOC, EGL_FALSE); } } @@ -498,23 +500,26 @@ EGLBoolean __stdcall eglQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surf if (surface == EGL_NO_SURFACE) { - return error(EGL_BAD_SURFACE, EGL_FALSE); + return egl::error(EGL_BAD_SURFACE, EGL_FALSE); } switch (attribute) { case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE: - *value = (void*) eglSurface->getShareHandle(); + { + rx::SwapChain *swapchain = eglSurface->getSwapChain(); + *value = (void*) (swapchain ? swapchain->getShareHandle() : NULL); + } break; default: - return error(EGL_BAD_ATTRIBUTE, EGL_FALSE); + return egl::error(EGL_BAD_ATTRIBUTE, EGL_FALSE); } - return success(EGL_TRUE); + return egl::success(EGL_TRUE); } catch(std::bad_alloc&) { - return error(EGL_BAD_ALLOC, EGL_FALSE); + return egl::error(EGL_BAD_ALLOC, EGL_FALSE); } } @@ -528,20 +533,20 @@ EGLBoolean __stdcall eglBindAPI(EGLenum api) { case EGL_OPENGL_API: case EGL_OPENVG_API: - return error(EGL_BAD_PARAMETER, EGL_FALSE); // Not supported by this implementation + return egl::error(EGL_BAD_PARAMETER, EGL_FALSE); // Not supported by this implementation case EGL_OPENGL_ES_API: break; default: - return error(EGL_BAD_PARAMETER, EGL_FALSE); + return egl::error(EGL_BAD_PARAMETER, EGL_FALSE); } egl::setCurrentAPI(api); - return success(EGL_TRUE); + return egl::success(EGL_TRUE); } catch(std::bad_alloc&) { - return error(EGL_BAD_ALLOC, EGL_FALSE); + return egl::error(EGL_BAD_ALLOC, EGL_FALSE); } } @@ -553,11 +558,11 @@ EGLenum __stdcall eglQueryAPI(void) { EGLenum API = egl::getCurrentAPI(); - return success(API); + return egl::success(API); } catch(std::bad_alloc&) { - return error(EGL_BAD_ALLOC, EGL_FALSE); + return egl::error(EGL_BAD_ALLOC, EGL_FALSE); } } @@ -569,11 +574,11 @@ EGLBoolean __stdcall eglWaitClient(void) { UNIMPLEMENTED(); // FIXME - return success(0); + return egl::success(0); } catch(std::bad_alloc&) { - return error(EGL_BAD_ALLOC, EGL_FALSE); + return egl::error(EGL_BAD_ALLOC, EGL_FALSE); } } @@ -585,11 +590,11 @@ EGLBoolean __stdcall eglReleaseThread(void) { eglMakeCurrent(EGL_NO_DISPLAY, EGL_NO_CONTEXT, EGL_NO_SURFACE, EGL_NO_SURFACE); - return success(EGL_TRUE); + return egl::success(EGL_TRUE); } catch(std::bad_alloc&) { - return error(EGL_BAD_ALLOC, EGL_FALSE); + return egl::error(EGL_BAD_ALLOC, EGL_FALSE); } } @@ -610,14 +615,14 @@ EGLSurface __stdcall eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum bu if (buftype != EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE || !buffer) { - return error(EGL_BAD_PARAMETER, EGL_NO_SURFACE); + return egl::error(EGL_BAD_PARAMETER, EGL_NO_SURFACE); } return display->createOffscreenSurface(config, (HANDLE)buffer, attrib_list); } catch(std::bad_alloc&) { - return error(EGL_BAD_ALLOC, EGL_NO_SURFACE); + return egl::error(EGL_BAD_ALLOC, EGL_NO_SURFACE); } } @@ -638,11 +643,11 @@ EGLBoolean __stdcall eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint UNIMPLEMENTED(); // FIXME - return success(EGL_TRUE); + return egl::success(EGL_TRUE); } catch(std::bad_alloc&) { - return error(EGL_BAD_ALLOC, EGL_FALSE); + return egl::error(EGL_BAD_ALLOC, EGL_FALSE); } } @@ -662,34 +667,34 @@ EGLBoolean __stdcall eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint if (buffer != EGL_BACK_BUFFER) { - return error(EGL_BAD_PARAMETER, EGL_FALSE); + return egl::error(EGL_BAD_PARAMETER, EGL_FALSE); } if (surface == EGL_NO_SURFACE || eglSurface->getWindowHandle()) { - return error(EGL_BAD_SURFACE, EGL_FALSE); + return egl::error(EGL_BAD_SURFACE, EGL_FALSE); } if (eglSurface->getBoundTexture()) { - return error(EGL_BAD_ACCESS, EGL_FALSE); + return egl::error(EGL_BAD_ACCESS, EGL_FALSE); } if (eglSurface->getTextureFormat() == EGL_NO_TEXTURE) { - return error(EGL_BAD_MATCH, EGL_FALSE); + return egl::error(EGL_BAD_MATCH, EGL_FALSE); } if (!glBindTexImage(eglSurface)) { - return error(EGL_BAD_MATCH, EGL_FALSE); + return egl::error(EGL_BAD_MATCH, EGL_FALSE); } - return success(EGL_TRUE); + return egl::success(EGL_TRUE); } catch(std::bad_alloc&) { - return error(EGL_BAD_ALLOC, EGL_FALSE); + return egl::error(EGL_BAD_ALLOC, EGL_FALSE); } } @@ -709,17 +714,17 @@ EGLBoolean __stdcall eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLi if (buffer != EGL_BACK_BUFFER) { - return error(EGL_BAD_PARAMETER, EGL_FALSE); + return egl::error(EGL_BAD_PARAMETER, EGL_FALSE); } if (surface == EGL_NO_SURFACE || eglSurface->getWindowHandle()) { - return error(EGL_BAD_SURFACE, EGL_FALSE); + return egl::error(EGL_BAD_SURFACE, EGL_FALSE); } if (eglSurface->getTextureFormat() == EGL_NO_TEXTURE) { - return error(EGL_BAD_MATCH, EGL_FALSE); + return egl::error(EGL_BAD_MATCH, EGL_FALSE); } gl::Texture2D *texture = eglSurface->getBoundTexture(); @@ -729,11 +734,11 @@ EGLBoolean __stdcall eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLi texture->releaseTexImage(); } - return success(EGL_TRUE); + return egl::success(EGL_TRUE); } catch(std::bad_alloc&) { - return error(EGL_BAD_ALLOC, EGL_FALSE); + return egl::error(EGL_BAD_ALLOC, EGL_FALSE); } } @@ -754,16 +759,16 @@ EGLBoolean __stdcall eglSwapInterval(EGLDisplay dpy, EGLint interval) if (draw_surface == NULL) { - return error(EGL_BAD_SURFACE, EGL_FALSE); + return egl::error(EGL_BAD_SURFACE, EGL_FALSE); } draw_surface->setSwapInterval(interval); - return success(EGL_TRUE); + return egl::success(EGL_TRUE); } catch(std::bad_alloc&) { - return error(EGL_BAD_ALLOC, EGL_FALSE); + return egl::error(EGL_BAD_ALLOC, EGL_FALSE); } } @@ -791,32 +796,32 @@ EGLContext __stdcall eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLConte case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT: if (attribute[1] == EGL_TRUE) { - return error(EGL_BAD_CONFIG, EGL_NO_CONTEXT); // Unimplemented + return egl::error(EGL_BAD_CONFIG, EGL_NO_CONTEXT); // Unimplemented // robust_access = true; } else if (attribute[1] != EGL_FALSE) - return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT); + return egl::error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT); break; case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT: if (attribute[1] == EGL_LOSE_CONTEXT_ON_RESET_EXT) reset_notification = true; else if (attribute[1] != EGL_NO_RESET_NOTIFICATION_EXT) - return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT); + return egl::error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT); break; default: - return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT); + return egl::error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT); } } } if (client_version != 2) { - return error(EGL_BAD_CONFIG, EGL_NO_CONTEXT); + return egl::error(EGL_BAD_CONFIG, EGL_NO_CONTEXT); } if (share_context && static_cast(share_context)->isResetNotificationEnabled() != reset_notification) { - return error(EGL_BAD_MATCH, EGL_NO_CONTEXT); + return egl::error(EGL_BAD_MATCH, EGL_NO_CONTEXT); } egl::Display *display = static_cast(dpy); @@ -829,13 +834,13 @@ EGLContext __stdcall eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLConte EGLContext context = display->createContext(config, static_cast(share_context), reset_notification, robust_access); if (context) - return success(context); + return egl::success(context); else - return error(EGL_CONTEXT_LOST, EGL_NO_CONTEXT); + return egl::error(EGL_CONTEXT_LOST, EGL_NO_CONTEXT); } catch(std::bad_alloc&) { - return error(EGL_BAD_ALLOC, EGL_NO_CONTEXT); + return egl::error(EGL_BAD_ALLOC, EGL_NO_CONTEXT); } } @@ -855,16 +860,16 @@ EGLBoolean __stdcall eglDestroyContext(EGLDisplay dpy, EGLContext ctx) if (ctx == EGL_NO_CONTEXT) { - return error(EGL_BAD_CONTEXT, EGL_FALSE); + return egl::error(EGL_BAD_CONTEXT, EGL_FALSE); } display->destroyContext(context); - return success(EGL_TRUE); + return egl::success(EGL_TRUE); } catch(std::bad_alloc&) { - return error(EGL_BAD_ALLOC, EGL_FALSE); + return egl::error(EGL_BAD_ALLOC, EGL_FALSE); } } @@ -877,22 +882,21 @@ EGLBoolean __stdcall eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface { egl::Display *display = static_cast(dpy); gl::Context *context = static_cast(ctx); - IDirect3DDevice9 *device = display->getDevice(); - if (!device || display->testDeviceLost()) + if (ctx != EGL_NO_CONTEXT && !validateContext(display, context)) { - display->notifyDeviceLost(); return EGL_FALSE; } - if (display->isDeviceLost()) + rx::Renderer *renderer = display->getRenderer(); + if (renderer->testDeviceLost(true)) { - return error(EGL_CONTEXT_LOST, EGL_FALSE); + return EGL_FALSE; } - if (ctx != EGL_NO_CONTEXT && !validateContext(display, context)) + if (renderer->isDeviceLost()) { - return EGL_FALSE; + return egl::error(EGL_CONTEXT_LOST, EGL_FALSE); } if ((draw != EGL_NO_SURFACE && !validateSurface(display, static_cast(draw))) || @@ -912,11 +916,11 @@ EGLBoolean __stdcall eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface glMakeCurrent(context, display, static_cast(draw)); - return success(EGL_TRUE); + return egl::success(EGL_TRUE); } catch(std::bad_alloc&) { - return error(EGL_BAD_ALLOC, EGL_FALSE); + return egl::error(EGL_BAD_ALLOC, EGL_FALSE); } } @@ -928,11 +932,11 @@ EGLContext __stdcall eglGetCurrentContext(void) { EGLContext context = glGetCurrentContext(); - return success(context); + return egl::success(context); } catch(std::bad_alloc&) { - return error(EGL_BAD_ALLOC, EGL_NO_CONTEXT); + return egl::error(EGL_BAD_ALLOC, EGL_NO_CONTEXT); } } @@ -945,21 +949,21 @@ EGLSurface __stdcall eglGetCurrentSurface(EGLint readdraw) if (readdraw == EGL_READ) { EGLSurface read = egl::getCurrentReadSurface(); - return success(read); + return egl::success(read); } else if (readdraw == EGL_DRAW) { EGLSurface draw = egl::getCurrentDrawSurface(); - return success(draw); + return egl::success(draw); } else { - return error(EGL_BAD_PARAMETER, EGL_NO_SURFACE); + return egl::error(EGL_BAD_PARAMETER, EGL_NO_SURFACE); } } catch(std::bad_alloc&) { - return error(EGL_BAD_ALLOC, EGL_NO_SURFACE); + return egl::error(EGL_BAD_ALLOC, EGL_NO_SURFACE); } } @@ -971,11 +975,11 @@ EGLDisplay __stdcall eglGetCurrentDisplay(void) { EGLDisplay dpy = egl::getCurrentDisplay(); - return success(dpy); + return egl::success(dpy); } catch(std::bad_alloc&) { - return error(EGL_BAD_ALLOC, EGL_NO_DISPLAY); + return egl::error(EGL_BAD_ALLOC, EGL_NO_DISPLAY); } } @@ -996,11 +1000,11 @@ EGLBoolean __stdcall eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attr UNIMPLEMENTED(); // FIXME - return success(0); + return egl::success(0); } catch(std::bad_alloc&) { - return error(EGL_BAD_ALLOC, EGL_FALSE); + return egl::error(EGL_BAD_ALLOC, EGL_FALSE); } } @@ -1012,11 +1016,11 @@ EGLBoolean __stdcall eglWaitGL(void) { UNIMPLEMENTED(); // FIXME - return success(0); + return egl::success(0); } catch(std::bad_alloc&) { - return error(EGL_BAD_ALLOC, EGL_FALSE); + return egl::error(EGL_BAD_ALLOC, EGL_FALSE); } } @@ -1028,11 +1032,11 @@ EGLBoolean __stdcall eglWaitNative(EGLint engine) { UNIMPLEMENTED(); // FIXME - return success(0); + return egl::success(0); } catch(std::bad_alloc&) { - return error(EGL_BAD_ALLOC, EGL_FALSE); + return egl::error(EGL_BAD_ALLOC, EGL_FALSE); } } @@ -1050,24 +1054,24 @@ EGLBoolean __stdcall eglSwapBuffers(EGLDisplay dpy, EGLSurface surface) return EGL_FALSE; } - if (display->isDeviceLost()) + if (display->getRenderer()->isDeviceLost()) { - return error(EGL_CONTEXT_LOST, EGL_FALSE); + return egl::error(EGL_CONTEXT_LOST, EGL_FALSE); } if (surface == EGL_NO_SURFACE) { - return error(EGL_BAD_SURFACE, EGL_FALSE); + return egl::error(EGL_BAD_SURFACE, EGL_FALSE); } if (eglSurface->swap()) { - return success(EGL_TRUE); + return egl::success(EGL_TRUE); } } catch(std::bad_alloc&) { - return error(EGL_BAD_ALLOC, EGL_FALSE); + return egl::error(EGL_BAD_ALLOC, EGL_FALSE); } return EGL_FALSE; @@ -1087,18 +1091,18 @@ EGLBoolean __stdcall eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativ return EGL_FALSE; } - if (display->isDeviceLost()) + if (display->getRenderer()->isDeviceLost()) { - return error(EGL_CONTEXT_LOST, EGL_FALSE); + return egl::error(EGL_CONTEXT_LOST, EGL_FALSE); } UNIMPLEMENTED(); // FIXME - return success(0); + return egl::success(0); } catch(std::bad_alloc&) { - return error(EGL_BAD_ALLOC, EGL_FALSE); + return egl::error(EGL_BAD_ALLOC, EGL_FALSE); } } @@ -1110,7 +1114,7 @@ EGLBoolean __stdcall eglPostSubBufferNV(EGLDisplay dpy, EGLSurface surface, EGLi { if (x < 0 || y < 0 || width < 0 || height < 0) { - return error(EGL_BAD_PARAMETER, EGL_FALSE); + return egl::error(EGL_BAD_PARAMETER, EGL_FALSE); } egl::Display *display = static_cast(dpy); @@ -1121,24 +1125,24 @@ EGLBoolean __stdcall eglPostSubBufferNV(EGLDisplay dpy, EGLSurface surface, EGLi return EGL_FALSE; } - if (display->isDeviceLost()) + if (display->getRenderer()->isDeviceLost()) { - return error(EGL_CONTEXT_LOST, EGL_FALSE); + return egl::error(EGL_CONTEXT_LOST, EGL_FALSE); } if (surface == EGL_NO_SURFACE) { - return error(EGL_BAD_SURFACE, EGL_FALSE); + return egl::error(EGL_BAD_SURFACE, EGL_FALSE); } if (eglSurface->postSubBuffer(x, y, width, height)) { - return success(EGL_TRUE); + return egl::success(EGL_TRUE); } } catch(std::bad_alloc&) { - return error(EGL_BAD_ALLOC, EGL_FALSE); + return egl::error(EGL_BAD_ALLOC, EGL_FALSE); } return EGL_FALSE; @@ -1163,7 +1167,7 @@ __eglMustCastToProperFunctionPointerType __stdcall eglGetProcAddress(const char {"", NULL}, }; - for (int ext = 0; ext < sizeof(eglExtensions) / sizeof(Extension); ext++) + for (unsigned int ext = 0; ext < ArraySize(eglExtensions); ext++) { if (strcmp(procname, eglExtensions[ext].name) == 0) { @@ -1175,7 +1179,7 @@ __eglMustCastToProperFunctionPointerType __stdcall eglGetProcAddress(const char } catch(std::bad_alloc&) { - return error(EGL_BAD_ALLOC, (__eglMustCastToProperFunctionPointerType)NULL); + return egl::error(EGL_BAD_ALLOC, (__eglMustCastToProperFunctionPointerType)NULL); } } } diff --git a/src/3rdparty/angle/src/libEGL/main.cpp b/src/3rdparty/angle/src/libEGL/main.cpp index 614bcf67ad..7ba77f08d1 100644 --- a/src/3rdparty/angle/src/libEGL/main.cpp +++ b/src/3rdparty/angle/src/libEGL/main.cpp @@ -155,9 +155,10 @@ EGLSurface getCurrentReadSurface() { return current()->readSurface; } -} void error(EGLint errorCode) { egl::setCurrentError(errorCode); } + +} diff --git a/src/3rdparty/angle/src/libEGL/main.h b/src/3rdparty/angle/src/libEGL/main.h index d09d9e6bc3..77da8f0f8e 100644 --- a/src/3rdparty/angle/src/libEGL/main.h +++ b/src/3rdparty/angle/src/libEGL/main.h @@ -38,7 +38,6 @@ EGLSurface getCurrentDrawSurface(); void setCurrentReadSurface(EGLSurface surface); EGLSurface getCurrentReadSurface(); -} void error(EGLint errorCode); @@ -58,4 +57,6 @@ const T &success(const T &returnValue) return returnValue; } +} + #endif // LIBEGL_MAIN_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/BinaryStream.h b/src/3rdparty/angle/src/libGLESv2/BinaryStream.h index 5f7213b8da..21c2f86ce8 100644 --- a/src/3rdparty/angle/src/libGLESv2/BinaryStream.h +++ b/src/3rdparty/angle/src/libGLESv2/BinaryStream.h @@ -9,9 +9,6 @@ #ifndef LIBGLESV2_BINARYSTREAM_H_ #define LIBGLESV2_BINARYSTREAM_H_ -#include -#include - #include "common/angleutils.h" namespace gl diff --git a/src/3rdparty/angle/src/libGLESv2/Blit.cpp b/src/3rdparty/angle/src/libGLESv2/Blit.cpp deleted file mode 100644 index 28f3fbffbb..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/Blit.cpp +++ /dev/null @@ -1,518 +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. - -#include "libGLESv2/Blit.h" - -#include "common/debug.h" - -#include "libGLESv2/main.h" -#include "libGLESv2/utilities.h" - -namespace -{ -#include "libGLESv2/shaders/standardvs.h" -#include "libGLESv2/shaders/flipyvs.h" -#include "libGLESv2/shaders/passthroughps.h" -#include "libGLESv2/shaders/luminanceps.h" -#include "libGLESv2/shaders/componentmaskps.h" - -const BYTE* const g_shaderCode[] = -{ - g_vs20_standardvs, - g_vs20_flipyvs, - g_ps20_passthroughps, - g_ps20_luminanceps, - g_ps20_componentmaskps -}; - -const size_t g_shaderSize[] = -{ - sizeof(g_vs20_standardvs), - sizeof(g_vs20_flipyvs), - sizeof(g_ps20_passthroughps), - sizeof(g_ps20_luminanceps), - sizeof(g_ps20_componentmaskps) -}; -} - -namespace gl -{ -Blit::Blit(Context *context) - : mContext(context), mQuadVertexBuffer(NULL), mQuadVertexDeclaration(NULL), mSavedRenderTarget(NULL), mSavedDepthStencil(NULL), mSavedStateBlock(NULL) -{ - initGeometry(); - memset(mCompiledShaders, 0, sizeof(mCompiledShaders)); -} - -Blit::~Blit() -{ - if (mSavedStateBlock) mSavedStateBlock->Release(); - if (mQuadVertexBuffer) mQuadVertexBuffer->Release(); - if (mQuadVertexDeclaration) mQuadVertexDeclaration->Release(); - - for (int i = 0; i < SHADER_COUNT; i++) - { - if (mCompiledShaders[i]) - { - mCompiledShaders[i]->Release(); - } - } -} - -void Blit::initGeometry() -{ - static const float quad[] = - { - -1, -1, - -1, 1, - 1, -1, - 1, 1 - }; - - IDirect3DDevice9 *device = getDevice(); - - HRESULT result = device->CreateVertexBuffer(sizeof(quad), D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &mQuadVertexBuffer, NULL); - - if (FAILED(result)) - { - ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - return error(GL_OUT_OF_MEMORY); - } - - void *lockPtr = NULL; - result = mQuadVertexBuffer->Lock(0, 0, &lockPtr, 0); - - if (FAILED(result) || lockPtr == NULL) - { - ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - return error(GL_OUT_OF_MEMORY); - } - - memcpy(lockPtr, quad, sizeof(quad)); - mQuadVertexBuffer->Unlock(); - - static const D3DVERTEXELEMENT9 elements[] = - { - { 0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 }, - D3DDECL_END() - }; - - result = device->CreateVertexDeclaration(elements, &mQuadVertexDeclaration); - - if (FAILED(result)) - { - ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - return error(GL_OUT_OF_MEMORY); - } -} - -template -bool Blit::setShader(ShaderId source, const char *profile, - D3DShaderType *(egl::Display::*createShader)(const DWORD *, size_t length), - HRESULT (WINAPI IDirect3DDevice9::*setShader)(D3DShaderType*)) -{ - egl::Display *display = getDisplay(); - IDirect3DDevice9 *device = display->getDevice(); - - D3DShaderType *shader; - - if (mCompiledShaders[source] != NULL) - { - shader = static_cast(mCompiledShaders[source]); - } - else - { - const BYTE* shaderCode = g_shaderCode[source]; - size_t shaderSize = g_shaderSize[source]; - - shader = (display->*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", &egl::Display::createVertexShader, &IDirect3DDevice9::SetVertexShader); -} - -bool Blit::setPixelShader(ShaderId shader) -{ - return setShader(shader, "ps_2_0", &egl::Display::createPixelShader, &IDirect3DDevice9::SetPixelShader); -} - -RECT Blit::getSurfaceRect(IDirect3DSurface9 *surface) const -{ - D3DSURFACE_DESC desc; - surface->GetDesc(&desc); - - RECT rect; - rect.left = 0; - rect.top = 0; - rect.right = desc.Width; - rect.bottom = desc.Height; - - return rect; -} - -bool Blit::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest) -{ - IDirect3DTexture9 *texture = copySurfaceToTexture(source, getSurfaceRect(source)); - if (!texture) - { - return false; - } - - IDirect3DDevice9 *device = getDevice(); - - saveState(); - - device->SetTexture(0, texture); - device->SetRenderTarget(0, dest); - - setVertexShader(SHADER_VS_STANDARD); - setPixelShader(SHADER_PS_PASSTHROUGH); - - setCommonBlitState(); - device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); - device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); - - setViewport(getSurfaceRect(dest), 0, 0); - - render(); - - texture->Release(); - - restoreState(); - - return true; -} - -bool Blit::copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest) -{ - IDirect3DDevice9 *device = getDevice(); - - D3DSURFACE_DESC sourceDesc; - D3DSURFACE_DESC destDesc; - source->GetDesc(&sourceDesc); - dest->GetDesc(&destDesc); - - if (sourceDesc.Format == destDesc.Format && destDesc.Usage & D3DUSAGE_RENDERTARGET && - dx2es::IsFormatChannelEquivalent(destDesc.Format, destFormat)) // Can use StretchRect - { - RECT destRect = {xoffset, yoffset, xoffset + (sourceRect.right - sourceRect.left), yoffset + (sourceRect.bottom - sourceRect.top)}; - HRESULT result = device->StretchRect(source, &sourceRect, dest, &destRect, D3DTEXF_POINT); - - if (FAILED(result)) - { - ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - return error(GL_OUT_OF_MEMORY, false); - } - } - else - { - return formatConvert(source, sourceRect, destFormat, xoffset, yoffset, dest); - } - - return true; -} - -bool Blit::formatConvert(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest) -{ - IDirect3DTexture9 *texture = copySurfaceToTexture(source, sourceRect); - if (!texture) - { - return false; - } - - IDirect3DDevice9 *device = getDevice(); - - saveState(); - - device->SetTexture(0, texture); - device->SetRenderTarget(0, dest); - - setViewport(sourceRect, xoffset, yoffset); - - setCommonBlitState(); - if (setFormatConvertShaders(destFormat)) - { - render(); - } - - texture->Release(); - - restoreState(); - - return true; -} - -bool Blit::setFormatConvertShaders(GLenum destFormat) -{ - bool okay = setVertexShader(SHADER_VS_STANDARD); - - switch (destFormat) - { - default: UNREACHABLE(); - case GL_RGBA: - case GL_BGRA_EXT: - case GL_RGB: - case GL_ALPHA: - okay = okay && setPixelShader(SHADER_PS_COMPONENTMASK); - break; - - case GL_LUMINANCE: - case GL_LUMINANCE_ALPHA: - okay = okay && setPixelShader(SHADER_PS_LUMINANCE); - break; - } - - if (!okay) - { - return false; - } - - enum { X = 0, Y = 1, Z = 2, W = 3 }; - - // The meaning of this constant depends on the shader that was selected. - // See the shader assembly code above for details. - float psConst0[4] = { 0, 0, 0, 0 }; - - switch (destFormat) - { - default: UNREACHABLE(); - case GL_RGBA: - case GL_BGRA_EXT: - psConst0[X] = 1; - psConst0[Z] = 1; - break; - - case GL_RGB: - psConst0[X] = 1; - psConst0[W] = 1; - break; - - case GL_ALPHA: - psConst0[Z] = 1; - break; - - case GL_LUMINANCE: - psConst0[Y] = 1; - break; - - case GL_LUMINANCE_ALPHA: - psConst0[X] = 1; - break; - } - - getDevice()->SetPixelShaderConstantF(0, psConst0, 1); - - return true; -} - -IDirect3DTexture9 *Blit::copySurfaceToTexture(IDirect3DSurface9 *surface, const RECT &sourceRect) -{ - if (!surface) - { - return NULL; - } - - egl::Display *display = getDisplay(); - IDirect3DDevice9 *device = getDevice(); - - D3DSURFACE_DESC sourceDesc; - surface->GetDesc(&sourceDesc); - - // Copy the render target into a texture - IDirect3DTexture9 *texture; - HRESULT result = device->CreateTexture(sourceRect.right - sourceRect.left, sourceRect.bottom - sourceRect.top, 1, D3DUSAGE_RENDERTARGET, sourceDesc.Format, D3DPOOL_DEFAULT, &texture, NULL); - - if (FAILED(result)) - { - ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - return error(GL_OUT_OF_MEMORY, (IDirect3DTexture9*)NULL); - } - - IDirect3DSurface9 *textureSurface; - result = texture->GetSurfaceLevel(0, &textureSurface); - - if (FAILED(result)) - { - ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - texture->Release(); - return error(GL_OUT_OF_MEMORY, (IDirect3DTexture9*)NULL); - } - - display->endScene(); - result = device->StretchRect(surface, &sourceRect, textureSurface, NULL, D3DTEXF_NONE); - - textureSurface->Release(); - - if (FAILED(result)) - { - ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - texture->Release(); - return error(GL_OUT_OF_MEMORY, (IDirect3DTexture9*)NULL); - } - - return texture; -} - -void Blit::setViewport(const RECT &sourceRect, GLint xoffset, GLint yoffset) -{ - IDirect3DDevice9 *device = getDevice(); - - D3DVIEWPORT9 vp; - vp.X = xoffset; - vp.Y = yoffset; - vp.Width = sourceRect.right - sourceRect.left; - vp.Height = sourceRect.bottom - sourceRect.top; - vp.MinZ = 0.0f; - vp.MaxZ = 1.0f; - device->SetViewport(&vp); - - float halfPixelAdjust[4] = { -1.0f/vp.Width, 1.0f/vp.Height, 0, 0 }; - device->SetVertexShaderConstantF(0, halfPixelAdjust, 1); -} - -void Blit::setCommonBlitState() -{ - IDirect3DDevice9 *device = getDevice(); - - device->SetDepthStencilSurface(NULL); - - device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); - device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); - device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); - device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); - device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0); - device->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA | D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_RED); - device->SetRenderState(D3DRS_SRGBWRITEENABLE, FALSE); - device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE); - - device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT); - device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT); - device->SetSamplerState(0, D3DSAMP_SRGBTEXTURE, FALSE); - device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); - device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); - - RECT scissorRect = {0}; // Scissoring is disabled for flipping, but we need this to capture and restore the old rectangle - device->SetScissorRect(&scissorRect); - - for(int i = 0; i < MAX_VERTEX_ATTRIBS; i++) - { - device->SetStreamSourceFreq(i, 1); - } -} - -void Blit::render() -{ - egl::Display *display = getDisplay(); - IDirect3DDevice9 *device = getDevice(); - - HRESULT hr = device->SetStreamSource(0, mQuadVertexBuffer, 0, 2 * sizeof(float)); - hr = device->SetVertexDeclaration(mQuadVertexDeclaration); - - display->startScene(); - hr = device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); -} - -void Blit::saveState() -{ - IDirect3DDevice9 *device = getDevice(); - - HRESULT hr; - - device->GetDepthStencilSurface(&mSavedDepthStencil); - device->GetRenderTarget(0, &mSavedRenderTarget); - - if (mSavedStateBlock == NULL) - { - hr = device->BeginStateBlock(); - ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY); - - setCommonBlitState(); - - static const float dummyConst[4] = { 0, 0, 0, 0 }; - - device->SetVertexShader(NULL); - device->SetVertexShaderConstantF(0, dummyConst, 1); - device->SetPixelShader(NULL); - device->SetPixelShaderConstantF(0, dummyConst, 1); - - D3DVIEWPORT9 dummyVp; - dummyVp.X = 0; - dummyVp.Y = 0; - dummyVp.Width = 1; - dummyVp.Height = 1; - dummyVp.MinZ = 0; - dummyVp.MaxZ = 1; - - device->SetViewport(&dummyVp); - - device->SetTexture(0, NULL); - - device->SetStreamSource(0, mQuadVertexBuffer, 0, 0); - - device->SetVertexDeclaration(mQuadVertexDeclaration); - - hr = device->EndStateBlock(&mSavedStateBlock); - ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY); - } - - ASSERT(mSavedStateBlock != NULL); - - if (mSavedStateBlock != NULL) - { - hr = mSavedStateBlock->Capture(); - ASSERT(SUCCEEDED(hr)); - } -} - -void Blit::restoreState() -{ - IDirect3DDevice9 *device = getDevice(); - - device->SetDepthStencilSurface(mSavedDepthStencil); - if (mSavedDepthStencil != NULL) - { - mSavedDepthStencil->Release(); - mSavedDepthStencil = NULL; - } - - device->SetRenderTarget(0, mSavedRenderTarget); - if (mSavedRenderTarget != NULL) - { - mSavedRenderTarget->Release(); - mSavedRenderTarget = NULL; - } - - ASSERT(mSavedStateBlock != NULL); - - if (mSavedStateBlock != NULL) - { - mSavedStateBlock->Apply(); - } -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/Blit.h b/src/3rdparty/angle/src/libGLESv2/Blit.h deleted file mode 100644 index a9bb4956eb..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/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 - -#define GL_APICALL -#include - -#include - -#include "common/angleutils.h" - -#include "libEGL/Display.h" - -namespace gl -{ -class Context; - -class Blit -{ - public: - explicit Blit(Context *context); - ~Blit(); - - // Copy from source surface to dest surface. - // sourceRect, xoffset, yoffset are in D3D coordinates (0,0 in upper-left) - bool copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest); - - // Copy from source surface to dest surface. - // sourceRect, xoffset, yoffset are in D3D coordinates (0,0 in upper-left) - // source is interpreted as RGBA and destFormat specifies the desired result format. For example, if destFormat = GL_RGB, the alpha channel will be forced to 0. - bool formatConvert(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest); - - // 2x2 box filter sample from source to dest. - // Requires that source is RGB(A) and dest has the same format as source. - bool boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest); - - private: - Context *mContext; - - IDirect3DVertexBuffer9 *mQuadVertexBuffer; - IDirect3DVertexDeclaration9 *mQuadVertexDeclaration; - - void initGeometry(); - - bool setFormatConvertShaders(GLenum destFormat); - - IDirect3DTexture9 *copySurfaceToTexture(IDirect3DSurface9 *surface, const RECT &sourceRect); - void setViewport(const RECT &sourceRect, GLint xoffset, GLint yoffset); - void setCommonBlitState(); - RECT getSurfaceRect(IDirect3DSurface9 *surface) const; - - // This enum is used to index mCompiledShaders and mShaderSource. - enum ShaderId - { - SHADER_VS_STANDARD, - SHADER_VS_FLIPY, - SHADER_PS_PASSTHROUGH, - SHADER_PS_LUMINANCE, - SHADER_PS_COMPONENTMASK, - SHADER_COUNT - }; - - // This actually contains IDirect3DVertexShader9 or IDirect3DPixelShader9 casted to IUnknown. - IUnknown *mCompiledShaders[SHADER_COUNT]; - - template - bool setShader(ShaderId source, const char *profile, - D3DShaderType *(egl::Display::*createShader)(const DWORD *, size_t length), - HRESULT (WINAPI IDirect3DDevice9::*setShader)(D3DShaderType*)); - - bool setVertexShader(ShaderId shader); - bool setPixelShader(ShaderId shader); - void render(); - - void saveState(); - void restoreState(); - IDirect3DStateBlock9 *mSavedStateBlock; - IDirect3DSurface9 *mSavedRenderTarget; - IDirect3DSurface9 *mSavedDepthStencil; - - DISALLOW_COPY_AND_ASSIGN(Blit); -}; -} - -#endif // LIBGLESV2_BLIT_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/Buffer.cpp b/src/3rdparty/angle/src/libGLESv2/Buffer.cpp index dd12e3c077..8d5b4ef2a1 100644 --- a/src/3rdparty/angle/src/libGLESv2/Buffer.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Buffer.cpp @@ -1,5 +1,6 @@ +#include "precompiled.h" // -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// 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. // @@ -10,19 +11,20 @@ #include "libGLESv2/Buffer.h" -#include "libGLESv2/main.h" -#include "libGLESv2/VertexDataManager.h" -#include "libGLESv2/IndexDataManager.h" +#include "libGLESv2/renderer/VertexBuffer.h" +#include "libGLESv2/renderer/IndexBuffer.h" +#include "libGLESv2/renderer/BufferStorage.h" +#include "libGLESv2/renderer/Renderer.h" namespace gl { -Buffer::Buffer(GLuint id) : RefCountObject(id) +Buffer::Buffer(rx::Renderer *renderer, GLuint id) : RefCountObject(id) { - mContents = NULL; - mSize = 0; + mRenderer = renderer; mUsage = GL_DYNAMIC_DRAW; + mBufferStorage = renderer->createBufferStorage(); mStaticVertexBuffer = NULL; mStaticIndexBuffer = NULL; mUnmodifiedDataUse = 0; @@ -30,47 +32,32 @@ Buffer::Buffer(GLuint id) : RefCountObject(id) Buffer::~Buffer() { - delete[] mContents; + delete mBufferStorage; delete mStaticVertexBuffer; delete mStaticIndexBuffer; } void Buffer::bufferData(const void *data, GLsizeiptr size, GLenum usage) { - if (size == 0) - { - delete[] mContents; - mContents = NULL; - } - else if (size != mSize) - { - delete[] mContents; - mContents = new GLubyte[size]; - memset(mContents, 0, size); - } + mBufferStorage->clear(); + mBufferStorage->setData(data, size, 0); - if (data != NULL && size > 0) - { - memcpy(mContents, data, size); - } - - mSize = size; mUsage = usage; invalidateStaticData(); if (usage == GL_STATIC_DRAW) { - mStaticVertexBuffer = new StaticVertexBuffer(getDevice()); - mStaticIndexBuffer = new StaticIndexBuffer(getDevice()); + mStaticVertexBuffer = new rx::StaticVertexBufferInterface(mRenderer); + mStaticIndexBuffer = new rx::StaticIndexBufferInterface(mRenderer); } } void Buffer::bufferSubData(const void *data, GLsizeiptr size, GLintptr offset) { - memcpy(mContents + offset, data, size); - - if ((mStaticVertexBuffer && mStaticVertexBuffer->size() != 0) || (mStaticIndexBuffer && mStaticIndexBuffer->size() != 0)) + mBufferStorage->setData(data, size, offset); + + if ((mStaticVertexBuffer && mStaticVertexBuffer->getBufferSize() != 0) || (mStaticIndexBuffer && mStaticIndexBuffer->getBufferSize() != 0)) { invalidateStaticData(); } @@ -78,12 +65,27 @@ void Buffer::bufferSubData(const void *data, GLsizeiptr size, GLintptr offset) mUnmodifiedDataUse = 0; } -StaticVertexBuffer *Buffer::getStaticVertexBuffer() +rx::BufferStorage *Buffer::getStorage() const +{ + return mBufferStorage; +} + +unsigned int Buffer::size() +{ + return mBufferStorage->getSize(); +} + +GLenum Buffer::usage() const +{ + return mUsage; +} + +rx::StaticVertexBufferInterface *Buffer::getStaticVertexBuffer() { return mStaticVertexBuffer; } -StaticIndexBuffer *Buffer::getStaticIndexBuffer() +rx::StaticIndexBufferInterface *Buffer::getStaticIndexBuffer() { return mStaticIndexBuffer; } @@ -106,10 +108,10 @@ void Buffer::promoteStaticUsage(int dataSize) { mUnmodifiedDataUse += dataSize; - if (mUnmodifiedDataUse > 3 * mSize) + if (mUnmodifiedDataUse > 3 * mBufferStorage->getSize()) { - mStaticVertexBuffer = new StaticVertexBuffer(getDevice()); - mStaticIndexBuffer = new StaticIndexBuffer(getDevice()); + mStaticVertexBuffer = new rx::StaticVertexBufferInterface(mRenderer); + mStaticIndexBuffer = new rx::StaticIndexBufferInterface(mRenderer); } } } diff --git a/src/3rdparty/angle/src/libGLESv2/Buffer.h b/src/3rdparty/angle/src/libGLESv2/Buffer.h index 7019c4e160..4376ada5c0 100644 --- a/src/3rdparty/angle/src/libGLESv2/Buffer.h +++ b/src/3rdparty/angle/src/libGLESv2/Buffer.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// 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. // @@ -11,49 +11,51 @@ #ifndef LIBGLESV2_BUFFER_H_ #define LIBGLESV2_BUFFER_H_ -#include -#include - -#define GL_APICALL -#include - #include "common/angleutils.h" #include "common/RefCountObject.h" +namespace rx +{ +class Renderer; +class BufferStorage; +class StaticIndexBufferInterface; +class StaticVertexBufferInterface; +}; + namespace gl { -class StaticVertexBuffer; -class StaticIndexBuffer; class Buffer : public RefCountObject { public: - explicit Buffer(GLuint id); + Buffer(rx::Renderer *renderer, GLuint id); virtual ~Buffer(); void bufferData(const void *data, GLsizeiptr size, GLenum usage); void bufferSubData(const void *data, GLsizeiptr size, GLintptr offset); - void *data() { return mContents; } - size_t size() const { return mSize; } - GLenum usage() const { return mUsage; } + GLenum usage() const; + + rx::BufferStorage *getStorage() const; + unsigned int size(); - StaticVertexBuffer *getStaticVertexBuffer(); - StaticIndexBuffer *getStaticIndexBuffer(); + rx::StaticVertexBufferInterface *getStaticVertexBuffer(); + rx::StaticIndexBufferInterface *getStaticIndexBuffer(); void invalidateStaticData(); void promoteStaticUsage(int dataSize); private: DISALLOW_COPY_AND_ASSIGN(Buffer); - GLubyte *mContents; - GLsizeiptr mSize; + rx::Renderer *mRenderer; GLenum mUsage; - StaticVertexBuffer *mStaticVertexBuffer; - StaticIndexBuffer *mStaticIndexBuffer; - GLsizeiptr mUnmodifiedDataUse; + rx::BufferStorage *mBufferStorage; + + rx::StaticVertexBufferInterface *mStaticVertexBuffer; + rx::StaticIndexBufferInterface *mStaticIndexBuffer; + unsigned int mUnmodifiedDataUse; }; } diff --git a/src/3rdparty/angle/src/libGLESv2/Context.cpp b/src/3rdparty/angle/src/libGLESv2/Context.cpp index 414bfa968d..90ba2539d8 100644 --- a/src/3rdparty/angle/src/libGLESv2/Context.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Context.cpp @@ -1,5 +1,6 @@ +#include "precompiled.h" // -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// 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. // @@ -9,38 +10,41 @@ #include "libGLESv2/Context.h" -#include - -#include "libEGL/Display.h" - #include "libGLESv2/main.h" -#include "libGLESv2/mathutil.h" #include "libGLESv2/utilities.h" -#include "libGLESv2/Blit.h" -#include "libGLESv2/ResourceManager.h" #include "libGLESv2/Buffer.h" #include "libGLESv2/Fence.h" #include "libGLESv2/Framebuffer.h" +#include "libGLESv2/Renderbuffer.h" #include "libGLESv2/Program.h" #include "libGLESv2/ProgramBinary.h" #include "libGLESv2/Query.h" -#include "libGLESv2/Renderbuffer.h" -#include "libGLESv2/Shader.h" #include "libGLESv2/Texture.h" -#include "libGLESv2/VertexDataManager.h" -#include "libGLESv2/IndexDataManager.h" +#include "libGLESv2/ResourceManager.h" +#include "libGLESv2/renderer/IndexDataManager.h" +#include "libGLESv2/renderer/RenderTarget.h" +#include "libGLESv2/renderer/Renderer.h" + +#include "libEGL/Surface.h" #undef near #undef far namespace gl { -Context::Context(const egl::Config *config, const gl::Context *shareContext, bool notifyResets, bool robustAccess) : mConfig(config) +static const char* makeStaticString(const std::string& str) { - ASSERT(robustAccess == false); // Unimplemented + static std::set strings; + std::set::iterator it = strings.find(str); + if (it != strings.end()) + return it->c_str(); - mDisplay = NULL; - mDevice = NULL; + return strings.insert(str).first->c_str(); +} + +Context::Context(const gl::Context *shareContext, rx::Renderer *renderer, bool notifyResets, bool robustAccess) : mRenderer(renderer) +{ + ASSERT(robustAccess == false); // Unimplemented mFenceHandleAllocator.setBaseHandle(0); @@ -49,68 +53,73 @@ Context::Context(const egl::Config *config, const gl::Context *shareContext, boo mState.depthClearValue = 1.0f; mState.stencilClearValue = 0; - mState.cullFace = false; - mState.cullMode = GL_BACK; - mState.frontFace = GL_CCW; - mState.depthTest = false; - mState.depthFunc = GL_LESS; - mState.blend = false; - mState.sourceBlendRGB = GL_ONE; - mState.sourceBlendAlpha = GL_ONE; - mState.destBlendRGB = GL_ZERO; - mState.destBlendAlpha = GL_ZERO; - mState.blendEquationRGB = GL_FUNC_ADD; - mState.blendEquationAlpha = GL_FUNC_ADD; + mState.rasterizer.cullFace = false; + mState.rasterizer.cullMode = GL_BACK; + mState.rasterizer.frontFace = GL_CCW; + mState.rasterizer.polygonOffsetFill = false; + mState.rasterizer.polygonOffsetFactor = 0.0f; + mState.rasterizer.polygonOffsetUnits = 0.0f; + mState.rasterizer.pointDrawMode = false; + mState.scissorTest = false; + mState.scissor.x = 0; + mState.scissor.y = 0; + mState.scissor.width = 0; + mState.scissor.height = 0; + + mState.blend.blend = false; + mState.blend.sourceBlendRGB = GL_ONE; + mState.blend.sourceBlendAlpha = GL_ONE; + mState.blend.destBlendRGB = GL_ZERO; + mState.blend.destBlendAlpha = GL_ZERO; + mState.blend.blendEquationRGB = GL_FUNC_ADD; + mState.blend.blendEquationAlpha = GL_FUNC_ADD; + mState.blend.sampleAlphaToCoverage = false; + mState.blend.dither = true; + mState.blendColor.red = 0; mState.blendColor.green = 0; mState.blendColor.blue = 0; mState.blendColor.alpha = 0; - mState.stencilTest = false; - mState.stencilFunc = GL_ALWAYS; + + mState.depthStencil.depthTest = false; + mState.depthStencil.depthFunc = GL_LESS; + mState.depthStencil.depthMask = true; + mState.depthStencil.stencilTest = false; + mState.depthStencil.stencilFunc = GL_ALWAYS; + mState.depthStencil.stencilMask = -1; + mState.depthStencil.stencilWritemask = -1; + mState.depthStencil.stencilBackFunc = GL_ALWAYS; + mState.depthStencil.stencilBackMask = - 1; + mState.depthStencil.stencilBackWritemask = -1; + mState.depthStencil.stencilFail = GL_KEEP; + mState.depthStencil.stencilPassDepthFail = GL_KEEP; + mState.depthStencil.stencilPassDepthPass = GL_KEEP; + mState.depthStencil.stencilBackFail = GL_KEEP; + mState.depthStencil.stencilBackPassDepthFail = GL_KEEP; + mState.depthStencil.stencilBackPassDepthPass = GL_KEEP; + mState.stencilRef = 0; - mState.stencilMask = -1; - mState.stencilWritemask = -1; - mState.stencilBackFunc = GL_ALWAYS; mState.stencilBackRef = 0; - mState.stencilBackMask = - 1; - mState.stencilBackWritemask = -1; - mState.stencilFail = GL_KEEP; - mState.stencilPassDepthFail = GL_KEEP; - mState.stencilPassDepthPass = GL_KEEP; - mState.stencilBackFail = GL_KEEP; - mState.stencilBackPassDepthFail = GL_KEEP; - mState.stencilBackPassDepthPass = GL_KEEP; - mState.polygonOffsetFill = false; - mState.polygonOffsetFactor = 0.0f; - mState.polygonOffsetUnits = 0.0f; - mState.sampleAlphaToCoverage = false; + mState.sampleCoverage = false; mState.sampleCoverageValue = 1.0f; mState.sampleCoverageInvert = false; - mState.scissorTest = false; - mState.dither = true; mState.generateMipmapHint = GL_DONT_CARE; mState.fragmentShaderDerivativeHint = GL_DONT_CARE; mState.lineWidth = 1.0f; - mState.viewportX = 0; - mState.viewportY = 0; - mState.viewportWidth = config->mDisplayMode.Width; - mState.viewportHeight = config->mDisplayMode.Height; + mState.viewport.x = 0; + mState.viewport.y = 0; + mState.viewport.width = 0; + mState.viewport.height = 0; mState.zNear = 0.0f; mState.zFar = 1.0f; - mState.scissorX = 0; - mState.scissorY = 0; - mState.scissorWidth = config->mDisplayMode.Width; - mState.scissorHeight = config->mDisplayMode.Height; - - mState.colorMaskRed = true; - mState.colorMaskGreen = true; - mState.colorMaskBlue = true; - mState.colorMaskAlpha = true; - mState.depthMask = true; + mState.blend.colorMaskRed = true; + mState.blend.colorMaskGreen = true; + mState.blend.colorMaskBlue = true; + mState.blend.colorMaskAlpha = true; if (shareContext != NULL) { @@ -119,7 +128,7 @@ Context::Context(const egl::Config *config, const gl::Context *shareContext, boo } else { - mResourceManager = new ResourceManager(); + mResourceManager = new ResourceManager(mRenderer); } // [OpenGL ES 2.0.24] section 3.7 page 83: @@ -128,8 +137,8 @@ Context::Context(const egl::Config *config, const gl::Context *shareContext, boo // In order that access to these initial textures not be lost, they are treated as texture // objects all of whose names are 0. - mTexture2DZero.set(new Texture2D(0)); - mTextureCubeMapZero.set(new TextureCubeMap(0)); + mTexture2DZero.set(new Texture2D(mRenderer, 0)); + mTextureCubeMapZero.set(new TextureCubeMap(mRenderer, 0)); mState.activeSampler = 0; bindArrayBuffer(0); @@ -147,10 +156,8 @@ Context::Context(const egl::Config *config, const gl::Context *shareContext, boo mState.unpackAlignment = 4; mState.packReverseRowOrder = false; - mVertexDataManager = NULL; - mIndexDataManager = NULL; - mBlit = NULL; - mLineLoopIB = NULL; + mExtensionString = NULL; + mRendererString = NULL; mInvalidEnum = false; mInvalidValue = false; @@ -164,15 +171,13 @@ Context::Context(const egl::Config *config, const gl::Context *shareContext, boo mResetStrategy = (notifyResets ? GL_LOSE_CONTEXT_ON_RESET_EXT : GL_NO_RESET_NOTIFICATION_EXT); mRobustAccess = robustAccess; + mSupportsBGRATextures = false; mSupportsDXT1Textures = false; mSupportsDXT3Textures = false; mSupportsDXT5Textures = false; mSupportsEventQueries = false; mSupportsOcclusionQueries = false; mNumCompressedTextureFormats = 0; - mMaxSupportedSamples = 0; - mMaskedClearSavedState = NULL; - markAllStateDirty(); } Context::~Context() @@ -203,15 +208,9 @@ Context::~Context() deleteQuery(mQueryMap.begin()->first); } - while (!mMultiSampleSupport.empty()) - { - delete [] mMultiSampleSupport.begin()->second; - mMultiSampleSupport.erase(mMultiSampleSupport.begin()); - } - for (int type = 0; type < TEXTURE_TYPE_COUNT; type++) { - for (int sampler = 0; sampler < MAX_COMBINED_TEXTURE_IMAGE_UNITS_VTF; sampler++) + for (int sampler = 0; sampler < IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS; sampler++) { mState.samplerTexture[type][sampler].set(NULL); } @@ -239,86 +238,42 @@ Context::~Context() mTexture2DZero.set(NULL); mTextureCubeMapZero.set(NULL); - delete mVertexDataManager; - delete mIndexDataManager; - delete mBlit; - delete mLineLoopIB; - - if (mMaskedClearSavedState) - { - mMaskedClearSavedState->Release(); - } - mResourceManager->release(); } -void Context::makeCurrent(egl::Display *display, egl::Surface *surface) +void Context::makeCurrent(egl::Surface *surface) { - mDisplay = display; - mDevice = mDisplay->getDevice(); - if (!mHasBeenCurrent) { - mDeviceCaps = mDisplay->getDeviceCaps(); - - mVertexDataManager = new VertexDataManager(this, mDevice); - mIndexDataManager = new IndexDataManager(this, mDevice); - mBlit = new Blit(this); + mMajorShaderModel = mRenderer->getMajorShaderModel(); + mMaximumPointSize = mRenderer->getMaxPointSize(); + mSupportsVertexTexture = mRenderer->getVertexTextureSupport(); + mSupportsNonPower2Texture = mRenderer->getNonPower2TextureSupport(); + mSupportsInstancing = mRenderer->getInstancingSupport(); - mSupportsShaderModel3 = mDeviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0); - mMaximumPointSize = mDeviceCaps.MaxPointSize; - mSupportsVertexTexture = mDisplay->getVertexTextureSupport(); - mSupportsNonPower2Texture = mDisplay->getNonPower2TextureSupport(); - mSupportsInstancing = mDisplay->getInstancingSupport(); - - mMaxTextureDimension = std::min(std::min((int)mDeviceCaps.MaxTextureWidth, (int)mDeviceCaps.MaxTextureHeight), + mMaxViewportDimension = mRenderer->getMaxViewportDimension(); + mMaxTextureDimension = std::min(std::min(mRenderer->getMaxTextureWidth(), mRenderer->getMaxTextureHeight()), (int)gl::IMPLEMENTATION_MAX_TEXTURE_SIZE); mMaxCubeTextureDimension = std::min(mMaxTextureDimension, (int)gl::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE); mMaxRenderbufferDimension = mMaxTextureDimension; mMaxTextureLevel = log2(mMaxTextureDimension) + 1; - mMaxTextureAnisotropy = mDisplay->getTextureFilterAnisotropySupport(); + mMaxTextureAnisotropy = mRenderer->getTextureMaxAnisotropy(); TRACE("MaxTextureDimension=%d, MaxCubeTextureDimension=%d, MaxRenderbufferDimension=%d, MaxTextureLevel=%d, MaxTextureAnisotropy=%f", mMaxTextureDimension, mMaxCubeTextureDimension, mMaxRenderbufferDimension, mMaxTextureLevel, mMaxTextureAnisotropy); - const D3DFORMAT renderBufferFormats[] = - { - D3DFMT_A8R8G8B8, - D3DFMT_X8R8G8B8, - D3DFMT_R5G6B5, - D3DFMT_D24S8 - }; - - int max = 0; - for (int i = 0; i < sizeof(renderBufferFormats) / sizeof(D3DFORMAT); ++i) - { - bool *multisampleArray = new bool[D3DMULTISAMPLE_16_SAMPLES + 1]; - mDisplay->getMultiSampleSupport(renderBufferFormats[i], multisampleArray); - mMultiSampleSupport[renderBufferFormats[i]] = multisampleArray; - - for (int j = D3DMULTISAMPLE_16_SAMPLES; j >= 0; --j) - { - if (multisampleArray[j] && j != D3DMULTISAMPLE_NONMASKABLE && j > max) - { - max = j; - } - } - } - - mMaxSupportedSamples = max; - - mSupportsEventQueries = mDisplay->getEventQuerySupport(); - mSupportsOcclusionQueries = mDisplay->getOcclusionQuerySupport(); - mSupportsDXT1Textures = mDisplay->getDXT1TextureSupport(); - mSupportsDXT3Textures = mDisplay->getDXT3TextureSupport(); - mSupportsDXT5Textures = mDisplay->getDXT5TextureSupport(); - mSupportsFloat32Textures = mDisplay->getFloat32TextureSupport(&mSupportsFloat32LinearFilter, &mSupportsFloat32RenderableTextures); - mSupportsFloat16Textures = mDisplay->getFloat16TextureSupport(&mSupportsFloat16LinearFilter, &mSupportsFloat16RenderableTextures); - mSupportsLuminanceTextures = mDisplay->getLuminanceTextureSupport(); - mSupportsLuminanceAlphaTextures = mDisplay->getLuminanceAlphaTextureSupport(); - mSupportsDepthTextures = mDisplay->getDepthTextureSupport(); - mSupportsTextureFilterAnisotropy = mMaxTextureAnisotropy >= 2.0f; - - mSupports32bitIndices = mDeviceCaps.MaxVertexIndex >= (1 << 16); + mSupportsEventQueries = mRenderer->getEventQuerySupport(); + mSupportsOcclusionQueries = mRenderer->getOcclusionQuerySupport(); + mSupportsBGRATextures = mRenderer->getBGRATextureSupport(); + mSupportsDXT1Textures = mRenderer->getDXT1TextureSupport(); + mSupportsDXT3Textures = mRenderer->getDXT3TextureSupport(); + mSupportsDXT5Textures = mRenderer->getDXT5TextureSupport(); + mSupportsFloat32Textures = mRenderer->getFloat32TextureSupport(&mSupportsFloat32LinearFilter, &mSupportsFloat32RenderableTextures); + mSupportsFloat16Textures = mRenderer->getFloat16TextureSupport(&mSupportsFloat16LinearFilter, &mSupportsFloat16RenderableTextures); + mSupportsLuminanceTextures = mRenderer->getLuminanceTextureSupport(); + mSupportsLuminanceAlphaTextures = mRenderer->getLuminanceAlphaTextureSupport(); + mSupportsDepthTextures = mRenderer->getDepthTextureSupport(); + mSupportsTextureFilterAnisotropy = mRenderer->getTextureFilterAnisotropySupport(); + mSupports32bitIndices = mRenderer->get32BitIndexSupport(); mNumCompressedTextureFormats = 0; if (supportsDXT1Textures()) @@ -337,89 +292,30 @@ void Context::makeCurrent(egl::Display *display, egl::Surface *surface) initExtensionString(); initRendererString(); - mState.viewportX = 0; - mState.viewportY = 0; - mState.viewportWidth = surface->getWidth(); - mState.viewportHeight = surface->getHeight(); + mState.viewport.x = 0; + mState.viewport.y = 0; + mState.viewport.width = surface->getWidth(); + mState.viewport.height = surface->getHeight(); - mState.scissorX = 0; - mState.scissorY = 0; - mState.scissorWidth = surface->getWidth(); - mState.scissorHeight = surface->getHeight(); + mState.scissor.x = 0; + mState.scissor.y = 0; + mState.scissor.width = surface->getWidth(); + mState.scissor.height = surface->getHeight(); mHasBeenCurrent = true; } - // Wrap the existing Direct3D 9 resources into GL objects and assign them to the '0' names - IDirect3DSurface9 *defaultRenderTarget = surface->getRenderTarget(); - IDirect3DSurface9 *depthStencil = surface->getDepthStencil(); + // Wrap the existing swapchain resources into GL objects and assign them to the '0' names + rx::SwapChain *swapchain = surface->getSwapChain(); - Colorbuffer *colorbufferZero = new Colorbuffer(defaultRenderTarget); - DepthStencilbuffer *depthStencilbufferZero = new DepthStencilbuffer(depthStencil); - Framebuffer *framebufferZero = new DefaultFramebuffer(colorbufferZero, depthStencilbufferZero); + Colorbuffer *colorbufferZero = new Colorbuffer(mRenderer, swapchain); + DepthStencilbuffer *depthStencilbufferZero = new DepthStencilbuffer(mRenderer, swapchain); + Framebuffer *framebufferZero = new DefaultFramebuffer(mRenderer, colorbufferZero, depthStencilbufferZero); setFramebufferZero(framebufferZero); - - if (defaultRenderTarget) - { - defaultRenderTarget->Release(); - } - - if (depthStencil) - { - depthStencil->Release(); - } - - // Reset pixel shader to null to work around a bug that only happens with Intel GPUs. - // http://crbug.com/110343 - mDevice->SetPixelShader(NULL); - - markAllStateDirty(); -} - -// This function will set all of the state-related dirty flags, so that all state is set during next pre-draw. -void Context::markAllStateDirty() -{ - for (int t = 0; t < MAX_TEXTURE_IMAGE_UNITS; t++) - { - mAppliedTextureSerialPS[t] = 0; - } - - for (int t = 0; t < MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF; t++) - { - mAppliedTextureSerialVS[t] = 0; - } - - mAppliedProgramBinarySerial = 0; - mAppliedRenderTargetSerial = 0; - mAppliedDepthbufferSerial = 0; - mAppliedStencilbufferSerial = 0; - mAppliedIBSerial = 0; - mDepthStencilInitialized = false; - mViewportInitialized = false; - mRenderTargetDescInitialized = false; - - mVertexDeclarationCache.markStateDirty(); - - mClearStateDirty = true; - mCullStateDirty = true; - mDepthStateDirty = true; - mMaskStateDirty = true; - mBlendStateDirty = true; - mStencilStateDirty = true; - mPolygonOffsetStateDirty = true; - mScissorStateDirty = true; - mSampleStateDirty = true; - mDitherStateDirty = true; - mFrontFaceDirty = true; - mDxUniformsDirty = true; -} - -void Context::markDxUniformsDirty() -{ - mDxUniformsDirty = true; } +// NOTE: this function should not assume that this context is current! void Context::markContextLost() { if (mResetStrategy == GL_LOSE_CONTEXT_ON_RESET_EXT) @@ -452,57 +348,37 @@ void Context::setClearStencil(int stencil) void Context::setCullFace(bool enabled) { - if (mState.cullFace != enabled) - { - mState.cullFace = enabled; - mCullStateDirty = true; - } + mState.rasterizer.cullFace = enabled; } bool Context::isCullFaceEnabled() const { - return mState.cullFace; + return mState.rasterizer.cullFace; } void Context::setCullMode(GLenum mode) { - if (mState.cullMode != mode) - { - mState.cullMode = mode; - mCullStateDirty = true; - } + mState.rasterizer.cullMode = mode; } void Context::setFrontFace(GLenum front) { - if (mState.frontFace != front) - { - mState.frontFace = front; - mFrontFaceDirty = true; - } + mState.rasterizer.frontFace = front; } void Context::setDepthTest(bool enabled) { - if (mState.depthTest != enabled) - { - mState.depthTest = enabled; - mDepthStateDirty = true; - } + mState.depthStencil.depthTest = enabled; } bool Context::isDepthTestEnabled() const { - return mState.depthTest; + return mState.depthStencil.depthTest; } void Context::setDepthFunc(GLenum depthFunc) { - if (mState.depthFunc != depthFunc) - { - mState.depthFunc = depthFunc; - mDepthStateDirty = true; - } + mState.depthStencil.depthFunc = depthFunc; } void Context::setDepthRange(float zNear, float zFar) @@ -513,190 +389,114 @@ void Context::setDepthRange(float zNear, float zFar) void Context::setBlend(bool enabled) { - if (mState.blend != enabled) - { - mState.blend = enabled; - mBlendStateDirty = true; - } + mState.blend.blend = enabled; } bool Context::isBlendEnabled() const { - return mState.blend; + return mState.blend.blend; } void Context::setBlendFactors(GLenum sourceRGB, GLenum destRGB, GLenum sourceAlpha, GLenum destAlpha) { - if (mState.sourceBlendRGB != sourceRGB || - mState.sourceBlendAlpha != sourceAlpha || - mState.destBlendRGB != destRGB || - mState.destBlendAlpha != destAlpha) - { - mState.sourceBlendRGB = sourceRGB; - mState.destBlendRGB = destRGB; - mState.sourceBlendAlpha = sourceAlpha; - mState.destBlendAlpha = destAlpha; - mBlendStateDirty = true; - } + mState.blend.sourceBlendRGB = sourceRGB; + mState.blend.destBlendRGB = destRGB; + mState.blend.sourceBlendAlpha = sourceAlpha; + mState.blend.destBlendAlpha = destAlpha; } void Context::setBlendColor(float red, float green, float blue, float alpha) { - if (mState.blendColor.red != red || - mState.blendColor.green != green || - mState.blendColor.blue != blue || - mState.blendColor.alpha != alpha) - { - mState.blendColor.red = red; - mState.blendColor.green = green; - mState.blendColor.blue = blue; - mState.blendColor.alpha = alpha; - mBlendStateDirty = true; - } + mState.blendColor.red = red; + mState.blendColor.green = green; + mState.blendColor.blue = blue; + mState.blendColor.alpha = alpha; } void Context::setBlendEquation(GLenum rgbEquation, GLenum alphaEquation) { - if (mState.blendEquationRGB != rgbEquation || - mState.blendEquationAlpha != alphaEquation) - { - mState.blendEquationRGB = rgbEquation; - mState.blendEquationAlpha = alphaEquation; - mBlendStateDirty = true; - } + mState.blend.blendEquationRGB = rgbEquation; + mState.blend.blendEquationAlpha = alphaEquation; } void Context::setStencilTest(bool enabled) { - if (mState.stencilTest != enabled) - { - mState.stencilTest = enabled; - mStencilStateDirty = true; - } + mState.depthStencil.stencilTest = enabled; } bool Context::isStencilTestEnabled() const { - return mState.stencilTest; + return mState.depthStencil.stencilTest; } void Context::setStencilParams(GLenum stencilFunc, GLint stencilRef, GLuint stencilMask) { - if (mState.stencilFunc != stencilFunc || - mState.stencilRef != stencilRef || - mState.stencilMask != stencilMask) - { - mState.stencilFunc = stencilFunc; - mState.stencilRef = (stencilRef > 0) ? stencilRef : 0; - mState.stencilMask = stencilMask; - mStencilStateDirty = true; - } + mState.depthStencil.stencilFunc = stencilFunc; + mState.stencilRef = (stencilRef > 0) ? stencilRef : 0; + mState.depthStencil.stencilMask = stencilMask; } void Context::setStencilBackParams(GLenum stencilBackFunc, GLint stencilBackRef, GLuint stencilBackMask) { - if (mState.stencilBackFunc != stencilBackFunc || - mState.stencilBackRef != stencilBackRef || - mState.stencilBackMask != stencilBackMask) - { - mState.stencilBackFunc = stencilBackFunc; - mState.stencilBackRef = (stencilBackRef > 0) ? stencilBackRef : 0; - mState.stencilBackMask = stencilBackMask; - mStencilStateDirty = true; - } + mState.depthStencil.stencilBackFunc = stencilBackFunc; + mState.stencilBackRef = (stencilBackRef > 0) ? stencilBackRef : 0; + mState.depthStencil.stencilBackMask = stencilBackMask; } void Context::setStencilWritemask(GLuint stencilWritemask) { - if (mState.stencilWritemask != stencilWritemask) - { - mState.stencilWritemask = stencilWritemask; - mStencilStateDirty = true; - } + mState.depthStencil.stencilWritemask = stencilWritemask; } void Context::setStencilBackWritemask(GLuint stencilBackWritemask) { - if (mState.stencilBackWritemask != stencilBackWritemask) - { - mState.stencilBackWritemask = stencilBackWritemask; - mStencilStateDirty = true; - } + mState.depthStencil.stencilBackWritemask = stencilBackWritemask; } void Context::setStencilOperations(GLenum stencilFail, GLenum stencilPassDepthFail, GLenum stencilPassDepthPass) { - if (mState.stencilFail != stencilFail || - mState.stencilPassDepthFail != stencilPassDepthFail || - mState.stencilPassDepthPass != stencilPassDepthPass) - { - mState.stencilFail = stencilFail; - mState.stencilPassDepthFail = stencilPassDepthFail; - mState.stencilPassDepthPass = stencilPassDepthPass; - mStencilStateDirty = true; - } + mState.depthStencil.stencilFail = stencilFail; + mState.depthStencil.stencilPassDepthFail = stencilPassDepthFail; + mState.depthStencil.stencilPassDepthPass = stencilPassDepthPass; } void Context::setStencilBackOperations(GLenum stencilBackFail, GLenum stencilBackPassDepthFail, GLenum stencilBackPassDepthPass) { - if (mState.stencilBackFail != stencilBackFail || - mState.stencilBackPassDepthFail != stencilBackPassDepthFail || - mState.stencilBackPassDepthPass != stencilBackPassDepthPass) - { - mState.stencilBackFail = stencilBackFail; - mState.stencilBackPassDepthFail = stencilBackPassDepthFail; - mState.stencilBackPassDepthPass = stencilBackPassDepthPass; - mStencilStateDirty = true; - } + mState.depthStencil.stencilBackFail = stencilBackFail; + mState.depthStencil.stencilBackPassDepthFail = stencilBackPassDepthFail; + mState.depthStencil.stencilBackPassDepthPass = stencilBackPassDepthPass; } void Context::setPolygonOffsetFill(bool enabled) { - if (mState.polygonOffsetFill != enabled) - { - mState.polygonOffsetFill = enabled; - mPolygonOffsetStateDirty = true; - } + mState.rasterizer.polygonOffsetFill = enabled; } bool Context::isPolygonOffsetFillEnabled() const { - return mState.polygonOffsetFill; - + return mState.rasterizer.polygonOffsetFill; } void Context::setPolygonOffsetParams(GLfloat factor, GLfloat units) { - if (mState.polygonOffsetFactor != factor || - mState.polygonOffsetUnits != units) - { - mState.polygonOffsetFactor = factor; - mState.polygonOffsetUnits = units; - mPolygonOffsetStateDirty = true; - } + // An application can pass NaN values here, so handle this gracefully + mState.rasterizer.polygonOffsetFactor = factor != factor ? 0.0f : factor; + mState.rasterizer.polygonOffsetUnits = units != units ? 0.0f : units; } void Context::setSampleAlphaToCoverage(bool enabled) { - if (mState.sampleAlphaToCoverage != enabled) - { - mState.sampleAlphaToCoverage = enabled; - mSampleStateDirty = true; - } + mState.blend.sampleAlphaToCoverage = enabled; } bool Context::isSampleAlphaToCoverageEnabled() const { - return mState.sampleAlphaToCoverage; + return mState.blend.sampleAlphaToCoverage; } void Context::setSampleCoverage(bool enabled) { - if (mState.sampleCoverage != enabled) - { - mState.sampleCoverage = enabled; - mSampleStateDirty = true; - } + mState.sampleCoverage = enabled; } bool Context::isSampleCoverageEnabled() const @@ -706,22 +506,13 @@ bool Context::isSampleCoverageEnabled() const void Context::setSampleCoverageParams(GLclampf value, bool invert) { - if (mState.sampleCoverageValue != value || - mState.sampleCoverageInvert != invert) - { - mState.sampleCoverageValue = value; - mState.sampleCoverageInvert = invert; - mSampleStateDirty = true; - } + mState.sampleCoverageValue = value; + mState.sampleCoverageInvert = invert; } void Context::setScissorTest(bool enabled) { - if (mState.scissorTest != enabled) - { - mState.scissorTest = enabled; - mScissorStateDirty = true; - } + mState.scissorTest = enabled; } bool Context::isScissorTestEnabled() const @@ -731,16 +522,12 @@ bool Context::isScissorTestEnabled() const void Context::setDither(bool enabled) { - if (mState.dither != enabled) - { - mState.dither = enabled; - mDitherStateDirty = true; - } + mState.blend.dither = enabled; } bool Context::isDitherEnabled() const { - return mState.dither; + return mState.blend.dither; } void Context::setLineWidth(GLfloat width) @@ -763,45 +550,31 @@ void Context::setFragmentShaderDerivativeHint(GLenum hint) void Context::setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height) { - mState.viewportX = x; - mState.viewportY = y; - mState.viewportWidth = width; - mState.viewportHeight = height; + mState.viewport.x = x; + mState.viewport.y = y; + mState.viewport.width = width; + mState.viewport.height = height; } void Context::setScissorParams(GLint x, GLint y, GLsizei width, GLsizei height) { - if (mState.scissorX != x || mState.scissorY != y || - mState.scissorWidth != width || mState.scissorHeight != height) - { - mState.scissorX = x; - mState.scissorY = y; - mState.scissorWidth = width; - mState.scissorHeight = height; - mScissorStateDirty = true; - } + mState.scissor.x = x; + mState.scissor.y = y; + mState.scissor.width = width; + mState.scissor.height = height; } void Context::setColorMask(bool red, bool green, bool blue, bool alpha) { - if (mState.colorMaskRed != red || mState.colorMaskGreen != green || - mState.colorMaskBlue != blue || mState.colorMaskAlpha != alpha) - { - mState.colorMaskRed = red; - mState.colorMaskGreen = green; - mState.colorMaskBlue = blue; - mState.colorMaskAlpha = alpha; - mMaskStateDirty = true; - } + mState.blend.colorMaskRed = red; + mState.blend.colorMaskGreen = green; + mState.blend.colorMaskBlue = blue; + mState.blend.colorMaskAlpha = alpha; } void Context::setDepthMask(bool mask) { - if (mState.depthMask != mask) - { - mState.depthMask = mask; - mMaskStateDirty = true; - } + mState.depthStencil.depthMask = mask; } void Context::setActiveSampler(unsigned int active) @@ -881,11 +654,6 @@ const void *Context::getVertexAttribPointer(unsigned int attribNum) const return mState.vertexAttribute[attribNum].mPointer; } -const VertexAttributeArray &Context::getVertexAttributes() -{ - return mState.vertexAttribute; -} - void Context::setPackAlignment(GLint alignment) { mState.packAlignment = alignment; @@ -955,7 +723,7 @@ GLuint Context::createFence() { GLuint handle = mFenceHandleAllocator.allocate(); - mFenceMap[handle] = new Fence(mDisplay); + mFenceMap[handle] = new Fence(mRenderer); return handle; } @@ -1117,7 +885,7 @@ void Context::bindReadFramebuffer(GLuint framebuffer) { if (!getFramebuffer(framebuffer)) { - mFramebufferMap[framebuffer] = new Framebuffer(); + mFramebufferMap[framebuffer] = new Framebuffer(mRenderer); } mState.readFramebuffer = framebuffer; @@ -1127,7 +895,7 @@ void Context::bindDrawFramebuffer(GLuint framebuffer) { if (!getFramebuffer(framebuffer)) { - mFramebufferMap[framebuffer] = new Framebuffer(); + mFramebufferMap[framebuffer] = new Framebuffer(mRenderer); } mState.drawFramebuffer = framebuffer; @@ -1152,7 +920,6 @@ void Context::useProgram(GLuint program) Program *newProgram = mResourceManager->getProgram(program); Program *oldProgram = mResourceManager->getProgram(priorProgram); mCurrentProgramBinary.set(NULL); - mDxUniformsDirty = true; if (newProgram) { @@ -1178,7 +945,6 @@ void Context::linkProgram(GLuint program) if (linked && program == mState.currentProgram) { mCurrentProgramBinary.set(programObject->getProgramBinary()); - mDxUniformsDirty = true; } } @@ -1193,7 +959,6 @@ void Context::setProgramBinary(GLuint program, const void *binary, GLint length) if (loaded && program == mState.currentProgram) { mCurrentProgramBinary.set(programObject->getProgramBinary()); - mDxUniformsDirty = true; } } @@ -1219,7 +984,7 @@ void Context::beginQuery(GLenum target, GLuint query) { if (mState.activeQuery[i].get() != NULL) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } } @@ -1242,13 +1007,13 @@ void Context::beginQuery(GLenum target, GLuint query) // check that name was obtained with glGenQueries if (!queryObject) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } // check for type mismatch if (queryObject->getType() != target) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } // set query as active for specified target @@ -1279,7 +1044,7 @@ void Context::endQuery(GLenum target) if (queryObject == NULL) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } queryObject->end(); @@ -1297,8 +1062,31 @@ void Context::setFramebufferZero(Framebuffer *buffer) } } -void Context::setRenderbufferStorage(RenderbufferStorage *renderbuffer) +void Context::setRenderbufferStorage(GLsizei width, GLsizei height, GLenum internalformat, GLsizei samples) { + RenderbufferStorage *renderbuffer = NULL; + switch (internalformat) + { + case GL_DEPTH_COMPONENT16: + renderbuffer = new gl::Depthbuffer(mRenderer, width, height, samples); + break; + case GL_RGBA4: + case GL_RGB5_A1: + case GL_RGB565: + case GL_RGB8_OES: + case GL_RGBA8_OES: + renderbuffer = new gl::Colorbuffer(mRenderer,width, height, internalformat, samples); + break; + case GL_STENCIL_INDEX8: + renderbuffer = new gl::Stencilbuffer(mRenderer, width, height, samples); + break; + case GL_DEPTH24_STENCIL8_OES: + renderbuffer = new gl::DepthStencilbuffer(mRenderer, width, height, samples); + break; + default: + UNREACHABLE(); return; + } + Renderbuffer *renderbufferObject = mState.renderbuffer.get(); renderbufferObject->setStorage(renderbuffer); } @@ -1343,7 +1131,7 @@ Query *Context::getQuery(unsigned int handle, bool create, GLenum type) { if (!query->second && create) { - query->second = new Query(handle, type); + query->second = new Query(mRenderer, type, handle); query->second->addRef(); } return query->second; @@ -1396,25 +1184,25 @@ bool Context::getBooleanv(GLenum pname, GLboolean *params) { switch (pname) { - case GL_SHADER_COMPILER: *params = GL_TRUE; break; - case GL_SAMPLE_COVERAGE_INVERT: *params = mState.sampleCoverageInvert; break; - case GL_DEPTH_WRITEMASK: *params = mState.depthMask; break; + case GL_SHADER_COMPILER: *params = GL_TRUE; break; + case GL_SAMPLE_COVERAGE_INVERT: *params = mState.sampleCoverageInvert; break; + case GL_DEPTH_WRITEMASK: *params = mState.depthStencil.depthMask; break; case GL_COLOR_WRITEMASK: - params[0] = mState.colorMaskRed; - params[1] = mState.colorMaskGreen; - params[2] = mState.colorMaskBlue; - params[3] = mState.colorMaskAlpha; + params[0] = mState.blend.colorMaskRed; + params[1] = mState.blend.colorMaskGreen; + params[2] = mState.blend.colorMaskBlue; + params[3] = mState.blend.colorMaskAlpha; break; - case GL_CULL_FACE: *params = mState.cullFace; break; - case GL_POLYGON_OFFSET_FILL: *params = mState.polygonOffsetFill; break; - case GL_SAMPLE_ALPHA_TO_COVERAGE: *params = mState.sampleAlphaToCoverage; break; - case GL_SAMPLE_COVERAGE: *params = mState.sampleCoverage; break; - case GL_SCISSOR_TEST: *params = mState.scissorTest; break; - case GL_STENCIL_TEST: *params = mState.stencilTest; break; - case GL_DEPTH_TEST: *params = mState.depthTest; break; - case GL_BLEND: *params = mState.blend; break; - case GL_DITHER: *params = mState.dither; break; - case GL_CONTEXT_ROBUST_ACCESS_EXT: *params = mRobustAccess ? GL_TRUE : GL_FALSE; break; + case GL_CULL_FACE: *params = mState.rasterizer.cullFace; break; + case GL_POLYGON_OFFSET_FILL: *params = mState.rasterizer.polygonOffsetFill; break; + case GL_SAMPLE_ALPHA_TO_COVERAGE: *params = mState.blend.sampleAlphaToCoverage; break; + case GL_SAMPLE_COVERAGE: *params = mState.sampleCoverage; break; + case GL_SCISSOR_TEST: *params = mState.scissorTest; break; + case GL_STENCIL_TEST: *params = mState.depthStencil.stencilTest; break; + case GL_DEPTH_TEST: *params = mState.depthStencil.depthTest; break; + case GL_BLEND: *params = mState.blend.blend; break; + case GL_DITHER: *params = mState.blend.dither; break; + case GL_CONTEXT_ROBUST_ACCESS_EXT: *params = mRobustAccess ? GL_TRUE : GL_FALSE; break; default: return false; } @@ -1430,11 +1218,11 @@ bool Context::getFloatv(GLenum pname, GLfloat *params) // case, this should make no difference to the calling application. switch (pname) { - case GL_LINE_WIDTH: *params = mState.lineWidth; break; - case GL_SAMPLE_COVERAGE_VALUE: *params = mState.sampleCoverageValue; break; - case GL_DEPTH_CLEAR_VALUE: *params = mState.depthClearValue; break; - case GL_POLYGON_OFFSET_FACTOR: *params = mState.polygonOffsetFactor; break; - case GL_POLYGON_OFFSET_UNITS: *params = mState.polygonOffsetUnits; break; + case GL_LINE_WIDTH: *params = mState.lineWidth; break; + case GL_SAMPLE_COVERAGE_VALUE: *params = mState.sampleCoverageValue; break; + case GL_DEPTH_CLEAR_VALUE: *params = mState.depthClearValue; break; + case GL_POLYGON_OFFSET_FACTOR: *params = mState.rasterizer.polygonOffsetFactor; break; + case GL_POLYGON_OFFSET_UNITS: *params = mState.rasterizer.polygonOffsetUnits; break; case GL_ALIASED_LINE_WIDTH_RANGE: params[0] = gl::ALIASED_LINE_WIDTH_RANGE_MIN; params[1] = gl::ALIASED_LINE_WIDTH_RANGE_MAX; @@ -1475,6 +1263,22 @@ bool Context::getFloatv(GLenum pname, GLfloat *params) bool Context::getIntegerv(GLenum pname, GLint *params) { + if (pname >= GL_DRAW_BUFFER0_EXT && pname <= GL_DRAW_BUFFER15_EXT) + { + unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0_EXT); + + if (colorAttachment >= mRenderer->getMaxRenderTargets()) + { + // return true to stop further operation in the parent call + return gl::error(GL_INVALID_OPERATION, true); + } + + Framebuffer *framebuffer = getDrawFramebuffer(); + + *params = framebuffer->getDrawBufferState(colorAttachment); + return true; + } + // Please note: DEPTH_CLEAR_VALUE is not included in our internal getIntegerv implementation // because it is stored as a float, despite the fact that the GL ES 2.0 spec names // GetIntegerv as its native query function. As it would require conversion in any @@ -1483,13 +1287,15 @@ bool Context::getIntegerv(GLenum pname, GLint *params) switch (pname) { case GL_MAX_VERTEX_ATTRIBS: *params = gl::MAX_VERTEX_ATTRIBS; break; - case GL_MAX_VERTEX_UNIFORM_VECTORS: *params = gl::MAX_VERTEX_UNIFORM_VECTORS; break; - case GL_MAX_VARYING_VECTORS: *params = getMaximumVaryingVectors(); break; - case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: *params = getMaximumCombinedTextureImageUnits(); break; - case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: *params = getMaximumVertexTextureImageUnits(); break; + case GL_MAX_VERTEX_UNIFORM_VECTORS: *params = mRenderer->getMaxVertexUniformVectors(); break; + case GL_MAX_VARYING_VECTORS: *params = mRenderer->getMaxVaryingVectors(); break; + case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: *params = mRenderer->getMaxCombinedTextureImageUnits(); break; + case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: *params = mRenderer->getMaxVertexTextureImageUnits(); break; case GL_MAX_TEXTURE_IMAGE_UNITS: *params = gl::MAX_TEXTURE_IMAGE_UNITS; break; - case GL_MAX_FRAGMENT_UNIFORM_VECTORS: *params = getMaximumFragmentUniformVectors(); break; + case GL_MAX_FRAGMENT_UNIFORM_VECTORS: *params = mRenderer->getMaxFragmentUniformVectors(); break; case GL_MAX_RENDERBUFFER_SIZE: *params = getMaximumRenderbufferDimension(); break; + case GL_MAX_COLOR_ATTACHMENTS_EXT: *params = mRenderer->getMaxRenderTargets(); break; + case GL_MAX_DRAW_BUFFERS_EXT: *params = mRenderer->getMaxRenderTargets(); break; case GL_NUM_SHADER_BINARY_FORMATS: *params = 0; break; case GL_SHADER_BINARY_FORMATS: /* no shader binary formats are supported */ break; case GL_ARRAY_BUFFER_BINDING: *params = mState.arrayBuffer.id(); break; @@ -1505,27 +1311,27 @@ bool Context::getIntegerv(GLenum pname, GLint *params) case GL_GENERATE_MIPMAP_HINT: *params = mState.generateMipmapHint; break; case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES: *params = mState.fragmentShaderDerivativeHint; break; case GL_ACTIVE_TEXTURE: *params = (mState.activeSampler + GL_TEXTURE0); break; - case GL_STENCIL_FUNC: *params = mState.stencilFunc; break; - case GL_STENCIL_REF: *params = mState.stencilRef; break; - case GL_STENCIL_VALUE_MASK: *params = mState.stencilMask; break; - case GL_STENCIL_BACK_FUNC: *params = mState.stencilBackFunc; break; - case GL_STENCIL_BACK_REF: *params = mState.stencilBackRef; break; - case GL_STENCIL_BACK_VALUE_MASK: *params = mState.stencilBackMask; break; - case GL_STENCIL_FAIL: *params = mState.stencilFail; break; - case GL_STENCIL_PASS_DEPTH_FAIL: *params = mState.stencilPassDepthFail; break; - case GL_STENCIL_PASS_DEPTH_PASS: *params = mState.stencilPassDepthPass; break; - case GL_STENCIL_BACK_FAIL: *params = mState.stencilBackFail; break; - case GL_STENCIL_BACK_PASS_DEPTH_FAIL: *params = mState.stencilBackPassDepthFail; break; - case GL_STENCIL_BACK_PASS_DEPTH_PASS: *params = mState.stencilBackPassDepthPass; break; - case GL_DEPTH_FUNC: *params = mState.depthFunc; break; - case GL_BLEND_SRC_RGB: *params = mState.sourceBlendRGB; break; - case GL_BLEND_SRC_ALPHA: *params = mState.sourceBlendAlpha; break; - case GL_BLEND_DST_RGB: *params = mState.destBlendRGB; break; - case GL_BLEND_DST_ALPHA: *params = mState.destBlendAlpha; break; - case GL_BLEND_EQUATION_RGB: *params = mState.blendEquationRGB; break; - case GL_BLEND_EQUATION_ALPHA: *params = mState.blendEquationAlpha; break; - case GL_STENCIL_WRITEMASK: *params = mState.stencilWritemask; break; - case GL_STENCIL_BACK_WRITEMASK: *params = mState.stencilBackWritemask; break; + case GL_STENCIL_FUNC: *params = mState.depthStencil.stencilFunc; break; + case GL_STENCIL_REF: *params = mState.stencilRef; break; + case GL_STENCIL_VALUE_MASK: *params = mState.depthStencil.stencilMask; break; + case GL_STENCIL_BACK_FUNC: *params = mState.depthStencil.stencilBackFunc; break; + case GL_STENCIL_BACK_REF: *params = mState.stencilBackRef; break; + case GL_STENCIL_BACK_VALUE_MASK: *params = mState.depthStencil.stencilBackMask; break; + case GL_STENCIL_FAIL: *params = mState.depthStencil.stencilFail; break; + case GL_STENCIL_PASS_DEPTH_FAIL: *params = mState.depthStencil.stencilPassDepthFail; break; + case GL_STENCIL_PASS_DEPTH_PASS: *params = mState.depthStencil.stencilPassDepthPass; break; + case GL_STENCIL_BACK_FAIL: *params = mState.depthStencil.stencilBackFail; break; + case GL_STENCIL_BACK_PASS_DEPTH_FAIL: *params = mState.depthStencil.stencilBackPassDepthFail; break; + case GL_STENCIL_BACK_PASS_DEPTH_PASS: *params = mState.depthStencil.stencilBackPassDepthPass; break; + case GL_DEPTH_FUNC: *params = mState.depthStencil.depthFunc; break; + case GL_BLEND_SRC_RGB: *params = mState.blend.sourceBlendRGB; break; + case GL_BLEND_SRC_ALPHA: *params = mState.blend.sourceBlendAlpha; break; + case GL_BLEND_DST_RGB: *params = mState.blend.destBlendRGB; break; + case GL_BLEND_DST_ALPHA: *params = mState.blend.destBlendAlpha; break; + case GL_BLEND_EQUATION_RGB: *params = mState.blend.blendEquationRGB; break; + case GL_BLEND_EQUATION_ALPHA: *params = mState.blend.blendEquationAlpha; break; + case GL_STENCIL_WRITEMASK: *params = mState.depthStencil.stencilWritemask; break; + case GL_STENCIL_BACK_WRITEMASK: *params = mState.depthStencil.stencilBackWritemask; break; case GL_STENCIL_CLEAR_VALUE: *params = mState.stencilClearValue; break; case GL_SUBPIXEL_BITS: *params = 4; break; case GL_MAX_TEXTURE_SIZE: *params = getMaximumTextureDimension(); break; @@ -1591,9 +1397,8 @@ bool Context::getIntegerv(GLenum pname, GLint *params) break; case GL_MAX_VIEWPORT_DIMS: { - int maxDimension = std::max(getMaximumRenderbufferDimension(), getMaximumTextureDimension()); - params[0] = maxDimension; - params[1] = maxDimension; + params[0] = mMaxViewportDimension; + params[1] = mMaxViewportDimension; } break; case GL_COMPRESSED_TEXTURE_FORMATS: @@ -1614,35 +1419,35 @@ bool Context::getIntegerv(GLenum pname, GLint *params) } break; case GL_VIEWPORT: - params[0] = mState.viewportX; - params[1] = mState.viewportY; - params[2] = mState.viewportWidth; - params[3] = mState.viewportHeight; + params[0] = mState.viewport.x; + params[1] = mState.viewport.y; + params[2] = mState.viewport.width; + params[3] = mState.viewport.height; break; case GL_SCISSOR_BOX: - params[0] = mState.scissorX; - params[1] = mState.scissorY; - params[2] = mState.scissorWidth; - params[3] = mState.scissorHeight; + params[0] = mState.scissor.x; + params[1] = mState.scissor.y; + params[2] = mState.scissor.width; + params[3] = mState.scissor.height; break; - case GL_CULL_FACE_MODE: *params = mState.cullMode; break; - case GL_FRONT_FACE: *params = mState.frontFace; break; + case GL_CULL_FACE_MODE: *params = mState.rasterizer.cullMode; break; + case GL_FRONT_FACE: *params = mState.rasterizer.frontFace; break; case GL_RED_BITS: case GL_GREEN_BITS: case GL_BLUE_BITS: case GL_ALPHA_BITS: { gl::Framebuffer *framebuffer = getDrawFramebuffer(); - gl::Renderbuffer *colorbuffer = framebuffer->getColorbuffer(); + gl::Renderbuffer *colorbuffer = framebuffer->getFirstColorbuffer(); if (colorbuffer) { switch (pname) { - case GL_RED_BITS: *params = colorbuffer->getRedSize(); break; - case GL_GREEN_BITS: *params = colorbuffer->getGreenSize(); break; - case GL_BLUE_BITS: *params = colorbuffer->getBlueSize(); break; - case GL_ALPHA_BITS: *params = colorbuffer->getAlphaSize(); break; + case GL_RED_BITS: *params = colorbuffer->getRedSize(); break; + case GL_GREEN_BITS: *params = colorbuffer->getGreenSize(); break; + case GL_BLUE_BITS: *params = colorbuffer->getBlueSize(); break; + case GL_ALPHA_BITS: *params = colorbuffer->getAlphaSize(); break; } } else @@ -1683,9 +1488,9 @@ bool Context::getIntegerv(GLenum pname, GLint *params) break; case GL_TEXTURE_BINDING_2D: { - if (mState.activeSampler < 0 || mState.activeSampler > getMaximumCombinedTextureImageUnits() - 1) + if (mState.activeSampler > mRenderer->getMaxCombinedTextureImageUnits() - 1) { - error(GL_INVALID_OPERATION); + gl::error(GL_INVALID_OPERATION); return false; } @@ -1694,9 +1499,9 @@ bool Context::getIntegerv(GLenum pname, GLint *params) break; case GL_TEXTURE_BINDING_CUBE_MAP: { - if (mState.activeSampler < 0 || mState.activeSampler > getMaximumCombinedTextureImageUnits() - 1) + if (mState.activeSampler > mRenderer->getMaxCombinedTextureImageUnits() - 1) { - error(GL_INVALID_OPERATION); + gl::error(GL_INVALID_OPERATION); return false; } @@ -1721,6 +1526,13 @@ bool Context::getIntegerv(GLenum pname, GLint *params) bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *numParams) { + if (pname >= GL_DRAW_BUFFER0_EXT && pname <= GL_DRAW_BUFFER15_EXT) + { + *type = GL_INT; + *numParams = 1; + return true; + } + // Please note: the query type returned for DEPTH_CLEAR_VALUE in this implementation // is FLOAT rather than INT, as would be suggested by the GL ES 2.0 spec. This is due // to the fact that it is stored internally as a float, and so would require conversion @@ -1750,6 +1562,8 @@ bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *nu case GL_MAX_TEXTURE_IMAGE_UNITS: case GL_MAX_FRAGMENT_UNIFORM_VECTORS: case GL_MAX_RENDERBUFFER_SIZE: + case GL_MAX_COLOR_ATTACHMENTS_EXT: + case GL_MAX_DRAW_BUFFERS_EXT: case GL_NUM_SHADER_BINARY_FORMATS: case GL_NUM_COMPRESSED_TEXTURE_FORMATS: case GL_ARRAY_BUFFER_BINDING: @@ -1901,594 +1715,135 @@ bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *nu } // Applies the render target surface, depth stencil surface, viewport rectangle and -// scissor rectangle to the Direct3D 9 device -bool Context::applyRenderTarget(bool ignoreViewport) +// scissor rectangle to the renderer +bool Context::applyRenderTarget(GLenum drawMode, bool ignoreViewport) { Framebuffer *framebufferObject = getDrawFramebuffer(); if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE) { - return error(GL_INVALID_FRAMEBUFFER_OPERATION, false); + return gl::error(GL_INVALID_FRAMEBUFFER_OPERATION, false); } - // if there is no color attachment we must synthesize a NULL colorattachment - // to keep the D3D runtime happy. This should only be possible if depth texturing. - Renderbuffer *renderbufferObject = NULL; - if (framebufferObject->getColorbufferType() != GL_NONE) - { - renderbufferObject = framebufferObject->getColorbuffer(); - } - else - { - renderbufferObject = framebufferObject->getNullColorbuffer(); - } - if (!renderbufferObject) - { - ERR("unable to locate renderbuffer for FBO."); - return false; - } + mRenderer->applyRenderTarget(framebufferObject); - bool renderTargetChanged = false; - unsigned int renderTargetSerial = renderbufferObject->getSerial(); - if (renderTargetSerial != mAppliedRenderTargetSerial) + if (!mRenderer->setViewport(mState.viewport, mState.zNear, mState.zFar, drawMode, mState.rasterizer.frontFace, + ignoreViewport)) { - IDirect3DSurface9 *renderTarget = renderbufferObject->getRenderTarget(); - if (!renderTarget) - { - ERR("render target pointer unexpectedly null."); - return false; // Context must be lost - } - mDevice->SetRenderTarget(0, renderTarget); - mAppliedRenderTargetSerial = renderTargetSerial; - mScissorStateDirty = true; // Scissor area must be clamped to render target's size-- this is different for different render targets. - renderTargetChanged = true; - renderTarget->Release(); + return false; } - IDirect3DSurface9 *depthStencil = NULL; - unsigned int depthbufferSerial = 0; - unsigned int stencilbufferSerial = 0; - if (framebufferObject->getDepthbufferType() != GL_NONE) - { - Renderbuffer *depthbuffer = framebufferObject->getDepthbuffer(); - depthStencil = depthbuffer->getDepthStencil(); - if (!depthStencil) - { - ERR("Depth stencil pointer unexpectedly null."); - return false; - } - - depthbufferSerial = depthbuffer->getSerial(); - } - else if (framebufferObject->getStencilbufferType() != GL_NONE) - { - Renderbuffer *stencilbuffer = framebufferObject->getStencilbuffer(); - depthStencil = stencilbuffer->getDepthStencil(); - if (!depthStencil) - { - ERR("Depth stencil pointer unexpectedly null."); - return false; - } - - stencilbufferSerial = stencilbuffer->getSerial(); - } + mRenderer->setScissorRectangle(mState.scissor, mState.scissorTest); - if (depthbufferSerial != mAppliedDepthbufferSerial || - stencilbufferSerial != mAppliedStencilbufferSerial || - !mDepthStencilInitialized) - { - mDevice->SetDepthStencilSurface(depthStencil); - mAppliedDepthbufferSerial = depthbufferSerial; - mAppliedStencilbufferSerial = stencilbufferSerial; - mDepthStencilInitialized = true; - } + return true; +} - if (depthStencil) - { - depthStencil->Release(); - } +// Applies the fixed-function state (culling, depth test, alpha blending, stenciling, etc) to the Direct3D 9 device +void Context::applyState(GLenum drawMode) +{ + mState.rasterizer.pointDrawMode = (drawMode == GL_POINTS); + mRenderer->setRasterizerState(mState.rasterizer); - if (!mRenderTargetDescInitialized || renderTargetChanged) + unsigned int mask = 0; + if (mState.sampleCoverage) { - IDirect3DSurface9 *renderTarget = renderbufferObject->getRenderTarget(); - if (!renderTarget) + if (mState.sampleCoverageValue != 0) { - return false; // Context must be lost - } - renderTarget->GetDesc(&mRenderTargetDesc); - mRenderTargetDescInitialized = true; - renderTarget->Release(); - } - - D3DVIEWPORT9 viewport; - - float zNear = clamp01(mState.zNear); - float zFar = clamp01(mState.zFar); + Framebuffer *framebufferObject = getDrawFramebuffer(); + float threshold = 0.5f; - if (ignoreViewport) - { - viewport.X = 0; - viewport.Y = 0; - viewport.Width = mRenderTargetDesc.Width; - viewport.Height = mRenderTargetDesc.Height; - viewport.MinZ = 0.0f; - viewport.MaxZ = 1.0f; - } - else - { - viewport.X = clamp(mState.viewportX, 0L, static_cast(mRenderTargetDesc.Width)); - viewport.Y = clamp(mState.viewportY, 0L, static_cast(mRenderTargetDesc.Height)); - viewport.Width = clamp(mState.viewportWidth, 0L, static_cast(mRenderTargetDesc.Width) - static_cast(viewport.X)); - viewport.Height = clamp(mState.viewportHeight, 0L, static_cast(mRenderTargetDesc.Height) - static_cast(viewport.Y)); - viewport.MinZ = zNear; - viewport.MaxZ = zFar; - } - - if (viewport.Width <= 0 || viewport.Height <= 0) - { - return false; // Nothing to render - } - - if (renderTargetChanged || !mViewportInitialized || memcmp(&viewport, &mSetViewport, sizeof mSetViewport) != 0) - { - mDevice->SetViewport(&viewport); - mSetViewport = viewport; - mViewportInitialized = true; - mDxUniformsDirty = true; - } + for (int i = 0; i < framebufferObject->getSamples(); ++i) + { + mask <<= 1; - if (mScissorStateDirty) - { - if (mState.scissorTest) - { - RECT rect; - rect.left = clamp(mState.scissorX, 0L, static_cast(mRenderTargetDesc.Width)); - rect.top = clamp(mState.scissorY, 0L, static_cast(mRenderTargetDesc.Height)); - rect.right = clamp(mState.scissorX + mState.scissorWidth, 0L, static_cast(mRenderTargetDesc.Width)); - rect.bottom = clamp(mState.scissorY + mState.scissorHeight, 0L, static_cast(mRenderTargetDesc.Height)); - mDevice->SetScissorRect(&rect); - mDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE); + if ((i + 1) * mState.sampleCoverageValue >= threshold) + { + threshold += 1.0f; + mask |= 1; + } + } } - else + + if (mState.sampleCoverageInvert) { - mDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE); + mask = ~mask; } - - mScissorStateDirty = false; } - - if (mState.currentProgram && mDxUniformsDirty) + else { - ProgramBinary *programBinary = getCurrentProgramBinary(); - - GLint halfPixelSize = programBinary->getDxHalfPixelSizeLocation(); - GLfloat xy[2] = {1.0f / viewport.Width, -1.0f / viewport.Height}; - programBinary->setUniform2fv(halfPixelSize, 1, xy); - - // These values are used for computing gl_FragCoord in Program::linkVaryings(). - GLint coord = programBinary->getDxCoordLocation(); - GLfloat whxy[4] = {mState.viewportWidth / 2.0f, mState.viewportHeight / 2.0f, - (float)mState.viewportX + mState.viewportWidth / 2.0f, - (float)mState.viewportY + mState.viewportHeight / 2.0f}; - programBinary->setUniform4fv(coord, 1, whxy); - - GLint depth = programBinary->getDxDepthLocation(); - GLfloat dz[2] = {(zFar - zNear) / 2.0f, (zNear + zFar) / 2.0f}; - programBinary->setUniform2fv(depth, 1, dz); - - GLint depthRange = programBinary->getDxDepthRangeLocation(); - GLfloat nearFarDiff[3] = {zNear, zFar, zFar - zNear}; - programBinary->setUniform3fv(depthRange, 1, nearFarDiff); - mDxUniformsDirty = false; + mask = 0xFFFFFFFF; } + mRenderer->setBlendState(mState.blend, mState.blendColor, mask); - return true; + mRenderer->setDepthStencilState(mState.depthStencil, mState.stencilRef, mState.stencilBackRef, + mState.rasterizer.frontFace == GL_CCW); } -// Applies the fixed-function state (culling, depth test, alpha blending, stenciling, etc) to the Direct3D 9 device -void Context::applyState(GLenum drawMode) +// Applies the shaders and shader constants to the Direct3D 9 device +void Context::applyShaders() { ProgramBinary *programBinary = getCurrentProgramBinary(); - Framebuffer *framebufferObject = getDrawFramebuffer(); - - GLint frontCCW = programBinary->getDxFrontCCWLocation(); - GLint ccw = (mState.frontFace == GL_CCW); - programBinary->setUniform1iv(frontCCW, 1, &ccw); - - GLint pointsOrLines = programBinary->getDxPointsOrLinesLocation(); - GLint alwaysFront = !isTriangleMode(drawMode); - programBinary->setUniform1iv(pointsOrLines, 1, &alwaysFront); + mRenderer->applyShaders(programBinary); + + programBinary->applyUniforms(); +} - D3DADAPTER_IDENTIFIER9 *identifier = mDisplay->getAdapterIdentifier(); - bool zeroColorMaskAllowed = identifier->VendorId != 0x1002; - // Apparently some ATI cards have a bug where a draw with a zero color - // write mask can cause later draws to have incorrect results. Instead, - // set a nonzero color write mask but modify the blend state so that no - // drawing is done. - // http://code.google.com/p/angleproject/issues/detail?id=169 +// Applies the textures and sampler states to the Direct3D 9 device +void Context::applyTextures() +{ + applyTextures(SAMPLER_PIXEL); - if (mCullStateDirty || mFrontFaceDirty) + if (mSupportsVertexTexture) { - if (mState.cullFace) - { - mDevice->SetRenderState(D3DRS_CULLMODE, es2dx::ConvertCullMode(mState.cullMode, mState.frontFace)); - } - else - { - mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); - } - - mCullStateDirty = false; + applyTextures(SAMPLER_VERTEX); } +} - if (mDepthStateDirty) - { - if (mState.depthTest) - { - mDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE); - mDevice->SetRenderState(D3DRS_ZFUNC, es2dx::ConvertComparison(mState.depthFunc)); - } - else - { - mDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE); - } +// For each Direct3D 9 sampler of either the pixel or vertex stage, +// looks up the corresponding OpenGL texture image unit and texture type, +// and sets the texture and its addressing/filtering state (or NULL when inactive). +void Context::applyTextures(SamplerType type) +{ + ProgramBinary *programBinary = getCurrentProgramBinary(); - mDepthStateDirty = false; - } + // Range of Direct3D samplers of given sampler type + int samplerCount = (type == SAMPLER_PIXEL) ? MAX_TEXTURE_IMAGE_UNITS : mRenderer->getMaxVertexTextureImageUnits(); + int samplerRange = programBinary->getUsedSamplerRange(type); - if (!zeroColorMaskAllowed && (mMaskStateDirty || mBlendStateDirty)) + for (int samplerIndex = 0; samplerIndex < samplerRange; samplerIndex++) { - mBlendStateDirty = true; - mMaskStateDirty = true; - } + int textureUnit = programBinary->getSamplerMapping(type, samplerIndex); // OpenGL texture image unit index - if (mBlendStateDirty) - { - if (mState.blend) + if (textureUnit != -1) { - mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); + TextureType textureType = programBinary->getSamplerTextureType(type, samplerIndex); + Texture *texture = getSamplerTexture(textureUnit, textureType); - if (mState.sourceBlendRGB != GL_CONSTANT_ALPHA && mState.sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA && - mState.destBlendRGB != GL_CONSTANT_ALPHA && mState.destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA) - { - mDevice->SetRenderState(D3DRS_BLENDFACTOR, es2dx::ConvertColor(mState.blendColor)); - } - else + if (texture->isSamplerComplete()) { - mDevice->SetRenderState(D3DRS_BLENDFACTOR, D3DCOLOR_RGBA(unorm<8>(mState.blendColor.alpha), - unorm<8>(mState.blendColor.alpha), - unorm<8>(mState.blendColor.alpha), - unorm<8>(mState.blendColor.alpha))); - } - - mDevice->SetRenderState(D3DRS_SRCBLEND, es2dx::ConvertBlendFunc(mState.sourceBlendRGB)); - mDevice->SetRenderState(D3DRS_DESTBLEND, es2dx::ConvertBlendFunc(mState.destBlendRGB)); - mDevice->SetRenderState(D3DRS_BLENDOP, es2dx::ConvertBlendOp(mState.blendEquationRGB)); + SamplerState samplerState; + texture->getSamplerState(&samplerState); + mRenderer->setSamplerState(type, samplerIndex, samplerState); - if (mState.sourceBlendRGB != mState.sourceBlendAlpha || - mState.destBlendRGB != mState.destBlendAlpha || - mState.blendEquationRGB != mState.blendEquationAlpha) - { - mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE); + mRenderer->setTexture(type, samplerIndex, texture); - mDevice->SetRenderState(D3DRS_SRCBLENDALPHA, es2dx::ConvertBlendFunc(mState.sourceBlendAlpha)); - mDevice->SetRenderState(D3DRS_DESTBLENDALPHA, es2dx::ConvertBlendFunc(mState.destBlendAlpha)); - mDevice->SetRenderState(D3DRS_BLENDOPALPHA, es2dx::ConvertBlendOp(mState.blendEquationAlpha)); + texture->resetDirty(); } else { - mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE); + mRenderer->setTexture(type, samplerIndex, getIncompleteTexture(textureType)); } } else { - mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); + mRenderer->setTexture(type, samplerIndex, NULL); } - - mBlendStateDirty = false; } - if (mStencilStateDirty || mFrontFaceDirty) + for (int samplerIndex = samplerRange; samplerIndex < samplerCount; samplerIndex++) { - if (mState.stencilTest && framebufferObject->hasStencil()) - { - mDevice->SetRenderState(D3DRS_STENCILENABLE, TRUE); - mDevice->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, TRUE); - - // FIXME: Unsupported by D3D9 - const D3DRENDERSTATETYPE D3DRS_CCW_STENCILREF = D3DRS_STENCILREF; - const D3DRENDERSTATETYPE D3DRS_CCW_STENCILMASK = D3DRS_STENCILMASK; - const D3DRENDERSTATETYPE D3DRS_CCW_STENCILWRITEMASK = D3DRS_STENCILWRITEMASK; - if (mState.stencilWritemask != mState.stencilBackWritemask || - mState.stencilRef != mState.stencilBackRef || - mState.stencilMask != mState.stencilBackMask) - { - ERR("Separate front/back stencil writemasks, reference values, or stencil mask values are invalid under WebGL."); - return error(GL_INVALID_OPERATION); - } - - // get the maximum size of the stencil ref - gl::Renderbuffer *stencilbuffer = framebufferObject->getStencilbuffer(); - GLuint maxStencil = (1 << stencilbuffer->getStencilSize()) - 1; - - mDevice->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, mState.stencilWritemask); - mDevice->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC, - es2dx::ConvertComparison(mState.stencilFunc)); - - mDevice->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, (mState.stencilRef < (GLint)maxStencil) ? mState.stencilRef : maxStencil); - mDevice->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, mState.stencilMask); - - mDevice->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL, - es2dx::ConvertStencilOp(mState.stencilFail)); - mDevice->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL, - es2dx::ConvertStencilOp(mState.stencilPassDepthFail)); - mDevice->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS, - es2dx::ConvertStencilOp(mState.stencilPassDepthPass)); - - mDevice->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, mState.stencilBackWritemask); - mDevice->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC, - es2dx::ConvertComparison(mState.stencilBackFunc)); - - mDevice->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, (mState.stencilBackRef < (GLint)maxStencil) ? mState.stencilBackRef : maxStencil); - mDevice->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, mState.stencilBackMask); - - mDevice->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL, - es2dx::ConvertStencilOp(mState.stencilBackFail)); - mDevice->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL, - es2dx::ConvertStencilOp(mState.stencilBackPassDepthFail)); - mDevice->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS, - es2dx::ConvertStencilOp(mState.stencilBackPassDepthPass)); - } - else - { - mDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE); - } - - mStencilStateDirty = false; - mFrontFaceDirty = false; - } - - if (mMaskStateDirty) - { - int colorMask = es2dx::ConvertColorMask(mState.colorMaskRed, mState.colorMaskGreen, - mState.colorMaskBlue, mState.colorMaskAlpha); - if (colorMask == 0 && !zeroColorMaskAllowed) - { - // Enable green channel, but set blending so nothing will be drawn. - mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_GREEN); - mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); - - mDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO); - mDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE); - mDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD); - } - else - { - mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, colorMask); - } - mDevice->SetRenderState(D3DRS_ZWRITEENABLE, mState.depthMask ? TRUE : FALSE); - - mMaskStateDirty = false; - } - - if (mPolygonOffsetStateDirty) - { - if (mState.polygonOffsetFill) - { - gl::Renderbuffer *depthbuffer = framebufferObject->getDepthbuffer(); - if (depthbuffer) - { - mDevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, *((DWORD*)&mState.polygonOffsetFactor)); - float depthBias = ldexp(mState.polygonOffsetUnits, -(int)(depthbuffer->getDepthSize())); - mDevice->SetRenderState(D3DRS_DEPTHBIAS, *((DWORD*)&depthBias)); - } - } - else - { - mDevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, 0); - mDevice->SetRenderState(D3DRS_DEPTHBIAS, 0); - } - - mPolygonOffsetStateDirty = false; - } - - if (mSampleStateDirty) - { - if (mState.sampleAlphaToCoverage) - { - FIXME("Sample alpha to coverage is unimplemented."); - } - - mDevice->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, TRUE); - if (mState.sampleCoverage) - { - unsigned int mask = 0; - if (mState.sampleCoverageValue != 0) - { - float threshold = 0.5f; - - for (int i = 0; i < framebufferObject->getSamples(); ++i) - { - mask <<= 1; - - if ((i + 1) * mState.sampleCoverageValue >= threshold) - { - threshold += 1.0f; - mask |= 1; - } - } - } - - if (mState.sampleCoverageInvert) - { - mask = ~mask; - } - - mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, mask); - } - else - { - mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF); - } - - mSampleStateDirty = false; - } - - if (mDitherStateDirty) - { - mDevice->SetRenderState(D3DRS_DITHERENABLE, mState.dither ? TRUE : FALSE); - - mDitherStateDirty = false; - } -} - -GLenum Context::applyVertexBuffer(GLint first, GLsizei count, GLsizei instances, GLsizei *repeatDraw) -{ - TranslatedAttribute attributes[MAX_VERTEX_ATTRIBS]; - - GLenum err = mVertexDataManager->prepareVertexData(first, count, attributes, instances); - if (err != GL_NO_ERROR) - { - return err; - } - - ProgramBinary *programBinary = getCurrentProgramBinary(); - return mVertexDeclarationCache.applyDeclaration(mDevice, attributes, programBinary, instances, repeatDraw); -} - -// Applies the indices and element array bindings to the Direct3D 9 device -GLenum Context::applyIndexBuffer(const GLvoid *indices, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo) -{ - GLenum err = mIndexDataManager->prepareIndexData(type, count, mState.elementArrayBuffer.get(), indices, indexInfo); - - if (err == GL_NO_ERROR) - { - if (indexInfo->serial != mAppliedIBSerial) - { - mDevice->SetIndices(indexInfo->indexBuffer); - mAppliedIBSerial = indexInfo->serial; - } - } - - return err; -} - -// Applies the shaders and shader constants to the Direct3D 9 device -void Context::applyShaders() -{ - ProgramBinary *programBinary = getCurrentProgramBinary(); - - if (programBinary->getSerial() != mAppliedProgramBinarySerial) - { - IDirect3DVertexShader9 *vertexShader = programBinary->getVertexShader(); - IDirect3DPixelShader9 *pixelShader = programBinary->getPixelShader(); - - mDevice->SetPixelShader(pixelShader); - mDevice->SetVertexShader(vertexShader); - programBinary->dirtyAllUniforms(); - mAppliedProgramBinarySerial = programBinary->getSerial(); - } - - programBinary->applyUniforms(); -} - -// Applies the textures and sampler states to the Direct3D 9 device -void Context::applyTextures() -{ - applyTextures(SAMPLER_PIXEL); - - if (mSupportsVertexTexture) - { - applyTextures(SAMPLER_VERTEX); - } -} - -// For each Direct3D 9 sampler of either the pixel or vertex stage, -// looks up the corresponding OpenGL texture image unit and texture type, -// and sets the texture and its addressing/filtering state (or NULL when inactive). -void Context::applyTextures(SamplerType type) -{ - ProgramBinary *programBinary = getCurrentProgramBinary(); - - int samplerCount = (type == SAMPLER_PIXEL) ? MAX_TEXTURE_IMAGE_UNITS : MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF; // Range of Direct3D 9 samplers of given sampler type - unsigned int *appliedTextureSerial = (type == SAMPLER_PIXEL) ? mAppliedTextureSerialPS : mAppliedTextureSerialVS; - int d3dSamplerOffset = (type == SAMPLER_PIXEL) ? 0 : D3DVERTEXTEXTURESAMPLER0; - int samplerRange = programBinary->getUsedSamplerRange(type); - - for (int samplerIndex = 0; samplerIndex < samplerRange; samplerIndex++) - { - int textureUnit = programBinary->getSamplerMapping(type, samplerIndex); // OpenGL texture image unit index - int d3dSampler = samplerIndex + d3dSamplerOffset; - - if (textureUnit != -1) - { - TextureType textureType = programBinary->getSamplerTextureType(type, samplerIndex); - - Texture *texture = getSamplerTexture(textureUnit, textureType); - unsigned int texSerial = texture->getTextureSerial(); - - if (appliedTextureSerial[samplerIndex] != texSerial || texture->hasDirtyParameters() || texture->hasDirtyImages()) - { - IDirect3DBaseTexture9 *d3dTexture = texture->getTexture(); - - if (d3dTexture) - { - if (appliedTextureSerial[samplerIndex] != texSerial || texture->hasDirtyParameters()) - { - GLenum wrapS = texture->getWrapS(); - GLenum wrapT = texture->getWrapT(); - GLenum minFilter = texture->getMinFilter(); - GLenum magFilter = texture->getMagFilter(); - float maxAnisotropy = texture->getMaxAnisotropy(); - - mDevice->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSU, es2dx::ConvertTextureWrap(wrapS)); - mDevice->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSV, es2dx::ConvertTextureWrap(wrapT)); - - mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAGFILTER, es2dx::ConvertMagFilter(magFilter, maxAnisotropy)); - D3DTEXTUREFILTERTYPE d3dMinFilter, d3dMipFilter; - es2dx::ConvertMinFilter(minFilter, &d3dMinFilter, &d3dMipFilter, maxAnisotropy); - mDevice->SetSamplerState(d3dSampler, D3DSAMP_MINFILTER, d3dMinFilter); - mDevice->SetSamplerState(d3dSampler, D3DSAMP_MIPFILTER, d3dMipFilter); - mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAXMIPLEVEL, texture->getLodOffset()); - - if (supportsTextureFilterAnisotropy()) - { - mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAXANISOTROPY, (DWORD)maxAnisotropy); - } - } - - if (appliedTextureSerial[samplerIndex] != texSerial || texture->hasDirtyImages()) - { - mDevice->SetTexture(d3dSampler, d3dTexture); - } - } - else - { - mDevice->SetTexture(d3dSampler, getIncompleteTexture(textureType)->getTexture()); - } - - appliedTextureSerial[samplerIndex] = texSerial; - texture->resetDirty(); - } - } - else - { - if (appliedTextureSerial[samplerIndex] != 0) - { - mDevice->SetTexture(d3dSampler, NULL); - appliedTextureSerial[samplerIndex] = 0; - } - } - } - - for (int samplerIndex = samplerRange; samplerIndex < samplerCount; samplerIndex++) - { - if (appliedTextureSerial[samplerIndex] != 0) - { - mDevice->SetTexture(samplerIndex + d3dSamplerOffset, NULL); - appliedTextureSerial[samplerIndex] = 0; - } + mRenderer->setTexture(type, samplerIndex, NULL); } } @@ -2499,339 +1854,26 @@ void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE) { - return error(GL_INVALID_FRAMEBUFFER_OPERATION); + return gl::error(GL_INVALID_FRAMEBUFFER_OPERATION); } if (getReadFramebufferHandle() != 0 && framebuffer->getSamples() != 0) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } - GLsizei outputPitch = ComputePitch(width, ConvertSizedInternalFormat(format, type), mState.packAlignment); + GLsizei outputPitch = ComputePitch(width, ConvertSizedInternalFormat(format, type), getPackAlignment()); // sized query sanity check if (bufSize) { int requiredSize = outputPitch * height; if (requiredSize > *bufSize) { - return error(GL_INVALID_OPERATION); - } - } - - IDirect3DSurface9 *renderTarget = framebuffer->getRenderTarget(); - if (!renderTarget) - { - return; // Context must be lost, return silently - } - - D3DSURFACE_DESC desc; - renderTarget->GetDesc(&desc); - - if (desc.MultiSampleType != D3DMULTISAMPLE_NONE) - { - UNIMPLEMENTED(); // FIXME: Requires resolve using StretchRect into non-multisampled render target - renderTarget->Release(); - return error(GL_OUT_OF_MEMORY); - } - - HRESULT result; - IDirect3DSurface9 *systemSurface = NULL; - bool directToPixels = !getPackReverseRowOrder() && getPackAlignment() <= 4 && mDisplay->isD3d9ExDevice() && - x == 0 && y == 0 && UINT(width) == desc.Width && UINT(height) == desc.Height && - desc.Format == D3DFMT_A8R8G8B8 && format == GL_BGRA_EXT && type == GL_UNSIGNED_BYTE; - if (directToPixels) - { - // Use the pixels ptr as a shared handle to write directly into client's memory - result = mDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, - D3DPOOL_SYSTEMMEM, &systemSurface, &pixels); - if (FAILED(result)) - { - // Try again without the shared handle - directToPixels = false; - } - } - - if (!directToPixels) - { - result = mDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, - D3DPOOL_SYSTEMMEM, &systemSurface, NULL); - if (FAILED(result)) - { - ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - renderTarget->Release(); - return error(GL_OUT_OF_MEMORY); - } - } - - result = mDevice->GetRenderTargetData(renderTarget, systemSurface); - renderTarget->Release(); - renderTarget = NULL; - - if (FAILED(result)) - { - systemSurface->Release(); - - // It turns out that D3D will sometimes produce more error - // codes than those documented. - if (checkDeviceLost(result)) - return error(GL_OUT_OF_MEMORY); - else - { - UNREACHABLE(); - return; - } - - } - - if (directToPixels) - { - systemSurface->Release(); - return; - } - - RECT rect; - rect.left = clamp(x, 0L, static_cast(desc.Width)); - rect.top = clamp(y, 0L, static_cast(desc.Height)); - rect.right = clamp(x + width, 0L, static_cast(desc.Width)); - rect.bottom = 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 (getPackReverseRowOrder()) - { - source = ((unsigned char*)lock.pBits) + lock.Pitch * (rect.bottom - rect.top - 1); - inputPitch = -lock.Pitch; - } - else - { - source = (unsigned char*)lock.pBits; - inputPitch = lock.Pitch; - } - - unsigned int fastPixelSize = 0; - - if (desc.Format == D3DFMT_A8R8G8B8 && - format == GL_BGRA_EXT && - type == GL_UNSIGNED_BYTE) - { - fastPixelSize = 4; - } - else if ((desc.Format == D3DFMT_A4R4G4B4 && - format == GL_BGRA_EXT && - type == GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT) || - (desc.Format == D3DFMT_A1R5G5B5 && - format == GL_BGRA_EXT && - type == GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT)) - { - fastPixelSize = 2; - } - else if (desc.Format == D3DFMT_A16B16G16R16F && - format == GL_RGBA && - type == GL_HALF_FLOAT_OES) - { - fastPixelSize = 8; - } - else if (desc.Format == D3DFMT_A32B32G32R32F && - format == GL_RGBA && - type == GL_FLOAT) - { - fastPixelSize = 16; - } - - for (int j = 0; j < rect.bottom - rect.top; j++) - { - if (fastPixelSize != 0) - { - // Fast path for formats which require no translation: - // D3DFMT_A8R8G8B8 to BGRA/UNSIGNED_BYTE - // D3DFMT_A4R4G4B4 to BGRA/UNSIGNED_SHORT_4_4_4_4_REV_EXT - // D3DFMT_A1R5G5B5 to BGRA/UNSIGNED_SHORT_1_5_5_5_REV_EXT - // D3DFMT_A16B16G16R16F to RGBA/HALF_FLOAT_OES - // D3DFMT_A32B32G32R32F to RGBA/FLOAT - // - // Note that buffers with no alpha go through the slow path below. - memcpy(dest + j * outputPitch, - source + j * inputPitch, - (rect.right - rect.left) * fastPixelSize); - continue; - } - - for (int i = 0; i < rect.right - rect.left; i++) - { - float r; - float g; - float b; - float a; - - switch (desc.Format) - { - case D3DFMT_R5G6B5: - { - unsigned short rgb = *(unsigned short*)(source + 2 * i + j * inputPitch); - - a = 1.0f; - b = (rgb & 0x001F) * (1.0f / 0x001F); - g = (rgb & 0x07E0) * (1.0f / 0x07E0); - r = (rgb & 0xF800) * (1.0f / 0xF800); - } - break; - case D3DFMT_A1R5G5B5: - { - unsigned short argb = *(unsigned short*)(source + 2 * i + j * inputPitch); - - a = (argb & 0x8000) ? 1.0f : 0.0f; - b = (argb & 0x001F) * (1.0f / 0x001F); - g = (argb & 0x03E0) * (1.0f / 0x03E0); - r = (argb & 0x7C00) * (1.0f / 0x7C00); - } - break; - case D3DFMT_A8R8G8B8: - { - unsigned int argb = *(unsigned int*)(source + 4 * i + j * inputPitch); - - a = (argb & 0xFF000000) * (1.0f / 0xFF000000); - b = (argb & 0x000000FF) * (1.0f / 0x000000FF); - g = (argb & 0x0000FF00) * (1.0f / 0x0000FF00); - r = (argb & 0x00FF0000) * (1.0f / 0x00FF0000); - } - break; - case D3DFMT_X8R8G8B8: - { - unsigned int xrgb = *(unsigned int*)(source + 4 * i + j * inputPitch); - - a = 1.0f; - b = (xrgb & 0x000000FF) * (1.0f / 0x000000FF); - g = (xrgb & 0x0000FF00) * (1.0f / 0x0000FF00); - r = (xrgb & 0x00FF0000) * (1.0f / 0x00FF0000); - } - break; - case D3DFMT_A2R10G10B10: - { - unsigned int argb = *(unsigned int*)(source + 4 * i + j * inputPitch); - - a = (argb & 0xC0000000) * (1.0f / 0xC0000000); - b = (argb & 0x000003FF) * (1.0f / 0x000003FF); - g = (argb & 0x000FFC00) * (1.0f / 0x000FFC00); - r = (argb & 0x3FF00000) * (1.0f / 0x3FF00000); - } - break; - case D3DFMT_A32B32G32R32F: - { - // float formats in D3D are stored rgba, rather than the other way round - r = *((float*)(source + 16 * i + j * inputPitch) + 0); - g = *((float*)(source + 16 * i + j * inputPitch) + 1); - b = *((float*)(source + 16 * i + j * inputPitch) + 2); - a = *((float*)(source + 16 * i + j * inputPitch) + 3); - } - break; - case D3DFMT_A16B16G16R16F: - { - // float formats in D3D are stored rgba, rather than the other way round - r = float16ToFloat32(*((unsigned short*)(source + 8 * i + j * inputPitch) + 0)); - g = float16ToFloat32(*((unsigned short*)(source + 8 * i + j * inputPitch) + 1)); - b = float16ToFloat32(*((unsigned short*)(source + 8 * i + j * inputPitch) + 2)); - a = float16ToFloat32(*((unsigned short*)(source + 8 * i + j * inputPitch) + 3)); - } - break; - default: - UNIMPLEMENTED(); // FIXME - UNREACHABLE(); - return; - } - - switch (format) - { - case GL_RGBA: - switch (type) - { - case GL_UNSIGNED_BYTE: - dest[4 * i + j * outputPitch + 0] = (unsigned char)(255 * r + 0.5f); - dest[4 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f); - dest[4 * i + j * outputPitch + 2] = (unsigned char)(255 * b + 0.5f); - dest[4 * i + j * outputPitch + 3] = (unsigned char)(255 * a + 0.5f); - break; - default: UNREACHABLE(); - } - break; - case GL_BGRA_EXT: - switch (type) - { - case GL_UNSIGNED_BYTE: - dest[4 * i + j * outputPitch + 0] = (unsigned char)(255 * b + 0.5f); - dest[4 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f); - dest[4 * i + j * outputPitch + 2] = (unsigned char)(255 * r + 0.5f); - dest[4 * i + j * outputPitch + 3] = (unsigned char)(255 * a + 0.5f); - break; - case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT: - // According to the desktop GL spec in the "Transfer of Pixel Rectangles" section - // this type is packed as follows: - // 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 - // -------------------------------------------------------------------------------- - // | 4th | 3rd | 2nd | 1st component | - // -------------------------------------------------------------------------------- - // in the case of BGRA_EXT, B is the first component, G the second, and so forth. - dest16[i + j * outputPitch / sizeof(unsigned short)] = - ((unsigned short)(15 * a + 0.5f) << 12)| - ((unsigned short)(15 * r + 0.5f) << 8) | - ((unsigned short)(15 * g + 0.5f) << 4) | - ((unsigned short)(15 * b + 0.5f) << 0); - break; - case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT: - // According to the desktop GL spec in the "Transfer of Pixel Rectangles" section - // this type is packed as follows: - // 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 - // -------------------------------------------------------------------------------- - // | 4th | 3rd | 2nd | 1st component | - // -------------------------------------------------------------------------------- - // in the case of BGRA_EXT, B is the first component, G the second, and so forth. - dest16[i + j * outputPitch / sizeof(unsigned short)] = - ((unsigned short)( a + 0.5f) << 15) | - ((unsigned short)(31 * r + 0.5f) << 10) | - ((unsigned short)(31 * g + 0.5f) << 5) | - ((unsigned short)(31 * b + 0.5f) << 0); - break; - default: UNREACHABLE(); - } - break; - case GL_RGB: - switch (type) - { - case GL_UNSIGNED_SHORT_5_6_5: - dest16[i + j * outputPitch / sizeof(unsigned short)] = - ((unsigned short)(31 * b + 0.5f) << 0) | - ((unsigned short)(63 * g + 0.5f) << 5) | - ((unsigned short)(31 * r + 0.5f) << 11); - break; - case GL_UNSIGNED_BYTE: - dest[3 * i + j * outputPitch + 0] = (unsigned char)(255 * r + 0.5f); - dest[3 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f); - dest[3 * i + j * outputPitch + 2] = (unsigned char)(255 * b + 0.5f); - break; - default: UNREACHABLE(); - } - break; - default: UNREACHABLE(); - } + return gl::error(GL_INVALID_OPERATION); } } - systemSurface->UnlockRect(); - - systemSurface->Release(); + mRenderer->readPixels(framebuffer, x, y, width, height, format, type, outputPitch, getPackReverseRowOrder(), getPackAlignment(), pixels); } void Context::clear(GLbitfield mask) @@ -2840,300 +1882,112 @@ void Context::clear(GLbitfield mask) if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE) { - return error(GL_INVALID_FRAMEBUFFER_OPERATION); + return gl::error(GL_INVALID_FRAMEBUFFER_OPERATION); } DWORD flags = 0; + GLbitfield finalMask = 0; if (mask & GL_COLOR_BUFFER_BIT) { mask &= ~GL_COLOR_BUFFER_BIT; - if (framebufferObject->getColorbufferType() != GL_NONE) + if (framebufferObject->hasEnabledColorAttachment()) { - flags |= D3DCLEAR_TARGET; + finalMask |= GL_COLOR_BUFFER_BIT; } } if (mask & GL_DEPTH_BUFFER_BIT) { mask &= ~GL_DEPTH_BUFFER_BIT; - if (mState.depthMask && framebufferObject->getDepthbufferType() != GL_NONE) + if (mState.depthStencil.depthMask && framebufferObject->getDepthbufferType() != GL_NONE) { - flags |= D3DCLEAR_ZBUFFER; + finalMask |= GL_DEPTH_BUFFER_BIT; } } - GLuint stencilUnmasked = 0x0; - if (mask & GL_STENCIL_BUFFER_BIT) { mask &= ~GL_STENCIL_BUFFER_BIT; if (framebufferObject->getStencilbufferType() != GL_NONE) { - IDirect3DSurface9 *depthStencil = framebufferObject->getStencilbuffer()->getDepthStencil(); + rx::RenderTarget *depthStencil = framebufferObject->getStencilbuffer()->getDepthStencil(); if (!depthStencil) { ERR("Depth stencil pointer unexpectedly null."); return; } - - D3DSURFACE_DESC desc; - depthStencil->GetDesc(&desc); - depthStencil->Release(); - unsigned int stencilSize = dx2es::GetStencilSize(desc.Format); - stencilUnmasked = (0x1 << stencilSize) - 1; - - if (stencilUnmasked != 0x0) + if (GetStencilSize(depthStencil->getActualFormat()) > 0) { - flags |= D3DCLEAR_STENCIL; + finalMask |= GL_STENCIL_BUFFER_BIT; } } } if (mask != 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } - if (!applyRenderTarget(true)) // Clips the clear to the scissor rectangle but not the viewport + if (!applyRenderTarget(GL_TRIANGLES, true)) // Clips the clear to the scissor rectangle but not the viewport { return; } - D3DCOLOR color = D3DCOLOR_ARGB(unorm<8>(mState.colorClearValue.alpha), - unorm<8>(mState.colorClearValue.red), - unorm<8>(mState.colorClearValue.green), - unorm<8>(mState.colorClearValue.blue)); - float depth = clamp01(mState.depthClearValue); - int stencil = mState.stencilClearValue & 0x000000FF; - - bool alphaUnmasked = (dx2es::GetAlphaSize(mRenderTargetDesc.Format) == 0) || mState.colorMaskAlpha; - - const bool needMaskedStencilClear = (flags & D3DCLEAR_STENCIL) && - (mState.stencilWritemask & stencilUnmasked) != stencilUnmasked; - const bool needMaskedColorClear = (flags & D3DCLEAR_TARGET) && - !(mState.colorMaskRed && mState.colorMaskGreen && - mState.colorMaskBlue && alphaUnmasked); - - if (needMaskedColorClear || needMaskedStencilClear) - { - // State which is altered in all paths from this point to the clear call is saved. - // State which is altered in only some paths will be flagged dirty in the case that - // that path is taken. - HRESULT hr; - if (mMaskedClearSavedState == NULL) - { - hr = mDevice->BeginStateBlock(); - ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY); - - mDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE); - mDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS); - mDevice->SetRenderState(D3DRS_ZENABLE, FALSE); - mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); - mDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); - mDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); - mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); - mDevice->SetRenderState(D3DRS_CLIPPLANEENABLE, 0); - mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0); - mDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE); - mDevice->SetPixelShader(NULL); - mDevice->SetVertexShader(NULL); - mDevice->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE); - mDevice->SetStreamSource(0, NULL, 0, 0); - mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE); - mDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); - mDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TFACTOR); - mDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); - mDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR); - mDevice->SetRenderState(D3DRS_TEXTUREFACTOR, color); - mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF); - - for(int i = 0; i < MAX_VERTEX_ATTRIBS; i++) - { - mDevice->SetStreamSourceFreq(i, 1); - } - - hr = mDevice->EndStateBlock(&mMaskedClearSavedState); - ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY); - } - - ASSERT(mMaskedClearSavedState != NULL); + ClearParameters clearParams; + clearParams.mask = finalMask; + clearParams.colorClearValue = mState.colorClearValue; + clearParams.colorMaskRed = mState.blend.colorMaskRed; + clearParams.colorMaskGreen = mState.blend.colorMaskGreen; + clearParams.colorMaskBlue = mState.blend.colorMaskBlue; + clearParams.colorMaskAlpha = mState.blend.colorMaskAlpha; + clearParams.depthClearValue = mState.depthClearValue; + clearParams.stencilClearValue = mState.stencilClearValue; + clearParams.stencilWriteMask = mState.depthStencil.stencilWritemask; - if (mMaskedClearSavedState != NULL) - { - hr = mMaskedClearSavedState->Capture(); - ASSERT(SUCCEEDED(hr)); - } - - mDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE); - mDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS); - mDevice->SetRenderState(D3DRS_ZENABLE, FALSE); - mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); - mDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); - mDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); - mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); - mDevice->SetRenderState(D3DRS_CLIPPLANEENABLE, 0); - - if (flags & D3DCLEAR_TARGET) - { - mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, es2dx::ConvertColorMask(mState.colorMaskRed, mState.colorMaskGreen, mState.colorMaskBlue, mState.colorMaskAlpha)); - } - else - { - mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0); - } - - if (stencilUnmasked != 0x0 && (flags & D3DCLEAR_STENCIL)) - { - mDevice->SetRenderState(D3DRS_STENCILENABLE, TRUE); - mDevice->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, FALSE); - mDevice->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS); - mDevice->SetRenderState(D3DRS_STENCILREF, stencil); - mDevice->SetRenderState(D3DRS_STENCILWRITEMASK, mState.stencilWritemask); - mDevice->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_REPLACE); - mDevice->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_REPLACE); - mDevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE); - mStencilStateDirty = true; - } - else - { - mDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE); - } - - mDevice->SetPixelShader(NULL); - mDevice->SetVertexShader(NULL); - mDevice->SetFVF(D3DFVF_XYZRHW); - mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE); - mDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); - mDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TFACTOR); - mDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); - mDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR); - mDevice->SetRenderState(D3DRS_TEXTUREFACTOR, color); - mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF); - - for(int i = 0; i < MAX_VERTEX_ATTRIBS; i++) - { - mDevice->SetStreamSourceFreq(i, 1); - } - - float quad[4][4]; // A quadrilateral covering the target, aligned to match the edges - quad[0][0] = -0.5f; - quad[0][1] = mRenderTargetDesc.Height - 0.5f; - quad[0][2] = 0.0f; - quad[0][3] = 1.0f; - - quad[1][0] = mRenderTargetDesc.Width - 0.5f; - quad[1][1] = mRenderTargetDesc.Height - 0.5f; - quad[1][2] = 0.0f; - quad[1][3] = 1.0f; - - quad[2][0] = -0.5f; - quad[2][1] = -0.5f; - quad[2][2] = 0.0f; - quad[2][3] = 1.0f; - - quad[3][0] = mRenderTargetDesc.Width - 0.5f; - quad[3][1] = -0.5f; - quad[3][2] = 0.0f; - quad[3][3] = 1.0f; - - mDisplay->startScene(); - mDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, quad, sizeof(float[4])); - - if (flags & D3DCLEAR_ZBUFFER) - { - mDevice->SetRenderState(D3DRS_ZENABLE, TRUE); - mDevice->SetRenderState(D3DRS_ZWRITEENABLE, TRUE); - mDevice->Clear(0, NULL, D3DCLEAR_ZBUFFER, color, depth, stencil); - } - - if (mMaskedClearSavedState != NULL) - { - mMaskedClearSavedState->Apply(); - } - } - else if (flags) - { - mDevice->Clear(0, NULL, flags, color, depth, stencil); - } + mRenderer->clear(clearParams, framebufferObject); } void Context::drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instances) { if (!mState.currentProgram) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } - D3DPRIMITIVETYPE primitiveType; - int primitiveCount; - - if(!es2dx::ConvertPrimitiveType(mode, count, &primitiveType, &primitiveCount)) - return error(GL_INVALID_ENUM); - - if (primitiveCount <= 0) + if (!mRenderer->applyPrimitiveType(mode, count)) { return; } - if (!applyRenderTarget(false)) + if (!applyRenderTarget(mode, false)) { return; } applyState(mode); - GLsizei repeatDraw = 1; - GLenum err = applyVertexBuffer(first, count, instances, &repeatDraw); + ProgramBinary *programBinary = getCurrentProgramBinary(); + + GLenum err = mRenderer->applyVertexBuffer(programBinary, mState.vertexAttribute, first, count, instances); if (err != GL_NO_ERROR) { - return error(err); + return gl::error(err); } applyShaders(); applyTextures(); - if (!getCurrentProgramBinary()->validateSamplers(NULL)) + if (!programBinary->validateSamplers(NULL)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } if (!skipDraw(mode)) { - mDisplay->startScene(); - - if (mode == GL_LINE_LOOP) - { - drawLineLoop(count, GL_NONE, NULL, 0); - } - else if (instances > 0) - { - StaticIndexBuffer *countingIB = mIndexDataManager->getCountingIndices(count); - if (countingIB) - { - if (mAppliedIBSerial != countingIB->getSerial()) - { - mDevice->SetIndices(countingIB->getBuffer()); - mAppliedIBSerial = countingIB->getSerial(); - } - - for (int i = 0; i < repeatDraw; i++) - { - mDevice->DrawIndexedPrimitive(primitiveType, 0, 0, count, 0, primitiveCount); - } - } - else - { - ERR("Could not create a counting index buffer for glDrawArraysInstanced."); - return error(GL_OUT_OF_MEMORY); - } - } - else // Regular case - { - mDevice->DrawPrimitive(primitiveType, 0, primitiveCount); - } + mRenderer->drawArrays(mode, count, instances); } } @@ -3141,224 +1995,62 @@ void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid { if (!mState.currentProgram) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } if (!indices && !mState.elementArrayBuffer) { - return error(GL_INVALID_OPERATION); - } - - D3DPRIMITIVETYPE primitiveType; - int primitiveCount; - - if(!es2dx::ConvertPrimitiveType(mode, count, &primitiveType, &primitiveCount)) - return error(GL_INVALID_ENUM); - - if (primitiveCount <= 0) - { - return; - } - - if (!applyRenderTarget(false)) - { - return; + return gl::error(GL_INVALID_OPERATION); } - - applyState(mode); - - TranslatedIndexData indexInfo; - GLenum err = applyIndexBuffer(indices, count, mode, type, &indexInfo); - if (err != GL_NO_ERROR) - { - return error(err); - } - - GLsizei vertexCount = indexInfo.maxIndex - indexInfo.minIndex + 1; - GLsizei repeatDraw = 1; - err = applyVertexBuffer(indexInfo.minIndex, vertexCount, instances, &repeatDraw); - if (err != GL_NO_ERROR) - { - return error(err); - } - - applyShaders(); - applyTextures(); - - if (!getCurrentProgramBinary()->validateSamplers(false)) - { - return error(GL_INVALID_OPERATION); - } - - if (!skipDraw(mode)) - { - mDisplay->startScene(); - - if (mode == GL_LINE_LOOP) - { - drawLineLoop(count, type, indices, indexInfo.minIndex); - } - else - { - for (int i = 0; i < repeatDraw; i++) - { - mDevice->DrawIndexedPrimitive(primitiveType, -(INT)indexInfo.minIndex, indexInfo.minIndex, vertexCount, indexInfo.startIndex, primitiveCount); - } - } - } -} - -// Implements glFlush when block is false, glFinish when block is true -void Context::sync(bool block) -{ - mDisplay->sync(block); -} - -void Context::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex) -{ - // Get the raw indices for an indexed draw - if (type != GL_NONE && mState.elementArrayBuffer.get()) + + if (!mRenderer->applyPrimitiveType(mode, count)) { - Buffer *indexBuffer = mState.elementArrayBuffer.get(); - intptr_t offset = reinterpret_cast(indices); - indices = static_cast(indexBuffer->data()) + offset; + return; } - UINT startIndex = 0; - bool succeeded = false; - - if (supports32bitIndices()) + if (!applyRenderTarget(mode, false)) { - const int spaceNeeded = (count + 1) * sizeof(unsigned int); - - if (!mLineLoopIB) - { - mLineLoopIB = new StreamingIndexBuffer(mDevice, INITIAL_INDEX_BUFFER_SIZE, D3DFMT_INDEX32); - } - - if (mLineLoopIB) - { - mLineLoopIB->reserveSpace(spaceNeeded, GL_UNSIGNED_INT); + return; + } - UINT offset = 0; - unsigned int *data = static_cast(mLineLoopIB->map(spaceNeeded, &offset)); - startIndex = offset / 4; - - if (data) - { - switch (type) - { - case GL_NONE: // Non-indexed draw - for (int i = 0; i < count; i++) - { - data[i] = i; - } - data[count] = 0; - break; - case GL_UNSIGNED_BYTE: - for (int i = 0; i < count; i++) - { - data[i] = static_cast(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(); - } + applyState(mode); - mLineLoopIB->unmap(); - succeeded = true; - } - } - } - else + rx::TranslatedIndexData indexInfo; + GLenum err = mRenderer->applyIndexBuffer(indices, mState.elementArrayBuffer.get(), count, mode, type, &indexInfo); + if (err != GL_NO_ERROR) { - const int spaceNeeded = (count + 1) * sizeof(unsigned short); + return gl::error(err); + } - if (!mLineLoopIB) - { - mLineLoopIB = new StreamingIndexBuffer(mDevice, INITIAL_INDEX_BUFFER_SIZE, D3DFMT_INDEX16); - } + ProgramBinary *programBinary = getCurrentProgramBinary(); - if (mLineLoopIB) - { - mLineLoopIB->reserveSpace(spaceNeeded, GL_UNSIGNED_SHORT); + GLsizei vertexCount = indexInfo.maxIndex - indexInfo.minIndex + 1; + err = mRenderer->applyVertexBuffer(programBinary, mState.vertexAttribute, indexInfo.minIndex, vertexCount, instances); + if (err != GL_NO_ERROR) + { + return gl::error(err); + } - UINT offset = 0; - unsigned short *data = static_cast(mLineLoopIB->map(spaceNeeded, &offset)); - startIndex = offset / 2; - - if (data) - { - switch (type) - { - case GL_NONE: // Non-indexed draw - for (int i = 0; i < count; i++) - { - data[i] = i; - } - data[count] = 0; - break; - case GL_UNSIGNED_BYTE: - for (int i = 0; i < count; i++) - { - data[i] = static_cast(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(); - } + applyShaders(); + applyTextures(); - mLineLoopIB->unmap(); - succeeded = true; - } - } - } - - if (succeeded) + if (!programBinary->validateSamplers(NULL)) { - if (mAppliedIBSerial != mLineLoopIB->getSerial()) - { - mDevice->SetIndices(mLineLoopIB->getBuffer()); - mAppliedIBSerial = mLineLoopIB->getSerial(); - } - - mDevice->DrawIndexedPrimitive(D3DPT_LINESTRIP, -minIndex, minIndex, count, startIndex, count); + return gl::error(GL_INVALID_OPERATION); } - else + + if (!skipDraw(mode)) { - ERR("Could not create a looping index buffer for GL_LINE_LOOP."); - return error(GL_OUT_OF_MEMORY); + mRenderer->drawElements(mode, count, type, indices, mState.elementArrayBuffer.get(), indexInfo, instances); } } +// Implements glFlush when block is false, glFinish when block is true +void Context::sync(bool block) +{ + mRenderer->sync(block); +} + void Context::recordInvalidEnum() { mInvalidEnum = true; @@ -3428,21 +2120,20 @@ GLenum Context::getError() GLenum Context::getResetStatus() { - if (mResetStatus == GL_NO_ERROR) + if (mResetStatus == GL_NO_ERROR && !mContextLost) { - bool lost = mDisplay->testDeviceLost(); - - if (lost) - { - mDisplay->notifyDeviceLost(); // Sets mResetStatus - } + // mResetStatus will be set by the markContextLost callback + // in the case a notification is sent + mRenderer->testDeviceLost(true); } GLenum status = mResetStatus; if (mResetStatus != GL_NO_ERROR) { - if (mDisplay->testDeviceResettable()) + ASSERT(mContextLost); + + if (mRenderer->testDeviceResettable()) { mResetStatus = GL_NO_ERROR; } @@ -3456,63 +2147,29 @@ bool Context::isResetNotificationEnabled() return (mResetStrategy == GL_LOSE_CONTEXT_ON_RESET_EXT); } -bool Context::supportsShaderModel3() const +int Context::getMajorShaderModel() const { - return mSupportsShaderModel3; + return mMajorShaderModel; } float Context::getMaximumPointSize() const { - return mSupportsShaderModel3 ? mMaximumPointSize : ALIASED_POINT_SIZE_RANGE_MAX_SM2; -} - -int Context::getMaximumVaryingVectors() const -{ - return mSupportsShaderModel3 ? MAX_VARYING_VECTORS_SM3 : MAX_VARYING_VECTORS_SM2; -} - -unsigned int Context::getMaximumVertexTextureImageUnits() const -{ - return mSupportsVertexTexture ? MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF : 0; + return mMaximumPointSize; } unsigned int Context::getMaximumCombinedTextureImageUnits() const { - return MAX_TEXTURE_IMAGE_UNITS + getMaximumVertexTextureImageUnits(); -} - -int Context::getMaximumFragmentUniformVectors() const -{ - return mSupportsShaderModel3 ? MAX_FRAGMENT_UNIFORM_VECTORS_SM3 : MAX_FRAGMENT_UNIFORM_VECTORS_SM2; + return mRenderer->getMaxCombinedTextureImageUnits(); } int Context::getMaxSupportedSamples() const { - return mMaxSupportedSamples; + return mRenderer->getMaxSupportedSamples(); } -int Context::getNearestSupportedSamples(D3DFORMAT format, int requested) const +unsigned int Context::getMaximumRenderTargets() const { - if (requested == 0) - { - return requested; - } - - std::map::const_iterator itr = mMultiSampleSupport.find(format); - if (itr == mMultiSampleSupport.end()) - { - return -1; - } - - for (int i = requested; i <= D3DMULTISAMPLE_16_SAMPLES; ++i) - { - if (itr->second[i] && i != D3DMULTISAMPLE_NONMASKABLE) - { - return i; - } - } - - return -1; + return mRenderer->getMaxRenderTargets(); } bool Context::supportsEventQueries() const @@ -3525,6 +2182,11 @@ bool Context::supportsOcclusionQueries() const return mSupportsOcclusionQueries; } +bool Context::supportsBGRATextures() const +{ + return mSupportsBGRATextures; +} + bool Context::supportsDXT1Textures() const { return mSupportsDXT1Textures; @@ -3635,20 +2297,17 @@ bool Context::getCurrentReadFormatType(GLenum *format, GLenum *type) Framebuffer *framebuffer = getReadFramebuffer(); if (!framebuffer || framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE) { - return error(GL_INVALID_OPERATION, false); + return gl::error(GL_INVALID_OPERATION, false); } - Renderbuffer *renderbuffer = framebuffer->getColorbuffer(); + Renderbuffer *renderbuffer = framebuffer->getReadColorbuffer(); if (!renderbuffer) { - return error(GL_INVALID_OPERATION, false); + return gl::error(GL_INVALID_OPERATION, false); } - if(!dx2es::ConvertReadBufferFormat(renderbuffer->getD3DFormat(), format, type)) - { - ASSERT(false); - return false; - } + *format = gl::ExtractFormat(renderbuffer->getActualFormat()); + *type = gl::ExtractType(renderbuffer->getActualFormat()); return true; } @@ -3686,7 +2345,7 @@ void Context::detachTexture(GLuint texture) for (int type = 0; type < TEXTURE_TYPE_COUNT; type++) { - for (int sampler = 0; sampler < MAX_COMBINED_TEXTURE_IMAGE_UNITS_VTF; sampler++) + for (int sampler = 0; sampler < IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS; sampler++) { if (mState.samplerTexture[type][sampler].id() == texture) { @@ -3777,7 +2436,7 @@ Texture *Context::getIncompleteTexture(TextureType type) case TEXTURE_2D: { - Texture2D *incomplete2d = new Texture2D(Texture::INCOMPLETE_TEXTURE_ID); + Texture2D *incomplete2d = new Texture2D(mRenderer, Texture::INCOMPLETE_TEXTURE_ID); incomplete2d->setImage(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color); t = incomplete2d; } @@ -3785,7 +2444,7 @@ Texture *Context::getIncompleteTexture(TextureType type) case TEXTURE_CUBE: { - TextureCubeMap *incompleteCube = new TextureCubeMap(Texture::INCOMPLETE_TEXTURE_ID); + TextureCubeMap *incompleteCube = new TextureCubeMap(mRenderer, Texture::INCOMPLETE_TEXTURE_ID); incompleteCube->setImagePosX(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color); incompleteCube->setImageNegX(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color); @@ -3821,9 +2480,9 @@ bool Context::skipDraw(GLenum drawMode) return true; } } - else if (isTriangleMode(drawMode)) + else if (IsTriangleMode(drawMode)) { - if (mState.cullFace && mState.cullMode == GL_FRONT_AND_BACK) + if (mState.rasterizer.cullFace && mState.rasterizer.cullMode == GL_FRONT_AND_BACK) { return true; } @@ -3832,25 +2491,6 @@ bool Context::skipDraw(GLenum drawMode) return false; } -bool Context::isTriangleMode(GLenum drawMode) -{ - switch (drawMode) - { - case GL_TRIANGLES: - case GL_TRIANGLE_FAN: - case GL_TRIANGLE_STRIP: - return true; - case GL_POINTS: - case GL_LINES: - case GL_LINE_LOOP: - case GL_LINE_STRIP: - return false; - default: UNREACHABLE(); - } - - return false; -} - void Context::setVertexAttrib(GLuint index, const GLfloat *values) { ASSERT(index < gl::MAX_VERTEX_ATTRIBS); @@ -3859,8 +2499,6 @@ void Context::setVertexAttrib(GLuint index, const GLfloat *values) mState.vertexAttribute[index].mCurrentValue[1] = values[1]; mState.vertexAttribute[index].mCurrentValue[2] = values[2]; mState.vertexAttribute[index].mCurrentValue[3] = values[3]; - - mVertexDataManager->dirtyCurrentValue(index); } void Context::setVertexAttribDivisor(GLuint index, GLuint divisor) @@ -3876,124 +2514,139 @@ void Context::setVertexAttribDivisor(GLuint index, GLuint divisor) // Vendor extensions void Context::initExtensionString() { - mExtensionString = ""; + std::string extensionString = ""; // OES extensions if (supports32bitIndices()) { - mExtensionString += "GL_OES_element_index_uint "; + extensionString += "GL_OES_element_index_uint "; } - mExtensionString += "GL_OES_packed_depth_stencil "; - mExtensionString += "GL_OES_get_program_binary "; - mExtensionString += "GL_OES_rgb8_rgba8 "; - mExtensionString += "GL_OES_standard_derivatives "; + extensionString += "GL_OES_packed_depth_stencil "; + extensionString += "GL_OES_get_program_binary "; + extensionString += "GL_OES_rgb8_rgba8 "; + if (mRenderer->getDerivativeInstructionSupport()) + { + extensionString += "GL_OES_standard_derivatives "; + } if (supportsFloat16Textures()) { - mExtensionString += "GL_OES_texture_half_float "; + extensionString += "GL_OES_texture_half_float "; } if (supportsFloat16LinearFilter()) { - mExtensionString += "GL_OES_texture_half_float_linear "; + extensionString += "GL_OES_texture_half_float_linear "; } if (supportsFloat32Textures()) { - mExtensionString += "GL_OES_texture_float "; + extensionString += "GL_OES_texture_float "; } if (supportsFloat32LinearFilter()) { - mExtensionString += "GL_OES_texture_float_linear "; + extensionString += "GL_OES_texture_float_linear "; } if (supportsNonPower2Texture()) { - mExtensionString += "GL_OES_texture_npot "; + extensionString += "GL_OES_texture_npot "; } // Multi-vendor (EXT) extensions if (supportsOcclusionQueries()) { - mExtensionString += "GL_EXT_occlusion_query_boolean "; + extensionString += "GL_EXT_occlusion_query_boolean "; } - mExtensionString += "GL_EXT_read_format_bgra "; - mExtensionString += "GL_EXT_robustness "; + extensionString += "GL_EXT_read_format_bgra "; + extensionString += "GL_EXT_robustness "; if (supportsDXT1Textures()) { - mExtensionString += "GL_EXT_texture_compression_dxt1 "; + extensionString += "GL_EXT_texture_compression_dxt1 "; } if (supportsTextureFilterAnisotropy()) { - mExtensionString += "GL_EXT_texture_filter_anisotropic "; + extensionString += "GL_EXT_texture_filter_anisotropic "; + } + + if (supportsBGRATextures()) + { + extensionString += "GL_EXT_texture_format_BGRA8888 "; + } + + if (mRenderer->getMaxRenderTargets() > 1) + { + extensionString += "GL_EXT_draw_buffers "; } - mExtensionString += "GL_EXT_texture_format_BGRA8888 "; - mExtensionString += "GL_EXT_texture_storage "; + extensionString += "GL_EXT_texture_storage "; // ANGLE-specific extensions if (supportsDepthTextures()) { - mExtensionString += "GL_ANGLE_depth_texture "; + extensionString += "GL_ANGLE_depth_texture "; } - mExtensionString += "GL_ANGLE_framebuffer_blit "; + extensionString += "GL_ANGLE_framebuffer_blit "; if (getMaxSupportedSamples() != 0) { - mExtensionString += "GL_ANGLE_framebuffer_multisample "; + extensionString += "GL_ANGLE_framebuffer_multisample "; } if (supportsInstancing()) { - mExtensionString += "GL_ANGLE_instanced_arrays "; + extensionString += "GL_ANGLE_instanced_arrays "; } - mExtensionString += "GL_ANGLE_pack_reverse_row_order "; + extensionString += "GL_ANGLE_pack_reverse_row_order "; if (supportsDXT3Textures()) { - mExtensionString += "GL_ANGLE_texture_compression_dxt3 "; + extensionString += "GL_ANGLE_texture_compression_dxt3 "; } if (supportsDXT5Textures()) { - mExtensionString += "GL_ANGLE_texture_compression_dxt5 "; + extensionString += "GL_ANGLE_texture_compression_dxt5 "; } - mExtensionString += "GL_ANGLE_texture_usage "; - mExtensionString += "GL_ANGLE_translated_shader_source "; + extensionString += "GL_ANGLE_texture_usage "; + extensionString += "GL_ANGLE_translated_shader_source "; // Other vendor-specific extensions if (supportsEventQueries()) { - mExtensionString += "GL_NV_fence "; + extensionString += "GL_NV_fence "; } - std::string::size_type end = mExtensionString.find_last_not_of(' '); + std::string::size_type end = extensionString.find_last_not_of(' '); if (end != std::string::npos) { - mExtensionString.resize(end+1); + extensionString.resize(end+1); } + + mExtensionString = makeStaticString(extensionString); } const char *Context::getExtensionString() const { - return mExtensionString.c_str(); + return mExtensionString; } void Context::initRendererString() { - D3DADAPTER_IDENTIFIER9 *identifier = mDisplay->getAdapterIdentifier(); + std::ostringstream rendererString; + rendererString << "ANGLE ("; + rendererString << mRenderer->getRendererDescription(); + rendererString << ")"; - mRendererString = "ANGLE ("; - mRendererString += identifier->Description; - mRendererString += ")"; + mRendererString = makeStaticString(rendererString.str()); } const char *Context::getRendererString() const { - return mRendererString.c_str(); + return mRendererString; } void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, @@ -4006,179 +2659,216 @@ void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1 if (!readFramebuffer || readFramebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE || !drawFramebuffer || drawFramebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE) { - return error(GL_INVALID_FRAMEBUFFER_OPERATION); + return gl::error(GL_INVALID_FRAMEBUFFER_OPERATION); } if (drawFramebuffer->getSamples() != 0) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); + } + + Renderbuffer *readColorBuffer = readFramebuffer->getReadColorbuffer(); + Renderbuffer *drawColorBuffer = drawFramebuffer->getFirstColorbuffer(); + + if (drawColorBuffer == NULL) + { + ERR("Draw buffers formats don't match, which is not supported in this implementation of BlitFramebufferANGLE"); + return gl::error(GL_INVALID_OPERATION); } - int readBufferWidth = readFramebuffer->getColorbuffer()->getWidth(); - int readBufferHeight = readFramebuffer->getColorbuffer()->getHeight(); - int drawBufferWidth = drawFramebuffer->getColorbuffer()->getWidth(); - int drawBufferHeight = drawFramebuffer->getColorbuffer()->getHeight(); + int readBufferWidth = readColorBuffer->getWidth(); + int readBufferHeight = readColorBuffer->getHeight(); + int drawBufferWidth = drawColorBuffer->getWidth(); + int drawBufferHeight = drawColorBuffer->getHeight(); - RECT sourceRect; - RECT destRect; + Rectangle sourceRect; + Rectangle destRect; if (srcX0 < srcX1) { - sourceRect.left = srcX0; - sourceRect.right = srcX1; - destRect.left = dstX0; - destRect.right = dstX1; + sourceRect.x = srcX0; + destRect.x = dstX0; + sourceRect.width = srcX1 - srcX0; + destRect.width = dstX1 - dstX0; } else { - sourceRect.left = srcX1; - destRect.left = dstX1; - sourceRect.right = srcX0; - destRect.right = dstX0; + sourceRect.x = srcX1; + destRect.x = dstX1; + sourceRect.width = srcX0 - srcX1; + destRect.width = dstX0 - dstX1; } if (srcY0 < srcY1) { - sourceRect.bottom = srcY1; - destRect.bottom = dstY1; - sourceRect.top = srcY0; - destRect.top = dstY0; + sourceRect.height = srcY1 - srcY0; + destRect.height = dstY1 - dstY0; + sourceRect.y = srcY0; + destRect.y = dstY0; } else { - sourceRect.bottom = srcY0; - destRect.bottom = dstY0; - sourceRect.top = srcY1; - destRect.top = dstY1; + sourceRect.height = srcY0 - srcY1; + destRect.height = dstY0 - srcY1; + sourceRect.y = srcY1; + destRect.y = dstY1; } - RECT sourceScissoredRect = sourceRect; - RECT destScissoredRect = destRect; + Rectangle sourceScissoredRect = sourceRect; + Rectangle destScissoredRect = destRect; if (mState.scissorTest) { - // Only write to parts of the destination framebuffer which pass the scissor test - // Please note: the destRect is now in D3D-style coordinates, so the *top* of the - // rect will be checked against scissorY, rather than the bottom. - if (destRect.left < mState.scissorX) + // Only write to parts of the destination framebuffer which pass the scissor test. + if (destRect.x < mState.scissor.x) { - int xDiff = mState.scissorX - destRect.left; - destScissoredRect.left = mState.scissorX; - sourceScissoredRect.left += xDiff; + int xDiff = mState.scissor.x - destRect.x; + destScissoredRect.x = mState.scissor.x; + destScissoredRect.width -= xDiff; + sourceScissoredRect.x += xDiff; + sourceScissoredRect.width -= xDiff; + } - if (destRect.right > mState.scissorX + mState.scissorWidth) + if (destRect.x + destRect.width > mState.scissor.x + mState.scissor.width) { - int xDiff = destRect.right - (mState.scissorX + mState.scissorWidth); - destScissoredRect.right = mState.scissorX + mState.scissorWidth; - sourceScissoredRect.right -= xDiff; + int xDiff = (destRect.x + destRect.width) - (mState.scissor.x + mState.scissor.width); + destScissoredRect.width -= xDiff; + sourceScissoredRect.width -= xDiff; } - if (destRect.top < mState.scissorY) + if (destRect.y < mState.scissor.y) { - int yDiff = mState.scissorY - destRect.top; - destScissoredRect.top = mState.scissorY; - sourceScissoredRect.top += yDiff; + int yDiff = mState.scissor.y - destRect.y; + destScissoredRect.y = mState.scissor.y; + destScissoredRect.height -= yDiff; + sourceScissoredRect.y += yDiff; + sourceScissoredRect.height -= yDiff; } - if (destRect.bottom > mState.scissorY + mState.scissorHeight) + if (destRect.y + destRect.height > mState.scissor.y + mState.scissor.height) { - int yDiff = destRect.bottom - (mState.scissorY + mState.scissorHeight); - destScissoredRect.bottom = mState.scissorY + mState.scissorHeight; - sourceScissoredRect.bottom -= yDiff; + int yDiff = (destRect.y + destRect.height) - (mState.scissor.y + mState.scissor.height); + destScissoredRect.height -= yDiff; + sourceScissoredRect.height -= yDiff; } } bool blitRenderTarget = false; bool blitDepthStencil = false; - RECT sourceTrimmedRect = sourceScissoredRect; - RECT destTrimmedRect = destScissoredRect; + Rectangle sourceTrimmedRect = sourceScissoredRect; + Rectangle destTrimmedRect = destScissoredRect; // The source & destination rectangles also may need to be trimmed if they fall out of the bounds of // the actual draw and read surfaces. - if (sourceTrimmedRect.left < 0) + if (sourceTrimmedRect.x < 0) { - int xDiff = 0 - sourceTrimmedRect.left; - sourceTrimmedRect.left = 0; - destTrimmedRect.left += xDiff; + int xDiff = 0 - sourceTrimmedRect.x; + sourceTrimmedRect.x = 0; + sourceTrimmedRect.width -= xDiff; + destTrimmedRect.x += xDiff; + destTrimmedRect.width -= xDiff; } - if (sourceTrimmedRect.right > readBufferWidth) + if (sourceTrimmedRect.x + sourceTrimmedRect.width > readBufferWidth) { - int xDiff = sourceTrimmedRect.right - readBufferWidth; - sourceTrimmedRect.right = readBufferWidth; - destTrimmedRect.right -= xDiff; + int xDiff = (sourceTrimmedRect.x + sourceTrimmedRect.width) - readBufferWidth; + sourceTrimmedRect.width -= xDiff; + destTrimmedRect.width -= xDiff; } - if (sourceTrimmedRect.top < 0) + if (sourceTrimmedRect.y < 0) { - int yDiff = 0 - sourceTrimmedRect.top; - sourceTrimmedRect.top = 0; - destTrimmedRect.top += yDiff; + int yDiff = 0 - sourceTrimmedRect.y; + sourceTrimmedRect.y = 0; + sourceTrimmedRect.height -= yDiff; + destTrimmedRect.y += yDiff; + destTrimmedRect.height -= yDiff; } - if (sourceTrimmedRect.bottom > readBufferHeight) + if (sourceTrimmedRect.y + sourceTrimmedRect.height > readBufferHeight) { - int yDiff = sourceTrimmedRect.bottom - readBufferHeight; - sourceTrimmedRect.bottom = readBufferHeight; - destTrimmedRect.bottom -= yDiff; + int yDiff = (sourceTrimmedRect.y + sourceTrimmedRect.height) - readBufferHeight; + sourceTrimmedRect.height -= yDiff; + destTrimmedRect.height -= yDiff; } - if (destTrimmedRect.left < 0) + if (destTrimmedRect.x < 0) { - int xDiff = 0 - destTrimmedRect.left; - destTrimmedRect.left = 0; - sourceTrimmedRect.left += xDiff; + int xDiff = 0 - destTrimmedRect.x; + destTrimmedRect.x = 0; + destTrimmedRect.width -= xDiff; + sourceTrimmedRect.x += xDiff; + sourceTrimmedRect.width -= xDiff; } - if (destTrimmedRect.right > drawBufferWidth) + if (destTrimmedRect.x + destTrimmedRect.width > drawBufferWidth) { - int xDiff = destTrimmedRect.right - drawBufferWidth; - destTrimmedRect.right = drawBufferWidth; - sourceTrimmedRect.right -= xDiff; + int xDiff = (destTrimmedRect.x + destTrimmedRect.width) - drawBufferWidth; + destTrimmedRect.width -= xDiff; + sourceTrimmedRect.width -= xDiff; } - if (destTrimmedRect.top < 0) + if (destTrimmedRect.y < 0) { - int yDiff = 0 - destTrimmedRect.top; - destTrimmedRect.top = 0; - sourceTrimmedRect.top += yDiff; + int yDiff = 0 - destTrimmedRect.y; + destTrimmedRect.y = 0; + destTrimmedRect.height -= yDiff; + sourceTrimmedRect.y += yDiff; + sourceTrimmedRect.height -= yDiff; } - if (destTrimmedRect.bottom > drawBufferHeight) + if (destTrimmedRect.y + destTrimmedRect.height > drawBufferHeight) { - int yDiff = destTrimmedRect.bottom - drawBufferHeight; - destTrimmedRect.bottom = drawBufferHeight; - sourceTrimmedRect.bottom -= yDiff; + int yDiff = (destTrimmedRect.y + destTrimmedRect.height) - drawBufferHeight; + destTrimmedRect.height -= yDiff; + sourceTrimmedRect.height -= yDiff; } bool partialBufferCopy = false; - if (sourceTrimmedRect.bottom - sourceTrimmedRect.top < readBufferHeight || - sourceTrimmedRect.right - sourceTrimmedRect.left < readBufferWidth || - destTrimmedRect.bottom - destTrimmedRect.top < drawBufferHeight || - destTrimmedRect.right - destTrimmedRect.left < drawBufferWidth || - sourceTrimmedRect.top != 0 || destTrimmedRect.top != 0 || sourceTrimmedRect.left != 0 || destTrimmedRect.left != 0) + if (sourceTrimmedRect.height < readBufferHeight || + sourceTrimmedRect.width < readBufferWidth || + destTrimmedRect.height < drawBufferHeight || + destTrimmedRect.width < drawBufferWidth || + sourceTrimmedRect.y != 0 || destTrimmedRect.y != 0 || sourceTrimmedRect.x != 0 || destTrimmedRect.x != 0) { partialBufferCopy = true; } if (mask & GL_COLOR_BUFFER_BIT) { - const bool validReadType = readFramebuffer->getColorbufferType() == GL_TEXTURE_2D || - readFramebuffer->getColorbufferType() == GL_RENDERBUFFER; - const bool validDrawType = drawFramebuffer->getColorbufferType() == GL_TEXTURE_2D || - drawFramebuffer->getColorbufferType() == GL_RENDERBUFFER; - if (!validReadType || !validDrawType || - readFramebuffer->getColorbuffer()->getD3DFormat() != drawFramebuffer->getColorbuffer()->getD3DFormat()) + const GLenum readColorbufferType = readFramebuffer->getReadColorbufferType(); + const bool validReadType = (readColorbufferType == GL_TEXTURE_2D) || (readColorbufferType == GL_RENDERBUFFER); + bool validDrawType = true; + bool validDrawFormat = true; + + for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) + { + if (drawFramebuffer->isEnabledColorAttachment(colorAttachment)) + { + if (drawFramebuffer->getColorbufferType(colorAttachment) != GL_TEXTURE_2D && + drawFramebuffer->getColorbufferType(colorAttachment) != GL_RENDERBUFFER) + { + validDrawType = false; + } + + if (drawFramebuffer->getColorbuffer(colorAttachment)->getActualFormat() != readColorBuffer->getActualFormat()) + { + validDrawFormat = false; + } + } + } + + if (!validReadType || !validDrawType || !validDrawFormat) { ERR("Color buffer format conversion in BlitFramebufferANGLE not supported by this implementation"); - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } if (partialBufferCopy && readFramebuffer->getSamples() != 0) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } blitRenderTarget = true; @@ -4198,9 +2888,9 @@ void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1 if (readFramebuffer->getDepthbuffer() && drawFramebuffer->getDepthbuffer()) { if (readFramebuffer->getDepthbufferType() != drawFramebuffer->getDepthbufferType() || - readFramebuffer->getDepthbuffer()->getD3DFormat() != drawFramebuffer->getDepthbuffer()->getD3DFormat()) + readFramebuffer->getDepthbuffer()->getActualFormat() != drawFramebuffer->getDepthbuffer()->getActualFormat()) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } blitDepthStencil = true; @@ -4214,9 +2904,9 @@ void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1 if (readFramebuffer->getStencilbuffer() && drawFramebuffer->getStencilbuffer()) { if (readFramebuffer->getStencilbufferType() != drawFramebuffer->getStencilbufferType() || - readFramebuffer->getStencilbuffer()->getD3DFormat() != drawFramebuffer->getStencilbuffer()->getD3DFormat()) + readFramebuffer->getStencilbuffer()->getActualFormat() != drawFramebuffer->getStencilbuffer()->getActualFormat()) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } blitDepthStencil = true; @@ -4228,255 +2918,29 @@ void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1 if (partialBufferCopy) { ERR("Only whole-buffer depth and stencil blits are supported by this implementation."); - return error(GL_INVALID_OPERATION); // only whole-buffer copies are permitted + return gl::error(GL_INVALID_OPERATION); // only whole-buffer copies are permitted } if ((drawDSBuffer && drawDSBuffer->getSamples() != 0) || (readDSBuffer && readDSBuffer->getSamples() != 0)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } } if (blitRenderTarget || blitDepthStencil) { - mDisplay->endScene(); - - if (blitRenderTarget) - { - IDirect3DSurface9* readRenderTarget = readFramebuffer->getRenderTarget(); - IDirect3DSurface9* drawRenderTarget = drawFramebuffer->getRenderTarget(); - - HRESULT result = mDevice->StretchRect(readRenderTarget, &sourceTrimmedRect, - drawRenderTarget, &destTrimmedRect, D3DTEXF_NONE); - - readRenderTarget->Release(); - drawRenderTarget->Release(); - - if (FAILED(result)) - { - ERR("BlitFramebufferANGLE failed: StretchRect returned %x.", result); - return; - } - } - - if (blitDepthStencil) - { - IDirect3DSurface9* readDepthStencil = readFramebuffer->getDepthStencil(); - IDirect3DSurface9* drawDepthStencil = drawFramebuffer->getDepthStencil(); - - HRESULT result = mDevice->StretchRect(readDepthStencil, NULL, drawDepthStencil, NULL, D3DTEXF_NONE); - - readDepthStencil->Release(); - drawDepthStencil->Release(); - - if (FAILED(result)) - { - ERR("BlitFramebufferANGLE failed: StretchRect returned %x.", result); - return; - } - } - } -} - -VertexDeclarationCache::VertexDeclarationCache() : mMaxLru(0) -{ - for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++) - { - mVertexDeclCache[i].vertexDeclaration = NULL; - mVertexDeclCache[i].lruCount = 0; - } -} - -VertexDeclarationCache::~VertexDeclarationCache() -{ - for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++) - { - if (mVertexDeclCache[i].vertexDeclaration) - { - mVertexDeclCache[i].vertexDeclaration->Release(); - } - } -} - -GLenum VertexDeclarationCache::applyDeclaration(IDirect3DDevice9 *device, TranslatedAttribute attributes[], ProgramBinary *programBinary, GLsizei instances, GLsizei *repeatDraw) -{ - *repeatDraw = 1; - - int indexedAttribute = MAX_VERTEX_ATTRIBS; - int instancedAttribute = MAX_VERTEX_ATTRIBS; - - if (instances > 0) - { - // Find an indexed attribute to be mapped to D3D stream 0 - for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) - { - if (attributes[i].active) - { - if (indexedAttribute == MAX_VERTEX_ATTRIBS) - { - if (attributes[i].divisor == 0) - { - indexedAttribute = i; - } - } - else if (instancedAttribute == MAX_VERTEX_ATTRIBS) - { - if (attributes[i].divisor != 0) - { - instancedAttribute = i; - } - } - else break; // Found both an indexed and instanced attribute - } - } - - if (indexedAttribute == MAX_VERTEX_ATTRIBS) - { - return GL_INVALID_OPERATION; - } - } - - D3DVERTEXELEMENT9 elements[MAX_VERTEX_ATTRIBS + 1]; - D3DVERTEXELEMENT9 *element = &elements[0]; - - for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) - { - if (attributes[i].active) - { - int stream = i; - - if (instances > 0) - { - // Due to a bug on ATI cards we can't enable instancing when none of the attributes are instanced. - if (instancedAttribute == MAX_VERTEX_ATTRIBS) - { - *repeatDraw = instances; - } - else - { - if (i == indexedAttribute) - { - stream = 0; - } - else if (i == 0) - { - stream = indexedAttribute; - } - - UINT frequency = 1; - - if (attributes[i].divisor == 0) - { - frequency = D3DSTREAMSOURCE_INDEXEDDATA | instances; - } - else - { - frequency = D3DSTREAMSOURCE_INSTANCEDATA | attributes[i].divisor; - } - - device->SetStreamSourceFreq(stream, frequency); - mInstancingEnabled = true; - } - } - - if (mAppliedVBs[stream].serial != attributes[i].serial || - mAppliedVBs[stream].stride != attributes[i].stride || - mAppliedVBs[stream].offset != attributes[i].offset) - { - device->SetStreamSource(stream, attributes[i].vertexBuffer, attributes[i].offset, attributes[i].stride); - mAppliedVBs[stream].serial = attributes[i].serial; - mAppliedVBs[stream].stride = attributes[i].stride; - mAppliedVBs[stream].offset = attributes[i].offset; - } - - element->Stream = stream; - element->Offset = 0; - element->Type = attributes[i].type; - element->Method = D3DDECLMETHOD_DEFAULT; - element->Usage = D3DDECLUSAGE_TEXCOORD; - element->UsageIndex = programBinary->getSemanticIndex(i); - element++; - } - } - - if (instances == 0 || instancedAttribute == MAX_VERTEX_ATTRIBS) - { - if (mInstancingEnabled) - { - for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) - { - device->SetStreamSourceFreq(i, 1); - } - - mInstancingEnabled = false; - } - } - - static const D3DVERTEXELEMENT9 end = D3DDECL_END(); - *(element++) = end; - - for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++) - { - VertexDeclCacheEntry *entry = &mVertexDeclCache[i]; - if (memcmp(entry->cachedElements, elements, (element - elements) * sizeof(D3DVERTEXELEMENT9)) == 0 && entry->vertexDeclaration) - { - entry->lruCount = ++mMaxLru; - if(entry->vertexDeclaration != mLastSetVDecl) - { - device->SetVertexDeclaration(entry->vertexDeclaration); - mLastSetVDecl = entry->vertexDeclaration; - } - - return GL_NO_ERROR; - } - } - - VertexDeclCacheEntry *lastCache = mVertexDeclCache; - - for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++) - { - if (mVertexDeclCache[i].lruCount < lastCache->lruCount) - { - lastCache = &mVertexDeclCache[i]; - } - } - - if (lastCache->vertexDeclaration != NULL) - { - lastCache->vertexDeclaration->Release(); - lastCache->vertexDeclaration = NULL; - // mLastSetVDecl is set to the replacement, so we don't have to worry - // about it. - } - - memcpy(lastCache->cachedElements, elements, (element - elements) * sizeof(D3DVERTEXELEMENT9)); - device->CreateVertexDeclaration(elements, &lastCache->vertexDeclaration); - device->SetVertexDeclaration(lastCache->vertexDeclaration); - mLastSetVDecl = lastCache->vertexDeclaration; - lastCache->lruCount = ++mMaxLru; - - return GL_NO_ERROR; -} - -void VertexDeclarationCache::markStateDirty() -{ - for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) - { - mAppliedVBs[i].serial = 0; + mRenderer->blitRect(readFramebuffer, sourceTrimmedRect, drawFramebuffer, destTrimmedRect, blitRenderTarget, blitDepthStencil); } - - mLastSetVDecl = NULL; - mInstancingEnabled = true; // Forces it to be disabled when not used } } extern "C" { -gl::Context *glCreateContext(const egl::Config *config, const gl::Context *shareContext, bool notifyResets, bool robustAccess) +gl::Context *glCreateContext(const gl::Context *shareContext, rx::Renderer *renderer, bool notifyResets, bool robustAccess) { - return new gl::Context(config, shareContext, notifyResets, robustAccess); + return new gl::Context(shareContext, renderer, notifyResets, robustAccess); } void glDestroyContext(gl::Context *context) @@ -4498,4 +2962,5 @@ gl::Context *glGetCurrentContext() { return gl::getContext(); } + } diff --git a/src/3rdparty/angle/src/libGLESv2/Context.h b/src/3rdparty/angle/src/libGLESv2/Context.h index 2bbae76ef8..9c222be24d 100644 --- a/src/3rdparty/angle/src/libGLESv2/Context.h +++ b/src/3rdparty/angle/src/libGLESv2/Context.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// 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. // @@ -15,7 +15,6 @@ #include #define EGLAPI #include -#include #include #include @@ -27,22 +26,23 @@ #include "common/angleutils.h" #include "common/RefCountObject.h" -#include "libGLESv2/ResourceManager.h" #include "libGLESv2/HandleAllocator.h" +#include "libGLESv2/angletypes.h" +#include "libGLESv2/Constants.h" + +namespace rx +{ +class Renderer; +} namespace egl { class Display; class Surface; -class Config; } namespace gl { -struct TranslatedAttribute; -struct TranslatedIndexData; - -class Buffer; class Shader; class Program; class ProgramBinary; @@ -54,35 +54,12 @@ class Renderbuffer; class RenderbufferStorage; class Colorbuffer; class Depthbuffer; -class StreamingIndexBuffer; class Stencilbuffer; class DepthStencilbuffer; -class VertexDataManager; -class IndexDataManager; -class Blit; class Fence; class Query; - -enum -{ - D3D9_MAX_FLOAT_CONSTANTS = 256, - D3D9_MAX_BOOL_CONSTANTS = 16, - D3D9_MAX_INT_CONSTANTS = 16, - - MAX_VERTEX_ATTRIBS = 16, - MAX_VERTEX_UNIFORM_VECTORS = D3D9_MAX_FLOAT_CONSTANTS - 2, // Reserve space for dx_HalfPixelSize and dx_DepthRange. - MAX_VARYING_VECTORS_SM2 = 8, - MAX_VARYING_VECTORS_SM3 = 10, - MAX_TEXTURE_IMAGE_UNITS = 16, - MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF = 4, // For devices supporting vertex texture fetch - MAX_COMBINED_TEXTURE_IMAGE_UNITS_VTF = MAX_TEXTURE_IMAGE_UNITS + MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF, - MAX_FRAGMENT_UNIFORM_VECTORS_SM2 = 32 - 3, // Reserve space for dx_Coord, dx_Depth, and dx_DepthRange. dx_PointOrLines and dx_FrontCCW use separate bool registers. - MAX_FRAGMENT_UNIFORM_VECTORS_SM3 = 224 - 3, - MAX_DRAW_BUFFERS = 1, - - GL_BGRA4_ANGLEX = 0x6ABC, - GL_BGR5_A1_ANGLEX = 0x6ABD -}; +class ResourceManager; +class Buffer; enum QueryType { @@ -92,19 +69,6 @@ enum QueryType QUERY_TYPE_COUNT }; -const float ALIASED_LINE_WIDTH_RANGE_MIN = 1.0f; -const float ALIASED_LINE_WIDTH_RANGE_MAX = 1.0f; -const float ALIASED_POINT_SIZE_RANGE_MIN = 1.0f; -const float ALIASED_POINT_SIZE_RANGE_MAX_SM2 = 1.0f; - -struct Color -{ - float red; - float green; - float blue; - float alpha; -}; - // Helper structure describing a single vertex attribute class VertexAttribute { @@ -155,8 +119,6 @@ class VertexAttribute unsigned int mDivisor; }; -typedef VertexAttribute VertexAttributeArray[MAX_VERTEX_ATTRIBS]; - // Helper structure to store all raw state struct State { @@ -164,67 +126,29 @@ struct State GLclampf depthClearValue; int stencilClearValue; - bool cullFace; - GLenum cullMode; - GLenum frontFace; - bool depthTest; - GLenum depthFunc; - bool blend; - GLenum sourceBlendRGB; - GLenum destBlendRGB; - GLenum sourceBlendAlpha; - GLenum destBlendAlpha; - GLenum blendEquationRGB; - GLenum blendEquationAlpha; + RasterizerState rasterizer; + bool scissorTest; + Rectangle scissor; + + BlendState blend; Color blendColor; - bool stencilTest; - GLenum stencilFunc; - GLint stencilRef; - GLuint stencilMask; - GLenum stencilFail; - GLenum stencilPassDepthFail; - GLenum stencilPassDepthPass; - GLuint stencilWritemask; - GLenum stencilBackFunc; - GLint stencilBackRef; - GLuint stencilBackMask; - GLenum stencilBackFail; - GLenum stencilBackPassDepthFail; - GLenum stencilBackPassDepthPass; - GLuint stencilBackWritemask; - bool polygonOffsetFill; - GLfloat polygonOffsetFactor; - GLfloat polygonOffsetUnits; - bool sampleAlphaToCoverage; bool sampleCoverage; GLclampf sampleCoverageValue; bool sampleCoverageInvert; - bool scissorTest; - bool dither; + + DepthStencilState depthStencil; + GLint stencilRef; + GLint stencilBackRef; GLfloat lineWidth; GLenum generateMipmapHint; GLenum fragmentShaderDerivativeHint; - GLint viewportX; - GLint viewportY; - GLsizei viewportWidth; - GLsizei viewportHeight; + Rectangle viewport; float zNear; float zFar; - GLint scissorX; - GLint scissorY; - GLsizei scissorWidth; - GLsizei scissorHeight; - - bool colorMaskRed; - bool colorMaskGreen; - bool colorMaskBlue; - bool colorMaskAlpha; - bool depthMask; - unsigned int activeSampler; // Active texture unit selector - GL_TEXTURE0 BindingPointer arrayBuffer; BindingPointer elementArrayBuffer; @@ -234,7 +158,7 @@ struct State GLuint currentProgram; VertexAttribute vertexAttribute[MAX_VERTEX_ATTRIBS]; - BindingPointer samplerTexture[TEXTURE_TYPE_COUNT][MAX_COMBINED_TEXTURE_IMAGE_UNITS_VTF]; + BindingPointer samplerTexture[TEXTURE_TYPE_COUNT][IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS]; BindingPointer activeQuery[QUERY_TYPE_COUNT]; GLint unpackAlignment; @@ -242,52 +166,14 @@ struct State bool packReverseRowOrder; }; -// Helper class to construct and cache vertex declarations -class VertexDeclarationCache -{ - public: - VertexDeclarationCache(); - ~VertexDeclarationCache(); - - GLenum applyDeclaration(IDirect3DDevice9 *device, TranslatedAttribute attributes[], ProgramBinary *programBinary, GLsizei instances, GLsizei *repeatDraw); - - void markStateDirty(); - - private: - UINT mMaxLru; - - enum { NUM_VERTEX_DECL_CACHE_ENTRIES = 32 }; - - struct VBData - { - unsigned int serial; - unsigned int stride; - unsigned int offset; - }; - - VBData mAppliedVBs[MAX_VERTEX_ATTRIBS]; - IDirect3DVertexDeclaration9 *mLastSetVDecl; - bool mInstancingEnabled; - - struct VertexDeclCacheEntry - { - D3DVERTEXELEMENT9 cachedElements[MAX_VERTEX_ATTRIBS + 1]; - UINT lruCount; - IDirect3DVertexDeclaration9 *vertexDeclaration; - } mVertexDeclCache[NUM_VERTEX_DECL_CACHE_ENTRIES]; -}; - class Context { public: - Context(const egl::Config *config, const gl::Context *shareContext, bool notifyResets, bool robustAccess); + Context(const gl::Context *shareContext, rx::Renderer *renderer, bool notifyResets, bool robustAccess); ~Context(); - void makeCurrent(egl::Display *display, egl::Surface *surface); - - virtual void markAllStateDirty(); - void markDxUniformsDirty(); + void makeCurrent(egl::Surface *surface); virtual void markContextLost(); bool isContextLost(); @@ -377,8 +263,6 @@ class Context bool normalized, GLsizei stride, const void *pointer); const void *getVertexAttribPointer(unsigned int attribNum) const; - const VertexAttributeArray &getVertexAttributes(); - void setUnpackAlignment(GLint alignment); GLint getUnpackAlignment() const; @@ -430,7 +314,7 @@ class Context void setFramebufferZero(Framebuffer *framebuffer); - void setRenderbufferStorage(RenderbufferStorage *renderbuffer); + void setRenderbufferStorage(GLsizei width, GLsizei height, GLenum internalformat, GLsizei samples); void setVertexAttrib(GLuint index, const GLfloat *values); void setVertexAttribDivisor(GLuint index, GLuint divisor); @@ -465,8 +349,6 @@ class Context void drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei instances); void sync(bool block); // flush/finish - void drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex); - void recordInvalidEnum(); void recordInvalidValue(); void recordInvalidOperation(); @@ -477,22 +359,20 @@ class Context GLenum getResetStatus(); virtual bool isResetNotificationEnabled(); - bool supportsShaderModel3() const; + int getMajorShaderModel() const; float getMaximumPointSize() const; - int getMaximumVaryingVectors() const; - unsigned int getMaximumVertexTextureImageUnits() const; unsigned int getMaximumCombinedTextureImageUnits() const; - int getMaximumFragmentUniformVectors() const; int getMaximumRenderbufferDimension() const; int getMaximumTextureDimension() const; int getMaximumCubeTextureDimension() const; int getMaximumTextureLevel() const; + unsigned int getMaximumRenderTargets() const; GLsizei getMaxSupportedSamples() const; - int getNearestSupportedSamples(D3DFORMAT format, int requested) const; const char *getExtensionString() const; const char *getRendererString() const; bool supportsEventQueries() const; bool supportsOcclusionQueries() const; + bool supportsBGRATextures() const; bool supportsDXT1Textures() const; bool supportsDXT3Textures() const; bool supportsDXT5Textures() const; @@ -518,17 +398,11 @@ class Context GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask); - Blit *getBlitter() { return mBlit; } - - const D3DCAPS9 &getDeviceCaps() { return mDeviceCaps; } - private: DISALLOW_COPY_AND_ASSIGN(Context); - bool applyRenderTarget(bool ignoreViewport); + bool applyRenderTarget(GLenum drawMode, bool ignoreViewport); void applyState(GLenum drawMode); - GLenum applyVertexBuffer(GLint first, GLsizei count, GLsizei instances, GLsizei *repeatDraw); - GLenum applyIndexBuffer(const GLvoid *indices, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo); void applyShaders(); void applyTextures(); void applyTextures(SamplerType type); @@ -541,14 +415,11 @@ class Context Texture *getIncompleteTexture(TextureType type); bool skipDraw(GLenum drawMode); - bool isTriangleMode(GLenum drawMode); void initExtensionString(); void initRendererString(); - const egl::Config *const mConfig; - egl::Display *mDisplay; - IDirect3DDevice9 *mDevice; + rx::Renderer *const mRenderer; State mState; @@ -575,15 +446,8 @@ class Context QueryMap mQueryMap; HandleAllocator mQueryHandleAllocator; - std::string mExtensionString; - std::string mRendererString; - - VertexDataManager *mVertexDataManager; - IndexDataManager *mIndexDataManager; - - Blit *mBlit; - - StreamingIndexBuffer *mLineLoopIB; + const char *mExtensionString; + const char *mRendererString; BindingPointer mIncompleteTextures[TEXTURE_TYPE_COUNT]; @@ -601,36 +465,23 @@ class Context GLenum mResetStrategy; bool mRobustAccess; - unsigned int mAppliedTextureSerialPS[MAX_TEXTURE_IMAGE_UNITS]; - unsigned int mAppliedTextureSerialVS[MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF]; - unsigned int mAppliedProgramBinarySerial; - unsigned int mAppliedRenderTargetSerial; - unsigned int mAppliedDepthbufferSerial; - unsigned int mAppliedStencilbufferSerial; - unsigned int mAppliedIBSerial; - bool mDepthStencilInitialized; - bool mViewportInitialized; - D3DVIEWPORT9 mSetViewport; - bool mRenderTargetDescInitialized; - D3DSURFACE_DESC mRenderTargetDesc; - bool mDxUniformsDirty; BindingPointer mCurrentProgramBinary; Framebuffer *mBoundDrawFramebuffer; - bool mSupportsShaderModel3; + int mMajorShaderModel; float mMaximumPointSize; bool mSupportsVertexTexture; bool mSupportsNonPower2Texture; bool mSupportsInstancing; + int mMaxViewportDimension; int mMaxRenderbufferDimension; int mMaxTextureDimension; int mMaxCubeTextureDimension; int mMaxTextureLevel; float mMaxTextureAnisotropy; - std::map mMultiSampleSupport; - GLsizei mMaxSupportedSamples; bool mSupportsEventQueries; bool mSupportsOcclusionQueries; + bool mSupportsBGRATextures; bool mSupportsDXT1Textures; bool mSupportsDXT3Textures; bool mSupportsDXT5Textures; @@ -647,39 +498,8 @@ class Context bool mSupportsTextureFilterAnisotropy; int mNumCompressedTextureFormats; - // state caching flags - bool mClearStateDirty; - bool mCullStateDirty; - bool mDepthStateDirty; - bool mMaskStateDirty; - bool mPixelPackingStateDirty; - bool mBlendStateDirty; - bool mStencilStateDirty; - bool mPolygonOffsetStateDirty; - bool mScissorStateDirty; - bool mSampleStateDirty; - bool mFrontFaceDirty; - bool mDitherStateDirty; - - IDirect3DStateBlock9 *mMaskedClearSavedState; - - D3DCAPS9 mDeviceCaps; - ResourceManager *mResourceManager; - - VertexDeclarationCache mVertexDeclarationCache; }; } -extern "C" -{ -// Exported functions for use by EGL -gl::Context *glCreateContext(const egl::Config *config, const gl::Context *shareContext, bool notifyResets, bool robustAccess); -void glDestroyContext(gl::Context *context); -void glMakeCurrent(gl::Context *context, egl::Display *display, egl::Surface *surface); -gl::Context *glGetCurrentContext(); -__eglMustCastToProperFunctionPointerType __stdcall glGetProcAddress(const char *procname); -bool __stdcall glBindTexImage(egl::Surface *surface); -} - #endif // INCLUDE_CONTEXT_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/D3DConstantTable.cpp b/src/3rdparty/angle/src/libGLESv2/D3DConstantTable.cpp deleted file mode 100644 index e136951bec..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/D3DConstantTable.cpp +++ /dev/null @@ -1,231 +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. -// - -// D3DConstantTable.cpp: Implements the D3DConstantTable class which parses -// information about constants from the CTAB comment in a D3D shader blob. -// Restructures the constant table as a hierarchy of constants in the same -// way as D3DX. - -#include "libGLESv2/D3DConstantTable.h" - -#include -#include -#include -#include - -#include "libGLESv2/BinaryStream.h" - -const static int SHADER_VERSION_MASK = D3DVS_VERSION(0, 0); -const static int FOURCC_CTAB = MAKEFOURCC('C','T','A','B'); - -namespace gl -{ -// These structs and constants correspond to the format of the constant table in a shader binary. -// They match the corresponding structures in d3dx9shader.h. -namespace ctab -{ -struct ConstantTable -{ - DWORD size; - DWORD creator; - DWORD version; - DWORD constants; - DWORD constantInfos; - DWORD flags; - DWORD target; -}; - -struct ConstantInfo -{ - DWORD name; - WORD registerSet; - WORD registerIndex; - WORD registerCount; - WORD reserved; - DWORD typeInfo; - DWORD defaultValue; -}; - -struct TypeInfo -{ - WORD typeClass; - WORD type; - WORD rows; - WORD columns; - WORD elements; - WORD structMembers; - DWORD structMemberInfos; -}; - -struct StructMemberInfo -{ - DWORD name; - DWORD typeInfo; -}; -} - -D3DConstant::D3DConstant(const char *base, const ctab::ConstantInfo *constantInfo) -{ - const ctab::TypeInfo *typeInfo = reinterpret_cast(base + constantInfo->typeInfo); - - name = base + constantInfo->name; - registerSet = static_cast(constantInfo->registerSet); - registerIndex = constantInfo->registerIndex; - registerCount = constantInfo->registerCount; - typeClass = static_cast(typeInfo->typeClass); - type = static_cast(typeInfo->type); - rows = typeInfo->rows; - columns = typeInfo->columns; - elements = typeInfo->elements; - - if (typeClass == CLASS_STRUCT) - { - addStructMembers(base, registerSet, registerIndex, typeInfo); - } -} - -D3DConstant::D3DConstant(const char *base, RegisterSet registerSet, unsigned registerIndex, const ctab::StructMemberInfo *memberInfo) - : registerSet(registerSet), registerIndex(registerIndex) -{ - const ctab::TypeInfo *typeInfo = reinterpret_cast(base + memberInfo->typeInfo); - - name = base + memberInfo->name; - registerCount = typeInfo->rows * typeInfo->elements; - typeClass = static_cast(typeInfo->typeClass); - type = static_cast(typeInfo->type); - rows = typeInfo->rows; - columns = typeInfo->columns; - elements = typeInfo->elements; - - if (typeClass == CLASS_STRUCT) - { - registerCount = addStructMembers(base, registerSet, registerIndex, typeInfo); - } -} - -D3DConstant::~D3DConstant() -{ - for (size_t j = 0; j < structMembers.size(); ++j) - { - for (size_t i = 0; i < structMembers[j].size(); ++i) - { - delete structMembers[j][i]; - } - } -} - -unsigned D3DConstant::addStructMembers(const char *base, RegisterSet registerSet, unsigned registerIndex, const ctab::TypeInfo *typeInfo) -{ - const ctab::StructMemberInfo *memberInfos = reinterpret_cast( - base + typeInfo->structMemberInfos); - - unsigned memberIndex = registerIndex; - - structMembers.resize(elements); - - for (unsigned j = 0; j < elements; ++j) - { - structMembers[j].resize(typeInfo->structMembers); - - for (unsigned i = 0; i < typeInfo->structMembers; ++i) - { - const ctab::TypeInfo *memberTypeInfo = reinterpret_cast( - base + memberInfos[i].typeInfo); - - D3DConstant *member = new D3DConstant(base, registerSet, memberIndex, memberInfos + i); - memberIndex += member->registerCount; - - structMembers[j][i] = member; - } - } - - return memberIndex - registerIndex; -} - -D3DConstantTable::D3DConstantTable(void *blob, size_t size) : mError(false) -{ - BinaryInputStream stream(blob, size); - - int version; - stream.read(&version); - if ((version & SHADER_VERSION_MASK) != SHADER_VERSION_MASK) - { - mError = true; - return; - } - - const ctab::ConstantTable* constantTable = NULL; - - while (!stream.error()) - { - int token; - stream.read(&token); - - if ((token & D3DSI_OPCODE_MASK) == D3DSIO_COMMENT) - { - size_t length = ((token & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT) * sizeof(DWORD); - - int fourcc; - stream.read(&fourcc); - if (fourcc == FOURCC_CTAB) - { - constantTable = reinterpret_cast(static_cast(blob) + stream.offset()); - break; - } - - stream.skip(length - sizeof(fourcc)); - } - else if (token == D3DSIO_END) - { - break; - } - } - - mError = !constantTable || stream.error(); - if (mError) - { - return; - } - - const char *base = reinterpret_cast(constantTable); - - mConstants.resize(constantTable->constants); - const ctab::ConstantInfo *constantInfos = - reinterpret_cast(base + constantTable->constantInfos); - for (size_t i = 0; i < constantTable->constants; ++i) - { - mConstants[i] = new D3DConstant(base, constantInfos + i); - } -} - -D3DConstantTable::~D3DConstantTable() -{ - for (size_t i = 0; i < mConstants.size(); ++i) - { - delete mConstants[i]; - } -} - -const D3DConstant *D3DConstantTable::getConstant(unsigned index) const -{ - return mConstants[index]; -} - -const D3DConstant *D3DConstantTable::getConstantByName(const char *name) const -{ - for (size_t i = 0; i < mConstants.size(); ++i) - { - const D3DConstant *constant = getConstant(i); - if (constant->name == name) - { - return constant; - } - } - - return NULL; -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/D3DConstantTable.h b/src/3rdparty/angle/src/libGLESv2/D3DConstantTable.h deleted file mode 100644 index ca6f3b9a3f..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/D3DConstantTable.h +++ /dev/null @@ -1,117 +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. -// - -// D3DConstantTable.h: Implements the D3DConstantTable class which parses -// information about constants from the CTAB comment in a D3D shader blob. -// Restructures the constant table as a hierarchy of constants in the same -// way as D3DX. - -#ifndef LIBGLESV2_D3DCONSTANTTABLE_H_ -#define LIBGLESV2_D3DCONSTANTTABLE_H_ - -#include -#include - -#include "common/angleutils.h" - -namespace gl -{ - -namespace ctab -{ -struct ConstantTable; -struct ConstantInfo; -struct TypeInfo; -struct StructMemberInfo; -} - -struct D3DConstant -{ - // These enums match those in d3dx9shader.h. - enum Class - { - CLASS_SCALAR, - CLASS_VECTOR, - CLASS_MATRIX_ROWS, - CLASS_MATRIX_COLUMNS, - CLASS_OBJECT, - CLASS_STRUCT, - }; - - enum RegisterSet - { - RS_BOOL, - RS_INT4, - RS_FLOAT4, - RS_SAMPLER, - }; - - enum Type - { - PT_VOID, - PT_BOOL, - PT_INT, - PT_FLOAT, - PT_STRING, - PT_TEXTURE, - PT_TEXTURE1D, - PT_TEXTURE2D, - PT_TEXTURE3D, - PT_TEXTURECUBE, - PT_SAMPLER, - PT_SAMPLER1D, - PT_SAMPLER2D, - PT_SAMPLER3D, - PT_SAMPLERCUBE, - PT_PIXELSHADER, - PT_VERTEXSHADER, - PT_PIXELFRAGMENT, - PT_VERTEXFRAGMENT, - PT_UNSUPPORTED, - }; - - D3DConstant(const char *base, const ctab::ConstantInfo *constantInfo); - ~D3DConstant(); - - std::string name; - RegisterSet registerSet; - unsigned registerIndex; - unsigned registerCount; - Class typeClass; - Type type; - unsigned rows; - unsigned columns; - unsigned elements; - - // Array of structure members. - std::vector > structMembers; - - private: - D3DConstant(const char *base, RegisterSet registerSet, unsigned registerIndex, const ctab::StructMemberInfo *memberInfo); - unsigned addStructMembers(const char *base, RegisterSet registerSet, unsigned registerIndex, const ctab::TypeInfo *typeInfo); -}; - -class D3DConstantTable -{ - public: - D3DConstantTable(void *blob, size_t size); - ~D3DConstantTable(); - - bool error() const { return mError; } - - unsigned constants() const { return mConstants.size(); } - const D3DConstant *getConstant(unsigned index) const; - const D3DConstant *getConstantByName(const char *name) const; - - private: - DISALLOW_COPY_AND_ASSIGN(D3DConstantTable); - std::vector mConstants; - bool mError; -}; - -} - -#endif // LIBGLESV2_D3DCONSTANTTABLE_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/Fence.cpp b/src/3rdparty/angle/src/libGLESv2/Fence.cpp index 14d1239abf..e4218bbeec 100644 --- a/src/3rdparty/angle/src/libGLESv2/Fence.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Fence.cpp @@ -1,5 +1,6 @@ +#include "precompiled.h" // -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// 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. // @@ -7,126 +8,45 @@ // Fence.cpp: Implements the gl::Fence class, which supports the GL_NV_fence extension. #include "libGLESv2/Fence.h" - -#include "libGLESv2/main.h" +#include "libGLESv2/renderer/FenceImpl.h" +#include "libGLESv2/renderer/Renderer.h" namespace gl { -Fence::Fence(egl::Display* display) +Fence::Fence(rx::Renderer *renderer) { - mDisplay = display; - mQuery = NULL; - mCondition = GL_NONE; - mStatus = GL_FALSE; + mFence = renderer->createFence(); } Fence::~Fence() { - if (mQuery != NULL) - { - mDisplay->freeEventQuery(mQuery); - } + delete mFence; } GLboolean Fence::isFence() { - // GL_NV_fence spec: - // A name returned by GenFencesNV, but not yet set via SetFenceNV, is not the name of an existing fence. - return mQuery != NULL; + return mFence->isFence(); } void Fence::setFence(GLenum condition) { - if (!mQuery) - { - mQuery = mDisplay->allocateEventQuery(); - if (!mQuery) - { - return error(GL_OUT_OF_MEMORY); - } - } - - HRESULT result = mQuery->Issue(D3DISSUE_END); - ASSERT(SUCCEEDED(result)); - - mCondition = condition; - mStatus = GL_FALSE; + mFence->setFence(condition); } GLboolean Fence::testFence() { - if (mQuery == NULL) - { - return error(GL_INVALID_OPERATION, GL_TRUE); - } - - HRESULT result = mQuery->GetData(NULL, 0, D3DGETDATA_FLUSH); - - if (checkDeviceLost(result)) - { - return error(GL_OUT_OF_MEMORY, GL_TRUE); - } - - ASSERT(result == S_OK || result == S_FALSE); - mStatus = result == S_OK; - return mStatus; + return mFence->testFence(); } void Fence::finishFence() { - if (mQuery == NULL) - { - return error(GL_INVALID_OPERATION); - } - - while (!testFence()) - { - Sleep(0); - } + mFence->finishFence(); } void Fence::getFenceiv(GLenum pname, GLint *params) { - if (mQuery == NULL) - { - return error(GL_INVALID_OPERATION); - } - - switch (pname) - { - case GL_FENCE_STATUS_NV: - { - // GL_NV_fence spec: - // Once the status of a fence has been finished (via FinishFenceNV) or tested and the returned status is TRUE (via either TestFenceNV - // or GetFenceivNV querying the FENCE_STATUS_NV), the status remains TRUE until the next SetFenceNV of the fence. - if (mStatus) - { - params[0] = GL_TRUE; - return; - } - - HRESULT result = mQuery->GetData(NULL, 0, 0); - - if (checkDeviceLost(result)) - { - params[0] = GL_TRUE; - return error(GL_OUT_OF_MEMORY); - } - - ASSERT(result == S_OK || result == S_FALSE); - mStatus = result == S_OK; - params[0] = mStatus; - - break; - } - case GL_FENCE_CONDITION_NV: - params[0] = mCondition; - break; - default: - return error(GL_INVALID_ENUM); - break; - } + mFence->getFenceiv(pname, params); } } diff --git a/src/3rdparty/angle/src/libGLESv2/Fence.h b/src/3rdparty/angle/src/libGLESv2/Fence.h index 9626cb0ff0..1cedebb112 100644 --- a/src/3rdparty/angle/src/libGLESv2/Fence.h +++ b/src/3rdparty/angle/src/libGLESv2/Fence.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// 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. // @@ -9,15 +9,12 @@ #ifndef LIBGLESV2_FENCE_H_ #define LIBGLESV2_FENCE_H_ -#define GL_APICALL -#include -#include - #include "common/angleutils.h" -namespace egl +namespace rx { -class Display; +class Renderer; +class FenceImpl; } namespace gl @@ -26,7 +23,7 @@ namespace gl class Fence { public: - explicit Fence(egl::Display* display); + explicit Fence(rx::Renderer *renderer); virtual ~Fence(); GLboolean isFence(); @@ -38,10 +35,7 @@ class Fence private: DISALLOW_COPY_AND_ASSIGN(Fence); - egl::Display* mDisplay; - IDirect3DQuery9* mQuery; - GLenum mCondition; - GLboolean mStatus; + rx::FenceImpl *mFence; }; } diff --git a/src/3rdparty/angle/src/libGLESv2/Float16ToFloat32.cpp b/src/3rdparty/angle/src/libGLESv2/Float16ToFloat32.cpp index 5bf7b3fce8..b90d2f6023 100644 --- a/src/3rdparty/angle/src/libGLESv2/Float16ToFloat32.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Float16ToFloat32.cpp @@ -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 diff --git a/src/3rdparty/angle/src/libGLESv2/Float16ToFloat32.py b/src/3rdparty/angle/src/libGLESv2/Float16ToFloat32.py index ae646ffa12..cf039bfc21 100644 --- a/src/3rdparty/angle/src/libGLESv2/Float16ToFloat32.py +++ b/src/3rdparty/angle/src/libGLESv2/Float16ToFloat32.py @@ -56,22 +56,22 @@ namespace gl print "const static unsigned g_mantissa[2048] = {" for i in range(0, 2048): - print " %08x," % convertMantissa(i) + print " %#010x," % convertMantissa(i) print "};\n" print "const static unsigned g_exponent[64] = {" for i in range(0, 64): - print " %08x," % convertExponent(i) + print " %#010x," % convertExponent(i) print "};\n" print "const static unsigned g_offset[64] = {" for i in range(0, 64): - print " %08x," % convertOffset(i) + print " %#010x," % convertOffset(i) print "};\n" print """float float16ToFloat32(unsigned short h) { - unsigned i32 = =g_mantissa[g_offset[h >> 10] + (h & 0x3ff)] + g_exponent[h >> 10]; + unsigned i32 = g_mantissa[g_offset[h >> 10] + (h & 0x3ff)] + g_exponent[h >> 10]; return *(float*) &i32; } } diff --git a/src/3rdparty/angle/src/libGLESv2/Framebuffer.cpp b/src/3rdparty/angle/src/libGLESv2/Framebuffer.cpp index 77d79c0be2..42fee3bbad 100644 --- a/src/3rdparty/angle/src/libGLESv2/Framebuffer.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Framebuffer.cpp @@ -1,5 +1,6 @@ +#include "precompiled.h" // -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// 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. // @@ -10,26 +11,38 @@ #include "libGLESv2/Framebuffer.h" #include "libGLESv2/main.h" -#include "libGLESv2/Renderbuffer.h" -#include "libGLESv2/Texture.h" #include "libGLESv2/utilities.h" +#include "libGLESv2/Texture.h" +#include "libGLESv2/Context.h" +#include "libGLESv2/renderer/Renderer.h" +#include "libGLESv2/Renderbuffer.h" namespace gl { -Framebuffer::Framebuffer() +Framebuffer::Framebuffer(rx::Renderer *renderer) + : mRenderer(renderer) { - mColorbufferType = GL_NONE; + for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) + { + mColorbufferTypes[colorAttachment] = GL_NONE; + mDrawBufferStates[colorAttachment] = GL_NONE; + } + mDrawBufferStates[0] = GL_COLOR_ATTACHMENT0_EXT; + mReadBufferState = GL_COLOR_ATTACHMENT0_EXT; + mDepthbufferType = GL_NONE; mStencilbufferType = GL_NONE; } Framebuffer::~Framebuffer() { - mColorbufferPointer.set(NULL); + for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) + { + mColorbufferPointers[colorAttachment].set(NULL); + } mDepthbufferPointer.set(NULL); mStencilbufferPointer.set(NULL); - mNullColorbufferPointer.set(NULL); } Renderbuffer *Framebuffer::lookupRenderbuffer(GLenum type, GLuint handle) const @@ -57,10 +70,11 @@ Renderbuffer *Framebuffer::lookupRenderbuffer(GLenum type, GLuint handle) const return buffer; } -void Framebuffer::setColorbuffer(GLenum type, GLuint colorbuffer) +void Framebuffer::setColorbuffer(unsigned int colorAttachment, GLenum type, GLuint colorbuffer) { - mColorbufferType = (colorbuffer != 0) ? type : GL_NONE; - mColorbufferPointer.set(lookupRenderbuffer(type, colorbuffer)); + ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS); + mColorbufferTypes[colorAttachment] = (colorbuffer != 0) ? type : GL_NONE; + mColorbufferPointers[colorAttachment].set(lookupRenderbuffer(type, colorbuffer)); } void Framebuffer::setDepthbuffer(GLenum type, GLuint depthbuffer) @@ -77,10 +91,13 @@ void Framebuffer::setStencilbuffer(GLenum type, GLuint stencilbuffer) void Framebuffer::detachTexture(GLuint texture) { - if (mColorbufferPointer.id() == texture && IsInternalTextureTarget(mColorbufferType)) + for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) { - mColorbufferType = GL_NONE; - mColorbufferPointer.set(NULL); + if (mColorbufferPointers[colorAttachment].id() == texture && IsInternalTextureTarget(mColorbufferTypes[colorAttachment])) + { + mColorbufferTypes[colorAttachment] = GL_NONE; + mColorbufferPointers[colorAttachment].set(NULL); + } } if (mDepthbufferPointer.id() == texture && IsInternalTextureTarget(mDepthbufferType)) @@ -98,10 +115,13 @@ void Framebuffer::detachTexture(GLuint texture) void Framebuffer::detachRenderbuffer(GLuint renderbuffer) { - if (mColorbufferPointer.id() == renderbuffer && mColorbufferType == GL_RENDERBUFFER) + for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) { - mColorbufferType = GL_NONE; - mColorbufferPointer.set(NULL); + if (mColorbufferPointers[colorAttachment].id() == renderbuffer && mColorbufferTypes[colorAttachment] == GL_RENDERBUFFER) + { + mColorbufferTypes[colorAttachment] = GL_NONE; + mColorbufferPointers[colorAttachment].set(NULL); + } } if (mDepthbufferPointer.id() == renderbuffer && mDepthbufferType == GL_RENDERBUFFER) @@ -117,9 +137,11 @@ void Framebuffer::detachRenderbuffer(GLuint renderbuffer) } } -unsigned int Framebuffer::getRenderTargetSerial() +unsigned int Framebuffer::getRenderTargetSerial(unsigned int colorAttachment) const { - Renderbuffer *colorbuffer = mColorbufferPointer.get(); + ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS); + + Renderbuffer *colorbuffer = mColorbufferPointers[colorAttachment].get(); if (colorbuffer) { @@ -129,40 +151,7 @@ unsigned int Framebuffer::getRenderTargetSerial() return 0; } -// Increments refcount on surface. -// caller must Release() the returned surface -IDirect3DSurface9 *Framebuffer::getRenderTarget() -{ - Renderbuffer *colorbuffer = mColorbufferPointer.get(); - - if (colorbuffer) - { - return colorbuffer->getRenderTarget(); - } - - return NULL; -} - -// Increments refcount on surface. -// caller must Release() the returned surface -IDirect3DSurface9 *Framebuffer::getDepthStencil() -{ - Renderbuffer *depthstencilbuffer = mDepthbufferPointer.get(); - - if (!depthstencilbuffer) - { - depthstencilbuffer = mStencilbufferPointer.get(); - } - - if (depthstencilbuffer) - { - return depthstencilbuffer->getDepthStencil(); - } - - return NULL; -} - -unsigned int Framebuffer::getDepthbufferSerial() +unsigned int Framebuffer::getDepthbufferSerial() const { Renderbuffer *depthbuffer = mDepthbufferPointer.get(); @@ -174,7 +163,7 @@ unsigned int Framebuffer::getDepthbufferSerial() return 0; } -unsigned int Framebuffer::getStencilbufferSerial() +unsigned int Framebuffer::getStencilbufferSerial() const { Renderbuffer *stencilbuffer = mStencilbufferPointer.get(); @@ -186,80 +175,124 @@ unsigned int Framebuffer::getStencilbufferSerial() return 0; } -Renderbuffer *Framebuffer::getColorbuffer() +Renderbuffer *Framebuffer::getColorbuffer(unsigned int colorAttachment) const { - return mColorbufferPointer.get(); + ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS); + return mColorbufferPointers[colorAttachment].get(); } -Renderbuffer *Framebuffer::getDepthbuffer() +Renderbuffer *Framebuffer::getDepthbuffer() const { return mDepthbufferPointer.get(); } -Renderbuffer *Framebuffer::getStencilbuffer() +Renderbuffer *Framebuffer::getStencilbuffer() const { return mStencilbufferPointer.get(); } -Renderbuffer *Framebuffer::getNullColorbuffer() +Renderbuffer *Framebuffer::getDepthOrStencilbuffer() const { - Renderbuffer *nullbuffer = mNullColorbufferPointer.get(); - Renderbuffer *depthbuffer = getDepthbuffer(); - - if (!depthbuffer) + Renderbuffer *depthstencilbuffer = mDepthbufferPointer.get(); + + if (!depthstencilbuffer) { - ERR("Unexpected null depthbuffer for depth-only FBO."); - return NULL; + depthstencilbuffer = mStencilbufferPointer.get(); } - GLsizei width = depthbuffer->getWidth(); - GLsizei height = depthbuffer->getHeight(); + return depthstencilbuffer; +} - if (!nullbuffer || - width != nullbuffer->getWidth() || height != nullbuffer->getHeight()) +Renderbuffer *Framebuffer::getReadColorbuffer() const +{ + // Will require more logic if glReadBuffers is supported + return mColorbufferPointers[0].get(); +} + +GLenum Framebuffer::getReadColorbufferType() const +{ + // Will require more logic if glReadBuffers is supported + return mColorbufferTypes[0]; +} + +Renderbuffer *Framebuffer::getFirstColorbuffer() const +{ + for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) { - nullbuffer = new Renderbuffer(0, new Colorbuffer(width, height, GL_NONE, 0)); - mNullColorbufferPointer.set(nullbuffer); + if (mColorbufferTypes[colorAttachment] != GL_NONE) + { + return mColorbufferPointers[colorAttachment].get(); + } } - return nullbuffer; + return NULL; } -GLenum Framebuffer::getColorbufferType() +GLenum Framebuffer::getColorbufferType(unsigned int colorAttachment) const { - return mColorbufferType; + ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS); + return mColorbufferTypes[colorAttachment]; } -GLenum Framebuffer::getDepthbufferType() +GLenum Framebuffer::getDepthbufferType() const { return mDepthbufferType; } -GLenum Framebuffer::getStencilbufferType() +GLenum Framebuffer::getStencilbufferType() const { return mStencilbufferType; } -GLuint Framebuffer::getColorbufferHandle() +GLuint Framebuffer::getColorbufferHandle(unsigned int colorAttachment) const { - return mColorbufferPointer.id(); + ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS); + return mColorbufferPointers[colorAttachment].id(); } -GLuint Framebuffer::getDepthbufferHandle() +GLuint Framebuffer::getDepthbufferHandle() const { return mDepthbufferPointer.id(); } -GLuint Framebuffer::getStencilbufferHandle() +GLuint Framebuffer::getStencilbufferHandle() const { return mStencilbufferPointer.id(); } -bool Framebuffer::hasStencil() +GLenum Framebuffer::getDrawBufferState(unsigned int colorAttachment) const +{ + return mDrawBufferStates[colorAttachment]; +} + +void Framebuffer::setDrawBufferState(unsigned int colorAttachment, GLenum drawBuffer) +{ + mDrawBufferStates[colorAttachment] = drawBuffer; +} + +bool Framebuffer::isEnabledColorAttachment(unsigned int colorAttachment) const +{ + return (mColorbufferTypes[colorAttachment] != GL_NONE && mDrawBufferStates[colorAttachment] != GL_NONE); +} + +bool Framebuffer::hasEnabledColorAttachment() const +{ + for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) + { + if (isEnabledColorAttachment(colorAttachment)) + { + return true; + } + } + + return false; +} + +bool Framebuffer::hasStencil() const { if (mStencilbufferType != GL_NONE) { - Renderbuffer *stencilbufferObject = getStencilbuffer(); + const Renderbuffer *stencilbufferObject = getStencilbuffer(); if (stencilbufferObject) { @@ -270,73 +303,112 @@ bool Framebuffer::hasStencil() return false; } -GLenum Framebuffer::completeness() +GLenum Framebuffer::completeness() const { - gl::Context *context = gl::getContext(); int width = 0; int height = 0; + int colorbufferSize = 0; int samples = -1; bool missingAttachment = true; - if (mColorbufferType != GL_NONE) + for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) { - Renderbuffer *colorbuffer = getColorbuffer(); - - if (!colorbuffer) + if (mColorbufferTypes[colorAttachment] != GL_NONE) { - return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; - } + const Renderbuffer *colorbuffer = getColorbuffer(colorAttachment); - if (colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0) - { - return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; - } - - if (mColorbufferType == GL_RENDERBUFFER) - { - if (!gl::IsColorRenderable(colorbuffer->getInternalFormat())) + if (!colorbuffer) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } - } - else if (IsInternalTextureTarget(mColorbufferType)) - { - GLint internalformat = colorbuffer->getInternalFormat(); - GLenum format = gl::ExtractFormat(internalformat); - if (IsCompressed(format) || - format == GL_ALPHA || - format == GL_LUMINANCE || - format == GL_LUMINANCE_ALPHA) + if (colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0) { - return GL_FRAMEBUFFER_UNSUPPORTED; + return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } - if ((gl::IsFloat32Format(internalformat) && !context->supportsFloat32RenderableTextures()) || - (gl::IsFloat16Format(internalformat) && !context->supportsFloat16RenderableTextures())) + if (mColorbufferTypes[colorAttachment] == GL_RENDERBUFFER) { - return GL_FRAMEBUFFER_UNSUPPORTED; + if (!gl::IsColorRenderable(colorbuffer->getInternalFormat())) + { + return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; + } } - - if (gl::IsDepthTexture(internalformat) || gl::IsStencilTexture(internalformat)) + else if (IsInternalTextureTarget(mColorbufferTypes[colorAttachment])) { + GLint internalformat = colorbuffer->getInternalFormat(); + GLenum format = gl::ExtractFormat(internalformat); + + if (IsCompressed(format) || + format == GL_ALPHA || + format == GL_LUMINANCE || + format == GL_LUMINANCE_ALPHA) + { + return GL_FRAMEBUFFER_UNSUPPORTED; + } + + bool filtering, renderable; + + if ((gl::IsFloat32Format(internalformat) && !mRenderer->getFloat32TextureSupport(&filtering, &renderable)) || + (gl::IsFloat16Format(internalformat) && !mRenderer->getFloat16TextureSupport(&filtering, &renderable))) + { + return GL_FRAMEBUFFER_UNSUPPORTED; + } + + if (gl::IsDepthTexture(internalformat) || gl::IsStencilTexture(internalformat)) + { + return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; + } + } + else + { + UNREACHABLE(); return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } - } - else - { - UNREACHABLE(); - return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; - } - width = colorbuffer->getWidth(); - height = colorbuffer->getHeight(); - samples = colorbuffer->getSamples(); - missingAttachment = false; + if (!missingAttachment) + { + // all color attachments must have the same width and height + if (colorbuffer->getWidth() != width || colorbuffer->getHeight() != height) + { + return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS; + } + + // APPLE_framebuffer_multisample, which EXT_draw_buffers refers to, requires that + // all color attachments have the same number of samples for the FBO to be complete. + if (colorbuffer->getSamples() != samples) + { + return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT; + } + + // all color attachments attachments must have the same number of bitplanes + if (gl::ComputePixelSize(colorbuffer->getInternalFormat()) != colorbufferSize) + { + return GL_FRAMEBUFFER_UNSUPPORTED; + } + + // D3D11 does not allow for overlapping RenderTargetViews, so ensure uniqueness + for (unsigned int previousColorAttachment = 0; previousColorAttachment < colorAttachment; previousColorAttachment++) + { + if (mColorbufferPointers[colorAttachment].get() == mColorbufferPointers[previousColorAttachment].get()) + { + return GL_FRAMEBUFFER_UNSUPPORTED; + } + } + } + else + { + width = colorbuffer->getWidth(); + height = colorbuffer->getHeight(); + samples = colorbuffer->getSamples(); + colorbufferSize = gl::ComputePixelSize(colorbuffer->getInternalFormat()); + missingAttachment = false; + } + } } - Renderbuffer *depthbuffer = NULL; - Renderbuffer *stencilbuffer = NULL; + const Renderbuffer *depthbuffer = NULL; + const Renderbuffer *stencilbuffer = NULL; if (mDepthbufferType != GL_NONE) { @@ -364,7 +436,7 @@ GLenum Framebuffer::completeness() GLint internalformat = depthbuffer->getInternalFormat(); // depth texture attachments require OES/ANGLE_depth_texture - if (!context->supportsDepthTextures()) + if (!mRenderer->getDepthTextureSupport()) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } @@ -424,7 +496,7 @@ GLenum Framebuffer::completeness() // texture stencil attachments come along as part // of OES_packed_depth_stencil + OES/ANGLE_depth_texture - if (!context->supportsDepthTextures()) + if (!mRenderer->getDepthTextureSupport()) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } @@ -473,36 +545,45 @@ GLenum Framebuffer::completeness() return GL_FRAMEBUFFER_COMPLETE; } -DefaultFramebuffer::DefaultFramebuffer(Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil) +DefaultFramebuffer::DefaultFramebuffer(rx::Renderer *renderer, Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil) + : Framebuffer(renderer) { - mColorbufferPointer.set(new Renderbuffer(0, colorbuffer)); + mColorbufferPointers[0].set(new Renderbuffer(mRenderer, 0, colorbuffer)); - Renderbuffer *depthStencilRenderbuffer = new Renderbuffer(0, depthStencil); + Renderbuffer *depthStencilRenderbuffer = new Renderbuffer(mRenderer, 0, depthStencil); mDepthbufferPointer.set(depthStencilRenderbuffer); mStencilbufferPointer.set(depthStencilRenderbuffer); - mColorbufferType = GL_RENDERBUFFER; + mColorbufferTypes[0] = GL_RENDERBUFFER; mDepthbufferType = (depthStencilRenderbuffer->getDepthSize() != 0) ? GL_RENDERBUFFER : GL_NONE; mStencilbufferType = (depthStencilRenderbuffer->getStencilSize() != 0) ? GL_RENDERBUFFER : GL_NONE; + + mDrawBufferStates[0] = GL_BACK; + mReadBufferState = GL_BACK; } -int Framebuffer::getSamples() +int Framebuffer::getSamples() const { if (completeness() == GL_FRAMEBUFFER_COMPLETE) { - return getColorbuffer()->getSamples(); - } - else - { - return 0; + // for a complete framebuffer, all attachments must have the same sample count + // in this case return the first nonzero sample size + for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) + { + if (mColorbufferTypes[colorAttachment] != GL_NONE) + { + return getColorbuffer(colorAttachment)->getSamples(); + } + } } + + return 0; } -GLenum DefaultFramebuffer::completeness() +GLenum DefaultFramebuffer::completeness() const { - // The default framebuffer should always be complete - ASSERT(Framebuffer::completeness() == GL_FRAMEBUFFER_COMPLETE); - + // The default framebuffer *must* always be complete, though it may not be + // subject to the same rules as application FBOs. ie, it could have 0x0 size. return GL_FRAMEBUFFER_COMPLETE; } diff --git a/src/3rdparty/angle/src/libGLESv2/Framebuffer.h b/src/3rdparty/angle/src/libGLESv2/Framebuffer.h index 14d9c2a74c..66acdc4c37 100644 --- a/src/3rdparty/angle/src/libGLESv2/Framebuffer.h +++ b/src/3rdparty/angle/src/libGLESv2/Framebuffer.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// 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. // @@ -10,12 +10,14 @@ #ifndef LIBGLESV2_FRAMEBUFFER_H_ #define LIBGLESV2_FRAMEBUFFER_H_ -#define GL_APICALL -#include -#include - #include "common/angleutils.h" #include "common/RefCountObject.h" +#include "constants.h" + +namespace rx +{ +class Renderer; +} namespace gl { @@ -28,45 +30,52 @@ class DepthStencilbuffer; class Framebuffer { public: - Framebuffer(); + explicit Framebuffer(rx::Renderer *renderer); virtual ~Framebuffer(); - void setColorbuffer(GLenum type, GLuint colorbuffer); + void setColorbuffer(unsigned int colorAttachment, GLenum type, GLuint colorbuffer); void setDepthbuffer(GLenum type, GLuint depthbuffer); void setStencilbuffer(GLenum type, GLuint stencilbuffer); void detachTexture(GLuint texture); void detachRenderbuffer(GLuint renderbuffer); - IDirect3DSurface9 *getRenderTarget(); - IDirect3DSurface9 *getDepthStencil(); + unsigned int getRenderTargetSerial(unsigned int colorAttachment) const; + unsigned int getDepthbufferSerial() const; + unsigned int getStencilbufferSerial() const; - unsigned int getRenderTargetSerial(); - unsigned int getDepthbufferSerial(); - unsigned int getStencilbufferSerial(); + Renderbuffer *getColorbuffer(unsigned int colorAttachment) const; + Renderbuffer *getDepthbuffer() const; + Renderbuffer *getStencilbuffer() const; + Renderbuffer *getDepthOrStencilbuffer() const; + Renderbuffer *getReadColorbuffer() const; + GLenum getReadColorbufferType() const; + Renderbuffer *getFirstColorbuffer() const; - Renderbuffer *getColorbuffer(); - Renderbuffer *getDepthbuffer(); - Renderbuffer *getStencilbuffer(); - Renderbuffer *getNullColorbuffer(); + GLenum getColorbufferType(unsigned int colorAttachment) const; + GLenum getDepthbufferType() const; + GLenum getStencilbufferType() const; - GLenum getColorbufferType(); - GLenum getDepthbufferType(); - GLenum getStencilbufferType(); + GLuint getColorbufferHandle(unsigned int colorAttachment) const; + GLuint getDepthbufferHandle() const; + GLuint getStencilbufferHandle() const; - GLuint getColorbufferHandle(); - GLuint getDepthbufferHandle(); - GLuint getStencilbufferHandle(); + GLenum getDrawBufferState(unsigned int colorAttachment) const; + void setDrawBufferState(unsigned int colorAttachment, GLenum drawBuffer); - bool hasStencil(); - int getSamples(); + bool isEnabledColorAttachment(unsigned int colorAttachment) const; + bool hasEnabledColorAttachment() const; + bool hasStencil() const; + int getSamples() const; - virtual GLenum completeness(); + virtual GLenum completeness() const; protected: - GLenum mColorbufferType; - BindingPointer mColorbufferPointer; + GLenum mColorbufferTypes[IMPLEMENTATION_MAX_DRAW_BUFFERS]; + BindingPointer mColorbufferPointers[IMPLEMENTATION_MAX_DRAW_BUFFERS]; + GLenum mDrawBufferStates[IMPLEMENTATION_MAX_DRAW_BUFFERS]; + GLenum mReadBufferState; GLenum mDepthbufferType; BindingPointer mDepthbufferPointer; @@ -74,7 +83,7 @@ class Framebuffer GLenum mStencilbufferType; BindingPointer mStencilbufferPointer; - BindingPointer mNullColorbufferPointer; + rx::Renderer *mRenderer; private: DISALLOW_COPY_AND_ASSIGN(Framebuffer); @@ -85,9 +94,9 @@ class Framebuffer class DefaultFramebuffer : public Framebuffer { public: - DefaultFramebuffer(Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil); + DefaultFramebuffer(rx::Renderer *Renderer, Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil); - virtual GLenum completeness(); + virtual GLenum completeness() const; private: DISALLOW_COPY_AND_ASSIGN(DefaultFramebuffer); diff --git a/src/3rdparty/angle/src/libGLESv2/HandleAllocator.cpp b/src/3rdparty/angle/src/libGLESv2/HandleAllocator.cpp index c498f8a178..37da99aa18 100644 --- a/src/3rdparty/angle/src/libGLESv2/HandleAllocator.cpp +++ b/src/3rdparty/angle/src/libGLESv2/HandleAllocator.cpp @@ -1,3 +1,4 @@ +#include "precompiled.h" // // 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 diff --git a/src/3rdparty/angle/src/libGLESv2/IndexDataManager.cpp b/src/3rdparty/angle/src/libGLESv2/IndexDataManager.cpp deleted file mode 100644 index 3dc0aef3f1..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/IndexDataManager.cpp +++ /dev/null @@ -1,473 +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. -// - -// IndexDataManager.cpp: Defines the IndexDataManager, a class that -// runs the Buffer translation process for index buffers. - -#include "libGLESv2/IndexDataManager.h" - -#include "common/debug.h" - -#include "libGLESv2/Buffer.h" -#include "libGLESv2/mathutil.h" -#include "libGLESv2/main.h" - -namespace gl -{ -unsigned int IndexBuffer::mCurrentSerial = 1; - -IndexDataManager::IndexDataManager(Context *context, IDirect3DDevice9 *device) : mDevice(device) -{ - mStreamingBufferShort = new StreamingIndexBuffer(mDevice, INITIAL_INDEX_BUFFER_SIZE, D3DFMT_INDEX16); - - if (context->supports32bitIndices()) - { - mStreamingBufferInt = new StreamingIndexBuffer(mDevice, INITIAL_INDEX_BUFFER_SIZE, D3DFMT_INDEX32); - - if (!mStreamingBufferInt) - { - // Don't leave it in a half-initialized state - delete mStreamingBufferShort; - mStreamingBufferShort = NULL; - } - } - else - { - mStreamingBufferInt = NULL; - } - - if (!mStreamingBufferShort) - { - ERR("Failed to allocate the streaming index buffer(s)."); - } - - mCountingBuffer = NULL; -} - -IndexDataManager::~IndexDataManager() -{ - delete mStreamingBufferShort; - delete mStreamingBufferInt; - delete mCountingBuffer; -} - -void convertIndices(GLenum type, const void *input, GLsizei count, void *output) -{ - if (type == GL_UNSIGNED_BYTE) - { - const GLubyte *in = static_cast(input); - GLushort *out = static_cast(output); - - for (GLsizei i = 0; i < count; i++) - { - out[i] = in[i]; - } - } - else if (type == GL_UNSIGNED_INT) - { - memcpy(output, input, count * sizeof(GLuint)); - } - else if (type == GL_UNSIGNED_SHORT) - { - memcpy(output, input, count * sizeof(GLushort)); - } - else UNREACHABLE(); -} - -template -void computeRange(const IndexType *indices, GLsizei count, GLuint *minIndex, GLuint *maxIndex) -{ - *minIndex = indices[0]; - *maxIndex = indices[0]; - - for (GLsizei i = 0; i < count; i++) - { - if (*minIndex > indices[i]) *minIndex = indices[i]; - if (*maxIndex < indices[i]) *maxIndex = indices[i]; - } -} - -void computeRange(GLenum type, const GLvoid *indices, GLsizei count, GLuint *minIndex, GLuint *maxIndex) -{ - if (type == GL_UNSIGNED_BYTE) - { - computeRange(static_cast(indices), count, minIndex, maxIndex); - } - else if (type == GL_UNSIGNED_INT) - { - computeRange(static_cast(indices), count, minIndex, maxIndex); - } - else if (type == GL_UNSIGNED_SHORT) - { - computeRange(static_cast(indices), count, minIndex, maxIndex); - } - else UNREACHABLE(); -} - -GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, Buffer *buffer, const GLvoid *indices, TranslatedIndexData *translated) -{ - if (!mStreamingBufferShort) - { - return GL_OUT_OF_MEMORY; - } - - D3DFORMAT format = (type == GL_UNSIGNED_INT) ? D3DFMT_INDEX32 : D3DFMT_INDEX16; - intptr_t offset = reinterpret_cast(indices); - bool alignedOffset = false; - - if (buffer != NULL) - { - switch (type) - { - case GL_UNSIGNED_BYTE: alignedOffset = (offset % sizeof(GLubyte) == 0); break; - case GL_UNSIGNED_SHORT: alignedOffset = (offset % sizeof(GLushort) == 0); break; - case GL_UNSIGNED_INT: alignedOffset = (offset % sizeof(GLuint) == 0); break; - default: UNREACHABLE(); alignedOffset = false; - } - - if (typeSize(type) * count + offset > static_cast(buffer->size())) - { - return GL_INVALID_OPERATION; - } - - indices = static_cast(buffer->data()) + offset; - } - - StreamingIndexBuffer *streamingBuffer = (type == GL_UNSIGNED_INT) ? mStreamingBufferInt : mStreamingBufferShort; - - StaticIndexBuffer *staticBuffer = buffer ? buffer->getStaticIndexBuffer() : NULL; - IndexBuffer *indexBuffer = streamingBuffer; - UINT streamOffset = 0; - - if (staticBuffer && staticBuffer->lookupType(type) && alignedOffset) - { - indexBuffer = staticBuffer; - streamOffset = staticBuffer->lookupRange(offset, count, &translated->minIndex, &translated->maxIndex); - - if (streamOffset == -1) - { - streamOffset = (offset / typeSize(type)) * indexSize(format); - computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex); - staticBuffer->addRange(offset, count, translated->minIndex, translated->maxIndex, streamOffset); - } - } - else - { - int convertCount = count; - - if (staticBuffer) - { - if (staticBuffer->size() == 0 && alignedOffset) - { - indexBuffer = staticBuffer; - convertCount = buffer->size() / typeSize(type); - } - else - { - buffer->invalidateStaticData(); - staticBuffer = NULL; - } - } - - void *output = NULL; - - if (indexBuffer) - { - indexBuffer->reserveSpace(convertCount * indexSize(format), type); - output = indexBuffer->map(indexSize(format) * convertCount, &streamOffset); - } - - if (output == NULL) - { - ERR("Failed to map index buffer."); - return GL_OUT_OF_MEMORY; - } - - convertIndices(type, staticBuffer ? buffer->data() : indices, convertCount, output); - indexBuffer->unmap(); - - computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex); - - if (staticBuffer) - { - streamOffset = (offset / typeSize(type)) * indexSize(format); - staticBuffer->addRange(offset, count, translated->minIndex, translated->maxIndex, streamOffset); - } - } - - translated->indexBuffer = indexBuffer->getBuffer(); - translated->serial = indexBuffer->getSerial(); - translated->startIndex = streamOffset / indexSize(format); - - if (buffer) - { - buffer->promoteStaticUsage(count * typeSize(type)); - } - - return GL_NO_ERROR; -} - -std::size_t IndexDataManager::indexSize(D3DFORMAT format) const -{ - return (format == D3DFMT_INDEX32) ? sizeof(unsigned int) : sizeof(unsigned short); -} - -std::size_t IndexDataManager::typeSize(GLenum type) const -{ - switch (type) - { - case GL_UNSIGNED_INT: return sizeof(GLuint); - case GL_UNSIGNED_SHORT: return sizeof(GLushort); - case GL_UNSIGNED_BYTE: return sizeof(GLubyte); - default: UNREACHABLE(); return sizeof(GLushort); - } -} - -StaticIndexBuffer *IndexDataManager::getCountingIndices(GLsizei count) -{ - if (count <= 65536) // 16-bit indices - { - const unsigned int spaceNeeded = count * sizeof(unsigned short); - - if (!mCountingBuffer || mCountingBuffer->size() < spaceNeeded) - { - delete mCountingBuffer; - mCountingBuffer = new StaticIndexBuffer(mDevice); - mCountingBuffer->reserveSpace(spaceNeeded, GL_UNSIGNED_SHORT); - - UINT offset; - unsigned short *data = static_cast(mCountingBuffer->map(spaceNeeded, &offset)); - - if (data) - { - for(int i = 0; i < count; i++) - { - data[i] = i; - } - - mCountingBuffer->unmap(); - } - } - } - else if (mStreamingBufferInt) // 32-bit indices supported - { - const unsigned int spaceNeeded = count * sizeof(unsigned int); - - if (!mCountingBuffer || mCountingBuffer->size() < spaceNeeded) - { - delete mCountingBuffer; - mCountingBuffer = new StaticIndexBuffer(mDevice); - mCountingBuffer->reserveSpace(spaceNeeded, GL_UNSIGNED_INT); - - UINT offset; - unsigned int *data = static_cast(mCountingBuffer->map(spaceNeeded, &offset)); - - if (data) - { - for(int i = 0; i < count; i++) - { - data[i] = i; - } - - mCountingBuffer->unmap(); - } - } - } - else return NULL; - - return mCountingBuffer; -} - -IndexBuffer::IndexBuffer(IDirect3DDevice9 *device, UINT size, D3DFORMAT format) : mDevice(device), mBufferSize(size), mIndexBuffer(NULL) -{ - if (size > 0) - { - D3DPOOL pool = getDisplay()->getBufferPool(D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY); - HRESULT result = device->CreateIndexBuffer(size, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, format, pool, &mIndexBuffer, NULL); - mSerial = issueSerial(); - - if (FAILED(result)) - { - ERR("Out of memory allocating an index buffer of size %lu.", size); - } - } -} - -IndexBuffer::~IndexBuffer() -{ - if (mIndexBuffer) - { - mIndexBuffer->Release(); - } -} - -IDirect3DIndexBuffer9 *IndexBuffer::getBuffer() const -{ - return mIndexBuffer; -} - -unsigned int IndexBuffer::getSerial() const -{ - return mSerial; -} - -unsigned int IndexBuffer::issueSerial() -{ - return mCurrentSerial++; -} - -void IndexBuffer::unmap() -{ - if (mIndexBuffer) - { - mIndexBuffer->Unlock(); - } -} - -StreamingIndexBuffer::StreamingIndexBuffer(IDirect3DDevice9 *device, UINT initialSize, D3DFORMAT format) : IndexBuffer(device, initialSize, format) -{ - mWritePosition = 0; -} - -StreamingIndexBuffer::~StreamingIndexBuffer() -{ -} - -void *StreamingIndexBuffer::map(UINT requiredSpace, UINT *offset) -{ - void *mapPtr = NULL; - - if (mIndexBuffer) - { - HRESULT result = mIndexBuffer->Lock(mWritePosition, requiredSpace, &mapPtr, D3DLOCK_NOOVERWRITE); - - if (FAILED(result)) - { - ERR(" Lock failed with error 0x%08x", result); - return NULL; - } - - *offset = mWritePosition; - mWritePosition += requiredSpace; - } - - return mapPtr; -} - -void StreamingIndexBuffer::reserveSpace(UINT requiredSpace, GLenum type) -{ - if (requiredSpace > mBufferSize) - { - if (mIndexBuffer) - { - mIndexBuffer->Release(); - mIndexBuffer = NULL; - } - - mBufferSize = std::max(requiredSpace, 2 * mBufferSize); - - D3DPOOL pool = getDisplay()->getBufferPool(D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY); - HRESULT result = mDevice->CreateIndexBuffer(mBufferSize, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, type == GL_UNSIGNED_INT ? D3DFMT_INDEX32 : D3DFMT_INDEX16, pool, &mIndexBuffer, NULL); - mSerial = issueSerial(); - - if (FAILED(result)) - { - ERR("Out of memory allocating a vertex buffer of size %lu.", mBufferSize); - } - - mWritePosition = 0; - } - else if (mWritePosition + requiredSpace > mBufferSize) // Recycle - { - void *dummy; - mIndexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD); - mIndexBuffer->Unlock(); - - mWritePosition = 0; - } -} - -StaticIndexBuffer::StaticIndexBuffer(IDirect3DDevice9 *device) : IndexBuffer(device, 0, D3DFMT_UNKNOWN) -{ - mCacheType = GL_NONE; -} - -StaticIndexBuffer::~StaticIndexBuffer() -{ -} - -void *StaticIndexBuffer::map(UINT requiredSpace, UINT *offset) -{ - void *mapPtr = NULL; - - if (mIndexBuffer) - { - HRESULT result = mIndexBuffer->Lock(0, requiredSpace, &mapPtr, 0); - - if (FAILED(result)) - { - ERR(" Lock failed with error 0x%08x", result); - return NULL; - } - - *offset = 0; - } - - return mapPtr; -} - -void StaticIndexBuffer::reserveSpace(UINT requiredSpace, GLenum type) -{ - if (!mIndexBuffer && mBufferSize == 0) - { - D3DPOOL pool = getDisplay()->getBufferPool(D3DUSAGE_WRITEONLY); - HRESULT result = mDevice->CreateIndexBuffer(requiredSpace, D3DUSAGE_WRITEONLY, type == GL_UNSIGNED_INT ? D3DFMT_INDEX32 : D3DFMT_INDEX16, pool, &mIndexBuffer, NULL); - mSerial = issueSerial(); - - if (FAILED(result)) - { - ERR("Out of memory allocating a vertex buffer of size %lu.", mBufferSize); - } - - mBufferSize = requiredSpace; - mCacheType = type; - } - else if (mIndexBuffer && mBufferSize >= requiredSpace && mCacheType == type) - { - // Already allocated - } - else UNREACHABLE(); // Static index buffers can't be resized -} - -bool StaticIndexBuffer::lookupType(GLenum type) -{ - return mCacheType == type; -} - -UINT StaticIndexBuffer::lookupRange(intptr_t offset, GLsizei count, UINT *minIndex, UINT *maxIndex) -{ - IndexRange range = {offset, count}; - - std::map::iterator res = mCache.find(range); - - if (res == mCache.end()) - { - return -1; - } - - *minIndex = res->second.minIndex; - *maxIndex = res->second.maxIndex; - return res->second.streamOffset; -} - -void StaticIndexBuffer::addRange(intptr_t offset, GLsizei count, UINT minIndex, UINT maxIndex, UINT streamOffset) -{ - IndexRange indexRange = {offset, count}; - IndexResult indexResult = {minIndex, maxIndex, streamOffset}; - mCache[indexRange] = indexResult; -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/IndexDataManager.h b/src/3rdparty/angle/src/libGLESv2/IndexDataManager.h deleted file mode 100644 index c1d4168315..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/IndexDataManager.h +++ /dev/null @@ -1,149 +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. -// - -// IndexDataManager.h: Defines the IndexDataManager, a class that -// runs the Buffer translation process for index buffers. - -#ifndef LIBGLESV2_INDEXDATAMANAGER_H_ -#define LIBGLESV2_INDEXDATAMANAGER_H_ - -#include -#include - -#define GL_APICALL -#include - -#include "libGLESv2/Context.h" - -namespace -{ - enum { INITIAL_INDEX_BUFFER_SIZE = 4096 * sizeof(GLuint) }; -} - -namespace gl -{ - -struct TranslatedIndexData -{ - UINT minIndex; - UINT maxIndex; - UINT startIndex; - - IDirect3DIndexBuffer9 *indexBuffer; - unsigned int serial; -}; - -class IndexBuffer -{ - public: - IndexBuffer(IDirect3DDevice9 *device, UINT size, D3DFORMAT format); - virtual ~IndexBuffer(); - - UINT size() const { return mBufferSize; } - virtual void *map(UINT requiredSpace, UINT *offset) = 0; - void unmap(); - virtual void reserveSpace(UINT requiredSpace, GLenum type) = 0; - - IDirect3DIndexBuffer9 *getBuffer() const; - unsigned int getSerial() const; - - protected: - IDirect3DDevice9 *const mDevice; - - IDirect3DIndexBuffer9 *mIndexBuffer; - UINT mBufferSize; - - unsigned int mSerial; - static unsigned int issueSerial(); - static unsigned int mCurrentSerial; - - private: - DISALLOW_COPY_AND_ASSIGN(IndexBuffer); -}; - -class StreamingIndexBuffer : public IndexBuffer -{ - public: - StreamingIndexBuffer(IDirect3DDevice9 *device, UINT initialSize, D3DFORMAT format); - ~StreamingIndexBuffer(); - - virtual void *map(UINT requiredSpace, UINT *offset); - virtual void reserveSpace(UINT requiredSpace, GLenum type); - - private: - UINT mWritePosition; -}; - -class StaticIndexBuffer : public IndexBuffer -{ - public: - explicit StaticIndexBuffer(IDirect3DDevice9 *device); - ~StaticIndexBuffer(); - - virtual void *map(UINT requiredSpace, UINT *offset); - virtual void reserveSpace(UINT requiredSpace, GLenum type); - - bool lookupType(GLenum type); - UINT lookupRange(intptr_t offset, GLsizei count, UINT *minIndex, UINT *maxIndex); // Returns the offset into the index buffer, or -1 if not found - void addRange(intptr_t offset, GLsizei count, UINT minIndex, UINT maxIndex, UINT streamOffset); - - private: - GLenum mCacheType; - - struct IndexRange - { - intptr_t offset; - GLsizei count; - - bool operator<(const IndexRange& rhs) const - { - if (offset != rhs.offset) - { - return offset < rhs.offset; - } - if (count != rhs.count) - { - return count < rhs.count; - } - return false; - } - }; - - struct IndexResult - { - UINT minIndex; - UINT maxIndex; - UINT streamOffset; - }; - - std::map mCache; -}; - -class IndexDataManager -{ - public: - IndexDataManager(Context *context, IDirect3DDevice9 *evice); - virtual ~IndexDataManager(); - - GLenum prepareIndexData(GLenum type, GLsizei count, Buffer *arrayElementBuffer, const GLvoid *indices, TranslatedIndexData *translated); - StaticIndexBuffer *getCountingIndices(GLsizei count); - - private: - DISALLOW_COPY_AND_ASSIGN(IndexDataManager); - - std::size_t typeSize(GLenum type) const; - std::size_t indexSize(D3DFORMAT format) const; - - IDirect3DDevice9 *const mDevice; - - StreamingIndexBuffer *mStreamingBufferShort; - StreamingIndexBuffer *mStreamingBufferInt; - StaticIndexBuffer *mCountingBuffer; -}; - -} - -#endif // LIBGLESV2_INDEXDATAMANAGER_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/Program.cpp b/src/3rdparty/angle/src/libGLESv2/Program.cpp index 5f53a1f581..c38aa5a61a 100644 --- a/src/3rdparty/angle/src/libGLESv2/Program.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Program.cpp @@ -1,5 +1,6 @@ +#include "precompiled.h" // -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// 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. // @@ -9,14 +10,7 @@ #include "libGLESv2/Program.h" #include "libGLESv2/ProgramBinary.h" - -#include "common/debug.h" - -#include "libGLESv2/main.h" -#include "libGLESv2/Shader.h" -#include "libGLESv2/utilities.h" - -#include +#include "libGLESv2/ResourceManager.h" namespace gl { @@ -91,7 +85,7 @@ void InfoLog::appendSanitized(const char *message) } while (found != std::string::npos); - append("%s\n", msg.c_str()); + append("%s", msg.c_str()); } void InfoLog::append(const char *format, ...) @@ -112,15 +106,17 @@ void InfoLog::append(const char *format, ...) if (!mInfoLog) { - mInfoLog = new char[infoLength + 1]; + mInfoLog = new char[infoLength + 2]; strcpy(mInfoLog, info); + strcpy(mInfoLog + infoLength, "\n"); } else { size_t logLength = strlen(mInfoLog); - char *newLog = new char[logLength + infoLength + 1]; + char *newLog = new char[logLength + infoLength + 2]; strcpy(newLog, mInfoLog); strcpy(newLog + logLength, info); + strcpy(newLog + logLength + infoLength, "\n"); delete[] mInfoLog; mInfoLog = newLog; @@ -136,7 +132,7 @@ void InfoLog::reset() } } -Program::Program(ResourceManager *manager, GLuint handle) : mResourceManager(manager), mHandle(handle) +Program::Program(rx::Renderer *renderer, ResourceManager *manager, GLuint handle) : mResourceManager(manager), mHandle(handle) { mFragmentShader = NULL; mVertexShader = NULL; @@ -144,6 +140,7 @@ Program::Program(ResourceManager *manager, GLuint handle) : mResourceManager(man mDeleteStatus = false; mLinked = false; mRefCount = 0; + mRenderer = renderer; } Program::~Program() @@ -247,7 +244,7 @@ bool Program::link() mInfoLog.reset(); - mProgramBinary.set(new ProgramBinary()); + mProgramBinary.set(new ProgramBinary(mRenderer)); mLinked = mProgramBinary->link(mInfoLog, mAttributeBindings, mFragmentShader, mVertexShader); return mLinked; @@ -304,7 +301,7 @@ bool Program::setProgramBinary(const void *binary, GLsizei length) mInfoLog.reset(); - mProgramBinary.set(new ProgramBinary()); + mProgramBinary.set(new ProgramBinary(mRenderer)); mLinked = mProgramBinary->load(mInfoLog, binary, length); if (!mLinked) { diff --git a/src/3rdparty/angle/src/libGLESv2/Program.h b/src/3rdparty/angle/src/libGLESv2/Program.h index 1c4716bfe8..a9db83403d 100644 --- a/src/3rdparty/angle/src/libGLESv2/Program.h +++ b/src/3rdparty/angle/src/libGLESv2/Program.h @@ -13,14 +13,22 @@ #include #include -#include "libGLESv2/Shader.h" -#include "libGLESv2/Context.h" +#include "common/angleutils.h" +#include "common/RefCountObject.h" +#include "libGLESv2/Constants.h" + +namespace rx +{ +class Renderer; +} namespace gl { class ResourceManager; class FragmentShader; class VertexShader; +class ProgramBinary; +class Shader; extern const char * const g_fakepath; @@ -57,7 +65,7 @@ class InfoLog class Program { public: - Program(ResourceManager *manager, GLuint handle); + Program(rx::Renderer *renderer, ResourceManager *manager, GLuint handle); ~Program(); @@ -112,6 +120,7 @@ class Program unsigned int mRefCount; ResourceManager *mResourceManager; + rx::Renderer *mRenderer; const GLuint mHandle; InfoLog mInfoLog; diff --git a/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp b/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp index b3f5e3b867..14e6c94ca4 100644 --- a/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp +++ b/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp @@ -1,5 +1,6 @@ +#include "precompiled.h" // -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// 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. // @@ -8,21 +9,21 @@ // and related functionality. [OpenGL ES 2.0.24] section 2.10.3 page 28. #include "libGLESv2/BinaryStream.h" -#include "libGLESv2/Program.h" #include "libGLESv2/ProgramBinary.h" +#include "libGLESv2/renderer/ShaderExecutable.h" #include "common/debug.h" #include "common/version.h" +#include "utilities.h" #include "libGLESv2/main.h" #include "libGLESv2/Shader.h" -#include "libGLESv2/utilities.h" - -#include +#include "libGLESv2/Program.h" +#include "libGLESv2/renderer/Renderer.h" +#include "libGLESv2/renderer/VertexDataManager.h" -#if !defined(ANGLE_COMPILE_OPTIMIZATION_LEVEL) -#define ANGLE_COMPILE_OPTIMIZATION_LEVEL D3DCOMPILE_OPTIMIZATION_LEVEL3 -#endif +#undef near +#undef far namespace gl { @@ -33,43 +34,18 @@ std::string str(int i) return buffer; } -Uniform::Uniform(GLenum type, const std::string &_name, unsigned int arraySize) - : type(type), _name(_name), name(ProgramBinary::undecorateUniform(_name)), arraySize(arraySize) -{ - int bytes = UniformInternalSize(type) * arraySize; - data = new unsigned char[bytes]; - memset(data, 0, bytes); - dirty = true; -} - -Uniform::~Uniform() -{ - delete[] data; -} - -bool Uniform::isArray() -{ - size_t dot = _name.find_last_of('.'); - if (dot == std::string::npos) dot = -1; - - return _name.compare(dot + 1, dot + 4, "ar_") == 0; -} - -UniformLocation::UniformLocation(const std::string &_name, unsigned int element, unsigned int index) - : name(ProgramBinary::undecorateUniform(_name)), element(element), index(index) +UniformLocation::UniformLocation(const std::string &name, unsigned int element, unsigned int index) + : name(name), element(element), index(index) { } unsigned int ProgramBinary::mCurrentSerial = 1; -ProgramBinary::ProgramBinary() : RefCountObject(0), mSerial(issueSerial()) +ProgramBinary::ProgramBinary(rx::Renderer *renderer) : mRenderer(renderer), RefCountObject(0), mSerial(issueSerial()) { - mDevice = getDevice(); - mPixelExecutable = NULL; mVertexExecutable = NULL; - mConstantTablePS = NULL; - mConstantTableVS = NULL; + mGeometryExecutable = NULL; mValidated = false; @@ -83,36 +59,26 @@ ProgramBinary::ProgramBinary() : RefCountObject(0), mSerial(issueSerial()) mSamplersPS[index].active = false; } - for (int index = 0; index < MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF; index++) + for (int index = 0; index < IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; index++) { mSamplersVS[index].active = false; } mUsedVertexSamplerRange = 0; mUsedPixelSamplerRange = 0; - - mDxDepthRangeLocation = -1; - mDxDepthLocation = -1; - mDxCoordLocation = -1; - mDxHalfPixelSizeLocation = -1; - mDxFrontCCWLocation = -1; - mDxPointsOrLinesLocation = -1; + mUsesPointSize = false; } ProgramBinary::~ProgramBinary() { - if (mPixelExecutable) - { - mPixelExecutable->Release(); - } + delete mPixelExecutable; + mPixelExecutable = NULL; - if (mVertexExecutable) - { - mVertexExecutable->Release(); - } + delete mVertexExecutable; + mVertexExecutable = NULL; - delete mConstantTablePS; - delete mConstantTableVS; + delete mGeometryExecutable; + mGeometryExecutable = NULL; while (!mUniforms.empty()) { @@ -131,16 +97,21 @@ unsigned int ProgramBinary::issueSerial() return mCurrentSerial++; } -IDirect3DPixelShader9 *ProgramBinary::getPixelShader() +rx::ShaderExecutable *ProgramBinary::getPixelExecutable() { return mPixelExecutable; } -IDirect3DVertexShader9 *ProgramBinary::getVertexShader() +rx::ShaderExecutable *ProgramBinary::getVertexExecutable() { return mVertexExecutable; } +rx::ShaderExecutable *ProgramBinary::getGeometryExecutable() +{ + return mGeometryExecutable; +} + GLuint ProgramBinary::getAttributeLocation(const char *name) { if (name) @@ -184,6 +155,16 @@ bool ProgramBinary::usesPointSize() const return mUsesPointSize; } +bool ProgramBinary::usesPointSpriteEmulation() const +{ + return mUsesPointSize && mRenderer->getMajorShaderModel() >= 4; +} + +bool ProgramBinary::usesGeometryShader() const +{ + return usesPointSpriteEmulation(); +} + // Returns the index of the texture image unit (0-19) corresponding to a Direct3D 9 sampler // index (0-15 for the pixel shader and 0-3 for the vertex shader). GLint ProgramBinary::getSamplerMapping(SamplerType type, unsigned int samplerIndex) @@ -211,7 +192,7 @@ GLint ProgramBinary::getSamplerMapping(SamplerType type, unsigned int samplerInd default: UNREACHABLE(); } - if (logicalTextureUnit >= 0 && logicalTextureUnit < (GLint)getContext()->getMaximumCombinedTextureImageUnits()) + if (logicalTextureUnit >= 0 && logicalTextureUnit < (GLint)mRenderer->getMaxCombinedTextureImageUnits()) { return logicalTextureUnit; } @@ -275,15 +256,15 @@ bool ProgramBinary::setUniform1fv(GLint location, GLsizei count, const GLfloat* Uniform *targetUniform = mUniforms[mUniformIndex[location].index]; targetUniform->dirty = true; - if (targetUniform->type == GL_FLOAT) - { - int arraySize = targetUniform->arraySize; + int elementCount = targetUniform->elementCount(); - if (arraySize == 1 && count > 1) - return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION + if (elementCount == 1 && count > 1) + return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION - count = std::min(arraySize - (int)mUniformIndex[location].element, count); + count = std::min(elementCount - (int)mUniformIndex[location].element, count); + if (targetUniform->type == GL_FLOAT) + { GLfloat *target = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4; for (int i = 0; i < count; i++) @@ -298,24 +279,16 @@ bool ProgramBinary::setUniform1fv(GLint location, GLsizei count, const GLfloat* } else if (targetUniform->type == GL_BOOL) { - int arraySize = targetUniform->arraySize; - - if (arraySize == 1 && count > 1) - return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION + GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; - count = std::min(arraySize - (int)mUniformIndex[location].element, count); - GLboolean *boolParams = (GLboolean*)targetUniform->data + mUniformIndex[location].element; - - for (int i = 0; i < count; ++i) + for (int i = 0; i < count; i++) { - if (v[i] == 0.0f) - { - boolParams[i] = GL_FALSE; - } - else - { - boolParams[i] = GL_TRUE; - } + boolParams[0] = (v[0] == 0.0f) ? GL_FALSE : GL_TRUE; + boolParams[1] = GL_FALSE; + boolParams[2] = GL_FALSE; + boolParams[3] = GL_FALSE; + boolParams += 4; + v += 1; } } else @@ -336,15 +309,15 @@ bool ProgramBinary::setUniform2fv(GLint location, GLsizei count, const GLfloat * Uniform *targetUniform = mUniforms[mUniformIndex[location].index]; targetUniform->dirty = true; - if (targetUniform->type == GL_FLOAT_VEC2) - { - int arraySize = targetUniform->arraySize; + int elementCount = targetUniform->elementCount(); - if (arraySize == 1 && count > 1) - return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION + if (elementCount == 1 && count > 1) + return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION - count = std::min(arraySize - (int)mUniformIndex[location].element, count); + count = std::min(elementCount - (int)mUniformIndex[location].element, count); + if (targetUniform->type == GL_FLOAT_VEC2) + { GLfloat *target = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4; for (int i = 0; i < count; i++) @@ -359,25 +332,16 @@ bool ProgramBinary::setUniform2fv(GLint location, GLsizei count, const GLfloat * } else if (targetUniform->type == GL_BOOL_VEC2) { - int arraySize = targetUniform->arraySize; - - if (arraySize == 1 && count > 1) - return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION - - count = std::min(arraySize - (int)mUniformIndex[location].element, count); - - GLboolean *boolParams = (GLboolean*)targetUniform->data + mUniformIndex[location].element * 2; + GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; - for (int i = 0; i < count * 2; ++i) + for (int i = 0; i < count; i++) { - if (v[i] == 0.0f) - { - boolParams[i] = GL_FALSE; - } - else - { - boolParams[i] = GL_TRUE; - } + boolParams[0] = (v[0] == 0.0f) ? GL_FALSE : GL_TRUE; + boolParams[1] = (v[1] == 0.0f) ? GL_FALSE : GL_TRUE; + boolParams[2] = GL_FALSE; + boolParams[3] = GL_FALSE; + boolParams += 4; + v += 2; } } else @@ -398,15 +362,15 @@ bool ProgramBinary::setUniform3fv(GLint location, GLsizei count, const GLfloat * Uniform *targetUniform = mUniforms[mUniformIndex[location].index]; targetUniform->dirty = true; - if (targetUniform->type == GL_FLOAT_VEC3) - { - int arraySize = targetUniform->arraySize; + int elementCount = targetUniform->elementCount(); - if (arraySize == 1 && count > 1) - return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION + if (elementCount == 1 && count > 1) + return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION - count = std::min(arraySize - (int)mUniformIndex[location].element, count); + count = std::min(elementCount - (int)mUniformIndex[location].element, count); + if (targetUniform->type == GL_FLOAT_VEC3) + { GLfloat *target = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4; for (int i = 0; i < count; i++) @@ -421,24 +385,16 @@ bool ProgramBinary::setUniform3fv(GLint location, GLsizei count, const GLfloat * } else if (targetUniform->type == GL_BOOL_VEC3) { - int arraySize = targetUniform->arraySize; + GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; - if (arraySize == 1 && count > 1) - return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION - - count = std::min(arraySize - (int)mUniformIndex[location].element, count); - GLboolean *boolParams = (GLboolean*)targetUniform->data + mUniformIndex[location].element * 3; - - for (int i = 0; i < count * 3; ++i) + for (int i = 0; i < count; i++) { - if (v[i] == 0.0f) - { - boolParams[i] = GL_FALSE; - } - else - { - boolParams[i] = GL_TRUE; - } + boolParams[0] = (v[0] == 0.0f) ? GL_FALSE : GL_TRUE; + boolParams[1] = (v[1] == 0.0f) ? GL_FALSE : GL_TRUE; + boolParams[2] = (v[2] == 0.0f) ? GL_FALSE : GL_TRUE; + boolParams[3] = GL_FALSE; + boolParams += 4; + v += 3; } } else @@ -459,38 +415,39 @@ bool ProgramBinary::setUniform4fv(GLint location, GLsizei count, const GLfloat * Uniform *targetUniform = mUniforms[mUniformIndex[location].index]; targetUniform->dirty = true; - if (targetUniform->type == GL_FLOAT_VEC4) - { - int arraySize = targetUniform->arraySize; + int elementCount = targetUniform->elementCount(); + + if (elementCount == 1 && count > 1) + return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION - if (arraySize == 1 && count > 1) - return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION + count = std::min(elementCount - (int)mUniformIndex[location].element, count); - count = std::min(arraySize - (int)mUniformIndex[location].element, count); + if (targetUniform->type == GL_FLOAT_VEC4) + { + GLfloat *target = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4; - memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * 4, - v, 4 * sizeof(GLfloat) * count); + for (int i = 0; i < count; i++) + { + target[0] = v[0]; + target[1] = v[1]; + target[2] = v[2]; + target[3] = v[3]; + target += 4; + v += 4; + } } else if (targetUniform->type == GL_BOOL_VEC4) { - int arraySize = targetUniform->arraySize; - - if (arraySize == 1 && count > 1) - return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION + GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; - count = std::min(arraySize - (int)mUniformIndex[location].element, count); - GLboolean *boolParams = (GLboolean*)targetUniform->data + mUniformIndex[location].element * 4; - - for (int i = 0; i < count * 4; ++i) + for (int i = 0; i < count; i++) { - if (v[i] == 0.0f) - { - boolParams[i] = GL_FALSE; - } - else - { - boolParams[i] = GL_TRUE; - } + boolParams[0] = (v[0] == 0.0f) ? GL_FALSE : GL_TRUE; + boolParams[1] = (v[1] == 0.0f) ? GL_FALSE : GL_TRUE; + boolParams[2] = (v[2] == 0.0f) ? GL_FALSE : GL_TRUE; + boolParams[3] = (v[3] == 0.0f) ? GL_FALSE : GL_TRUE; + boolParams += 4; + v += 4; } } else @@ -547,14 +504,14 @@ bool ProgramBinary::setUniformMatrix2fv(GLint location, GLsizei count, const GLf return false; } - int arraySize = targetUniform->arraySize; + int elementCount = targetUniform->elementCount(); - if (arraySize == 1 && count > 1) + if (elementCount == 1 && count > 1) return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION - count = std::min(arraySize - (int)mUniformIndex[location].element, count); - + count = std::min(elementCount - (int)mUniformIndex[location].element, count); GLfloat *target = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 8; + for (int i = 0; i < count; i++) { transposeMatrix(target, value); @@ -580,14 +537,14 @@ bool ProgramBinary::setUniformMatrix3fv(GLint location, GLsizei count, const GLf return false; } - int arraySize = targetUniform->arraySize; + int elementCount = targetUniform->elementCount(); - if (arraySize == 1 && count > 1) + if (elementCount == 1 && count > 1) return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION - count = std::min(arraySize - (int)mUniformIndex[location].element, count); - + count = std::min(elementCount - (int)mUniformIndex[location].element, count); GLfloat *target = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 12; + for (int i = 0; i < count; i++) { transposeMatrix(target, value); @@ -614,14 +571,14 @@ bool ProgramBinary::setUniformMatrix4fv(GLint location, GLsizei count, const GLf return false; } - int arraySize = targetUniform->arraySize; + int elementCount = targetUniform->elementCount(); - if (arraySize == 1 && count > 1) + if (elementCount == 1 && count > 1) return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION - count = std::min(arraySize - (int)mUniformIndex[location].element, count); - + count = std::min(elementCount - (int)mUniformIndex[location].element, count); GLfloat *target = (GLfloat*)(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * 16); + for (int i = 0; i < count; i++) { transposeMatrix(target, value); @@ -642,40 +599,41 @@ bool ProgramBinary::setUniform1iv(GLint location, GLsizei count, const GLint *v) Uniform *targetUniform = mUniforms[mUniformIndex[location].index]; targetUniform->dirty = true; + int elementCount = targetUniform->elementCount(); + + if (elementCount == 1 && count > 1) + return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION + + count = std::min(elementCount - (int)mUniformIndex[location].element, count); + if (targetUniform->type == GL_INT || targetUniform->type == GL_SAMPLER_2D || targetUniform->type == GL_SAMPLER_CUBE) { - int arraySize = targetUniform->arraySize; - - if (arraySize == 1 && count > 1) - return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION + GLint *target = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; - count = std::min(arraySize - (int)mUniformIndex[location].element, count); - - memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLint), - v, sizeof(GLint) * count); + for (int i = 0; i < count; i++) + { + target[0] = v[0]; + target[1] = 0; + target[2] = 0; + target[3] = 0; + target += 4; + v += 1; + } } else if (targetUniform->type == GL_BOOL) { - int arraySize = targetUniform->arraySize; + GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; - if (arraySize == 1 && count > 1) - return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION - - count = std::min(arraySize - (int)mUniformIndex[location].element, count); - GLboolean *boolParams = (GLboolean*)targetUniform->data + mUniformIndex[location].element; - - for (int i = 0; i < count; ++i) + for (int i = 0; i < count; i++) { - if (v[i] == 0) - { - boolParams[i] = GL_FALSE; - } - else - { - boolParams[i] = GL_TRUE; - } + boolParams[0] = (v[0] == 0) ? GL_FALSE : GL_TRUE; + boolParams[1] = GL_FALSE; + boolParams[2] = GL_FALSE; + boolParams[3] = GL_FALSE; + boolParams += 4; + v += 1; } } else @@ -696,38 +654,39 @@ bool ProgramBinary::setUniform2iv(GLint location, GLsizei count, const GLint *v) Uniform *targetUniform = mUniforms[mUniformIndex[location].index]; targetUniform->dirty = true; - if (targetUniform->type == GL_INT_VEC2) - { - int arraySize = targetUniform->arraySize; + int elementCount = targetUniform->elementCount(); + + if (elementCount == 1 && count > 1) + return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION - if (arraySize == 1 && count > 1) - return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION + count = std::min(elementCount - (int)mUniformIndex[location].element, count); - count = std::min(arraySize - (int)mUniformIndex[location].element, count); + if (targetUniform->type == GL_INT_VEC2) + { + GLint *target = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; - memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLint) * 2, - v, 2 * sizeof(GLint) * count); + for (int i = 0; i < count; i++) + { + target[0] = v[0]; + target[1] = v[1]; + target[2] = 0; + target[3] = 0; + target += 4; + v += 2; + } } else if (targetUniform->type == GL_BOOL_VEC2) { - int arraySize = targetUniform->arraySize; + GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; - if (arraySize == 1 && count > 1) - return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION - - count = std::min(arraySize - (int)mUniformIndex[location].element, count); - GLboolean *boolParams = (GLboolean*)targetUniform->data + mUniformIndex[location].element * 2; - - for (int i = 0; i < count * 2; ++i) + for (int i = 0; i < count; i++) { - if (v[i] == 0) - { - boolParams[i] = GL_FALSE; - } - else - { - boolParams[i] = GL_TRUE; - } + boolParams[0] = (v[0] == 0) ? GL_FALSE : GL_TRUE; + boolParams[1] = (v[1] == 0) ? GL_FALSE : GL_TRUE; + boolParams[2] = GL_FALSE; + boolParams[3] = GL_FALSE; + boolParams += 4; + v += 2; } } else @@ -748,38 +707,39 @@ bool ProgramBinary::setUniform3iv(GLint location, GLsizei count, const GLint *v) Uniform *targetUniform = mUniforms[mUniformIndex[location].index]; targetUniform->dirty = true; - if (targetUniform->type == GL_INT_VEC3) - { - int arraySize = targetUniform->arraySize; + int elementCount = targetUniform->elementCount(); + + if (elementCount == 1 && count > 1) + return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION - if (arraySize == 1 && count > 1) - return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION + count = std::min(elementCount - (int)mUniformIndex[location].element, count); - count = std::min(arraySize - (int)mUniformIndex[location].element, count); + if (targetUniform->type == GL_INT_VEC3) + { + GLint *target = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; - memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLint) * 3, - v, 3 * sizeof(GLint) * count); + for (int i = 0; i < count; i++) + { + target[0] = v[0]; + target[1] = v[1]; + target[2] = v[2]; + target[3] = 0; + target += 4; + v += 3; + } } else if (targetUniform->type == GL_BOOL_VEC3) { - int arraySize = targetUniform->arraySize; + GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; - if (arraySize == 1 && count > 1) - return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION - - count = std::min(arraySize - (int)mUniformIndex[location].element, count); - GLboolean *boolParams = (GLboolean*)targetUniform->data + mUniformIndex[location].element * 3; - - for (int i = 0; i < count * 3; ++i) + for (int i = 0; i < count; i++) { - if (v[i] == 0) - { - boolParams[i] = GL_FALSE; - } - else - { - boolParams[i] = GL_TRUE; - } + boolParams[0] = (v[0] == 0) ? GL_FALSE : GL_TRUE; + boolParams[1] = (v[1] == 0) ? GL_FALSE : GL_TRUE; + boolParams[2] = (v[2] == 0) ? GL_FALSE : GL_TRUE; + boolParams[3] = GL_FALSE; + boolParams += 4; + v += 3; } } else @@ -800,38 +760,39 @@ bool ProgramBinary::setUniform4iv(GLint location, GLsizei count, const GLint *v) Uniform *targetUniform = mUniforms[mUniformIndex[location].index]; targetUniform->dirty = true; - if (targetUniform->type == GL_INT_VEC4) - { - int arraySize = targetUniform->arraySize; + int elementCount = targetUniform->elementCount(); + + if (elementCount == 1 && count > 1) + return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION - if (arraySize == 1 && count > 1) - return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION + count = std::min(elementCount - (int)mUniformIndex[location].element, count); - count = std::min(arraySize - (int)mUniformIndex[location].element, count); + if (targetUniform->type == GL_INT_VEC4) + { + GLint *target = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; - memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLint) * 4, - v, 4 * sizeof(GLint) * count); + for (int i = 0; i < count; i++) + { + target[0] = v[0]; + target[1] = v[1]; + target[2] = v[2]; + target[3] = v[3]; + target += 4; + v += 4; + } } else if (targetUniform->type == GL_BOOL_VEC4) { - int arraySize = targetUniform->arraySize; - - if (arraySize == 1 && count > 1) - return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION - - count = std::min(arraySize - (int)mUniformIndex[location].element, count); - GLboolean *boolParams = (GLboolean*)targetUniform->data + mUniformIndex[location].element * 4; + GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; - for (int i = 0; i < count * 4; ++i) + for (int i = 0; i < count; i++) { - if (v[i] == 0) - { - boolParams[i] = GL_FALSE; - } - else - { - boolParams[i] = GL_TRUE; - } + boolParams[0] = (v[0] == 0) ? GL_FALSE : GL_TRUE; + boolParams[1] = (v[1] == 0) ? GL_FALSE : GL_TRUE; + boolParams[2] = (v[2] == 0) ? GL_FALSE : GL_TRUE; + boolParams[3] = (v[3] == 0) ? GL_FALSE : GL_TRUE; + boolParams += 4; + v += 4; } } else @@ -874,30 +835,29 @@ bool ProgramBinary::getUniformfv(GLint location, GLsizei *bufSize, GLfloat *para break; default: { - unsigned int count = UniformExternalComponentCount(targetUniform->type); - unsigned int internalCount = UniformInternalComponentCount(targetUniform->type); + unsigned int size = UniformComponentCount(targetUniform->type); switch (UniformComponentType(targetUniform->type)) { case GL_BOOL: { - GLboolean *boolParams = (GLboolean*)targetUniform->data + mUniformIndex[location].element * internalCount; + GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; - for (unsigned int i = 0; i < count; ++i) + for (unsigned int i = 0; i < size; i++) { params[i] = (boolParams[i] == GL_FALSE) ? 0.0f : 1.0f; } } break; case GL_FLOAT: - memcpy(params, targetUniform->data + mUniformIndex[location].element * internalCount * sizeof(GLfloat), - count * sizeof(GLfloat)); + memcpy(params, targetUniform->data + mUniformIndex[location].element * 4 * sizeof(GLfloat), + size * sizeof(GLfloat)); break; case GL_INT: { - GLint *intParams = (GLint*)targetUniform->data + mUniformIndex[location].element * internalCount; + GLint *intParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; - for (unsigned int i = 0; i < count; ++i) + for (unsigned int i = 0; i < size; i++) { params[i] = (float)intParams[i]; } @@ -933,50 +893,43 @@ bool ProgramBinary::getUniformiv(GLint location, GLsizei *bufSize, GLint *params switch (targetUniform->type) { case GL_FLOAT_MAT2: - { - transposeMatrix(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 8); - } + transposeMatrix(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 8); break; case GL_FLOAT_MAT3: - { - transposeMatrix(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 12); - } + transposeMatrix(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 12); break; case GL_FLOAT_MAT4: - { - transposeMatrix(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 16); - } + transposeMatrix(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 16); break; default: { - unsigned int count = UniformExternalComponentCount(targetUniform->type); - unsigned int internalCount = UniformInternalComponentCount(targetUniform->type); + unsigned int size = VariableColumnCount(targetUniform->type); switch (UniformComponentType(targetUniform->type)) { case GL_BOOL: { - GLboolean *boolParams = targetUniform->data + mUniformIndex[location].element * internalCount; + GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; - for (unsigned int i = 0; i < count; ++i) + for (unsigned int i = 0; i < size; i++) { - params[i] = (GLint)boolParams[i]; + params[i] = boolParams[i]; } } break; case GL_FLOAT: { - GLfloat *floatParams = (GLfloat*)targetUniform->data + mUniformIndex[location].element * internalCount; + GLfloat *floatParams = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4; - for (unsigned int i = 0; i < count; ++i) + for (unsigned int i = 0; i < size; i++) { params[i] = (GLint)floatParams[i]; } } break; case GL_INT: - memcpy(params, targetUniform->data + mUniformIndex[location].element * internalCount * sizeof(GLint), - count * sizeof(GLint)); + memcpy(params, targetUniform->data + mUniformIndex[location].element * 4 * sizeof(GLint), + size * sizeof(GLint)); break; default: UNREACHABLE(); } @@ -995,153 +948,67 @@ void ProgramBinary::dirtyAllUniforms() } } -// Applies all the uniforms set for this program object to the Direct3D 9 device +// Applies all the uniforms set for this program object to the renderer void ProgramBinary::applyUniforms() { - for (std::vector::iterator ub = mUniforms.begin(), ue = mUniforms.end(); ub != ue; ++ub) { + // Retrieve sampler uniform values + for (std::vector::iterator ub = mUniforms.begin(), ue = mUniforms.end(); ub != ue; ++ub) + { Uniform *targetUniform = *ub; if (targetUniform->dirty) { - int arraySize = targetUniform->arraySize; - GLfloat *f = (GLfloat*)targetUniform->data; - GLint *i = (GLint*)targetUniform->data; - GLboolean *b = (GLboolean*)targetUniform->data; - - switch (targetUniform->type) + if (targetUniform->type == GL_SAMPLER_2D || + targetUniform->type == GL_SAMPLER_CUBE) { - case GL_BOOL: applyUniformnbv(targetUniform, arraySize, 1, b); break; - case GL_BOOL_VEC2: applyUniformnbv(targetUniform, arraySize, 2, b); break; - case GL_BOOL_VEC3: applyUniformnbv(targetUniform, arraySize, 3, b); break; - case GL_BOOL_VEC4: applyUniformnbv(targetUniform, arraySize, 4, b); break; - case GL_FLOAT: - case GL_FLOAT_VEC2: - case GL_FLOAT_VEC3: - case GL_FLOAT_VEC4: - case GL_FLOAT_MAT2: - case GL_FLOAT_MAT3: - case GL_FLOAT_MAT4: applyUniformnfv(targetUniform, f); break; - case GL_SAMPLER_2D: - case GL_SAMPLER_CUBE: - case GL_INT: applyUniform1iv(targetUniform, arraySize, i); break; - case GL_INT_VEC2: applyUniform2iv(targetUniform, arraySize, i); break; - case GL_INT_VEC3: applyUniform3iv(targetUniform, arraySize, i); break; - case GL_INT_VEC4: applyUniform4iv(targetUniform, arraySize, i); break; - default: - UNREACHABLE(); - } - - targetUniform->dirty = false; - } - } -} - -// Compiles the HLSL code of the attached shaders into executable binaries -ID3D10Blob *ProgramBinary::compileToBinary(InfoLog &infoLog, const char *hlsl, const char *profile, D3DConstantTable **constantTable) -{ - if (!hlsl) - { - return NULL; - } - - DWORD result = NOERROR; - UINT flags = 0; - std::string sourceText; - if (perfActive()) - { - flags |= D3DCOMPILE_DEBUG; -#ifdef NDEBUG - flags |= ANGLE_COMPILE_OPTIMIZATION_LEVEL; -#else - flags |= D3DCOMPILE_SKIP_OPTIMIZATION; -#endif - - std::string sourcePath = getTempPath(); - sourceText = std::string("#line 2 \"") + sourcePath + std::string("\"\n\n") + std::string(hlsl); - writeFile(sourcePath.c_str(), sourceText.c_str(), sourceText.size()); - } - else - { - flags |= ANGLE_COMPILE_OPTIMIZATION_LEVEL; - sourceText = hlsl; - } - - // Sometimes D3DCompile will fail with the default compilation flags for complicated shaders when it would otherwise pass with alternative options. - // Try the default flags first and if compilation fails, try some alternatives. - const static UINT extraFlags[] = - { - 0, - D3DCOMPILE_AVOID_FLOW_CONTROL, - D3DCOMPILE_PREFER_FLOW_CONTROL - }; - - const static char * const extraFlagNames[] = - { - "default", - "avoid flow control", - "prefer flow control" - }; - - for (int i = 0; i < sizeof(extraFlags) / sizeof(UINT); ++i) - { - ID3D10Blob *errorMessage = NULL; - ID3D10Blob *binary = NULL; - result = D3DCompile(hlsl, strlen(hlsl), g_fakepath, NULL, NULL, "main", profile, flags | extraFlags[i], 0, &binary, &errorMessage); + int count = targetUniform->elementCount(); + GLint (*v)[4] = (GLint(*)[4])targetUniform->data; - if (errorMessage) - { - const char *message = (const char*)errorMessage->GetBufferPointer(); + if (targetUniform->psRegisterIndex >= 0) + { + unsigned int firstIndex = targetUniform->psRegisterIndex; - infoLog.appendSanitized(message); - TRACE("\n%s", hlsl); - TRACE("\n%s", message); + for (int i = 0; i < count; i++) + { + unsigned int samplerIndex = firstIndex + i; - errorMessage->Release(); - errorMessage = NULL; - } + if (samplerIndex < MAX_TEXTURE_IMAGE_UNITS) + { + ASSERT(mSamplersPS[samplerIndex].active); + mSamplersPS[samplerIndex].logicalTextureUnit = v[i][0]; + } + } + } - if (SUCCEEDED(result)) - { - D3DConstantTable *table = new D3DConstantTable(binary->GetBufferPointer(), binary->GetBufferSize()); - if (table->error()) - { - delete table; - binary->Release(); - return NULL; - } + if (targetUniform->vsRegisterIndex >= 0) + { + unsigned int firstIndex = targetUniform->vsRegisterIndex; - *constantTable = table; - - return binary; - } - else - { - if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY) - { - return error(GL_OUT_OF_MEMORY, (ID3D10Blob*) NULL); - } + for (int i = 0; i < count; i++) + { + unsigned int samplerIndex = firstIndex + i; - infoLog.append("Warning: D3D shader compilation failed with "); - infoLog.append(extraFlagNames[i]); - infoLog.append(" flags."); - if (i + 1 < sizeof(extraFlagNames) / sizeof(char*)) - { - infoLog.append(" Retrying with "); - infoLog.append(extraFlagNames[i + 1]); - infoLog.append(".\n"); + if (samplerIndex < IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS) + { + ASSERT(mSamplersVS[samplerIndex].active); + mSamplersVS[samplerIndex].logicalTextureUnit = v[i][0]; + } + } + } } } } - return NULL; + mRenderer->applyUniforms(this, &mUniforms); } // Packs varyings into generic varying registers, using the algorithm from [OpenGL ES Shading Language 1.00 rev. 17] appendix A section 7 page 111 // Returns the number of used varying registers, or -1 if unsuccesful int ProgramBinary::packVaryings(InfoLog &infoLog, const Varying *packing[][4], FragmentShader *fragmentShader) { - Context *context = getContext(); - const int maxVaryingVectors = context->getMaximumVaryingVectors(); + const int maxVaryingVectors = mRenderer->getMaxVaryingVectors(); + + fragmentShader->resetVaryingsRegisterAssignment(); for (VaryingList::iterator varying = fragmentShader->mVaryings.begin(); varying != fragmentShader->mVaryings.end(); varying++) { @@ -1286,46 +1153,38 @@ int ProgramBinary::packVaryings(InfoLog &infoLog, const Varying *packing[][4], F return registers; } -bool ProgramBinary::linkVaryings(InfoLog &infoLog, std::string& pixelHLSL, std::string& vertexHLSL, FragmentShader *fragmentShader, VertexShader *vertexShader) +bool ProgramBinary::linkVaryings(InfoLog &infoLog, int registers, const Varying *packing[][4], + std::string& pixelHLSL, std::string& vertexHLSL, + FragmentShader *fragmentShader, VertexShader *vertexShader) { if (pixelHLSL.empty() || vertexHLSL.empty()) { return false; } - // Reset the varying register assignments - for (VaryingList::iterator fragVar = fragmentShader->mVaryings.begin(); fragVar != fragmentShader->mVaryings.end(); fragVar++) + bool usesMRT = fragmentShader->mUsesMultipleRenderTargets; + bool usesFragColor = fragmentShader->mUsesFragColor; + bool usesFragData = fragmentShader->mUsesFragData; + if (usesMRT && usesFragColor && usesFragData) { - fragVar->reg = -1; - fragVar->col = -1; + infoLog.append("Cannot use both gl_FragColor and gl_FragData in the same fragment shader."); + return false; } - for (VaryingList::iterator vtxVar = vertexShader->mVaryings.begin(); vtxVar != vertexShader->mVaryings.end(); vtxVar++) + // Write the HLSL input/output declarations + const int shaderModel = mRenderer->getMajorShaderModel(); + const int maxVaryingVectors = mRenderer->getMaxVaryingVectors(); + + const int registersNeeded = registers + (fragmentShader->mUsesFragCoord ? 1 : 0) + (fragmentShader->mUsesPointCoord ? 1 : 0); + + if (registersNeeded > maxVaryingVectors) { - vtxVar->reg = -1; - vtxVar->col = -1; + infoLog.append("No varying registers left to support gl_FragCoord/gl_PointCoord"); + + return false; } - // Map the varyings to the register file - const Varying *packing[MAX_VARYING_VECTORS_SM3][4] = {NULL}; - int registers = packVaryings(infoLog, packing, fragmentShader); - - if (registers < 0) - { - return false; - } - - // Write the HLSL input/output declarations - Context *context = getContext(); - const bool sm3 = context->supportsShaderModel3(); - const int maxVaryingVectors = context->getMaximumVaryingVectors(); - - if (registers == maxVaryingVectors && fragmentShader->mUsesFragCoord) - { - infoLog.append("No varying registers left to support gl_FragCoord"); - - return false; - } + vertexShader->resetVaryingsRegisterAssignment(); for (VaryingList::iterator input = fragmentShader->mVaryings.begin(); input != fragmentShader->mVaryings.end(); input++) { @@ -1359,10 +1218,38 @@ bool ProgramBinary::linkVaryings(InfoLog &infoLog, std::string& pixelHLSL, std:: } mUsesPointSize = vertexShader->mUsesPointSize; - std::string varyingSemantic = (mUsesPointSize && sm3) ? "COLOR" : "TEXCOORD"; + std::string varyingSemantic = (mUsesPointSize && shaderModel == 3) ? "COLOR" : "TEXCOORD"; + std::string targetSemantic = (shaderModel >= 4) ? "SV_Target" : "COLOR"; + std::string positionSemantic = (shaderModel >= 4) ? "SV_Position" : "POSITION"; + + const unsigned int renderTargetCount = usesMRT ? mRenderer->getMaxRenderTargets() : 1; + + // special varyings that use reserved registers + int reservedRegisterIndex = registers; + std::string fragCoordSemantic; + std::string pointCoordSemantic; + + if (fragmentShader->mUsesFragCoord) + { + fragCoordSemantic = varyingSemantic + str(reservedRegisterIndex++); + } + + if (fragmentShader->mUsesPointCoord) + { + // Shader model 3 uses a special TEXCOORD semantic for point sprite texcoords. + // In DX11 we compute this in the GS. + if (shaderModel == 3) + { + pointCoordSemantic = "TEXCOORD0"; + } + else if (shaderModel >= 4) + { + pointCoordSemantic = varyingSemantic + str(reservedRegisterIndex++); + } + } vertexHLSL += "struct VS_INPUT\n" - "{\n"; + "{\n"; int semanticIndex = 0; for (AttributeArray::iterator attribute = vertexShader->mAttributes.begin(); attribute != vertexShader->mAttributes.end(); attribute++) @@ -1385,10 +1272,14 @@ bool ProgramBinary::linkVaryings(InfoLog &infoLog, std::string& pixelHLSL, std:: } vertexHLSL += "};\n" - "\n" - "struct VS_OUTPUT\n" - "{\n" - " float4 gl_Position : POSITION;\n"; + "\n" + "struct VS_OUTPUT\n" + "{\n"; + + if (shaderModel < 4) + { + vertexHLSL += " float4 gl_Position : " + positionSemantic + ";\n"; + } for (int r = 0; r < registers; r++) { @@ -1399,18 +1290,23 @@ bool ProgramBinary::linkVaryings(InfoLog &infoLog, std::string& pixelHLSL, std:: if (fragmentShader->mUsesFragCoord) { - vertexHLSL += " float4 gl_FragCoord : " + varyingSemantic + str(registers) + ";\n"; + vertexHLSL += " float4 gl_FragCoord : " + fragCoordSemantic + ";\n"; } - if (vertexShader->mUsesPointSize && sm3) + if (vertexShader->mUsesPointSize && shaderModel >= 3) { vertexHLSL += " float gl_PointSize : PSIZE;\n"; } + if (shaderModel >= 4) + { + vertexHLSL += " float4 gl_Position : " + positionSemantic + ";\n"; + } + vertexHLSL += "};\n" - "\n" - "VS_OUTPUT main(VS_INPUT input)\n" - "{\n"; + "\n" + "VS_OUTPUT main(VS_INPUT input)\n" + "{\n"; for (AttributeArray::iterator attribute = vertexShader->mAttributes.begin(); attribute != vertexShader->mAttributes.end(); attribute++) { @@ -1424,16 +1320,30 @@ bool ProgramBinary::linkVaryings(InfoLog &infoLog, std::string& pixelHLSL, std:: vertexHLSL += "(input." + decorateAttribute(attribute->name) + ");\n"; } - vertexHLSL += "\n" - " gl_main();\n" - "\n" - " VS_OUTPUT output;\n" - " output.gl_Position.x = gl_Position.x - dx_HalfPixelSize.x * gl_Position.w;\n" - " output.gl_Position.y = -(gl_Position.y + dx_HalfPixelSize.y * gl_Position.w);\n" - " output.gl_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n" - " output.gl_Position.w = gl_Position.w;\n"; + if (shaderModel >= 4) + { + vertexHLSL += "\n" + " gl_main();\n" + "\n" + " VS_OUTPUT output;\n" + " output.gl_Position.x = gl_Position.x;\n" + " output.gl_Position.y = -gl_Position.y;\n" + " output.gl_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n" + " output.gl_Position.w = gl_Position.w;\n"; + } + else + { + vertexHLSL += "\n" + " gl_main();\n" + "\n" + " VS_OUTPUT output;\n" + " output.gl_Position.x = gl_Position.x * dx_ViewAdjust.z + dx_ViewAdjust.x * gl_Position.w;\n" + " output.gl_Position.y = -(gl_Position.y * dx_ViewAdjust.w + dx_ViewAdjust.y * gl_Position.w);\n" + " output.gl_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n" + " output.gl_Position.w = gl_Position.w;\n"; + } - if (vertexShader->mUsesPointSize && sm3) + if (vertexShader->mUsesPointSize && shaderModel >= 3) { vertexHLSL += " output.gl_PointSize = gl_PointSize;\n"; } @@ -1505,11 +1415,11 @@ bool ProgramBinary::linkVaryings(InfoLog &infoLog, std::string& pixelHLSL, std:: } vertexHLSL += "\n" - " return output;\n" - "}\n"; + " return output;\n" + "}\n"; pixelHLSL += "struct PS_INPUT\n" - "{\n"; + "{\n"; for (VaryingList::iterator varying = fragmentShader->mVaryings.begin(); varying != fragmentShader->mVaryings.end(); varying++) { @@ -1521,7 +1431,7 @@ bool ProgramBinary::linkVaryings(InfoLog &infoLog, std::string& pixelHLSL, std:: for (int j = 0; j < rows; j++) { std::string n = str(varying->reg + i * rows + j); - pixelHLSL += " float4 v" + n + " : " + varyingSemantic + n + ";\n"; + pixelHLSL += " float" + str(VariableColumnCount(varying->type)) + " v" + n + " : " + varyingSemantic + n + ";\n"; } } } @@ -1530,53 +1440,91 @@ bool ProgramBinary::linkVaryings(InfoLog &infoLog, std::string& pixelHLSL, std:: if (fragmentShader->mUsesFragCoord) { - pixelHLSL += " float4 gl_FragCoord : " + varyingSemantic + str(registers) + ";\n"; - if (sm3) { + pixelHLSL += " float4 gl_FragCoord : " + fragCoordSemantic + ";\n"; + } + + if (fragmentShader->mUsesPointCoord && shaderModel >= 3) + { + pixelHLSL += " float2 gl_PointCoord : " + pointCoordSemantic + ";\n"; + } + + // Must consume the PSIZE element if the geometry shader is not active + // We won't know if we use a GS until we draw + if (vertexShader->mUsesPointSize && shaderModel >= 4) + { + pixelHLSL += " float gl_PointSize : PSIZE;\n"; + } + + if (fragmentShader->mUsesFragCoord) + { + if (shaderModel >= 4) + { + pixelHLSL += " float4 dx_VPos : SV_Position;\n"; + } + else if (shaderModel >= 3) + { pixelHLSL += " float2 dx_VPos : VPOS;\n"; } } - if (fragmentShader->mUsesPointCoord && sm3) + pixelHLSL += "};\n" + "\n" + "struct PS_OUTPUT\n" + "{\n"; + + for (unsigned int i = 0; i < renderTargetCount; i++) { - pixelHLSL += " float2 gl_PointCoord : TEXCOORD0;\n"; + pixelHLSL += " float4 gl_Color" + str(i) + " : " + targetSemantic + str(i) + ";\n"; } + pixelHLSL += "};\n" + "\n"; + if (fragmentShader->mUsesFrontFacing) { - pixelHLSL += " float vFace : VFACE;\n"; + if (shaderModel >= 4) + { + pixelHLSL += "PS_OUTPUT main(PS_INPUT input, bool isFrontFace : SV_IsFrontFace)\n" + "{\n"; + } + else + { + pixelHLSL += "PS_OUTPUT main(PS_INPUT input, float vFace : VFACE)\n" + "{\n"; + } + } + else + { + pixelHLSL += "PS_OUTPUT main(PS_INPUT input)\n" + "{\n"; } - - pixelHLSL += "};\n" - "\n" - "struct PS_OUTPUT\n" - "{\n" - " float4 gl_Color[1] : COLOR;\n" - "};\n" - "\n" - "PS_OUTPUT main(PS_INPUT input)\n" - "{\n"; if (fragmentShader->mUsesFragCoord) { pixelHLSL += " float rhw = 1.0 / input.gl_FragCoord.w;\n"; - if (sm3) + if (shaderModel >= 4) + { + pixelHLSL += " gl_FragCoord.x = input.dx_VPos.x;\n" + " gl_FragCoord.y = input.dx_VPos.y;\n"; + } + else if (shaderModel >= 3) { pixelHLSL += " gl_FragCoord.x = input.dx_VPos.x + 0.5;\n" - " gl_FragCoord.y = input.dx_VPos.y + 0.5;\n"; + " gl_FragCoord.y = input.dx_VPos.y + 0.5;\n"; } else { - // dx_Coord contains the viewport width/2, height/2, center.x and center.y. See Context::applyRenderTarget() - pixelHLSL += " gl_FragCoord.x = (input.gl_FragCoord.x * rhw) * dx_Coord.x + dx_Coord.z;\n" - " gl_FragCoord.y = (input.gl_FragCoord.y * rhw) * dx_Coord.y + dx_Coord.w;\n"; + // dx_ViewCoords contains the viewport width/2, height/2, center.x and center.y. See Renderer::setViewport() + pixelHLSL += " gl_FragCoord.x = (input.gl_FragCoord.x * rhw) * dx_ViewCoords.x + dx_ViewCoords.z;\n" + " gl_FragCoord.y = (input.gl_FragCoord.y * rhw) * dx_ViewCoords.y + dx_ViewCoords.w;\n"; } - pixelHLSL += " gl_FragCoord.z = (input.gl_FragCoord.z * rhw) * dx_Depth.x + dx_Depth.y;\n" - " gl_FragCoord.w = rhw;\n"; + pixelHLSL += " gl_FragCoord.z = (input.gl_FragCoord.z * rhw) * dx_DepthFront.x + dx_DepthFront.y;\n" + " gl_FragCoord.w = rhw;\n"; } - if (fragmentShader->mUsesPointCoord && sm3) + if (fragmentShader->mUsesPointCoord && shaderModel >= 3) { pixelHLSL += " gl_PointCoord.x = input.gl_PointCoord.x;\n"; pixelHLSL += " gl_PointCoord.y = 1.0 - input.gl_PointCoord.y;\n"; @@ -1584,7 +1532,14 @@ bool ProgramBinary::linkVaryings(InfoLog &infoLog, std::string& pixelHLSL, std:: if (fragmentShader->mUsesFrontFacing) { - pixelHLSL += " gl_FrontFacing = dx_PointsOrLines || (dx_FrontCCW ? (input.vFace >= 0.0) : (input.vFace <= 0.0));\n"; + if (shaderModel <= 3) + { + pixelHLSL += " gl_FrontFacing = (vFace * dx_DepthFront.z >= 0.0);\n"; + } + else + { + pixelHLSL += " gl_FrontFacing = isFrontFace;\n"; + } } for (VaryingList::iterator varying = fragmentShader->mVaryings.begin(); varying != fragmentShader->mVaryings.end(); varying++) @@ -1609,7 +1564,14 @@ bool ProgramBinary::linkVaryings(InfoLog &infoLog, std::string& pixelHLSL, std:: pixelHLSL += "[" + str(j) + "]"; } - pixelHLSL += " = input.v" + n + ";\n"; + switch (VariableColumnCount(varying->type)) + { + case 1: pixelHLSL += " = input.v" + n + ".x;\n"; break; + case 2: pixelHLSL += " = input.v" + n + ".xy;\n"; break; + case 3: pixelHLSL += " = input.v" + n + ".xyz;\n"; break; + case 4: pixelHLSL += " = input.v" + n + ";\n"; break; + default: UNREACHABLE(); + } } } } @@ -1617,13 +1579,20 @@ bool ProgramBinary::linkVaryings(InfoLog &infoLog, std::string& pixelHLSL, std:: } pixelHLSL += "\n" - " gl_main();\n" - "\n" - " PS_OUTPUT output;\n" - " output.gl_Color[0] = gl_Color[0];\n" - "\n" - " return output;\n" - "}\n"; + " gl_main();\n" + "\n" + " PS_OUTPUT output;\n"; + + for (unsigned int i = 0; i < renderTargetCount; i++) + { + unsigned int sourceColor = fragmentShader->mUsesFragData ? i : 0; + + pixelHLSL += " output.gl_Color" + str(i) + " = gl_Color[" + str(sourceColor) + "];\n"; + } + + pixelHLSL += "\n" + " return output;\n" + "}\n"; return true; } @@ -1642,7 +1611,7 @@ bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length) int version = 0; stream.read(&version); - if (version != BUILD_REVISION) + if (version != VERSION_DWORD) { infoLog.append("Invalid program binary version."); return false; @@ -1667,7 +1636,7 @@ bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length) mSamplersPS[i].textureType = (TextureType) textureType; } - for (unsigned int i = 0; i < MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF; ++i) + for (unsigned int i = 0; i < IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; ++i) { stream.read(&mSamplersVS[i].active); stream.read(&mSamplersVS[i].logicalTextureUnit); @@ -1679,8 +1648,9 @@ bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length) stream.read(&mUsedVertexSamplerRange); stream.read(&mUsedPixelSamplerRange); + stream.read(&mUsesPointSize); - unsigned int size; + size_t size; stream.read(&size); if (stream.error()) { @@ -1692,24 +1662,20 @@ bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length) for (unsigned int i = 0; i < size; ++i) { GLenum type; - std::string _name; + GLenum precision; + std::string name; unsigned int arraySize; stream.read(&type); - stream.read(&_name); + stream.read(&precision); + stream.read(&name); stream.read(&arraySize); - mUniforms[i] = new Uniform(type, _name, arraySize); + mUniforms[i] = new Uniform(type, precision, name, arraySize); - stream.read(&mUniforms[i]->ps.float4Index); - stream.read(&mUniforms[i]->ps.samplerIndex); - stream.read(&mUniforms[i]->ps.boolIndex); - stream.read(&mUniforms[i]->ps.registerCount); - - stream.read(&mUniforms[i]->vs.float4Index); - stream.read(&mUniforms[i]->vs.samplerIndex); - stream.read(&mUniforms[i]->vs.boolIndex); - stream.read(&mUniforms[i]->vs.registerCount); + stream.read(&mUniforms[i]->psRegisterIndex); + stream.read(&mUniforms[i]->vsRegisterIndex); + stream.read(&mUniforms[i]->registerCount); } stream.read(&size); @@ -1727,26 +1693,22 @@ bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length) stream.read(&mUniformIndex[i].index); } - stream.read(&mDxDepthRangeLocation); - stream.read(&mDxDepthLocation); - stream.read(&mDxCoordLocation); - stream.read(&mDxHalfPixelSizeLocation); - stream.read(&mDxFrontCCWLocation); - stream.read(&mDxPointsOrLinesLocation); - unsigned int pixelShaderSize; stream.read(&pixelShaderSize); unsigned int vertexShaderSize; stream.read(&vertexShaderSize); + unsigned int geometryShaderSize; + stream.read(&geometryShaderSize); + const char *ptr = (const char*) binary + stream.offset(); - const D3DCAPS9 *binaryIdentifier = (const D3DCAPS9*) ptr; + const GUID *binaryIdentifier = (const GUID *) ptr; ptr += sizeof(GUID); - D3DADAPTER_IDENTIFIER9 *currentIdentifier = getDisplay()->getAdapterIdentifier(); - if (memcmp(¤tIdentifier->DeviceIdentifier, binaryIdentifier, sizeof(GUID)) != 0) + GUID identifier = mRenderer->getAdapterIdentifier(); + if (memcmp(&identifier, binaryIdentifier, sizeof(GUID)) != 0) { infoLog.append("Invalid program binary."); return false; @@ -1758,22 +1720,46 @@ bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length) const char *vertexShaderFunction = ptr; ptr += vertexShaderSize; - mPixelExecutable = getDisplay()->createPixelShader(reinterpret_cast(pixelShaderFunction), pixelShaderSize); + const char *geometryShaderFunction = geometryShaderSize > 0 ? ptr : NULL; + ptr += geometryShaderSize; + + mPixelExecutable = mRenderer->loadExecutable(reinterpret_cast(pixelShaderFunction), + pixelShaderSize, rx::SHADER_PIXEL); if (!mPixelExecutable) { infoLog.append("Could not create pixel shader."); return false; } - mVertexExecutable = getDisplay()->createVertexShader(reinterpret_cast(vertexShaderFunction), vertexShaderSize); + mVertexExecutable = mRenderer->loadExecutable(reinterpret_cast(vertexShaderFunction), + vertexShaderSize, rx::SHADER_VERTEX); if (!mVertexExecutable) { infoLog.append("Could not create vertex shader."); - mPixelExecutable->Release(); + delete mPixelExecutable; mPixelExecutable = NULL; return false; } + if (geometryShaderFunction != NULL && geometryShaderSize > 0) + { + mGeometryExecutable = mRenderer->loadExecutable(reinterpret_cast(geometryShaderFunction), + geometryShaderSize, rx::SHADER_GEOMETRY); + if (!mGeometryExecutable) + { + infoLog.append("Could not create geometry shader."); + delete mPixelExecutable; + mPixelExecutable = NULL; + delete mVertexExecutable; + mVertexExecutable = NULL; + return false; + } + } + else + { + mGeometryExecutable = NULL; + } + return true; } @@ -1782,7 +1768,7 @@ bool ProgramBinary::save(void* binary, GLsizei bufSize, GLsizei *length) BinaryOutputStream stream; stream.write(GL_PROGRAM_BINARY_ANGLE); - stream.write(BUILD_REVISION); + stream.write(VERSION_DWORD); for (unsigned int i = 0; i < MAX_VERTEX_ATTRIBS; ++i) { @@ -1798,7 +1784,7 @@ bool ProgramBinary::save(void* binary, GLsizei bufSize, GLsizei *length) stream.write((int) mSamplersPS[i].textureType); } - for (unsigned int i = 0; i < MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF; ++i) + for (unsigned int i = 0; i < IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; ++i) { stream.write(mSamplersVS[i].active); stream.write(mSamplersVS[i].logicalTextureUnit); @@ -1807,23 +1793,19 @@ bool ProgramBinary::save(void* binary, GLsizei bufSize, GLsizei *length) stream.write(mUsedVertexSamplerRange); stream.write(mUsedPixelSamplerRange); + stream.write(mUsesPointSize); stream.write(mUniforms.size()); for (unsigned int i = 0; i < mUniforms.size(); ++i) { stream.write(mUniforms[i]->type); - stream.write(mUniforms[i]->_name); + stream.write(mUniforms[i]->precision); + stream.write(mUniforms[i]->name); stream.write(mUniforms[i]->arraySize); - stream.write(mUniforms[i]->ps.float4Index); - stream.write(mUniforms[i]->ps.samplerIndex); - stream.write(mUniforms[i]->ps.boolIndex); - stream.write(mUniforms[i]->ps.registerCount); - - stream.write(mUniforms[i]->vs.float4Index); - stream.write(mUniforms[i]->vs.samplerIndex); - stream.write(mUniforms[i]->vs.boolIndex); - stream.write(mUniforms[i]->vs.registerCount); + stream.write(mUniforms[i]->psRegisterIndex); + stream.write(mUniforms[i]->vsRegisterIndex); + stream.write(mUniforms[i]->registerCount); } stream.write(mUniformIndex.size()); @@ -1834,29 +1816,21 @@ bool ProgramBinary::save(void* binary, GLsizei bufSize, GLsizei *length) stream.write(mUniformIndex[i].index); } - stream.write(mDxDepthRangeLocation); - stream.write(mDxDepthLocation); - stream.write(mDxCoordLocation); - stream.write(mDxHalfPixelSizeLocation); - stream.write(mDxFrontCCWLocation); - stream.write(mDxPointsOrLinesLocation); - - UINT pixelShaderSize; - HRESULT result = mPixelExecutable->GetFunction(NULL, &pixelShaderSize); - ASSERT(SUCCEEDED(result)); + UINT pixelShaderSize = mPixelExecutable->getLength(); stream.write(pixelShaderSize); - UINT vertexShaderSize; - result = mVertexExecutable->GetFunction(NULL, &vertexShaderSize); - ASSERT(SUCCEEDED(result)); + UINT vertexShaderSize = mVertexExecutable->getLength(); stream.write(vertexShaderSize); - D3DADAPTER_IDENTIFIER9 *identifier = getDisplay()->getAdapterIdentifier(); + UINT geometryShaderSize = (mGeometryExecutable != NULL) ? mGeometryExecutable->getLength() : 0; + stream.write(geometryShaderSize); + + GUID identifier = mRenderer->getAdapterIdentifier(); GLsizei streamLength = stream.length(); const void *streamData = stream.data(); - GLsizei totalLength = streamLength + sizeof(GUID) + pixelShaderSize + vertexShaderSize; + GLsizei totalLength = streamLength + sizeof(GUID) + pixelShaderSize + vertexShaderSize + geometryShaderSize; if (totalLength > bufSize) { if (length) @@ -1874,17 +1848,21 @@ bool ProgramBinary::save(void* binary, GLsizei bufSize, GLsizei *length) memcpy(ptr, streamData, streamLength); ptr += streamLength; - memcpy(ptr, &identifier->DeviceIdentifier, sizeof(GUID)); + memcpy(ptr, &identifier, sizeof(GUID)); ptr += sizeof(GUID); - result = mPixelExecutable->GetFunction(ptr, &pixelShaderSize); - ASSERT(SUCCEEDED(result)); + memcpy(ptr, mPixelExecutable->getFunction(), pixelShaderSize); ptr += pixelShaderSize; - result = mVertexExecutable->GetFunction(ptr, &vertexShaderSize); - ASSERT(SUCCEEDED(result)); + memcpy(ptr, mVertexExecutable->getFunction(), vertexShaderSize); ptr += vertexShaderSize; + if (mGeometryExecutable != NULL && geometryShaderSize > 0) + { + memcpy(ptr, mGeometryExecutable->getFunction(), geometryShaderSize); + ptr += geometryShaderSize; + } + ASSERT(ptr - totalLength == binary); } @@ -1924,69 +1902,54 @@ bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBin std::string pixelHLSL = fragmentShader->getHLSL(); std::string vertexHLSL = vertexShader->getHLSL(); - if (!linkVaryings(infoLog, pixelHLSL, vertexHLSL, fragmentShader, vertexShader)) + // Map the varyings to the register file + const Varying *packing[IMPLEMENTATION_MAX_VARYING_VECTORS][4] = {NULL}; + int registers = packVaryings(infoLog, packing, fragmentShader); + + if (registers < 0) { return false; } - Context *context = getContext(); - const char *vertexProfile = context->supportsShaderModel3() ? "vs_3_0" : "vs_2_0"; - const char *pixelProfile = context->supportsShaderModel3() ? "ps_3_0" : "ps_2_0"; - - ID3D10Blob *vertexBinary = compileToBinary(infoLog, vertexHLSL.c_str(), vertexProfile, &mConstantTableVS); - ID3D10Blob *pixelBinary = compileToBinary(infoLog, pixelHLSL.c_str(), pixelProfile, &mConstantTablePS); - - if (vertexBinary && pixelBinary) + if (!linkVaryings(infoLog, registers, packing, pixelHLSL, vertexHLSL, fragmentShader, vertexShader)) { - mVertexExecutable = getDisplay()->createVertexShader((DWORD*)vertexBinary->GetBufferPointer(), vertexBinary->GetBufferSize()); - if (!mVertexExecutable) - { - return error(GL_OUT_OF_MEMORY, false); - } - - mPixelExecutable = getDisplay()->createPixelShader((DWORD*)pixelBinary->GetBufferPointer(), pixelBinary->GetBufferSize()); - if (!mPixelExecutable) - { - mVertexExecutable->Release(); - mVertexExecutable = NULL; - return error(GL_OUT_OF_MEMORY, false); - } + return false; + } - vertexBinary->Release(); - pixelBinary->Release(); - vertexBinary = NULL; - pixelBinary = NULL; + bool success = true; + mVertexExecutable = mRenderer->compileToExecutable(infoLog, vertexHLSL.c_str(), rx::SHADER_VERTEX); + mPixelExecutable = mRenderer->compileToExecutable(infoLog, pixelHLSL.c_str(), rx::SHADER_PIXEL); - if (!linkAttributes(infoLog, attributeBindings, fragmentShader, vertexShader)) - { - return false; - } - - if (!linkUniforms(infoLog, GL_FRAGMENT_SHADER, mConstantTablePS)) - { - return false; - } + if (usesGeometryShader()) + { + std::string geometryHLSL = generateGeometryShaderHLSL(registers, packing, fragmentShader, vertexShader); + mGeometryExecutable = mRenderer->compileToExecutable(infoLog, geometryHLSL.c_str(), rx::SHADER_GEOMETRY); + } - if (!linkUniforms(infoLog, GL_VERTEX_SHADER, mConstantTableVS)) - { - return false; - } + if (!mVertexExecutable || !mPixelExecutable || (usesGeometryShader() && !mGeometryExecutable)) + { + infoLog.append("Failed to create D3D shaders."); + success = false; - // these uniforms are searched as already-decorated because gl_ and dx_ - // are reserved prefixes, and do not receive additional decoration - mDxDepthRangeLocation = getUniformLocation("dx_DepthRange"); - mDxDepthLocation = getUniformLocation("dx_Depth"); - mDxCoordLocation = getUniformLocation("dx_Coord"); - mDxHalfPixelSizeLocation = getUniformLocation("dx_HalfPixelSize"); - mDxFrontCCWLocation = getUniformLocation("dx_FrontCCW"); - mDxPointsOrLinesLocation = getUniformLocation("dx_PointsOrLines"); + delete mVertexExecutable; + mVertexExecutable = NULL; + delete mPixelExecutable; + mPixelExecutable = NULL; + delete mGeometryExecutable; + mGeometryExecutable = NULL; + } - context->markDxUniformsDirty(); + if (!linkAttributes(infoLog, attributeBindings, fragmentShader, vertexShader)) + { + success = false; + } - return true; + if (!linkUniforms(infoLog, vertexShader->getUniforms(), fragmentShader->getUniforms())) + { + success = false; } - return false; + return success; } // Determines the mapping between GL attributes and Direct3D 9 vertex stream usage indices @@ -2059,13 +2022,19 @@ bool ProgramBinary::linkAttributes(InfoLog &infoLog, const AttributeBindings &at return true; } -bool ProgramBinary::linkUniforms(InfoLog &infoLog, GLenum shader, D3DConstantTable *constantTable) +bool ProgramBinary::linkUniforms(InfoLog &infoLog, const sh::ActiveUniforms &vertexUniforms, const sh::ActiveUniforms &fragmentUniforms) { - for (unsigned int constantIndex = 0; constantIndex < constantTable->constants(); constantIndex++) + for (sh::ActiveUniforms::const_iterator uniform = vertexUniforms.begin(); uniform != vertexUniforms.end(); uniform++) { - const D3DConstant *constant = constantTable->getConstant(constantIndex); + if (!defineUniform(GL_VERTEX_SHADER, *uniform, infoLog)) + { + return false; + } + } - if (!defineUniform(infoLog, shader, constant)) + for (sh::ActiveUniforms::const_iterator uniform = fragmentUniforms.begin(); uniform != fragmentUniforms.end(); uniform++) + { + if (!defineUniform(GL_FRAGMENT_SHADER, *uniform, infoLog)) { return false; } @@ -2074,432 +2043,271 @@ bool ProgramBinary::linkUniforms(InfoLog &infoLog, GLenum shader, D3DConstantTab return true; } -// Adds the description of a constant found in the binary shader to the list of uniforms -// Returns true if succesful (uniform not already defined) -bool ProgramBinary::defineUniform(InfoLog &infoLog, GLenum shader, const D3DConstant *constant, std::string name) +bool ProgramBinary::defineUniform(GLenum shader, const sh::Uniform &constant, InfoLog &infoLog) { - if (constant->registerSet == D3DConstant::RS_SAMPLER) + if (constant.type == GL_SAMPLER_2D || + constant.type == GL_SAMPLER_CUBE) { - for (unsigned int i = 0; i < constant->registerCount; i++) + unsigned int samplerIndex = constant.registerIndex; + + do { - const D3DConstant *psConstant = mConstantTablePS->getConstantByName(constant->name.c_str()); - const D3DConstant *vsConstant = mConstantTableVS->getConstantByName(constant->name.c_str()); - - if (psConstant) + if (shader == GL_VERTEX_SHADER) { - unsigned int samplerIndex = psConstant->registerIndex + i; - - if (samplerIndex < MAX_TEXTURE_IMAGE_UNITS) + if (samplerIndex < mRenderer->getMaxVertexTextureImageUnits()) { - mSamplersPS[samplerIndex].active = true; - mSamplersPS[samplerIndex].textureType = (constant->type == D3DConstant::PT_SAMPLERCUBE) ? TEXTURE_CUBE : TEXTURE_2D; - mSamplersPS[samplerIndex].logicalTextureUnit = 0; - mUsedPixelSamplerRange = std::max(samplerIndex + 1, mUsedPixelSamplerRange); + mSamplersVS[samplerIndex].active = true; + mSamplersVS[samplerIndex].textureType = (constant.type == GL_SAMPLER_CUBE) ? TEXTURE_CUBE : TEXTURE_2D; + mSamplersVS[samplerIndex].logicalTextureUnit = 0; + mUsedVertexSamplerRange = std::max(samplerIndex + 1, mUsedVertexSamplerRange); } else { - infoLog.append("Pixel shader sampler count exceeds MAX_TEXTURE_IMAGE_UNITS (%d).", MAX_TEXTURE_IMAGE_UNITS); + infoLog.append("Vertex shader sampler count exceeds the maximum vertex texture units (%d).", mRenderer->getMaxVertexTextureImageUnits()); return false; } } - - if (vsConstant) + else if (shader == GL_FRAGMENT_SHADER) { - unsigned int samplerIndex = vsConstant->registerIndex + i; - - if (samplerIndex < getContext()->getMaximumVertexTextureImageUnits()) + if (samplerIndex < MAX_TEXTURE_IMAGE_UNITS) { - mSamplersVS[samplerIndex].active = true; - mSamplersVS[samplerIndex].textureType = (constant->type == D3DConstant::PT_SAMPLERCUBE) ? TEXTURE_CUBE : TEXTURE_2D; - mSamplersVS[samplerIndex].logicalTextureUnit = 0; - mUsedVertexSamplerRange = std::max(samplerIndex + 1, mUsedVertexSamplerRange); + mSamplersPS[samplerIndex].active = true; + mSamplersPS[samplerIndex].textureType = (constant.type == GL_SAMPLER_CUBE) ? TEXTURE_CUBE : TEXTURE_2D; + mSamplersPS[samplerIndex].logicalTextureUnit = 0; + mUsedPixelSamplerRange = std::max(samplerIndex + 1, mUsedPixelSamplerRange); } else { - infoLog.append("Vertex shader sampler count exceeds MAX_VERTEX_TEXTURE_IMAGE_UNITS (%d).", getContext()->getMaximumVertexTextureImageUnits()); + infoLog.append("Pixel shader sampler count exceeds MAX_TEXTURE_IMAGE_UNITS (%d).", MAX_TEXTURE_IMAGE_UNITS); return false; } } + else UNREACHABLE(); + + samplerIndex++; } + while (samplerIndex < constant.registerIndex + constant.arraySize); } - switch(constant->typeClass) - { - case D3DConstant::CLASS_STRUCT: - { - for (unsigned int arrayIndex = 0; arrayIndex < constant->elements; arrayIndex++) - { - for (unsigned int field = 0; field < constant->structMembers[arrayIndex].size(); field++) - { - const D3DConstant *fieldConstant = constant->structMembers[arrayIndex][field]; + Uniform *uniform = NULL; + GLint location = getUniformLocation(constant.name); - std::string structIndex = (constant->elements > 1) ? ("[" + str(arrayIndex) + "]") : ""; + if (location >= 0) // Previously defined, type and precision must match + { + uniform = mUniforms[mUniformIndex[location].index]; - if (!defineUniform(infoLog, shader, fieldConstant, name + constant->name + structIndex + ".")) - { - return false; - } - } - } + if (uniform->type != constant.type) + { + infoLog.append("Types for uniform %s do not match between the vertex and fragment shader", uniform->name.c_str()); + return false; + } - return true; + if (uniform->precision != constant.precision) + { + infoLog.append("Precisions for uniform %s do not match between the vertex and fragment shader", uniform->name.c_str()); + return false; } - case D3DConstant::CLASS_SCALAR: - case D3DConstant::CLASS_VECTOR: - case D3DConstant::CLASS_MATRIX_COLUMNS: - case D3DConstant::CLASS_OBJECT: - return defineUniform(shader, constant, name + constant->name); - default: - UNREACHABLE(); - return false; } -} - -bool ProgramBinary::defineUniform(GLenum shader, const D3DConstant *constant, const std::string &_name) -{ - Uniform *uniform = createUniform(constant, _name); + else + { + uniform = new Uniform(constant.type, constant.precision, constant.name, constant.arraySize); + } - if(!uniform) + if (!uniform) { return false; } - // Check if already defined - GLint location = getUniformLocation(uniform->name); - GLenum type = uniform->type; - - if (location >= 0) + if (shader == GL_FRAGMENT_SHADER) { - delete uniform; - uniform = mUniforms[mUniformIndex[location].index]; + uniform->psRegisterIndex = constant.registerIndex; } - - if (shader == GL_FRAGMENT_SHADER) uniform->ps.set(constant); - if (shader == GL_VERTEX_SHADER) uniform->vs.set(constant); + else if (shader == GL_VERTEX_SHADER) + { + uniform->vsRegisterIndex = constant.registerIndex; + } + else UNREACHABLE(); if (location >= 0) { - return uniform->type == type; + return uniform->type == constant.type; } mUniforms.push_back(uniform); unsigned int uniformIndex = mUniforms.size() - 1; - for (unsigned int i = 0; i < uniform->arraySize; ++i) + for (unsigned int i = 0; i < uniform->elementCount(); i++) { - mUniformIndex.push_back(UniformLocation(_name, i, uniformIndex)); + mUniformIndex.push_back(UniformLocation(constant.name, i, uniformIndex)); } - return true; -} - -Uniform *ProgramBinary::createUniform(const D3DConstant *constant, const std::string &_name) -{ - if (constant->rows == 1) // Vectors and scalars + if (shader == GL_VERTEX_SHADER) { - switch (constant->type) + if (constant.registerIndex + uniform->registerCount > mRenderer->getReservedVertexUniformVectors() + mRenderer->getMaxVertexUniformVectors()) { - case D3DConstant::PT_SAMPLER2D: - switch (constant->columns) - { - case 1: return new Uniform(GL_SAMPLER_2D, _name, constant->elements); - default: UNREACHABLE(); - } - break; - case D3DConstant::PT_SAMPLERCUBE: - switch (constant->columns) - { - case 1: return new Uniform(GL_SAMPLER_CUBE, _name, constant->elements); - default: UNREACHABLE(); - } - break; - case D3DConstant::PT_BOOL: - switch (constant->columns) - { - case 1: return new Uniform(GL_BOOL, _name, constant->elements); - case 2: return new Uniform(GL_BOOL_VEC2, _name, constant->elements); - case 3: return new Uniform(GL_BOOL_VEC3, _name, constant->elements); - case 4: return new Uniform(GL_BOOL_VEC4, _name, constant->elements); - default: UNREACHABLE(); - } - break; - case D3DConstant::PT_INT: - switch (constant->columns) - { - case 1: return new Uniform(GL_INT, _name, constant->elements); - case 2: return new Uniform(GL_INT_VEC2, _name, constant->elements); - case 3: return new Uniform(GL_INT_VEC3, _name, constant->elements); - case 4: return new Uniform(GL_INT_VEC4, _name, constant->elements); - default: UNREACHABLE(); - } - break; - case D3DConstant::PT_FLOAT: - switch (constant->columns) - { - case 1: return new Uniform(GL_FLOAT, _name, constant->elements); - case 2: return new Uniform(GL_FLOAT_VEC2, _name, constant->elements); - case 3: return new Uniform(GL_FLOAT_VEC3, _name, constant->elements); - case 4: return new Uniform(GL_FLOAT_VEC4, _name, constant->elements); - default: UNREACHABLE(); - } - break; - default: - UNREACHABLE(); + infoLog.append("Vertex shader active uniforms exceed GL_MAX_VERTEX_UNIFORM_VECTORS (%u)", mRenderer->getMaxVertexUniformVectors()); + return false; } } - else if (constant->rows == constant->columns) // Square matrices + else if (shader == GL_FRAGMENT_SHADER) { - switch (constant->type) + if (constant.registerIndex + uniform->registerCount > mRenderer->getReservedFragmentUniformVectors() + mRenderer->getMaxFragmentUniformVectors()) { - case D3DConstant::PT_FLOAT: - switch (constant->rows) - { - case 2: return new Uniform(GL_FLOAT_MAT2, _name, constant->elements); - case 3: return new Uniform(GL_FLOAT_MAT3, _name, constant->elements); - case 4: return new Uniform(GL_FLOAT_MAT4, _name, constant->elements); - default: UNREACHABLE(); - } - break; - default: UNREACHABLE(); + infoLog.append("Fragment shader active uniforms exceed GL_MAX_FRAGMENT_UNIFORM_VECTORS (%u)", mRenderer->getMaxFragmentUniformVectors()); + return false; } } else UNREACHABLE(); - return 0; + return true; } -// This method needs to match OutputHLSL::decorate -std::string ProgramBinary::decorateAttribute(const std::string &name) +std::string ProgramBinary::generateGeometryShaderHLSL(int registers, const Varying *packing[][4], FragmentShader *fragmentShader, VertexShader *vertexShader) const { - if (name.compare(0, 3, "gl_") != 0 && name.compare(0, 3, "dx_") != 0) - { - return "_" + name; - } - - return name; + // for now we only handle point sprite emulation + ASSERT(usesPointSpriteEmulation()); + return generatePointSpriteHLSL(registers, packing, fragmentShader, vertexShader); } -std::string ProgramBinary::undecorateUniform(const std::string &_name) +std::string ProgramBinary::generatePointSpriteHLSL(int registers, const Varying *packing[][4], FragmentShader *fragmentShader, VertexShader *vertexShader) const { - std::string name = _name; - - // Remove any structure field decoration - size_t pos = 0; - while ((pos = name.find("._", pos)) != std::string::npos) - { - name.replace(pos, 2, "."); - } + ASSERT(registers >= 0); + ASSERT(vertexShader->mUsesPointSize); + ASSERT(mRenderer->getMajorShaderModel() >= 4); - // Remove the leading decoration - if (name[0] == '_') - { - return name.substr(1); - } - else if (name.compare(0, 3, "ar_") == 0) - { - return name.substr(3); - } - - return name; -} + std::string geomHLSL; -void ProgramBinary::applyUniformnbv(Uniform *targetUniform, GLsizei count, int width, const GLboolean *v) -{ - float vector[D3D9_MAX_FLOAT_CONSTANTS * 4]; - BOOL boolVector[D3D9_MAX_BOOL_CONSTANTS]; + std::string varyingSemantic = "TEXCOORD"; - if (targetUniform->ps.float4Index >= 0 || targetUniform->vs.float4Index >= 0) - { - ASSERT(count <= D3D9_MAX_FLOAT_CONSTANTS); - for (int i = 0; i < count; i++) - { - for (int j = 0; j < 4; j++) - { - if (j < width) - { - vector[i * 4 + j] = (v[i * width + j] == GL_FALSE) ? 0.0f : 1.0f; - } - else - { - vector[i * 4 + j] = 0.0f; - } - } - } - } + std::string fragCoordSemantic; + std::string pointCoordSemantic; - if (targetUniform->ps.boolIndex >= 0 || targetUniform->vs.boolIndex >= 0) - { - int psCount = targetUniform->ps.boolIndex >= 0 ? targetUniform->ps.registerCount : 0; - int vsCount = targetUniform->vs.boolIndex >= 0 ? targetUniform->vs.registerCount : 0; - int copyCount = std::min(count * width, std::max(psCount, vsCount)); - ASSERT(copyCount <= D3D9_MAX_BOOL_CONSTANTS); - for (int i = 0; i < copyCount; i++) - { - boolVector[i] = v[i] != GL_FALSE; - } - } + int reservedRegisterIndex = registers; - if (targetUniform->ps.float4Index >= 0) - { - mDevice->SetPixelShaderConstantF(targetUniform->ps.float4Index, vector, targetUniform->ps.registerCount); - } - - if (targetUniform->ps.boolIndex >= 0) - { - mDevice->SetPixelShaderConstantB(targetUniform->ps.boolIndex, boolVector, targetUniform->ps.registerCount); - } - - if (targetUniform->vs.float4Index >= 0) + if (fragmentShader->mUsesFragCoord) { - mDevice->SetVertexShaderConstantF(targetUniform->vs.float4Index, vector, targetUniform->vs.registerCount); + fragCoordSemantic = varyingSemantic + str(reservedRegisterIndex++); } - - if (targetUniform->vs.boolIndex >= 0) + + if (fragmentShader->mUsesPointCoord) { - mDevice->SetVertexShaderConstantB(targetUniform->vs.boolIndex, boolVector, targetUniform->vs.registerCount); + pointCoordSemantic = varyingSemantic + str(reservedRegisterIndex++); } -} -bool ProgramBinary::applyUniformnfv(Uniform *targetUniform, const GLfloat *v) -{ - if (targetUniform->ps.registerCount) + geomHLSL += "uniform float4 dx_ViewCoords : register(c1);\n" + "\n" + "struct GS_INPUT\n" + "{\n"; + + for (int r = 0; r < registers; r++) { - mDevice->SetPixelShaderConstantF(targetUniform->ps.float4Index, v, targetUniform->ps.registerCount); + int registerSize = packing[r][3] ? 4 : (packing[r][2] ? 3 : (packing[r][1] ? 2 : 1)); + + geomHLSL += " float" + str(registerSize) + " v" + str(r) + " : " + varyingSemantic + str(r) + ";\n"; } - if (targetUniform->vs.registerCount) + if (fragmentShader->mUsesFragCoord) { - mDevice->SetVertexShaderConstantF(targetUniform->vs.float4Index, v, targetUniform->vs.registerCount); + geomHLSL += " float4 gl_FragCoord : " + fragCoordSemantic + ";\n"; } - return true; -} - -bool ProgramBinary::applyUniform1iv(Uniform *targetUniform, GLsizei count, const GLint *v) -{ - ASSERT(count <= D3D9_MAX_FLOAT_CONSTANTS); - Vector4 vector[D3D9_MAX_FLOAT_CONSTANTS]; + geomHLSL += " float gl_PointSize : PSIZE;\n" + " float4 gl_Position : SV_Position;\n" + "};\n" + "\n" + "struct GS_OUTPUT\n" + "{\n"; - for (int i = 0; i < count; i++) + for (int r = 0; r < registers; r++) { - vector[i] = Vector4((float)v[i], 0, 0, 0); + int registerSize = packing[r][3] ? 4 : (packing[r][2] ? 3 : (packing[r][1] ? 2 : 1)); + + geomHLSL += " float" + str(registerSize) + " v" + str(r) + " : " + varyingSemantic + str(r) + ";\n"; } - if (targetUniform->ps.registerCount) + if (fragmentShader->mUsesFragCoord) { - if (targetUniform->ps.samplerIndex >= 0) - { - unsigned int firstIndex = targetUniform->ps.samplerIndex; - - for (int i = 0; i < count; i++) - { - unsigned int samplerIndex = firstIndex + i; - - if (samplerIndex < MAX_TEXTURE_IMAGE_UNITS) - { - ASSERT(mSamplersPS[samplerIndex].active); - mSamplersPS[samplerIndex].logicalTextureUnit = v[i]; - } - } - } - else - { - ASSERT(targetUniform->ps.float4Index >= 0); - mDevice->SetPixelShaderConstantF(targetUniform->ps.float4Index, (const float*)vector, targetUniform->ps.registerCount); - } + geomHLSL += " float4 gl_FragCoord : " + fragCoordSemantic + ";\n"; } - if (targetUniform->vs.registerCount) + if (fragmentShader->mUsesPointCoord) { - if (targetUniform->vs.samplerIndex >= 0) - { - unsigned int firstIndex = targetUniform->vs.samplerIndex; - - for (int i = 0; i < count; i++) - { - unsigned int samplerIndex = firstIndex + i; - - if (samplerIndex < MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF) - { - ASSERT(mSamplersVS[samplerIndex].active); - mSamplersVS[samplerIndex].logicalTextureUnit = v[i]; - } - } - } - else - { - ASSERT(targetUniform->vs.float4Index >= 0); - mDevice->SetVertexShaderConstantF(targetUniform->vs.float4Index, (const float *)vector, targetUniform->vs.registerCount); - } + geomHLSL += " float2 gl_PointCoord : " + pointCoordSemantic + ";\n"; } - return true; -} - -bool ProgramBinary::applyUniform2iv(Uniform *targetUniform, GLsizei count, const GLint *v) -{ - ASSERT(count <= D3D9_MAX_FLOAT_CONSTANTS); - Vector4 vector[D3D9_MAX_FLOAT_CONSTANTS]; + geomHLSL += " float gl_PointSize : PSIZE;\n" + " float4 gl_Position : SV_Position;\n" + "};\n" + "\n" + "static float2 pointSpriteCorners[] = \n" + "{\n" + " float2( 0.5f, -0.5f),\n" + " float2( 0.5f, 0.5f),\n" + " float2(-0.5f, -0.5f),\n" + " float2(-0.5f, 0.5f)\n" + "};\n" + "\n" + "static float2 pointSpriteTexcoords[] = \n" + "{\n" + " float2(1.0f, 1.0f),\n" + " float2(1.0f, 0.0f),\n" + " float2(0.0f, 1.0f),\n" + " float2(0.0f, 0.0f)\n" + "};\n" + "\n" + "static float minPointSize = " + str(ALIASED_POINT_SIZE_RANGE_MIN) + ".0f;\n" + "static float maxPointSize = " + str(mRenderer->getMaxPointSize()) + ".0f;\n" + "\n" + "[maxvertexcount(4)]\n" + "void main(point GS_INPUT input[1], inout TriangleStream outStream)\n" + "{\n" + " GS_OUTPUT output = (GS_OUTPUT)0;\n" + " output.gl_PointSize = input[0].gl_PointSize;\n"; - for (int i = 0; i < count; i++) + for (int r = 0; r < registers; r++) { - vector[i] = Vector4((float)v[0], (float)v[1], 0, 0); - - v += 2; + geomHLSL += " output.v" + str(r) + " = input[0].v" + str(r) + ";\n"; } - applyUniformniv(targetUniform, count, vector); - - return true; -} - -bool ProgramBinary::applyUniform3iv(Uniform *targetUniform, GLsizei count, const GLint *v) -{ - ASSERT(count <= D3D9_MAX_FLOAT_CONSTANTS); - Vector4 vector[D3D9_MAX_FLOAT_CONSTANTS]; - - for (int i = 0; i < count; i++) + if (fragmentShader->mUsesFragCoord) { - vector[i] = Vector4((float)v[0], (float)v[1], (float)v[2], 0); - - v += 3; + geomHLSL += " output.gl_FragCoord = input[0].gl_FragCoord;\n"; } - applyUniformniv(targetUniform, count, vector); + geomHLSL += " \n" + " float gl_PointSize = clamp(input[0].gl_PointSize, minPointSize, maxPointSize);\n" + " float4 gl_Position = input[0].gl_Position;\n" + " float2 viewportScale = float2(1.0f / dx_ViewCoords.x, 1.0f / dx_ViewCoords.y) * gl_Position.w;\n"; - return true; -} - -bool ProgramBinary::applyUniform4iv(Uniform *targetUniform, GLsizei count, const GLint *v) -{ - ASSERT(count <= D3D9_MAX_FLOAT_CONSTANTS); - Vector4 vector[D3D9_MAX_FLOAT_CONSTANTS]; - - for (int i = 0; i < count; i++) + for (int corner = 0; corner < 4; corner++) { - vector[i] = Vector4((float)v[0], (float)v[1], (float)v[2], (float)v[3]); + geomHLSL += " \n" + " output.gl_Position = gl_Position + float4(pointSpriteCorners[" + str(corner) + "] * viewportScale * gl_PointSize, 0.0f, 0.0f);\n"; - v += 4; + if (fragmentShader->mUsesPointCoord) + { + geomHLSL += " output.gl_PointCoord = pointSpriteTexcoords[" + str(corner) + "];\n"; + } + + geomHLSL += " outStream.Append(output);\n"; } - applyUniformniv(targetUniform, count, vector); + geomHLSL += " \n" + " outStream.RestartStrip();\n" + "}\n"; - return true; + return geomHLSL; } -void ProgramBinary::applyUniformniv(Uniform *targetUniform, GLsizei count, const Vector4 *vector) +// This method needs to match OutputHLSL::decorate +std::string ProgramBinary::decorateAttribute(const std::string &name) { - if (targetUniform->ps.registerCount) - { - ASSERT(targetUniform->ps.float4Index >= 0); - mDevice->SetPixelShaderConstantF(targetUniform->ps.float4Index, (const float *)vector, targetUniform->ps.registerCount); - } - - if (targetUniform->vs.registerCount) + if (name.compare(0, 3, "gl_") != 0 && name.compare(0, 3, "dx_") != 0) { - ASSERT(targetUniform->vs.float4Index >= 0); - mDevice->SetVertexShaderConstantF(targetUniform->vs.float4Index, (const float *)vector, targetUniform->vs.registerCount); + return "_" + name; } + + return name; } bool ProgramBinary::isValidated() const @@ -2507,7 +2315,7 @@ bool ProgramBinary::isValidated() const return mValidated; } -void ProgramBinary::getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) +void ProgramBinary::getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const { // Skip over inactive attributes unsigned int activeAttribute = 0; @@ -2545,7 +2353,7 @@ void ProgramBinary::getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *l *type = mLinkedAttribute[attribute].type; } -GLint ProgramBinary::getActiveAttributeCount() +GLint ProgramBinary::getActiveAttributeCount() const { int count = 0; @@ -2560,7 +2368,7 @@ GLint ProgramBinary::getActiveAttributeCount() return count; } -GLint ProgramBinary::getActiveAttributeMaxLength() +GLint ProgramBinary::getActiveAttributeMaxLength() const { int maxLength = 0; @@ -2575,33 +2383,15 @@ GLint ProgramBinary::getActiveAttributeMaxLength() return maxLength; } -void ProgramBinary::getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) +void ProgramBinary::getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const { - // Skip over internal uniforms - unsigned int activeUniform = 0; - unsigned int uniform; - for (uniform = 0; uniform < mUniforms.size(); uniform++) - { - if (mUniforms[uniform]->name.compare(0, 3, "dx_") == 0) - { - continue; - } - - if (activeUniform == index) - { - break; - } - - activeUniform++; - } - - ASSERT(uniform < mUniforms.size()); // index must be smaller than getActiveUniformCount() + ASSERT(index < mUniforms.size()); // index must be smaller than getActiveUniformCount() if (bufsize > 0) { - std::string string = mUniforms[uniform]->name; + std::string string = mUniforms[index]->name; - if (mUniforms[uniform]->isArray()) + if (mUniforms[index]->isArray()) { string += "[0]"; } @@ -2615,35 +2405,24 @@ void ProgramBinary::getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *len } } - *size = mUniforms[uniform]->arraySize; + *size = mUniforms[index]->elementCount(); - *type = mUniforms[uniform]->type; + *type = mUniforms[index]->type; } -GLint ProgramBinary::getActiveUniformCount() +GLint ProgramBinary::getActiveUniformCount() const { - int count = 0; - - unsigned int numUniforms = mUniforms.size(); - for (unsigned int uniformIndex = 0; uniformIndex < numUniforms; uniformIndex++) - { - if (mUniforms[uniformIndex]->name.compare(0, 3, "dx_") != 0) - { - count++; - } - } - - return count; + return mUniforms.size(); } -GLint ProgramBinary::getActiveUniformMaxLength() +GLint ProgramBinary::getActiveUniformMaxLength() const { int maxLength = 0; unsigned int numUniforms = mUniforms.size(); for (unsigned int uniformIndex = 0; uniformIndex < numUniforms; uniformIndex++) { - if (!mUniforms[uniformIndex]->name.empty() && mUniforms[uniformIndex]->name.compare(0, 3, "dx_") != 0) + if (!mUniforms[uniformIndex]->name.empty()) { int length = (int)(mUniforms[uniformIndex]->name.length() + 1); if (mUniforms[uniformIndex]->isArray()) @@ -2676,10 +2455,10 @@ bool ProgramBinary::validateSamplers(InfoLog *infoLog) // texture image unit, and this is the current program, then ValidateProgram will fail, and // DrawArrays and DrawElements will issue the INVALID_OPERATION error. - const unsigned int maxCombinedTextureImageUnits = getContext()->getMaximumCombinedTextureImageUnits(); - TextureType textureUnitType[MAX_COMBINED_TEXTURE_IMAGE_UNITS_VTF]; + const unsigned int maxCombinedTextureImageUnits = mRenderer->getMaxCombinedTextureImageUnits(); + TextureType textureUnitType[IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS]; - for (unsigned int i = 0; i < MAX_COMBINED_TEXTURE_IMAGE_UNITS_VTF; ++i) + for (unsigned int i = 0; i < IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS; ++i) { textureUnitType[i] = TEXTURE_UNKNOWN; } @@ -2694,7 +2473,7 @@ bool ProgramBinary::validateSamplers(InfoLog *infoLog) { if (infoLog) { - infoLog->append("Sampler uniform (%d) exceeds MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, maxCombinedTextureImageUnits); + infoLog->append("Sampler uniform (%d) exceeds IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, maxCombinedTextureImageUnits); } return false; @@ -2729,7 +2508,7 @@ bool ProgramBinary::validateSamplers(InfoLog *infoLog) { if (infoLog) { - infoLog->append("Sampler uniform (%d) exceeds MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, maxCombinedTextureImageUnits); + infoLog->append("Sampler uniform (%d) exceeds IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, maxCombinedTextureImageUnits); } return false; @@ -2757,38 +2536,51 @@ bool ProgramBinary::validateSamplers(InfoLog *infoLog) return true; } -GLint ProgramBinary::getDxDepthRangeLocation() const +ProgramBinary::Sampler::Sampler() : active(false), logicalTextureUnit(0), textureType(TEXTURE_2D) { - return mDxDepthRangeLocation; } -GLint ProgramBinary::getDxDepthLocation() const +struct AttributeSorter { - return mDxDepthLocation; -} + AttributeSorter(const int (&semanticIndices)[MAX_VERTEX_ATTRIBS]) + : originalIndices(semanticIndices) + { + for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) + { + indices[i] = i; + } -GLint ProgramBinary::getDxCoordLocation() const -{ - return mDxCoordLocation; -} + std::sort(&indices[0], &indices[MAX_VERTEX_ATTRIBS], *this); + } -GLint ProgramBinary::getDxHalfPixelSizeLocation() const -{ - return mDxHalfPixelSizeLocation; -} + bool operator()(int a, int b) + { + return originalIndices[a] == -1 ? false : originalIndices[a] < originalIndices[b]; + } -GLint ProgramBinary::getDxFrontCCWLocation() const -{ - return mDxFrontCCWLocation; -} + int indices[MAX_VERTEX_ATTRIBS]; + const int (&originalIndices)[MAX_VERTEX_ATTRIBS]; +}; -GLint ProgramBinary::getDxPointsOrLinesLocation() const +void ProgramBinary::sortAttributesByLayout(rx::TranslatedAttribute attributes[MAX_VERTEX_ATTRIBS], int sortedSemanticIndices[MAX_VERTEX_ATTRIBS]) const { - return mDxPointsOrLinesLocation; -} + AttributeSorter sorter(mSemanticIndex); -ProgramBinary::Sampler::Sampler() : active(false), logicalTextureUnit(0), textureType(TEXTURE_2D) -{ + int oldIndices[MAX_VERTEX_ATTRIBS]; + rx::TranslatedAttribute oldTranslatedAttributes[MAX_VERTEX_ATTRIBS]; + + for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) + { + oldIndices[i] = mSemanticIndex[i]; + oldTranslatedAttributes[i] = attributes[i]; + } + + for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) + { + int oldIndex = sorter.indices[i]; + sortedSemanticIndices[i] = oldIndices[oldIndex]; + attributes[i] = oldTranslatedAttributes[oldIndex]; + } } } diff --git a/src/3rdparty/angle/src/libGLESv2/ProgramBinary.h b/src/3rdparty/angle/src/libGLESv2/ProgramBinary.h index 9ffe70b617..2386c0bd6f 100644 --- a/src/3rdparty/angle/src/libGLESv2/ProgramBinary.h +++ b/src/3rdparty/angle/src/libGLESv2/ProgramBinary.h @@ -14,71 +14,30 @@ #include #include -#include #include #include -#include "libGLESv2/Context.h" -#include "libGLESv2/D3DConstantTable.h" +#include "common/RefCountObject.h" +#include "angletypes.h" #include "libGLESv2/mathutil.h" +#include "libGLESv2/Uniform.h" #include "libGLESv2/Shader.h" +#include "libGLESv2/Constants.h" + +namespace rx +{ +class ShaderExecutable; +class Renderer; +struct TranslatedAttribute; +} namespace gl { class FragmentShader; class VertexShader; - -// Helper struct representing a single shader uniform -struct Uniform -{ - Uniform(GLenum type, const std::string &_name, unsigned int arraySize); - - ~Uniform(); - - bool isArray(); - - const GLenum type; - const std::string _name; // Decorated name - const std::string name; // Undecorated name - const unsigned int arraySize; - - unsigned char *data; - bool dirty; - - struct RegisterInfo - { - RegisterInfo() - { - float4Index = -1; - samplerIndex = -1; - boolIndex = -1; - registerCount = 0; - } - - void set(const D3DConstant *constant) - { - switch(constant->registerSet) - { - case D3DConstant::RS_BOOL: boolIndex = constant->registerIndex; break; - case D3DConstant::RS_FLOAT4: float4Index = constant->registerIndex; break; - case D3DConstant::RS_SAMPLER: samplerIndex = constant->registerIndex; break; - default: UNREACHABLE(); - } - - ASSERT(registerCount == 0 || registerCount == (int)constant->registerCount); - registerCount = constant->registerCount; - } - - int float4Index; - int samplerIndex; - int boolIndex; - - int registerCount; - }; - - RegisterInfo ps; - RegisterInfo vs; -}; +class InfoLog; +class AttributeBindings; +struct Varying; // Struct used for correlating uniforms/elements of uniform arrays to handles struct UniformLocation @@ -87,7 +46,7 @@ struct UniformLocation { } - UniformLocation(const std::string &_name, unsigned int element, unsigned int index); + UniformLocation(const std::string &name, unsigned int element, unsigned int index); std::string name; unsigned int element; @@ -98,11 +57,12 @@ struct UniformLocation class ProgramBinary : public RefCountObject { public: - ProgramBinary(); + explicit ProgramBinary(rx::Renderer *renderer); ~ProgramBinary(); - IDirect3DPixelShader9 *getPixelShader(); - IDirect3DVertexShader9 *getVertexShader(); + rx::ShaderExecutable *getPixelExecutable(); + rx::ShaderExecutable *getVertexExecutable(); + rx::ShaderExecutable *getGeometryExecutable(); GLuint getAttributeLocation(const char *name); int getSemanticIndex(int attributeIndex); @@ -111,6 +71,8 @@ class ProgramBinary : public RefCountObject TextureType getSamplerTextureType(SamplerType type, unsigned int samplerIndex); GLint getUsedSamplerRange(SamplerType type); bool usesPointSize() const; + bool usesPointSpriteEmulation() const; + bool usesGeometryShader() const; GLint getUniformLocation(std::string name); bool setUniform1fv(GLint location, GLsizei count, const GLfloat *v); @@ -128,13 +90,6 @@ class ProgramBinary : public RefCountObject bool getUniformfv(GLint location, GLsizei *bufSize, GLfloat *params); bool getUniformiv(GLint location, GLsizei *bufSize, GLint *params); - GLint getDxDepthRangeLocation() const; - GLint getDxDepthLocation() const; - GLint getDxCoordLocation() const; - GLint getDxHalfPixelSizeLocation() const; - GLint getDxFrontCCWLocation() const; - GLint getDxPointsOrLinesLocation() const; - void dirtyAllUniforms(); void applyUniforms(); @@ -145,13 +100,13 @@ class ProgramBinary : public RefCountObject bool link(InfoLog &infoLog, const AttributeBindings &attributeBindings, FragmentShader *fragmentShader, VertexShader *vertexShader); void getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders); - void getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name); - GLint getActiveAttributeCount(); - GLint getActiveAttributeMaxLength(); + void getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const; + GLint getActiveAttributeCount() const; + GLint getActiveAttributeMaxLength() const; - void getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name); - GLint getActiveUniformCount(); - GLint getActiveUniformMaxLength(); + void getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const; + GLint getActiveUniformCount() const; + GLint getActiveUniformMaxLength() const; void validate(InfoLog &infoLog); bool validateSamplers(InfoLog *infoLog); @@ -159,39 +114,31 @@ class ProgramBinary : public RefCountObject unsigned int getSerial() const; + void sortAttributesByLayout(rx::TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS], int sortedSemanticIndices[MAX_VERTEX_ATTRIBS]) const; + static std::string decorateAttribute(const std::string &name); // Prepend an underscore - static std::string undecorateUniform(const std::string &_name); // Remove leading underscore private: DISALLOW_COPY_AND_ASSIGN(ProgramBinary); - ID3D10Blob *compileToBinary(InfoLog &infoLog, const char *hlsl, const char *profile, D3DConstantTable **constantTable); - int packVaryings(InfoLog &infoLog, const Varying *packing[][4], FragmentShader *fragmentShader); - bool linkVaryings(InfoLog &infoLog, std::string& pixelHLSL, std::string& vertexHLSL, FragmentShader *fragmentShader, VertexShader *vertexShader); + bool linkVaryings(InfoLog &infoLog, int registers, const Varying *packing[][4], + std::string& pixelHLSL, std::string& vertexHLSL, + FragmentShader *fragmentShader, VertexShader *vertexShader); bool linkAttributes(InfoLog &infoLog, const AttributeBindings &attributeBindings, FragmentShader *fragmentShader, VertexShader *vertexShader); - bool linkUniforms(InfoLog &infoLog, GLenum shader, D3DConstantTable *constantTable); - bool defineUniform(InfoLog &infoLog, GLenum shader, const D3DConstant *constant, std::string name = ""); - bool defineUniform(GLenum shader, const D3DConstant *constant, const std::string &name); - Uniform *createUniform( const D3DConstant *constant, const std::string &name); - bool applyUniformnfv(Uniform *targetUniform, const GLfloat *v); - bool applyUniform1iv(Uniform *targetUniform, GLsizei count, const GLint *v); - bool applyUniform2iv(Uniform *targetUniform, GLsizei count, const GLint *v); - bool applyUniform3iv(Uniform *targetUniform, GLsizei count, const GLint *v); - bool applyUniform4iv(Uniform *targetUniform, GLsizei count, const GLint *v); - void applyUniformniv(Uniform *targetUniform, GLsizei count, const Vector4 *vector); - void applyUniformnbv(Uniform *targetUniform, GLsizei count, int width, const GLboolean *v); + bool linkUniforms(InfoLog &infoLog, const sh::ActiveUniforms &vertexUniforms, const sh::ActiveUniforms &fragmentUniforms); + bool defineUniform(GLenum shader, const sh::Uniform &constant, InfoLog &infoLog); + + std::string generateGeometryShaderHLSL(int registers, const Varying *packing[][4], FragmentShader *fragmentShader, VertexShader *vertexShader) const; + std::string generatePointSpriteHLSL(int registers, const Varying *packing[][4], FragmentShader *fragmentShader, VertexShader *vertexShader) const; - IDirect3DDevice9 *mDevice; + rx::Renderer *const mRenderer; - IDirect3DPixelShader9 *mPixelExecutable; - IDirect3DVertexShader9 *mVertexExecutable; - - // These are only used during linking. - D3DConstantTable *mConstantTablePS; - D3DConstantTable *mConstantTableVS; + rx::ShaderExecutable *mPixelExecutable; + rx::ShaderExecutable *mVertexExecutable; + rx::ShaderExecutable *mGeometryExecutable; Attribute mLinkedAttribute[MAX_VERTEX_ATTRIBS]; int mSemanticIndex[MAX_VERTEX_ATTRIBS]; @@ -206,23 +153,15 @@ class ProgramBinary : public RefCountObject }; Sampler mSamplersPS[MAX_TEXTURE_IMAGE_UNITS]; - Sampler mSamplersVS[MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF]; + Sampler mSamplersVS[IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS]; GLuint mUsedVertexSamplerRange; GLuint mUsedPixelSamplerRange; bool mUsesPointSize; - typedef std::vector UniformArray; UniformArray mUniforms; typedef std::vector UniformIndex; UniformIndex mUniformIndex; - GLint mDxDepthRangeLocation; - GLint mDxDepthLocation; - GLint mDxCoordLocation; - GLint mDxHalfPixelSizeLocation; - GLint mDxFrontCCWLocation; - GLint mDxPointsOrLinesLocation; - bool mValidated; const unsigned int mSerial; diff --git a/src/3rdparty/angle/src/libGLESv2/Query.cpp b/src/3rdparty/angle/src/libGLESv2/Query.cpp index 10edda5c57..bd987954f1 100644 --- a/src/3rdparty/angle/src/libGLESv2/Query.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Query.cpp @@ -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 @@ -7,122 +8,45 @@ // Query.cpp: Implements the gl::Query class #include "libGLESv2/Query.h" - -#include "libGLESv2/main.h" +#include "libGLESv2/renderer/QueryImpl.h" +#include "libGLESv2/renderer/Renderer.h" namespace gl { -Query::Query(GLuint id, GLenum type) : RefCountObject(id) +Query::Query(rx::Renderer *renderer, GLenum type, GLuint id) : RefCountObject(id) { - mQuery = NULL; - mStatus = GL_FALSE; - mResult = GL_FALSE; - mType = type; + mQuery = renderer->createQuery(type); } Query::~Query() { - if (mQuery != NULL) - { - mQuery->Release(); - mQuery = NULL; - } + delete mQuery; } void Query::begin() { - if (mQuery == NULL) - { - if (FAILED(getDevice()->CreateQuery(D3DQUERYTYPE_OCCLUSION, &mQuery))) - { - return error(GL_OUT_OF_MEMORY); - } - } - - HRESULT result = mQuery->Issue(D3DISSUE_BEGIN); - ASSERT(SUCCEEDED(result)); + mQuery->begin(); } void Query::end() { - if (mQuery == NULL) - { - return error(GL_INVALID_OPERATION); - } - - HRESULT result = mQuery->Issue(D3DISSUE_END); - ASSERT(SUCCEEDED(result)); - - mStatus = GL_FALSE; - mResult = GL_FALSE; + mQuery->end(); } GLuint Query::getResult() { - if (mQuery != NULL) - { - while (!testQuery()) - { - Sleep(0); - // explicitly check for device loss - // some drivers seem to return S_FALSE even if the device is lost - // instead of D3DERR_DEVICELOST like they should - if (gl::getDisplay()->testDeviceLost()) - { - gl::getDisplay()->notifyDeviceLost(); - return error(GL_OUT_OF_MEMORY, 0); - } - } - } - - return (GLuint)mResult; + return mQuery->getResult(); } GLboolean Query::isResultAvailable() { - if (mQuery != NULL) - { - testQuery(); - } - - return mStatus; + return mQuery->isResultAvailable(); } GLenum Query::getType() const { - return mType; + return mQuery->getType(); } -GLboolean Query::testQuery() -{ - if (mQuery != NULL && mStatus != GL_TRUE) - { - DWORD numPixels = 0; - - HRESULT hres = mQuery->GetData(&numPixels, sizeof(DWORD), D3DGETDATA_FLUSH); - if (hres == S_OK) - { - mStatus = GL_TRUE; - - switch (mType) - { - case GL_ANY_SAMPLES_PASSED_EXT: - case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT: - mResult = (numPixels > 0) ? GL_TRUE : GL_FALSE; - break; - default: - ASSERT(false); - } - } - else if (checkDeviceLost(hres)) - { - return error(GL_OUT_OF_MEMORY, GL_TRUE); - } - - return mStatus; - } - - return GL_TRUE; // prevent blocking when query is null -} } diff --git a/src/3rdparty/angle/src/libGLESv2/Query.h b/src/3rdparty/angle/src/libGLESv2/Query.h index 79357a0583..e9b95b729b 100644 --- a/src/3rdparty/angle/src/libGLESv2/Query.h +++ b/src/3rdparty/angle/src/libGLESv2/Query.h @@ -11,22 +11,28 @@ #define GL_APICALL #include -#include #include "common/angleutils.h" #include "common/RefCountObject.h" +namespace rx +{ +class Renderer; +class QueryImpl; +} + namespace gl { class Query : public RefCountObject { public: - Query(GLuint id, GLenum type); + Query(rx::Renderer *renderer, GLenum type, GLuint id); virtual ~Query(); void begin(); void end(); + GLuint getResult(); GLboolean isResultAvailable(); @@ -35,12 +41,7 @@ class Query : public RefCountObject private: DISALLOW_COPY_AND_ASSIGN(Query); - GLboolean testQuery(); - - IDirect3DQuery9* mQuery; - GLenum mType; - GLboolean mStatus; - GLint mResult; + rx::QueryImpl *mQuery; }; } diff --git a/src/3rdparty/angle/src/libGLESv2/Renderbuffer.cpp b/src/3rdparty/angle/src/libGLESv2/Renderbuffer.cpp index 4b911e8120..127513741c 100644 --- a/src/3rdparty/angle/src/libGLESv2/Renderbuffer.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Renderbuffer.cpp @@ -1,5 +1,6 @@ +#include "precompiled.h" // -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// 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. // @@ -9,9 +10,10 @@ // objects and related functionality. [OpenGL ES 2.0.24] section 4.4.3 page 108. #include "libGLESv2/Renderbuffer.h" +#include "libGLESv2/renderer/RenderTarget.h" -#include "libGLESv2/main.h" #include "libGLESv2/Texture.h" +#include "libGLESv2/renderer/Renderer.h" #include "libGLESv2/utilities.h" namespace gl @@ -35,32 +37,32 @@ void RenderbufferInterface::releaseProxy(const Renderbuffer *proxy) GLuint RenderbufferInterface::getRedSize() const { - return dx2es::GetRedSize(getD3DFormat()); + return gl::GetRedSize(getActualFormat()); } GLuint RenderbufferInterface::getGreenSize() const { - return dx2es::GetGreenSize(getD3DFormat()); + return gl::GetGreenSize(getActualFormat()); } GLuint RenderbufferInterface::getBlueSize() const { - return dx2es::GetBlueSize(getD3DFormat()); + return gl::GetBlueSize(getActualFormat()); } GLuint RenderbufferInterface::getAlphaSize() const { - return dx2es::GetAlphaSize(getD3DFormat()); + return gl::GetAlphaSize(getActualFormat()); } GLuint RenderbufferInterface::getDepthSize() const { - return dx2es::GetDepthSize(getD3DFormat()); + return gl::GetDepthSize(getActualFormat()); } GLuint RenderbufferInterface::getStencilSize() const { - return dx2es::GetStencilSize(getD3DFormat()); + return gl::GetStencilSize(getActualFormat()); } ///// RenderbufferTexture2D Implementation //////// @@ -87,16 +89,12 @@ void RenderbufferTexture2D::releaseProxy(const Renderbuffer *proxy) mTexture2D->releaseProxy(proxy); } -// Increments refcount on surface. -// caller must Release() the returned surface -IDirect3DSurface9 *RenderbufferTexture2D::getRenderTarget() +rx::RenderTarget *RenderbufferTexture2D::getRenderTarget() { return mTexture2D->getRenderTarget(mTarget); } -// Increments refcount on surface. -// caller must Release() the returned surface -IDirect3DSurface9 *RenderbufferTexture2D::getDepthStencil() +rx::RenderTarget *RenderbufferTexture2D::getDepthStencil() { return mTexture2D->getDepthStencil(mTarget); } @@ -116,9 +114,9 @@ GLenum RenderbufferTexture2D::getInternalFormat() const return mTexture2D->getInternalFormat(0); } -D3DFORMAT RenderbufferTexture2D::getD3DFormat() const +GLenum RenderbufferTexture2D::getActualFormat() const { - return mTexture2D->getD3DFormat(0); + return mTexture2D->getActualFormat(0); } GLsizei RenderbufferTexture2D::getSamples() const @@ -155,16 +153,12 @@ void RenderbufferTextureCubeMap::releaseProxy(const Renderbuffer *proxy) mTextureCubeMap->releaseProxy(proxy); } -// Increments refcount on surface. -// caller must Release() the returned surface -IDirect3DSurface9 *RenderbufferTextureCubeMap::getRenderTarget() +rx::RenderTarget *RenderbufferTextureCubeMap::getRenderTarget() { return mTextureCubeMap->getRenderTarget(mTarget); } -// Increments refcount on surface. -// caller must Release() the returned surface -IDirect3DSurface9 *RenderbufferTextureCubeMap::getDepthStencil() +rx::RenderTarget *RenderbufferTextureCubeMap::getDepthStencil() { return NULL; } @@ -184,9 +178,9 @@ GLenum RenderbufferTextureCubeMap::getInternalFormat() const return mTextureCubeMap->getInternalFormat(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0); } -D3DFORMAT RenderbufferTextureCubeMap::getD3DFormat() const +GLenum RenderbufferTextureCubeMap::getActualFormat() const { - return mTextureCubeMap->getD3DFormat(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0); + return mTextureCubeMap->getActualFormat(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0); } GLsizei RenderbufferTextureCubeMap::getSamples() const @@ -201,7 +195,7 @@ unsigned int RenderbufferTextureCubeMap::getSerial() const ////// Renderbuffer Implementation ////// -Renderbuffer::Renderbuffer(GLuint id, RenderbufferInterface *instance) : RefCountObject(id) +Renderbuffer::Renderbuffer(rx::Renderer *renderer, GLuint id, RenderbufferInterface *instance) : RefCountObject(id) { ASSERT(instance != NULL); mInstance = instance; @@ -228,16 +222,12 @@ void Renderbuffer::release() const RefCountObject::release(); } -// Increments refcount on surface. -// caller must Release() the returned surface -IDirect3DSurface9 *Renderbuffer::getRenderTarget() +rx::RenderTarget *Renderbuffer::getRenderTarget() { return mInstance->getRenderTarget(); } -// Increments refcount on surface. -// caller must Release() the returned surface -IDirect3DSurface9 *Renderbuffer::getDepthStencil() +rx::RenderTarget *Renderbuffer::getDepthStencil() { return mInstance->getDepthStencil(); } @@ -257,9 +247,9 @@ GLenum Renderbuffer::getInternalFormat() const return mInstance->getInternalFormat(); } -D3DFORMAT Renderbuffer::getD3DFormat() const +GLenum Renderbuffer::getActualFormat() const { - return mInstance->getD3DFormat(); + return mInstance->getActualFormat(); } GLuint Renderbuffer::getRedSize() const @@ -315,7 +305,7 @@ RenderbufferStorage::RenderbufferStorage() : mSerial(issueSerial()) mWidth = 0; mHeight = 0; mInternalFormat = GL_RGBA4; - mD3DFormat = D3DFMT_A8R8G8B8; + mActualFormat = GL_RGBA8_OES; mSamples = 0; } @@ -323,16 +313,12 @@ RenderbufferStorage::~RenderbufferStorage() { } -// Increments refcount on surface. -// caller must Release() the returned surface -IDirect3DSurface9 *RenderbufferStorage::getRenderTarget() +rx::RenderTarget *RenderbufferStorage::getRenderTarget() { return NULL; } -// Increments refcount on surface. -// caller must Release() the returned surface -IDirect3DSurface9 *RenderbufferStorage::getDepthStencil() +rx::RenderTarget *RenderbufferStorage::getDepthStencil() { return NULL; } @@ -352,9 +338,9 @@ GLenum RenderbufferStorage::getInternalFormat() const return mInternalFormat; } -D3DFORMAT RenderbufferStorage::getD3DFormat() const +GLenum RenderbufferStorage::getActualFormat() const { - return mD3DFormat; + return mActualFormat; } GLsizei RenderbufferStorage::getSamples() const @@ -379,164 +365,96 @@ unsigned int RenderbufferStorage::issueCubeSerials() return firstSerial; } -Colorbuffer::Colorbuffer(IDirect3DSurface9 *renderTarget) : mRenderTarget(renderTarget) +Colorbuffer::Colorbuffer(rx::Renderer *renderer, rx::SwapChain *swapChain) { - if (renderTarget) - { - renderTarget->AddRef(); - - D3DSURFACE_DESC description; - renderTarget->GetDesc(&description); + mRenderTarget = renderer->createRenderTarget(swapChain, false); - mWidth = description.Width; - mHeight = description.Height; - mInternalFormat = dx2es::ConvertBackBufferFormat(description.Format); - mD3DFormat = description.Format; - mSamples = dx2es::GetSamplesFromMultisampleType(description.MultiSampleType); + if (mRenderTarget) + { + mWidth = mRenderTarget->getWidth(); + mHeight = mRenderTarget->getHeight(); + mInternalFormat = mRenderTarget->getInternalFormat(); + mActualFormat = mRenderTarget->getActualFormat(); + mSamples = mRenderTarget->getSamples(); } } -Colorbuffer::Colorbuffer(int width, int height, GLenum format, GLsizei samples) : mRenderTarget(NULL) +Colorbuffer::Colorbuffer(rx::Renderer *renderer, int width, int height, GLenum format, GLsizei samples) : mRenderTarget(NULL) { - IDirect3DDevice9 *device = getDevice(); - - D3DFORMAT requestedFormat = es2dx::ConvertRenderbufferFormat(format); - int supportedSamples = getContext()->getNearestSupportedSamples(requestedFormat, samples); + mRenderTarget = renderer->createRenderTarget(width, height, format, samples, false); - if (supportedSamples == -1) + if (mRenderTarget) { - error(GL_OUT_OF_MEMORY); - - return; + mWidth = width; + mHeight = height; + mInternalFormat = format; + mActualFormat = mRenderTarget->getActualFormat(); + mSamples = mRenderTarget->getSamples(); } - - if (width > 0 && height > 0) - { - HRESULT result = device->CreateRenderTarget(width, height, requestedFormat, - es2dx::GetMultisampleTypeFromSamples(supportedSamples), 0, FALSE, &mRenderTarget, NULL); - - if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY) - { - error(GL_OUT_OF_MEMORY); - - return; - } - - ASSERT(SUCCEEDED(result)); - } - - mWidth = width; - mHeight = height; - mInternalFormat = format; - mD3DFormat = requestedFormat; - mSamples = supportedSamples; } Colorbuffer::~Colorbuffer() { if (mRenderTarget) { - mRenderTarget->Release(); + delete mRenderTarget; } } -// Increments refcount on surface. -// caller must Release() the returned surface -IDirect3DSurface9 *Colorbuffer::getRenderTarget() +rx::RenderTarget *Colorbuffer::getRenderTarget() { if (mRenderTarget) { - mRenderTarget->AddRef(); + return mRenderTarget; } - return mRenderTarget; + return NULL; } -DepthStencilbuffer::DepthStencilbuffer(IDirect3DSurface9 *depthStencil) : mDepthStencil(depthStencil) +DepthStencilbuffer::DepthStencilbuffer(rx::Renderer *renderer, rx::SwapChain *swapChain) { - if (depthStencil) + mDepthStencil = renderer->createRenderTarget(swapChain, true); + if (mDepthStencil) { - depthStencil->AddRef(); - - D3DSURFACE_DESC description; - depthStencil->GetDesc(&description); - - mWidth = description.Width; - mHeight = description.Height; - mInternalFormat = dx2es::ConvertDepthStencilFormat(description.Format); - mSamples = dx2es::GetSamplesFromMultisampleType(description.MultiSampleType); - mD3DFormat = description.Format; + mWidth = mDepthStencil->getWidth(); + mHeight = mDepthStencil->getHeight(); + mInternalFormat = mDepthStencil->getInternalFormat(); + mSamples = mDepthStencil->getSamples(); + mActualFormat = mDepthStencil->getActualFormat(); } } -DepthStencilbuffer::DepthStencilbuffer(int width, int height, GLsizei samples) +DepthStencilbuffer::DepthStencilbuffer(rx::Renderer *renderer, int width, int height, GLsizei samples) { - IDirect3DDevice9 *device = getDevice(); - mDepthStencil = NULL; - - int supportedSamples = getContext()->getNearestSupportedSamples(D3DFMT_D24S8, samples); + mDepthStencil = renderer->createRenderTarget(width, height, GL_DEPTH24_STENCIL8_OES, samples, true); - if (supportedSamples == -1) - { - error(GL_OUT_OF_MEMORY); - - return; - } - - if (width > 0 && height > 0) - { - HRESULT result = device->CreateDepthStencilSurface(width, height, D3DFMT_D24S8, es2dx::GetMultisampleTypeFromSamples(supportedSamples), - 0, FALSE, &mDepthStencil, 0); - - if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY) - { - error(GL_OUT_OF_MEMORY); - - return; - } - - ASSERT(SUCCEEDED(result)); - } - - mWidth = width; - mHeight = height; + mWidth = mDepthStencil->getWidth(); + mHeight = mDepthStencil->getHeight(); mInternalFormat = GL_DEPTH24_STENCIL8_OES; - mD3DFormat = D3DFMT_D24S8; - mSamples = supportedSamples; + mActualFormat = mDepthStencil->getActualFormat(); + mSamples = mDepthStencil->getSamples(); } DepthStencilbuffer::~DepthStencilbuffer() { if (mDepthStencil) { - mDepthStencil->Release(); + delete mDepthStencil; } } -// Increments refcount on surface. -// caller must Release() the returned surface -IDirect3DSurface9 *DepthStencilbuffer::getDepthStencil() +rx::RenderTarget *DepthStencilbuffer::getDepthStencil() { if (mDepthStencil) { - mDepthStencil->AddRef(); + return mDepthStencil; } - return mDepthStencil; -} - -Depthbuffer::Depthbuffer(IDirect3DSurface9 *depthStencil) : DepthStencilbuffer(depthStencil) -{ - if (depthStencil) - { - mInternalFormat = GL_DEPTH_COMPONENT16; // If the renderbuffer parameters are queried, the calling function - // will expect one of the valid renderbuffer formats for use in - // glRenderbufferStorage - } + return NULL; } -Depthbuffer::Depthbuffer(int width, int height, GLsizei samples) : DepthStencilbuffer(width, height, samples) +Depthbuffer::Depthbuffer(rx::Renderer *renderer, int width, int height, GLsizei samples) : DepthStencilbuffer(renderer, width, height, samples) { if (mDepthStencil) { @@ -550,17 +468,7 @@ Depthbuffer::~Depthbuffer() { } -Stencilbuffer::Stencilbuffer(IDirect3DSurface9 *depthStencil) : DepthStencilbuffer(depthStencil) -{ - if (depthStencil) - { - mInternalFormat = GL_STENCIL_INDEX8; // If the renderbuffer parameters are queried, the calling function - // will expect one of the valid renderbuffer formats for use in - // glRenderbufferStorage - } -} - -Stencilbuffer::Stencilbuffer(int width, int height, GLsizei samples) : DepthStencilbuffer(width, height, samples) +Stencilbuffer::Stencilbuffer(rx::Renderer *renderer, int width, int height, GLsizei samples) : DepthStencilbuffer(renderer, width, height, samples) { if (mDepthStencil) { diff --git a/src/3rdparty/angle/src/libGLESv2/Renderbuffer.h b/src/3rdparty/angle/src/libGLESv2/Renderbuffer.h index e6d5ddb875..eca2f3a780 100644 --- a/src/3rdparty/angle/src/libGLESv2/Renderbuffer.h +++ b/src/3rdparty/angle/src/libGLESv2/Renderbuffer.h @@ -14,11 +14,17 @@ #define GL_APICALL #include -#include #include "common/angleutils.h" #include "common/RefCountObject.h" +namespace rx +{ +class Renderer; +class SwapChain; +class RenderTarget; +} + namespace gl { class Texture2D; @@ -37,13 +43,13 @@ class RenderbufferInterface virtual void addProxyRef(const Renderbuffer *proxy); virtual void releaseProxy(const Renderbuffer *proxy); - virtual IDirect3DSurface9 *getRenderTarget() = 0; - virtual IDirect3DSurface9 *getDepthStencil() = 0; + virtual rx::RenderTarget *getRenderTarget() = 0; + virtual rx::RenderTarget *getDepthStencil() = 0; virtual GLsizei getWidth() const = 0; virtual GLsizei getHeight() const = 0; virtual GLenum getInternalFormat() const = 0; - virtual D3DFORMAT getD3DFormat() const = 0; + virtual GLenum getActualFormat() const = 0; virtual GLsizei getSamples() const = 0; GLuint getRedSize() const; @@ -69,13 +75,13 @@ class RenderbufferTexture2D : public RenderbufferInterface void addProxyRef(const Renderbuffer *proxy); void releaseProxy(const Renderbuffer *proxy); - IDirect3DSurface9 *getRenderTarget(); - IDirect3DSurface9 *getDepthStencil(); + rx::RenderTarget *getRenderTarget(); + rx::RenderTarget *getDepthStencil(); virtual GLsizei getWidth() const; virtual GLsizei getHeight() const; virtual GLenum getInternalFormat() const; - virtual D3DFORMAT getD3DFormat() const; + virtual GLenum getActualFormat() const; virtual GLsizei getSamples() const; virtual unsigned int getSerial() const; @@ -97,13 +103,13 @@ class RenderbufferTextureCubeMap : public RenderbufferInterface void addProxyRef(const Renderbuffer *proxy); void releaseProxy(const Renderbuffer *proxy); - IDirect3DSurface9 *getRenderTarget(); - IDirect3DSurface9 *getDepthStencil(); + rx::RenderTarget *getRenderTarget(); + rx::RenderTarget *getDepthStencil(); virtual GLsizei getWidth() const; virtual GLsizei getHeight() const; virtual GLenum getInternalFormat() const; - virtual D3DFORMAT getD3DFormat() const; + virtual GLenum getActualFormat() const; virtual GLsizei getSamples() const; virtual unsigned int getSerial() const; @@ -125,13 +131,13 @@ class RenderbufferStorage : public RenderbufferInterface virtual ~RenderbufferStorage() = 0; - virtual IDirect3DSurface9 *getRenderTarget(); - virtual IDirect3DSurface9 *getDepthStencil(); + virtual rx::RenderTarget *getRenderTarget(); + virtual rx::RenderTarget *getDepthStencil(); virtual GLsizei getWidth() const; virtual GLsizei getHeight() const; virtual GLenum getInternalFormat() const; - virtual D3DFORMAT getD3DFormat() const; + virtual GLenum getActualFormat() const; virtual GLsizei getSamples() const; virtual unsigned int getSerial() const; @@ -143,7 +149,7 @@ class RenderbufferStorage : public RenderbufferInterface GLsizei mWidth; GLsizei mHeight; GLenum mInternalFormat; - D3DFORMAT mD3DFormat; + GLenum mActualFormat; GLsizei mSamples; private: @@ -160,7 +166,7 @@ class RenderbufferStorage : public RenderbufferInterface class Renderbuffer : public RefCountObject { public: - Renderbuffer(GLuint id, RenderbufferInterface *storage); + Renderbuffer(rx::Renderer *renderer, GLuint id, RenderbufferInterface *storage); virtual ~Renderbuffer(); @@ -171,13 +177,13 @@ class Renderbuffer : public RefCountObject void addRef() const; void release() const; - IDirect3DSurface9 *getRenderTarget(); - IDirect3DSurface9 *getDepthStencil(); + rx::RenderTarget *getRenderTarget(); + rx::RenderTarget *getDepthStencil(); GLsizei getWidth() const; GLsizei getHeight() const; GLenum getInternalFormat() const; - D3DFORMAT getD3DFormat() const; + GLenum getActualFormat() const; GLuint getRedSize() const; GLuint getGreenSize() const; GLuint getBlueSize() const; @@ -199,31 +205,31 @@ class Renderbuffer : public RefCountObject class Colorbuffer : public RenderbufferStorage { public: - explicit Colorbuffer(IDirect3DSurface9 *renderTarget); - Colorbuffer(GLsizei width, GLsizei height, GLenum format, GLsizei samples); + Colorbuffer(rx::Renderer *renderer, rx::SwapChain *swapChain); + Colorbuffer(rx::Renderer *renderer, GLsizei width, GLsizei height, GLenum format, GLsizei samples); virtual ~Colorbuffer(); - virtual IDirect3DSurface9 *getRenderTarget(); + virtual rx::RenderTarget *getRenderTarget(); private: DISALLOW_COPY_AND_ASSIGN(Colorbuffer); - IDirect3DSurface9 *mRenderTarget; + rx::RenderTarget *mRenderTarget; }; class DepthStencilbuffer : public RenderbufferStorage { public: - explicit DepthStencilbuffer(IDirect3DSurface9 *depthStencil); - DepthStencilbuffer(GLsizei width, GLsizei height, GLsizei samples); + DepthStencilbuffer(rx::Renderer *renderer, rx::SwapChain *swapChain); + DepthStencilbuffer(rx::Renderer *renderer, GLsizei width, GLsizei height, GLsizei samples); ~DepthStencilbuffer(); - virtual IDirect3DSurface9 *getDepthStencil(); + virtual rx::RenderTarget *getDepthStencil(); protected: - IDirect3DSurface9 *mDepthStencil; + rx::RenderTarget *mDepthStencil; private: DISALLOW_COPY_AND_ASSIGN(DepthStencilbuffer); @@ -232,8 +238,7 @@ class DepthStencilbuffer : public RenderbufferStorage class Depthbuffer : public DepthStencilbuffer { public: - explicit Depthbuffer(IDirect3DSurface9 *depthStencil); - Depthbuffer(GLsizei width, GLsizei height, GLsizei samples); + Depthbuffer(rx::Renderer *renderer, GLsizei width, GLsizei height, GLsizei samples); virtual ~Depthbuffer(); @@ -244,8 +249,7 @@ class Depthbuffer : public DepthStencilbuffer class Stencilbuffer : public DepthStencilbuffer { public: - explicit Stencilbuffer(IDirect3DSurface9 *depthStencil); - Stencilbuffer(GLsizei width, GLsizei height, GLsizei samples); + Stencilbuffer(rx::Renderer *renderer, GLsizei width, GLsizei height, GLsizei samples); virtual ~Stencilbuffer(); diff --git a/src/3rdparty/angle/src/libGLESv2/ResourceManager.cpp b/src/3rdparty/angle/src/libGLESv2/ResourceManager.cpp index 4b97e9c113..58dd44fd95 100644 --- a/src/3rdparty/angle/src/libGLESv2/ResourceManager.cpp +++ b/src/3rdparty/angle/src/libGLESv2/ResourceManager.cpp @@ -1,3 +1,4 @@ +#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 @@ -17,9 +18,10 @@ namespace gl { -ResourceManager::ResourceManager() +ResourceManager::ResourceManager(rx::Renderer *renderer) { mRefCount = 1; + mRenderer = renderer; } ResourceManager::~ResourceManager() @@ -80,11 +82,11 @@ GLuint ResourceManager::createShader(GLenum type) if (type == GL_VERTEX_SHADER) { - mShaderMap[handle] = new VertexShader(this, handle); + mShaderMap[handle] = new VertexShader(this, mRenderer, handle); } else if (type == GL_FRAGMENT_SHADER) { - mShaderMap[handle] = new FragmentShader(this, handle); + mShaderMap[handle] = new FragmentShader(this, mRenderer, handle); } else UNREACHABLE(); @@ -96,7 +98,7 @@ GLuint ResourceManager::createProgram() { GLuint handle = mProgramShaderHandleAllocator.allocate(); - mProgramMap[handle] = new Program(this, handle); + mProgramMap[handle] = new Program(mRenderer, this, handle); return handle; } @@ -276,7 +278,7 @@ void ResourceManager::checkBufferAllocation(unsigned int buffer) { if (buffer != 0 && !getBuffer(buffer)) { - Buffer *bufferObject = new Buffer(buffer); + Buffer *bufferObject = new Buffer(mRenderer, buffer); mBufferMap[buffer] = bufferObject; bufferObject->addRef(); } @@ -290,11 +292,11 @@ void ResourceManager::checkTextureAllocation(GLuint texture, TextureType type) if (type == TEXTURE_2D) { - textureObject = new Texture2D(texture); + textureObject = new Texture2D(mRenderer, texture); } else if (type == TEXTURE_CUBE) { - textureObject = new TextureCubeMap(texture); + textureObject = new TextureCubeMap(mRenderer, texture); } else { @@ -311,7 +313,7 @@ void ResourceManager::checkRenderbufferAllocation(GLuint renderbuffer) { if (renderbuffer != 0 && !getRenderbuffer(renderbuffer)) { - Renderbuffer *renderbufferObject = new Renderbuffer(renderbuffer, new Colorbuffer(0, 0, GL_RGBA4, 0)); + Renderbuffer *renderbufferObject = new Renderbuffer(mRenderer, renderbuffer, new Colorbuffer(mRenderer, 0, 0, GL_RGBA4, 0)); mRenderbufferMap[renderbuffer] = renderbufferObject; renderbufferObject->addRef(); } diff --git a/src/3rdparty/angle/src/libGLESv2/ResourceManager.h b/src/3rdparty/angle/src/libGLESv2/ResourceManager.h index ae4f1b04a5..e99c77c35d 100644 --- a/src/3rdparty/angle/src/libGLESv2/ResourceManager.h +++ b/src/3rdparty/angle/src/libGLESv2/ResourceManager.h @@ -20,8 +20,14 @@ #endif #include "common/angleutils.h" +#include "libGLESv2/angletypes.h" #include "libGLESv2/HandleAllocator.h" +namespace rx +{ +class Renderer; +} + namespace gl { class Buffer; @@ -30,25 +36,10 @@ class Program; class Texture; class Renderbuffer; -enum TextureType -{ - TEXTURE_2D, - TEXTURE_CUBE, - - TEXTURE_TYPE_COUNT, - TEXTURE_UNKNOWN -}; - -enum SamplerType -{ - SAMPLER_PIXEL, - SAMPLER_VERTEX -}; - class ResourceManager { public: - ResourceManager(); + explicit ResourceManager(rx::Renderer *renderer); ~ResourceManager(); void addRef(); @@ -82,6 +73,7 @@ class ResourceManager DISALLOW_COPY_AND_ASSIGN(ResourceManager); std::size_t mRefCount; + rx::Renderer *mRenderer; #ifndef HASH_MAP # ifdef _MSC_VER diff --git a/src/3rdparty/angle/src/libGLESv2/Shader.cpp b/src/3rdparty/angle/src/libGLESv2/Shader.cpp index 1087f11b4a..abddab427b 100644 --- a/src/3rdparty/angle/src/libGLESv2/Shader.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Shader.cpp @@ -1,5 +1,6 @@ +#include "precompiled.h" // -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// 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. // @@ -10,18 +11,19 @@ #include "libGLESv2/Shader.h" -#include - #include "GLSLANG/ShaderLang.h" -#include "libGLESv2/main.h" #include "libGLESv2/utilities.h" +#include "libGLESv2/renderer/Renderer.h" +#include "libGLESv2/Constants.h" +#include "libGLESv2/ResourceManager.h" namespace gl { void *Shader::mFragmentCompiler = NULL; void *Shader::mVertexCompiler = NULL; -Shader::Shader(ResourceManager *manager, GLuint handle) : mHandle(handle), mResourceManager(manager) +Shader::Shader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle) + : mHandle(handle), mRenderer(renderer), mResourceManager(manager) { mSource = NULL; mHlsl = NULL; @@ -174,6 +176,11 @@ void Shader::getTranslatedSource(GLsizei bufSize, GLsizei *length, char *buffer) getSourceImpl(mHlsl, bufSize, length, buffer); } +const sh::ActiveUniforms &Shader::getUniforms() +{ + return mActiveUniforms; +} + bool Shader::isCompiled() { return mHlsl != NULL; @@ -223,23 +230,26 @@ void Shader::initializeCompiler() if (result) { + ShShaderOutput hlslVersion = (mRenderer->getMajorShaderModel() >= 4) ? SH_HLSL11_OUTPUT : SH_HLSL9_OUTPUT; + ShBuiltInResources resources; ShInitBuiltInResources(&resources); - Context *context = getContext(); resources.MaxVertexAttribs = MAX_VERTEX_ATTRIBS; - resources.MaxVertexUniformVectors = MAX_VERTEX_UNIFORM_VECTORS; - resources.MaxVaryingVectors = context->getMaximumVaryingVectors(); - resources.MaxVertexTextureImageUnits = context->getMaximumVertexTextureImageUnits(); - resources.MaxCombinedTextureImageUnits = context->getMaximumCombinedTextureImageUnits(); + resources.MaxVertexUniformVectors = mRenderer->getMaxVertexUniformVectors(); + resources.MaxVaryingVectors = mRenderer->getMaxVaryingVectors(); + resources.MaxVertexTextureImageUnits = mRenderer->getMaxVertexTextureImageUnits(); + resources.MaxCombinedTextureImageUnits = mRenderer->getMaxCombinedTextureImageUnits(); resources.MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS; - resources.MaxFragmentUniformVectors = context->getMaximumFragmentUniformVectors(); - resources.MaxDrawBuffers = MAX_DRAW_BUFFERS; - resources.OES_standard_derivatives = 1; - // resources.OES_EGL_image_external = getDisplay()->isD3d9ExDevice() ? 1 : 0; // TODO: commented out until the extension is actually supported. - - mFragmentCompiler = ShConstructCompiler(SH_FRAGMENT_SHADER, SH_GLES2_SPEC, SH_HLSL_OUTPUT, &resources); - mVertexCompiler = ShConstructCompiler(SH_VERTEX_SHADER, SH_GLES2_SPEC, SH_HLSL_OUTPUT, &resources); + resources.MaxFragmentUniformVectors = mRenderer->getMaxFragmentUniformVectors(); + resources.MaxDrawBuffers = mRenderer->getMaxRenderTargets(); + resources.OES_standard_derivatives = mRenderer->getDerivativeInstructionSupport(); + resources.EXT_draw_buffers = mRenderer->getMaxRenderTargets() > 1; + // resources.OES_EGL_image_external = mRenderer->getShareHandleSupport() ? 1 : 0; // TODO: commented out until the extension is actually supported. + resources.FragmentPrecisionHigh = 1; // Shader Model 2+ always supports FP24 (s16e7) which corresponds to highp + + mFragmentCompiler = ShConstructCompiler(SH_FRAGMENT_SHADER, SH_GLES2_SPEC, hlslVersion, &resources); + mVertexCompiler = ShConstructCompiler(SH_VERTEX_SHADER, SH_GLES2_SPEC, hlslVersion, &resources); } } } @@ -287,6 +297,9 @@ void Shader::parseVaryings() input = strstr(input, ";") + 2; } + mUsesMultipleRenderTargets = strstr(mHlsl, "GL_USES_MRT") != NULL; + mUsesFragColor = strstr(mHlsl, "GL_USES_FRAG_COLOR") != NULL; + mUsesFragData = strstr(mHlsl, "GL_USES_FRAG_DATA") != NULL; mUsesFragCoord = strstr(mHlsl, "GL_USES_FRAG_COORD") != NULL; mUsesFrontFacing = strstr(mHlsl, "GL_USES_FRONT_FACING") != NULL; mUsesPointSize = strstr(mHlsl, "GL_USES_POINT_SIZE") != NULL; @@ -294,6 +307,15 @@ void Shader::parseVaryings() } } +void Shader::resetVaryingsRegisterAssignment() +{ + for (VaryingList::iterator var = mVaryings.begin(); var != mVaryings.end(); var++) + { + var->reg = -1; + var->col = -1; + } +} + // initialize/clean up previous state void Shader::uncompile() { @@ -306,16 +328,21 @@ void Shader::uncompile() // set by parseVaryings mVaryings.clear(); + mUsesMultipleRenderTargets = false; + mUsesFragColor = false; + mUsesFragData = false; mUsesFragCoord = false; mUsesFrontFacing = false; mUsesPointSize = false; mUsesPointCoord = false; + + mActiveUniforms.clear(); } void Shader::compileToHLSL(void *compiler) { // ensure we don't pass a NULL source to the compiler - char *source = "\0"; + const char *source = "\0"; if (mSource) { source = mSource; @@ -351,14 +378,18 @@ void Shader::compileToHLSL(void *compiler) if (result) { - int objCodeLen = 0; + size_t objCodeLen = 0; ShGetInfo(compiler, SH_OBJECT_CODE_LENGTH, &objCodeLen); mHlsl = new char[objCodeLen]; ShGetObjectCode(compiler, mHlsl); + + void *activeUniforms; + ShGetInfoPointer(compiler, SH_ACTIVE_UNIFORMS_ARRAY, &activeUniforms); + mActiveUniforms = *(sh::ActiveUniforms*)activeUniforms; } else { - int infoLogLen = 0; + size_t infoLogLen = 0; ShGetInfo(compiler, SH_INFO_LOG_LENGTH, &infoLogLen); mInfoLog = new char[infoLogLen]; ShGetInfoLog(compiler, mInfoLog); @@ -485,7 +516,8 @@ bool Shader::compareVarying(const Varying &x, const Varying &y) return false; } -VertexShader::VertexShader(ResourceManager *manager, GLuint handle) : Shader(manager, handle) +VertexShader::VertexShader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle) + : Shader(manager, renderer, handle) { } @@ -504,7 +536,7 @@ void VertexShader::uncompile() // set by ParseAttributes mAttributes.clear(); -}; +} void VertexShader::compile() { @@ -560,7 +592,8 @@ void VertexShader::parseAttributes() } } -FragmentShader::FragmentShader(ResourceManager *manager, GLuint handle) : Shader(manager, handle) +FragmentShader::FragmentShader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle) + : Shader(manager, renderer, handle) { } diff --git a/src/3rdparty/angle/src/libGLESv2/Shader.h b/src/3rdparty/angle/src/libGLESv2/Shader.h index b73fc288a1..f471968550 100644 --- a/src/3rdparty/angle/src/libGLESv2/Shader.h +++ b/src/3rdparty/angle/src/libGLESv2/Shader.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// 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. // @@ -18,10 +18,18 @@ #include #include -#include "libGLESv2/ResourceManager.h" +#include "compiler/Uniform.h" +#include "common/angleutils.h" + +namespace rx +{ +class Renderer; +} namespace gl { +class ResourceManager; + struct Varying { Varying(GLenum type, const std::string &name, int size, bool array) @@ -45,7 +53,7 @@ class Shader friend class ProgramBinary; public: - Shader(ResourceManager *manager, GLuint handle); + Shader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle); virtual ~Shader(); @@ -60,6 +68,7 @@ class Shader void getSource(GLsizei bufSize, GLsizei *length, char *buffer); int getTranslatedSourceLength() const; void getTranslatedSource(GLsizei bufSize, GLsizei *length, char *buffer); + const sh::ActiveUniforms &getUniforms(); virtual void compile() = 0; virtual void uncompile(); @@ -76,6 +85,7 @@ class Shader protected: void parseVaryings(); + void resetVaryingsRegisterAssignment(); void compileToHLSL(void *compiler); @@ -84,8 +94,13 @@ class Shader static GLenum parseType(const std::string &type); static bool compareVarying(const Varying &x, const Varying &y); + const rx::Renderer *const mRenderer; + VaryingList mVaryings; + bool mUsesMultipleRenderTargets; + bool mUsesFragColor; + bool mUsesFragData; bool mUsesFragCoord; bool mUsesFrontFacing; bool mUsesPointSize; @@ -106,6 +121,7 @@ class Shader char *mSource; char *mHlsl; char *mInfoLog; + sh::ActiveUniforms mActiveUniforms; ResourceManager *mResourceManager; }; @@ -131,7 +147,7 @@ class VertexShader : public Shader friend class ProgramBinary; public: - VertexShader(ResourceManager *manager, GLuint handle); + VertexShader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle); ~VertexShader(); @@ -151,7 +167,7 @@ class VertexShader : public Shader class FragmentShader : public Shader { public: - FragmentShader(ResourceManager *manager, GLuint handle); + FragmentShader(ResourceManager *manager,const rx::Renderer *renderer, GLuint handle); ~FragmentShader(); diff --git a/src/3rdparty/angle/src/libGLESv2/Texture.cpp b/src/3rdparty/angle/src/libGLESv2/Texture.cpp index 0ea475d088..461357a1ce 100644 --- a/src/3rdparty/angle/src/libGLESv2/Texture.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Texture.cpp @@ -1,5 +1,6 @@ +#include "precompiled.h" // -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// 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. // @@ -10,1320 +11,34 @@ #include "libGLESv2/Texture.h" -#include - -#include "common/debug.h" - -#include "libEGL/Display.h" - -#include "libGLESv2/main.h" -#include "libGLESv2/mathutil.h" -#include "libGLESv2/utilities.h" -#include "libGLESv2/Blit.h" -#include "libGLESv2/Framebuffer.h" - -namespace gl -{ -unsigned int TextureStorage::mCurrentTextureSerial = 1; - -static D3DFORMAT ConvertTextureInternalFormat(GLint internalformat) -{ - switch (internalformat) - { - case GL_DEPTH_COMPONENT16: - case GL_DEPTH_COMPONENT32_OES: - case GL_DEPTH24_STENCIL8_OES: - return D3DFMT_INTZ; - case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: - case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: - return D3DFMT_DXT1; - case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: - return D3DFMT_DXT3; - case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: - return D3DFMT_DXT5; - case GL_RGBA32F_EXT: - case GL_RGB32F_EXT: - case GL_ALPHA32F_EXT: - case GL_LUMINANCE32F_EXT: - case GL_LUMINANCE_ALPHA32F_EXT: - return D3DFMT_A32B32G32R32F; - case GL_RGBA16F_EXT: - case GL_RGB16F_EXT: - case GL_ALPHA16F_EXT: - case GL_LUMINANCE16F_EXT: - case GL_LUMINANCE_ALPHA16F_EXT: - return D3DFMT_A16B16G16R16F; - case GL_LUMINANCE8_EXT: - if (getContext()->supportsLuminanceTextures()) - { - return D3DFMT_L8; - } - break; - case GL_LUMINANCE8_ALPHA8_EXT: - if (getContext()->supportsLuminanceAlphaTextures()) - { - return D3DFMT_A8L8; - } - break; - case GL_RGB8_OES: - case GL_RGB565: - return D3DFMT_X8R8G8B8; - } - - return D3DFMT_A8R8G8B8; -} - -static bool IsTextureFormatRenderable(D3DFORMAT format) -{ - if (format == D3DFMT_INTZ) - { - return true; - } - switch(format) - { - case D3DFMT_L8: - case D3DFMT_A8L8: - case D3DFMT_DXT1: - case D3DFMT_DXT3: - case D3DFMT_DXT5: - return false; - case D3DFMT_A8R8G8B8: - case D3DFMT_X8R8G8B8: - case D3DFMT_A16B16G16R16F: - case D3DFMT_A32B32G32R32F: - return true; - default: - UNREACHABLE(); - } - - return false; -} - -static inline DWORD GetTextureUsage(D3DFORMAT d3dfmt, GLenum glusage, bool forceRenderable) -{ - DWORD d3dusage = 0; - - if (d3dfmt == D3DFMT_INTZ) - { - d3dusage |= D3DUSAGE_DEPTHSTENCIL; - } - else if(forceRenderable || (IsTextureFormatRenderable(d3dfmt) && (glusage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE))) - { - d3dusage |= D3DUSAGE_RENDERTARGET; - } - return d3dusage; -} - -static void MakeValidSize(bool isImage, bool isCompressed, GLsizei *requestWidth, GLsizei *requestHeight, int *levelOffset) -{ - int upsampleCount = 0; - - if (isCompressed) - { - // Don't expand the size of full textures that are at least 4x4 - // already. - if (isImage || *requestWidth < 4 || *requestHeight < 4) - { - while (*requestWidth % 4 != 0 || *requestHeight % 4 != 0) - { - *requestWidth <<= 1; - *requestHeight <<= 1; - upsampleCount++; - } - } - } - *levelOffset = upsampleCount; -} - -static void CopyLockableSurfaces(IDirect3DSurface9 *dest, IDirect3DSurface9 *source) -{ - D3DLOCKED_RECT sourceLock = {0}; - D3DLOCKED_RECT destLock = {0}; - - source->LockRect(&sourceLock, NULL, 0); - dest->LockRect(&destLock, NULL, 0); - - if (sourceLock.pBits && destLock.pBits) - { - D3DSURFACE_DESC desc; - source->GetDesc(&desc); - - int rows = dx::IsCompressedFormat(desc.Format) ? desc.Height / 4 : desc.Height; - int bytes = dx::ComputeRowSize(desc.Format, desc.Width); - ASSERT(bytes <= sourceLock.Pitch && bytes <= destLock.Pitch); - - for(int i = 0; i < rows; i++) - { - memcpy((char*)destLock.pBits + destLock.Pitch * i, (char*)sourceLock.pBits + sourceLock.Pitch * i, bytes); - } - - source->UnlockRect(); - dest->UnlockRect(); - } - else UNREACHABLE(); -} - -Image::Image() -{ - mWidth = 0; - mHeight = 0; - mInternalFormat = GL_NONE; - - mSurface = NULL; - - mDirty = false; - - mD3DPool = D3DPOOL_SYSTEMMEM; - mD3DFormat = D3DFMT_UNKNOWN; -} - -Image::~Image() -{ - if (mSurface) - { - mSurface->Release(); - } -} - -bool Image::redefine(GLint internalformat, GLsizei width, GLsizei height, bool forceRelease) -{ - if (mWidth != width || - mHeight != height || - mInternalFormat != internalformat || - forceRelease) - { - mWidth = width; - mHeight = height; - mInternalFormat = internalformat; - // compute the d3d format that will be used - mD3DFormat = ConvertTextureInternalFormat(internalformat); - - if (mSurface) - { - mSurface->Release(); - mSurface = NULL; - } - - return true; - } - - return false; -} - -void Image::createSurface() -{ - if(mSurface) - { - return; - } - - IDirect3DTexture9 *newTexture = NULL; - IDirect3DSurface9 *newSurface = NULL; - const D3DPOOL poolToUse = D3DPOOL_SYSTEMMEM; - const D3DFORMAT d3dFormat = getD3DFormat(); - ASSERT(d3dFormat != D3DFMT_INTZ); // We should never get here for depth textures - - if (mWidth != 0 && mHeight != 0) - { - int levelToFetch = 0; - GLsizei requestWidth = mWidth; - GLsizei requestHeight = mHeight; - MakeValidSize(true, IsCompressed(mInternalFormat), &requestWidth, &requestHeight, &levelToFetch); - - HRESULT result = getDevice()->CreateTexture(requestWidth, requestHeight, levelToFetch + 1, NULL, d3dFormat, - poolToUse, &newTexture, NULL); - - if (FAILED(result)) - { - ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - ERR("Creating image surface failed."); - return error(GL_OUT_OF_MEMORY); - } - - newTexture->GetSurfaceLevel(levelToFetch, &newSurface); - newTexture->Release(); - } - - mSurface = newSurface; - mDirty = false; - mD3DPool = poolToUse; -} - -HRESULT Image::lock(D3DLOCKED_RECT *lockedRect, const RECT *rect) -{ - createSurface(); - - HRESULT result = D3DERR_INVALIDCALL; - - if (mSurface) - { - result = mSurface->LockRect(lockedRect, rect, 0); - ASSERT(SUCCEEDED(result)); - - mDirty = true; - } - - return result; -} - -void Image::unlock() -{ - if (mSurface) - { - HRESULT result = mSurface->UnlockRect(); - ASSERT(SUCCEEDED(result)); - } -} - -bool Image::isRenderableFormat() const -{ - return IsTextureFormatRenderable(getD3DFormat()); -} - -D3DFORMAT Image::getD3DFormat() const -{ - // this should only happen if the image hasn't been redefined first - // which would be a bug by the caller - ASSERT(mD3DFormat != D3DFMT_UNKNOWN); - - return mD3DFormat; -} - -IDirect3DSurface9 *Image::getSurface() -{ - createSurface(); - - return mSurface; -} - -void Image::setManagedSurface(IDirect3DSurface9 *surface) -{ - D3DSURFACE_DESC desc; - surface->GetDesc(&desc); - ASSERT(desc.Pool == D3DPOOL_MANAGED); - - if ((GLsizei)desc.Width == mWidth && (GLsizei)desc.Height == mHeight) - { - if (mSurface) - { - CopyLockableSurfaces(surface, mSurface); - mSurface->Release(); - } - - mSurface = surface; - mD3DPool = desc.Pool; - } -} - -void Image::updateSurface(IDirect3DSurface9 *destSurface, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) -{ - IDirect3DSurface9 *sourceSurface = getSurface(); - - if (sourceSurface && sourceSurface != destSurface) - { - RECT rect; - rect.left = xoffset; - rect.top = yoffset; - rect.right = xoffset + width; - rect.bottom = yoffset + height; - - POINT point = {rect.left, rect.top}; - - if (mD3DPool == D3DPOOL_MANAGED) - { - D3DSURFACE_DESC desc; - sourceSurface->GetDesc(&desc); - - IDirect3DSurface9 *surf = 0; - HRESULT result = getDevice()->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &surf, NULL); - - if (SUCCEEDED(result)) - { - CopyLockableSurfaces(surf, sourceSurface); - result = getDevice()->UpdateSurface(surf, &rect, destSurface, &point); - ASSERT(SUCCEEDED(result)); - surf->Release(); - } - } - else - { - // UpdateSurface: source must be SYSTEMMEM, dest must be DEFAULT pools - HRESULT result = getDevice()->UpdateSurface(sourceSurface, &rect, destSurface, &point); - ASSERT(SUCCEEDED(result)); - } - } -} - -// Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as format/type at input -// into the target pixel rectangle. -void Image::loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, - GLint unpackAlignment, const void *input) -{ - RECT lockRect = - { - xoffset, yoffset, - xoffset + width, yoffset + height - }; - - D3DLOCKED_RECT locked; - HRESULT result = lock(&locked, &lockRect); - if (FAILED(result)) - { - return; - } - - - GLsizei inputPitch = ComputePitch(width, mInternalFormat, unpackAlignment); - - switch (mInternalFormat) - { - case GL_ALPHA8_EXT: -#if defined(__SSE2__) - if (supportsSSE2()) - { - loadAlphaDataSSE2(width, height, inputPitch, input, locked.Pitch, locked.pBits); - } - else -#endif - { - loadAlphaData(width, height, inputPitch, input, locked.Pitch, locked.pBits); - } - break; - case GL_LUMINANCE8_EXT: - loadLuminanceData(width, height, inputPitch, input, locked.Pitch, locked.pBits, getD3DFormat() == D3DFMT_L8); - break; - case GL_ALPHA32F_EXT: - loadAlphaFloatData(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - case GL_LUMINANCE32F_EXT: - loadLuminanceFloatData(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - case GL_ALPHA16F_EXT: - loadAlphaHalfFloatData(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - case GL_LUMINANCE16F_EXT: - loadLuminanceHalfFloatData(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - case GL_LUMINANCE8_ALPHA8_EXT: - loadLuminanceAlphaData(width, height, inputPitch, input, locked.Pitch, locked.pBits, getD3DFormat() == D3DFMT_A8L8); - break; - case GL_LUMINANCE_ALPHA32F_EXT: - loadLuminanceAlphaFloatData(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - case GL_LUMINANCE_ALPHA16F_EXT: - loadLuminanceAlphaHalfFloatData(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - case GL_RGB8_OES: - loadRGBUByteData(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - case GL_RGB565: - loadRGB565Data(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - case GL_RGBA8_OES: -#if defined(__SSE2__) - if (supportsSSE2()) - { - loadRGBAUByteDataSSE2(width, height, inputPitch, input, locked.Pitch, locked.pBits); - } - else -#endif - { - loadRGBAUByteData(width, height, inputPitch, input, locked.Pitch, locked.pBits); - } - break; - case GL_RGBA4: - loadRGBA4444Data(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - case GL_RGB5_A1: - loadRGBA5551Data(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - case GL_BGRA8_EXT: - loadBGRAData(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - // float textures are converted to RGBA, not BGRA, as they're stored that way in D3D - case GL_RGB32F_EXT: - loadRGBFloatData(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - case GL_RGB16F_EXT: - loadRGBHalfFloatData(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - case GL_RGBA32F_EXT: - loadRGBAFloatData(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - case GL_RGBA16F_EXT: - loadRGBAHalfFloatData(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - default: UNREACHABLE(); - } - - unlock(); -} - -void Image::loadAlphaData(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const -{ - const unsigned char *source = NULL; - unsigned char *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = static_cast(input) + y * inputPitch; - dest = static_cast(output) + y * outputPitch; - for (int x = 0; x < width; x++) - { - dest[4 * x + 0] = 0; - dest[4 * x + 1] = 0; - dest[4 * x + 2] = 0; - dest[4 * x + 3] = source[x]; - } - } -} - -void Image::loadAlphaFloatData(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const -{ - const float *source = NULL; - float *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = reinterpret_cast(static_cast(input) + y * inputPitch); - dest = reinterpret_cast(static_cast(output) + y * outputPitch); - for (int x = 0; x < width; x++) - { - dest[4 * x + 0] = 0; - dest[4 * x + 1] = 0; - dest[4 * x + 2] = 0; - dest[4 * x + 3] = source[x]; - } - } -} - -void Image::loadAlphaHalfFloatData(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const -{ - const unsigned short *source = NULL; - unsigned short *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = reinterpret_cast(static_cast(input) + y * inputPitch); - dest = reinterpret_cast(static_cast(output) + y * outputPitch); - for (int x = 0; x < width; x++) - { - dest[4 * x + 0] = 0; - dest[4 * x + 1] = 0; - dest[4 * x + 2] = 0; - dest[4 * x + 3] = source[x]; - } - } -} - -void Image::loadLuminanceData(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output, bool native) const -{ - const unsigned char *source = NULL; - unsigned char *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = static_cast(input) + y * inputPitch; - dest = static_cast(output) + y * outputPitch; - - if (!native) // BGRA8 destination format - { - for (int x = 0; x < width; x++) - { - dest[4 * x + 0] = source[x]; - dest[4 * x + 1] = source[x]; - dest[4 * x + 2] = source[x]; - dest[4 * x + 3] = 0xFF; - } - } - else // L8 destination format - { - memcpy(dest, source, width); - } - } -} - -void Image::loadLuminanceFloatData(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const -{ - const float *source = NULL; - float *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = reinterpret_cast(static_cast(input) + y * inputPitch); - dest = reinterpret_cast(static_cast(output) + y * outputPitch); - for (int x = 0; x < width; x++) - { - dest[4 * x + 0] = source[x]; - dest[4 * x + 1] = source[x]; - dest[4 * x + 2] = source[x]; - dest[4 * x + 3] = 1.0f; - } - } -} - -void Image::loadLuminanceHalfFloatData(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const -{ - const unsigned short *source = NULL; - unsigned short *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = reinterpret_cast(static_cast(input) + y * inputPitch); - dest = reinterpret_cast(static_cast(output) + y * outputPitch); - for (int x = 0; x < width; x++) - { - dest[4 * x + 0] = source[x]; - dest[4 * x + 1] = source[x]; - dest[4 * x + 2] = source[x]; - dest[4 * x + 3] = 0x3C00; // SEEEEEMMMMMMMMMM, S = 0, E = 15, M = 0: 16bit flpt representation of 1 - } - } -} - -void Image::loadLuminanceAlphaData(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output, bool native) const -{ - const unsigned char *source = NULL; - unsigned char *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = static_cast(input) + y * inputPitch; - dest = static_cast(output) + y * outputPitch; - - if (!native) // BGRA8 destination format - { - for (int x = 0; x < width; x++) - { - dest[4 * x + 0] = source[2*x+0]; - dest[4 * x + 1] = source[2*x+0]; - dest[4 * x + 2] = source[2*x+0]; - dest[4 * x + 3] = source[2*x+1]; - } - } - else - { - memcpy(dest, source, width * 2); - } - } -} - -void Image::loadLuminanceAlphaFloatData(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const -{ - const float *source = NULL; - float *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = reinterpret_cast(static_cast(input) + y * inputPitch); - dest = reinterpret_cast(static_cast(output) + y * outputPitch); - for (int x = 0; x < width; x++) - { - dest[4 * x + 0] = source[2*x+0]; - dest[4 * x + 1] = source[2*x+0]; - dest[4 * x + 2] = source[2*x+0]; - dest[4 * x + 3] = source[2*x+1]; - } - } -} - -void Image::loadLuminanceAlphaHalfFloatData(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const -{ - const unsigned short *source = NULL; - unsigned short *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = reinterpret_cast(static_cast(input) + y * inputPitch); - dest = reinterpret_cast(static_cast(output) + y * outputPitch); - for (int x = 0; x < width; x++) - { - dest[4 * x + 0] = source[2*x+0]; - dest[4 * x + 1] = source[2*x+0]; - dest[4 * x + 2] = source[2*x+0]; - dest[4 * x + 3] = source[2*x+1]; - } - } -} - -void Image::loadRGBUByteData(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const -{ - const unsigned char *source = NULL; - unsigned char *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = static_cast(input) + y * inputPitch; - dest = static_cast(output) + y * outputPitch; - for (int x = 0; x < width; x++) - { - dest[4 * x + 0] = source[x * 3 + 2]; - dest[4 * x + 1] = source[x * 3 + 1]; - dest[4 * x + 2] = source[x * 3 + 0]; - dest[4 * x + 3] = 0xFF; - } - } -} - -void Image::loadRGB565Data(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const -{ - const unsigned short *source = NULL; - unsigned char *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = reinterpret_cast(static_cast(input) + y * inputPitch); - dest = static_cast(output) + y * outputPitch; - for (int x = 0; x < width; x++) - { - unsigned short rgba = source[x]; - dest[4 * x + 0] = ((rgba & 0x001F) << 3) | ((rgba & 0x001F) >> 2); - dest[4 * x + 1] = ((rgba & 0x07E0) >> 3) | ((rgba & 0x07E0) >> 9); - dest[4 * x + 2] = ((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13); - dest[4 * x + 3] = 0xFF; - } - } -} - -void Image::loadRGBFloatData(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const -{ - const float *source = NULL; - float *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = reinterpret_cast(static_cast(input) + y * inputPitch); - dest = reinterpret_cast(static_cast(output) + y * outputPitch); - for (int x = 0; x < width; x++) - { - dest[4 * x + 0] = source[x * 3 + 0]; - dest[4 * x + 1] = source[x * 3 + 1]; - dest[4 * x + 2] = source[x * 3 + 2]; - dest[4 * x + 3] = 1.0f; - } - } -} - -void Image::loadRGBHalfFloatData(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const -{ - const unsigned short *source = NULL; - unsigned short *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = reinterpret_cast(static_cast(input) + y * inputPitch); - dest = reinterpret_cast(static_cast(output) + y * outputPitch); - for (int x = 0; x < width; x++) - { - dest[4 * x + 0] = source[x * 3 + 0]; - dest[4 * x + 1] = source[x * 3 + 1]; - dest[4 * x + 2] = source[x * 3 + 2]; - dest[4 * x + 3] = 0x3C00; // SEEEEEMMMMMMMMMM, S = 0, E = 15, M = 0: 16bit flpt representation of 1 - } - } -} - -void Image::loadRGBAUByteData(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const -{ - const unsigned int *source = NULL; - unsigned int *dest = NULL; - for (int y = 0; y < height; y++) - { - source = reinterpret_cast(static_cast(input) + y * inputPitch); - dest = reinterpret_cast(static_cast(output) + y * outputPitch); - - for (int x = 0; x < width; x++) - { - unsigned int rgba = source[x]; - dest[x] = (_rotl(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00); - } - } -} - -void Image::loadRGBA4444Data(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const -{ - const unsigned short *source = NULL; - unsigned char *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = reinterpret_cast(static_cast(input) + y * inputPitch); - dest = static_cast(output) + y * outputPitch; - for (int x = 0; x < width; x++) - { - unsigned short rgba = source[x]; - dest[4 * x + 0] = ((rgba & 0x00F0) << 0) | ((rgba & 0x00F0) >> 4); - dest[4 * x + 1] = ((rgba & 0x0F00) >> 4) | ((rgba & 0x0F00) >> 8); - dest[4 * x + 2] = ((rgba & 0xF000) >> 8) | ((rgba & 0xF000) >> 12); - dest[4 * x + 3] = ((rgba & 0x000F) << 4) | ((rgba & 0x000F) >> 0); - } - } -} - -void Image::loadRGBA5551Data(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const -{ - const unsigned short *source = NULL; - unsigned char *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = reinterpret_cast(static_cast(input) + y * inputPitch); - dest = static_cast(output) + y * outputPitch; - for (int x = 0; x < width; x++) - { - unsigned short rgba = source[x]; - dest[4 * x + 0] = ((rgba & 0x003E) << 2) | ((rgba & 0x003E) >> 3); - dest[4 * x + 1] = ((rgba & 0x07C0) >> 3) | ((rgba & 0x07C0) >> 8); - dest[4 * x + 2] = ((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13); - dest[4 * x + 3] = (rgba & 0x0001) ? 0xFF : 0; - } - } -} - -void Image::loadRGBAFloatData(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const -{ - const float *source = NULL; - float *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = reinterpret_cast(static_cast(input) + y * inputPitch); - dest = reinterpret_cast(static_cast(output) + y * outputPitch); - memcpy(dest, source, width * 16); - } -} - -void Image::loadRGBAHalfFloatData(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const -{ - const unsigned char *source = NULL; - unsigned char *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = static_cast(input) + y * inputPitch; - dest = static_cast(output) + y * outputPitch; - memcpy(dest, source, width * 8); - } -} - -void Image::loadBGRAData(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const -{ - const unsigned char *source = NULL; - unsigned char *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = static_cast(input) + y * inputPitch; - dest = static_cast(output) + y * outputPitch; - memcpy(dest, source, width*4); - } -} - -void Image::loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, - const void *input) { - ASSERT(xoffset % 4 == 0); - ASSERT(yoffset % 4 == 0); - - RECT lockRect = { - xoffset, yoffset, - xoffset + width, yoffset + height - }; - - D3DLOCKED_RECT locked; - HRESULT result = lock(&locked, &lockRect); - if (FAILED(result)) - { - return; - } - - GLsizei inputSize = ComputeCompressedSize(width, height, mInternalFormat); - GLsizei inputPitch = ComputeCompressedPitch(width, mInternalFormat); - int rows = inputSize / inputPitch; - for (int i = 0; i < rows; ++i) - { - memcpy((void*)((BYTE*)locked.pBits + i * locked.Pitch), (void*)((BYTE*)input + i * inputPitch), inputPitch); - } - - unlock(); -} - -// This implements glCopyTex[Sub]Image2D for non-renderable internal texture formats and incomplete textures -void Image::copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, IDirect3DSurface9 *renderTarget) -{ - IDirect3DDevice9 *device = getDevice(); - IDirect3DSurface9 *renderTargetData = NULL; - D3DSURFACE_DESC description; - renderTarget->GetDesc(&description); - - HRESULT result = device->CreateOffscreenPlainSurface(description.Width, description.Height, description.Format, D3DPOOL_SYSTEMMEM, &renderTargetData, NULL); - - if (FAILED(result)) - { - ERR("Could not create matching destination surface."); - return error(GL_OUT_OF_MEMORY); - } - - result = device->GetRenderTargetData(renderTarget, renderTargetData); - - if (FAILED(result)) - { - ERR("GetRenderTargetData unexpectedly failed."); - renderTargetData->Release(); - return error(GL_OUT_OF_MEMORY); - } - - RECT sourceRect = {x, y, x + width, y + height}; - RECT destRect = {xoffset, yoffset, xoffset + width, yoffset + height}; - - D3DLOCKED_RECT sourceLock = {0}; - result = renderTargetData->LockRect(&sourceLock, &sourceRect, 0); - - if (FAILED(result)) - { - ERR("Failed to lock the source surface (rectangle might be invalid)."); - renderTargetData->Release(); - return error(GL_OUT_OF_MEMORY); - } - - D3DLOCKED_RECT destLock = {0}; - result = lock(&destLock, &destRect); - - if (FAILED(result)) - { - ERR("Failed to lock the destination surface (rectangle might be invalid)."); - renderTargetData->UnlockRect(); - renderTargetData->Release(); - return error(GL_OUT_OF_MEMORY); - } - - if (destLock.pBits && sourceLock.pBits) - { - unsigned char *source = (unsigned char*)sourceLock.pBits; - unsigned char *dest = (unsigned char*)destLock.pBits; - - switch (description.Format) - { - case D3DFMT_X8R8G8B8: - case D3DFMT_A8R8G8B8: - switch(getD3DFormat()) - { - case D3DFMT_X8R8G8B8: - case D3DFMT_A8R8G8B8: - for(int y = 0; y < height; y++) - { - memcpy(dest, source, 4 * width); - - source += sourceLock.Pitch; - dest += destLock.Pitch; - } - break; - case D3DFMT_L8: - for(int y = 0; y < height; y++) - { - for(int x = 0; x < width; x++) - { - dest[x] = source[x * 4 + 2]; - } - - source += sourceLock.Pitch; - dest += destLock.Pitch; - } - break; - case D3DFMT_A8L8: - for(int y = 0; y < height; y++) - { - for(int x = 0; x < width; x++) - { - dest[x * 2 + 0] = source[x * 4 + 2]; - dest[x * 2 + 1] = source[x * 4 + 3]; - } - - source += sourceLock.Pitch; - dest += destLock.Pitch; - } - break; - default: - UNREACHABLE(); - } - break; - case D3DFMT_R5G6B5: - switch(getD3DFormat()) - { - case D3DFMT_X8R8G8B8: - for(int y = 0; y < height; y++) - { - for(int x = 0; x < width; x++) - { - unsigned short rgb = ((unsigned short*)source)[x]; - unsigned char red = (rgb & 0xF800) >> 8; - unsigned char green = (rgb & 0x07E0) >> 3; - unsigned char blue = (rgb & 0x001F) << 3; - dest[x + 0] = blue | (blue >> 5); - dest[x + 1] = green | (green >> 6); - dest[x + 2] = red | (red >> 5); - dest[x + 3] = 0xFF; - } - - source += sourceLock.Pitch; - dest += destLock.Pitch; - } - break; - case D3DFMT_L8: - for(int y = 0; y < height; y++) - { - for(int x = 0; x < width; x++) - { - unsigned char red = source[x * 2 + 1] & 0xF8; - dest[x] = red | (red >> 5); - } - - source += sourceLock.Pitch; - dest += destLock.Pitch; - } - break; - default: - UNREACHABLE(); - } - break; - case D3DFMT_A1R5G5B5: - switch(getD3DFormat()) - { - case D3DFMT_X8R8G8B8: - for(int y = 0; y < height; y++) - { - for(int x = 0; x < width; x++) - { - unsigned short argb = ((unsigned short*)source)[x]; - unsigned char red = (argb & 0x7C00) >> 7; - unsigned char green = (argb & 0x03E0) >> 2; - unsigned char blue = (argb & 0x001F) << 3; - dest[x + 0] = blue | (blue >> 5); - dest[x + 1] = green | (green >> 5); - dest[x + 2] = red | (red >> 5); - dest[x + 3] = 0xFF; - } - - source += sourceLock.Pitch; - dest += destLock.Pitch; - } - break; - case D3DFMT_A8R8G8B8: - for(int y = 0; y < height; y++) - { - for(int x = 0; x < width; x++) - { - unsigned short argb = ((unsigned short*)source)[x]; - unsigned char red = (argb & 0x7C00) >> 7; - unsigned char green = (argb & 0x03E0) >> 2; - unsigned char blue = (argb & 0x001F) << 3; - unsigned char alpha = (signed short)argb >> 15; - dest[x + 0] = blue | (blue >> 5); - dest[x + 1] = green | (green >> 5); - dest[x + 2] = red | (red >> 5); - dest[x + 3] = alpha; - } - - source += sourceLock.Pitch; - dest += destLock.Pitch; - } - break; - case D3DFMT_L8: - for(int y = 0; y < height; y++) - { - for(int x = 0; x < width; x++) - { - unsigned char red = source[x * 2 + 1] & 0x7C; - dest[x] = (red << 1) | (red >> 4); - } - - source += sourceLock.Pitch; - dest += destLock.Pitch; - } - break; - case D3DFMT_A8L8: - for(int y = 0; y < height; y++) - { - for(int x = 0; x < width; x++) - { - unsigned char red = source[x * 2 + 1] & 0x7C; - dest[x * 2 + 0] = (red << 1) | (red >> 4); - dest[x * 2 + 1] = (signed char)source[x * 2 + 1] >> 7; - } - - source += sourceLock.Pitch; - dest += destLock.Pitch; - } - break; - default: - UNREACHABLE(); - } - break; - default: - UNREACHABLE(); - } - } - - unlock(); - renderTargetData->UnlockRect(); - - renderTargetData->Release(); - - mDirty = true; -} - -namespace -{ -struct L8 -{ - unsigned char L; - - static void average(L8 *dst, const L8 *src1, const L8 *src2) - { - dst->L = ((src1->L ^ src2->L) >> 1) + (src1->L & src2->L); - } -}; - -struct A8L8 -{ - unsigned char L; - unsigned char A; - - static void average(A8L8 *dst, const A8L8 *src1, const A8L8 *src2) - { - *(unsigned short*)dst = (((*(unsigned short*)src1 ^ *(unsigned short*)src2) & 0xFEFE) >> 1) + (*(unsigned short*)src1 & *(unsigned short*)src2); - } -}; - -struct A8R8G8B8 -{ - unsigned char B; - unsigned char G; - unsigned char R; - unsigned char A; - - static void average(A8R8G8B8 *dst, const A8R8G8B8 *src1, const A8R8G8B8 *src2) - { - *(unsigned int*)dst = (((*(unsigned int*)src1 ^ *(unsigned int*)src2) & 0xFEFEFEFE) >> 1) + (*(unsigned int*)src1 & *(unsigned int*)src2); - } -}; - -struct A16B16G16R16F -{ - unsigned short R; - unsigned short G; - unsigned short B; - unsigned short A; - - static void average(A16B16G16R16F *dst, const A16B16G16R16F *src1, const A16B16G16R16F *src2) - { - dst->R = float32ToFloat16((float16ToFloat32(src1->R) + float16ToFloat32(src2->R)) * 0.5f); - dst->G = float32ToFloat16((float16ToFloat32(src1->G) + float16ToFloat32(src2->G)) * 0.5f); - dst->B = float32ToFloat16((float16ToFloat32(src1->B) + float16ToFloat32(src2->B)) * 0.5f); - dst->A = float32ToFloat16((float16ToFloat32(src1->A) + float16ToFloat32(src2->A)) * 0.5f); - } -}; - -struct A32B32G32R32F -{ - float R; - float G; - float B; - float A; - - static void average(A32B32G32R32F *dst, const A32B32G32R32F *src1, const A32B32G32R32F *src2) - { - dst->R = (src1->R + src2->R) * 0.5f; - dst->G = (src1->G + src2->G) * 0.5f; - dst->B = (src1->B + src2->B) * 0.5f; - dst->A = (src1->A + src2->A) * 0.5f; - } -}; - -template -void GenerateMip(unsigned int sourceWidth, unsigned int sourceHeight, - const unsigned char *sourceData, int sourcePitch, - unsigned char *destData, int destPitch) -{ - unsigned int mipWidth = std::max(1U, sourceWidth >> 1); - unsigned int mipHeight = std::max(1U, sourceHeight >> 1); - - if (sourceHeight == 1) - { - ASSERT(sourceWidth != 1); - - const T *src = (const T*)sourceData; - T *dst = (T*)destData; - - for (unsigned int x = 0; x < mipWidth; x++) - { - T::average(&dst[x], &src[x * 2], &src[x * 2 + 1]); - } - } - else if (sourceWidth == 1) - { - ASSERT(sourceHeight != 1); - - for (unsigned int y = 0; y < mipHeight; y++) - { - const T *src0 = (const T*)(sourceData + y * 2 * sourcePitch); - const T *src1 = (const T*)(sourceData + y * 2 * sourcePitch + sourcePitch); - T *dst = (T*)(destData + y * destPitch); - - T::average(dst, src0, src1); - } - } - else - { - for (unsigned int y = 0; y < mipHeight; y++) - { - const T *src0 = (const T*)(sourceData + y * 2 * sourcePitch); - const T *src1 = (const T*)(sourceData + y * 2 * sourcePitch + sourcePitch); - T *dst = (T*)(destData + y * destPitch); - - for (unsigned int x = 0; x < mipWidth; x++) - { - T tmp0; - T tmp1; - - T::average(&tmp0, &src0[x * 2], &src0[x * 2 + 1]); - T::average(&tmp1, &src1[x * 2], &src1[x * 2 + 1]); - T::average(&dst[x], &tmp0, &tmp1); - } - } - } -} - -void GenerateMip(IDirect3DSurface9 *destSurface, IDirect3DSurface9 *sourceSurface) -{ - D3DSURFACE_DESC destDesc; - HRESULT result = destSurface->GetDesc(&destDesc); - ASSERT(SUCCEEDED(result)); - - D3DSURFACE_DESC sourceDesc; - result = sourceSurface->GetDesc(&sourceDesc); - ASSERT(SUCCEEDED(result)); - - ASSERT(sourceDesc.Format == destDesc.Format); - ASSERT(sourceDesc.Width == 1 || sourceDesc.Width / 2 == destDesc.Width); - ASSERT(sourceDesc.Height == 1 || sourceDesc.Height / 2 == destDesc.Height); - - D3DLOCKED_RECT sourceLocked = {0}; - result = sourceSurface->LockRect(&sourceLocked, NULL, D3DLOCK_READONLY); - ASSERT(SUCCEEDED(result)); - - D3DLOCKED_RECT destLocked = {0}; - result = destSurface->LockRect(&destLocked, NULL, 0); - ASSERT(SUCCEEDED(result)); - - const unsigned char *sourceData = reinterpret_cast(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(); - } -} -} - -TextureStorage::TextureStorage(DWORD usage) - : mD3DUsage(usage), - mD3DPool(getDisplay()->getTexturePool(usage)), - mTextureSerial(issueTextureSerial()), - mLodOffset(0) -{ -} - -TextureStorage::~TextureStorage() -{ -} - -bool TextureStorage::isRenderTarget() const -{ - return (mD3DUsage & (D3DUSAGE_RENDERTARGET | D3DUSAGE_DEPTHSTENCIL)) != 0; -} - -bool TextureStorage::isManaged() const -{ - return (mD3DPool == D3DPOOL_MANAGED); -} - -D3DPOOL TextureStorage::getPool() const -{ - return mD3DPool; -} - -DWORD TextureStorage::getUsage() const -{ - return mD3DUsage; -} - -unsigned int TextureStorage::getTextureSerial() const -{ - return mTextureSerial; -} +#include "libGLESv2/main.h" +#include "libGLESv2/mathutil.h" +#include "libGLESv2/utilities.h" +#if defined(ANGLE_ENABLE_D3D11) +# define D3DFMT_UNKNOWN DXGI_FORMAT_UNKNOWN +#else +# include "libGLESv2/renderer/Blit.h" +#endif +#include "libGLESv2/Renderbuffer.h" +#include "libGLESv2/renderer/Image.h" +#include "libGLESv2/renderer/Renderer.h" +#include "libGLESv2/renderer/TextureStorage.h" +#include "libEGL/Surface.h" -unsigned int TextureStorage::issueTextureSerial() +namespace gl { - return mCurrentTextureSerial++; -} -int TextureStorage::getLodOffset() const +Texture::Texture(rx::Renderer *renderer, GLuint id) : RefCountObject(id) { - return mLodOffset; -} + mRenderer = renderer; -Texture::Texture(GLuint id) : RefCountObject(id) -{ - mMinFilter = GL_NEAREST_MIPMAP_LINEAR; - mMagFilter = GL_LINEAR; - mWrapS = GL_REPEAT; - mWrapT = GL_REPEAT; - mDirtyParameters = true; + mSamplerState.minFilter = GL_NEAREST_MIPMAP_LINEAR; + mSamplerState.magFilter = GL_LINEAR; + mSamplerState.wrapS = GL_REPEAT; + mSamplerState.wrapT = GL_REPEAT; + mSamplerState.maxAnisotropy = 1.0f; + mSamplerState.lodOffset = 0; mUsage = GL_NONE; - mMaxAnisotropy = 1.0f; mDirtyImages = true; @@ -1345,14 +60,8 @@ bool Texture::setMinFilter(GLenum filter) case GL_LINEAR_MIPMAP_NEAREST: case GL_NEAREST_MIPMAP_LINEAR: case GL_LINEAR_MIPMAP_LINEAR: - { - if (mMinFilter != filter) - { - mMinFilter = filter; - mDirtyParameters = true; - } - return true; - } + mSamplerState.minFilter = filter; + return true; default: return false; } @@ -1365,14 +74,8 @@ bool Texture::setMagFilter(GLenum filter) { case GL_NEAREST: case GL_LINEAR: - { - if (mMagFilter != filter) - { - mMagFilter = filter; - mDirtyParameters = true; - } - return true; - } + mSamplerState.magFilter = filter; + return true; default: return false; } @@ -1386,14 +89,8 @@ bool Texture::setWrapS(GLenum wrap) case GL_REPEAT: case GL_CLAMP_TO_EDGE: case GL_MIRRORED_REPEAT: - { - if (mWrapS != wrap) - { - mWrapS = wrap; - mDirtyParameters = true; - } - return true; - } + mSamplerState.wrapS = wrap; + return true; default: return false; } @@ -1407,14 +104,8 @@ bool Texture::setWrapT(GLenum wrap) case GL_REPEAT: case GL_CLAMP_TO_EDGE: case GL_MIRRORED_REPEAT: - { - if (mWrapT != wrap) - { - mWrapT = wrap; - mDirtyParameters = true; - } - return true; - } + mSamplerState.wrapT = wrap; + return true; default: return false; } @@ -1428,11 +119,9 @@ bool Texture::setMaxAnisotropy(float textureMaxAnisotropy, float contextMaxAniso { return false; } - if (mMaxAnisotropy != textureMaxAnisotropy) - { - mMaxAnisotropy = textureMaxAnisotropy; - mDirtyParameters = true; - } + + mSamplerState.maxAnisotropy = textureMaxAnisotropy; + return true; } @@ -1452,27 +141,39 @@ bool Texture::setUsage(GLenum usage) GLenum Texture::getMinFilter() const { - return mMinFilter; + return mSamplerState.minFilter; } GLenum Texture::getMagFilter() const { - return mMagFilter; + return mSamplerState.magFilter; } GLenum Texture::getWrapS() const { - return mWrapS; + return mSamplerState.wrapS; } GLenum Texture::getWrapT() const { - return mWrapT; + return mSamplerState.wrapT; } float Texture::getMaxAnisotropy() const { - return mMaxAnisotropy; + return mSamplerState.maxAnisotropy; +} + +int Texture::getLodOffset() +{ + rx::TextureStorageInterface *texture = getStorage(false); + return texture ? texture->getLodOffset() : 0; +} + +void Texture::getSamplerState(SamplerState *sampler) +{ + *sampler = mSamplerState; + sampler->lodOffset = getLodOffset(); } GLenum Texture::getUsage() const @@ -1480,7 +181,24 @@ GLenum Texture::getUsage() const return mUsage; } -void Texture::setImage(GLint unpackAlignment, const void *pixels, Image *image) +bool Texture::isMipmapFiltered() const +{ + switch (mSamplerState.minFilter) + { + case GL_NEAREST: + case GL_LINEAR: + return false; + case GL_NEAREST_MIPMAP_NEAREST: + case GL_LINEAR_MIPMAP_NEAREST: + case GL_NEAREST_MIPMAP_LINEAR: + case GL_LINEAR_MIPMAP_LINEAR: + return true; + default: UNREACHABLE(); + return false; + } +} + +void Texture::setImage(GLint unpackAlignment, const void *pixels, rx::Image *image) { if (pixels != NULL) { @@ -1489,7 +207,7 @@ void Texture::setImage(GLint unpackAlignment, const void *pixels, Image *image) } } -void Texture::setCompressedImage(GLsizei imageSize, const void *pixels, Image *image) +void Texture::setCompressedImage(GLsizei imageSize, const void *pixels, rx::Image *image) { if (pixels != NULL) { @@ -1498,7 +216,7 @@ void Texture::setCompressedImage(GLsizei imageSize, const void *pixels, Image *i } } -bool Texture::subImage(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels, Image *image) +bool Texture::subImage(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels, rx::Image *image) { if (pixels != NULL) { @@ -1509,7 +227,7 @@ bool Texture::subImage(GLint xoffset, GLint yoffset, GLsizei width, GLsizei heig return true; } -bool Texture::subImageCompressed(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels, Image *image) +bool Texture::subImageCompressed(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels, rx::Image *image) { if (pixels != NULL) { @@ -1520,27 +238,17 @@ bool Texture::subImageCompressed(GLint xoffset, GLint yoffset, GLsizei width, GL return true; } -IDirect3DBaseTexture9 *Texture::getTexture() +rx::TextureStorageInterface *Texture::getNativeTexture() { - if (!isSamplerComplete()) - { - return NULL; - } - // ensure the underlying texture is created - if (getStorage(false) == NULL) + + rx::TextureStorageInterface *storage = getStorage(false); + if (storage) { - return NULL; + updateTexture(); } - updateTexture(); - - return getBaseTexture(); -} - -bool Texture::hasDirtyParameters() const -{ - return mDirtyParameters; + return storage; } bool Texture::hasDirtyImages() const @@ -1550,19 +258,18 @@ bool Texture::hasDirtyImages() const void Texture::resetDirty() { - mDirtyParameters = false; mDirtyImages = false; } unsigned int Texture::getTextureSerial() { - TextureStorage *texture = getStorage(false); + rx::TextureStorageInterface *texture = getStorage(false); return texture ? texture->getTextureSerial() : 0; } unsigned int Texture::getRenderTargetSerial(GLenum target) { - TextureStorage *texture = getStorage(true); + rx::TextureStorageInterface *texture = getStorage(true); return texture ? texture->getRenderTargetSerial(target) : 0; } @@ -1571,15 +278,9 @@ bool Texture::isImmutable() const return mImmutable; } -int Texture::getLodOffset() -{ - TextureStorage *texture = getStorage(false); - return texture ? texture->getLodOffset() : 0; -} - GLint Texture::creationLevels(GLsizei width, GLsizei height) const { - if ((isPow2(width) && isPow2(height)) || getContext()->supportsNonPower2Texture()) + if ((isPow2(width) && isPow2(height)) || mRenderer->getNonPower2TextureSupport()) { return 0; // Maximum number of levels } @@ -1595,127 +296,17 @@ GLint Texture::creationLevels(GLsizei size) const return creationLevels(size, size); } -int Texture::levelCount() -{ - return getBaseTexture() ? getBaseTexture()->GetLevelCount() - getLodOffset() : 0; -} - -Blit *Texture::getBlitter() -{ - Context *context = getContext(); - return context->getBlitter(); -} - -bool Texture::copyToRenderTarget(IDirect3DSurface9 *dest, IDirect3DSurface9 *source, bool fromManaged) -{ - if (source && dest) - { - HRESULT result = D3DERR_OUTOFVIDEOMEMORY; - - if (fromManaged) - { - D3DSURFACE_DESC desc; - source->GetDesc(&desc); - - IDirect3DSurface9 *surf = 0; - result = getDevice()->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &surf, NULL); - - if (SUCCEEDED(result)) - { - CopyLockableSurfaces(surf, source); - result = getDevice()->UpdateSurface(surf, NULL, dest, NULL); - surf->Release(); - } - } - else - { - egl::Display *display = getDisplay(); - IDirect3DDevice9 *device = display->getDevice(); - - display->endScene(); - result = device->StretchRect(source, NULL, dest, NULL, D3DTEXF_NONE); - } - - if (FAILED(result)) - { - ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - return false; - } - } - - return true; -} - -TextureStorage2D::TextureStorage2D(IDirect3DTexture9 *surfaceTexture) : TextureStorage(D3DUSAGE_RENDERTARGET), mRenderTargetSerial(RenderbufferStorage::issueSerial()) -{ - mTexture = surfaceTexture; -} - -TextureStorage2D::TextureStorage2D(int levels, D3DFORMAT format, DWORD usage, int width, int height) - : TextureStorage(usage), mRenderTargetSerial(RenderbufferStorage::issueSerial()) -{ - mTexture = NULL; - // if the width or height is not positive this should be treated as an incomplete texture - // we handle that here by skipping the d3d texture creation - if (width > 0 && height > 0) - { - IDirect3DDevice9 *device = getDevice(); - MakeValidSize(false, dx::IsCompressedFormat(format), &width, &height, &mLodOffset); - HRESULT result = device->CreateTexture(width, height, levels ? levels + mLodOffset : 0, getUsage(), format, getPool(), &mTexture, NULL); - - if (FAILED(result)) - { - ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - error(GL_OUT_OF_MEMORY); - } - } -} - -TextureStorage2D::~TextureStorage2D() -{ - if (mTexture) - { - mTexture->Release(); - } -} - -// Increments refcount on surface. -// caller must Release() the returned surface -IDirect3DSurface9 *TextureStorage2D::getSurfaceLevel(int level, bool dirty) -{ - IDirect3DSurface9 *surface = NULL; - - if (mTexture) - { - HRESULT result = mTexture->GetSurfaceLevel(level + mLodOffset, &surface); - ASSERT(SUCCEEDED(result)); - - // With managed textures the driver needs to be informed of updates to the lower mipmap levels - if (level != 0 && isManaged() && dirty) - { - mTexture->AddDirtyRect(NULL); - } - } - - return surface; -} - -IDirect3DBaseTexture9 *TextureStorage2D::getBaseTexture() const -{ - return mTexture; -} - -unsigned int TextureStorage2D::getRenderTargetSerial(GLenum target) const -{ - return mRenderTargetSerial; -} - -Texture2D::Texture2D(GLuint id) : Texture(id) +Texture2D::Texture2D(rx::Renderer *renderer, GLuint id) : Texture(renderer, id) { mTexStorage = NULL; mSurface = NULL; mColorbufferProxy = NULL; mProxyRefs = 0; + + for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i) + { + mImageArray[i] = renderer->createImage(); + } } Texture2D::~Texture2D() @@ -1730,6 +321,11 @@ Texture2D::~Texture2D() mSurface->setBoundTexture(NULL); mSurface = NULL; } + + for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i) + { + delete mImageArray[i]; + } } // We need to maintain a count of references to renderbuffers acting as @@ -1757,7 +353,7 @@ GLenum Texture2D::getTarget() const GLsizei Texture2D::getWidth(GLint level) const { if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) - return mImageArray[level].getWidth(); + return mImageArray[level]->getWidth(); else return 0; } @@ -1765,7 +361,7 @@ GLsizei Texture2D::getWidth(GLint level) const GLsizei Texture2D::getHeight(GLint level) const { if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) - return mImageArray[level].getHeight(); + return mImageArray[level]->getHeight(); else return 0; } @@ -1773,15 +369,15 @@ GLsizei Texture2D::getHeight(GLint level) const GLenum Texture2D::getInternalFormat(GLint level) const { if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) - return mImageArray[level].getInternalFormat(); + return mImageArray[level]->getInternalFormat(); else return GL_NONE; } -D3DFORMAT Texture2D::getD3DFormat(GLint level) const +GLenum Texture2D::getActualFormat(GLint level) const { if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) - return mImageArray[level].getD3DFormat(); + return mImageArray[level]->getActualFormat(); else return D3DFMT_UNKNOWN; } @@ -1790,18 +386,31 @@ void Texture2D::redefineImage(GLint level, GLint internalformat, GLsizei width, { releaseTexImage(); - bool redefined = mImageArray[level].redefine(internalformat, width, height, false); + // If there currently is a corresponding storage texture image, it has these parameters + const int storageWidth = std::max(1, mImageArray[0]->getWidth() >> level); + const int storageHeight = std::max(1, mImageArray[0]->getHeight() >> level); + const int storageFormat = mImageArray[0]->getInternalFormat(); + + mImageArray[level]->redefine(mRenderer, internalformat, width, height, false); - if (mTexStorage && redefined) + if (mTexStorage) { - for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) + const int storageLevels = mTexStorage->levelCount(); + + if ((level >= storageLevels && storageLevels != 0) || + width != storageWidth || + height != storageHeight || + internalformat != storageFormat) // Discard mismatched storage { - mImageArray[i].markDirty(); - } + for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) + { + mImageArray[i]->markDirty(); + } - delete mTexStorage; - mTexStorage = NULL; - mDirtyImages = true; + delete mTexStorage; + mTexStorage = NULL; + mDirtyImages = true; + } } } @@ -1810,32 +419,19 @@ void Texture2D::setImage(GLint level, GLsizei width, GLsizei height, GLenum form GLint internalformat = ConvertSizedInternalFormat(format, type); redefineImage(level, internalformat, width, height); - Texture::setImage(unpackAlignment, pixels, &mImageArray[level]); + Texture::setImage(unpackAlignment, pixels, mImageArray[level]); } void Texture2D::bindTexImage(egl::Surface *surface) { releaseTexImage(); - GLint internalformat; - - switch(surface->getFormat()) - { - case D3DFMT_A8R8G8B8: - internalformat = GL_RGBA8_OES; - break; - case D3DFMT_X8R8G8B8: - internalformat = GL_RGB8_OES; - break; - default: - UNIMPLEMENTED(); - return; - } + GLint internalformat = surface->getFormat(); - mImageArray[0].redefine(internalformat, surface->getWidth(), surface->getHeight(), true); + mImageArray[0]->redefine(mRenderer, internalformat, surface->getWidth(), surface->getHeight(), true); delete mTexStorage; - mTexStorage = new TextureStorage2D(surface->getOffscreenTexture()); + mTexStorage = new rx::TextureStorageInterface2D(mRenderer, surface->getSwapChain()); mDirtyImages = true; mSurface = surface; @@ -1857,7 +453,7 @@ void Texture2D::releaseTexImage() for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) { - mImageArray[i].redefine(GL_RGBA8_OES, 0, 0, true); + mImageArray[i]->redefine(mRenderer, GL_NONE, 0, 0, true); } } } @@ -1867,23 +463,16 @@ void Texture2D::setCompressedImage(GLint level, GLenum format, GLsizei width, GL // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly redefineImage(level, format, width, height); - Texture::setCompressedImage(imageSize, pixels, &mImageArray[level]); + Texture::setCompressedImage(imageSize, pixels, mImageArray[level]); } void Texture2D::commitRect(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) { - ASSERT(mImageArray[level].getSurface() != NULL); - if (level < levelCount()) { - IDirect3DSurface9 *destLevel = mTexStorage->getSurfaceLevel(level, true); - - if (destLevel) + rx::Image *image = mImageArray[level]; + if (image->updateSurface(mTexStorage, level, xoffset, yoffset, width, height)) { - Image *image = &mImageArray[level]; - image->updateSurface(destLevel, xoffset, yoffset, width, height); - - destLevel->Release(); image->markClean(); } } @@ -1891,7 +480,7 @@ void Texture2D::commitRect(GLint level, GLint xoffset, GLint yoffset, GLsizei wi void Texture2D::subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels) { - if (Texture::subImage(xoffset, yoffset, width, height, format, type, unpackAlignment, pixels, &mImageArray[level])) + if (Texture::subImage(xoffset, yoffset, width, height, format, type, unpackAlignment, pixels, mImageArray[level])) { commitRect(level, xoffset, yoffset, width, height); } @@ -1899,7 +488,7 @@ void Texture2D::subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei widt void Texture2D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels) { - if (Texture::subImageCompressed(xoffset, yoffset, width, height, format, imageSize, pixels, &mImageArray[level])) + if (Texture::subImageCompressed(xoffset, yoffset, width, height, format, imageSize, pixels, mImageArray[level])) { commitRect(level, xoffset, yoffset, width, height); } @@ -1907,20 +496,12 @@ void Texture2D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GL void Texture2D::copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source) { - IDirect3DSurface9 *renderTarget = source->getRenderTarget(); - - if (!renderTarget) - { - ERR("Failed to retrieve the render target."); - return error(GL_OUT_OF_MEMORY); - } - GLint internalformat = ConvertSizedInternalFormat(format, GL_UNSIGNED_BYTE); redefineImage(level, internalformat, width, height); - - if (!mImageArray[level].isRenderableFormat()) + + if (!mImageArray[level]->isRenderableFormat()) { - mImageArray[level].copy(0, 0, x, y, width, height, renderTarget); + mImageArray[level]->copy(0, 0, x, y, width, height, source); mDirtyImages = true; } else @@ -1930,47 +511,31 @@ void Texture2D::copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei convertToRenderTarget(); } - mImageArray[level].markClean(); + mImageArray[level]->markClean(); if (width != 0 && height != 0 && level < levelCount()) { - RECT sourceRect; - sourceRect.left = x; - sourceRect.right = x + width; - sourceRect.top = y; - sourceRect.bottom = y + height; - - IDirect3DSurface9 *dest = mTexStorage->getSurfaceLevel(level, true); - - if (dest) - { - getBlitter()->copy(renderTarget, sourceRect, format, 0, 0, dest); - dest->Release(); - } + gl::Rectangle sourceRect; + sourceRect.x = x; + sourceRect.width = width; + sourceRect.y = y; + sourceRect.height = height; + + mRenderer->copyImage(source, sourceRect, format, 0, 0, mTexStorage, level); } } - - renderTarget->Release(); } void Texture2D::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source) { - if (xoffset + width > mImageArray[level].getWidth() || yoffset + height > mImageArray[level].getHeight()) - { - return error(GL_INVALID_VALUE); - } - - IDirect3DSurface9 *renderTarget = source->getRenderTarget(); - - if (!renderTarget) + if (xoffset + width > mImageArray[level]->getWidth() || yoffset + height > mImageArray[level]->getHeight()) { - ERR("Failed to retrieve the render target."); - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_INVALID_VALUE); } - if (!mImageArray[level].isRenderableFormat() || (!mTexStorage && !isSamplerComplete())) + if (!mImageArray[level]->isRenderableFormat() || (!mTexStorage && !isSamplerComplete())) { - mImageArray[level].copy(xoffset, yoffset, x, y, width, height, renderTarget); + mImageArray[level]->copy(xoffset, yoffset, x, y, width, height, source); mDirtyImages = true; } else @@ -1984,46 +549,35 @@ void Texture2D::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yo if (level < levelCount()) { - RECT sourceRect; - sourceRect.left = x; - sourceRect.right = x + width; - sourceRect.top = y; - sourceRect.bottom = y + height; - - IDirect3DSurface9 *dest = mTexStorage->getSurfaceLevel(level, true); + gl::Rectangle sourceRect; + sourceRect.x = x; + sourceRect.width = width; + sourceRect.y = y; + sourceRect.height = height; - if (dest) - { - getBlitter()->copy(renderTarget, sourceRect, - gl::ExtractFormat(mImageArray[0].getInternalFormat()), - xoffset, yoffset, dest); - dest->Release(); - } + mRenderer->copyImage(source, sourceRect, + gl::ExtractFormat(mImageArray[0]->getInternalFormat()), + xoffset, yoffset, mTexStorage, level); } } - - renderTarget->Release(); } void Texture2D::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) { - D3DFORMAT d3dfmt = ConvertTextureInternalFormat(internalformat); - DWORD d3dusage = GetTextureUsage(d3dfmt, mUsage, false); - delete mTexStorage; - mTexStorage = new TextureStorage2D(levels, d3dfmt, d3dusage, width, height); + mTexStorage = new rx::TextureStorageInterface2D(mRenderer, levels, internalformat, mUsage, false, width, height); mImmutable = true; for (int level = 0; level < levels; level++) { - mImageArray[level].redefine(internalformat, width, height, true); + mImageArray[level]->redefine(mRenderer, internalformat, width, height, true); width = std::max(1, width >> 1); height = std::max(1, height >> 1); } for (int level = levels; level < IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) { - mImageArray[level].redefine(GL_NONE, 0, 0, true); + mImageArray[level]->redefine(mRenderer, GL_NONE, 0, 0, true); } if (mTexStorage->isManaged()) @@ -2032,8 +586,7 @@ void Texture2D::storage(GLsizei levels, GLenum internalformat, GLsizei width, GL for (int level = 0; level < levels; level++) { - IDirect3DSurface9 *surface = mTexStorage->getSurfaceLevel(level, false); - mImageArray[level].setManagedSurface(surface); + mImageArray[level]->setManagedSurface(mTexStorage, level); } } } @@ -2041,46 +594,33 @@ void Texture2D::storage(GLsizei levels, GLenum internalformat, GLsizei width, GL // Tests for 2D texture sampling completeness. [OpenGL ES 2.0.24] section 3.8.2 page 85. bool Texture2D::isSamplerComplete() const { - GLsizei width = mImageArray[0].getWidth(); - GLsizei height = mImageArray[0].getHeight(); + GLsizei width = mImageArray[0]->getWidth(); + GLsizei height = mImageArray[0]->getHeight(); if (width <= 0 || height <= 0) { return false; } - bool mipmapping = false; - - switch (mMinFilter) - { - case GL_NEAREST: - case GL_LINEAR: - mipmapping = false; - break; - case GL_NEAREST_MIPMAP_NEAREST: - case GL_LINEAR_MIPMAP_NEAREST: - case GL_NEAREST_MIPMAP_LINEAR: - case GL_LINEAR_MIPMAP_LINEAR: - mipmapping = true; - break; - default: UNREACHABLE(); - } + bool mipmapping = isMipmapFiltered(); + bool filtering, renderable; - if ((IsFloat32Format(getInternalFormat(0)) && !getContext()->supportsFloat32LinearFilter()) || - (IsFloat16Format(getInternalFormat(0)) && !getContext()->supportsFloat16LinearFilter())) + if ((IsFloat32Format(getInternalFormat(0)) && !mRenderer->getFloat32TextureSupport(&filtering, &renderable)) || + (IsFloat16Format(getInternalFormat(0)) && !mRenderer->getFloat16TextureSupport(&filtering, &renderable))) { - if (mMagFilter != GL_NEAREST || (mMinFilter != GL_NEAREST && mMinFilter != GL_NEAREST_MIPMAP_NEAREST)) + if (mSamplerState.magFilter != GL_NEAREST || + (mSamplerState.minFilter != GL_NEAREST && mSamplerState.minFilter != GL_NEAREST_MIPMAP_NEAREST)) { return false; } } - bool npotSupport = getContext()->supportsNonPower2Texture(); + bool npotSupport = mRenderer->getNonPower2TextureSupport(); if (!npotSupport) { - if ((getWrapS() != GL_CLAMP_TO_EDGE && !isPow2(width)) || - (getWrapT() != GL_CLAMP_TO_EDGE && !isPow2(height))) + if ((mSamplerState.wrapS != GL_CLAMP_TO_EDGE && !isPow2(width)) || + (mSamplerState.wrapT != GL_CLAMP_TO_EDGE && !isPow2(height))) { return false; } @@ -2113,8 +653,8 @@ bool Texture2D::isMipmapComplete() const return true; } - GLsizei width = mImageArray[0].getWidth(); - GLsizei height = mImageArray[0].getHeight(); + GLsizei width = mImageArray[0]->getWidth(); + GLsizei height = mImageArray[0]->getHeight(); if (width <= 0 || height <= 0) { @@ -2125,17 +665,17 @@ bool Texture2D::isMipmapComplete() const for (int level = 1; level <= q; level++) { - if (mImageArray[level].getInternalFormat() != mImageArray[0].getInternalFormat()) + if (mImageArray[level]->getInternalFormat() != mImageArray[0]->getInternalFormat()) { return false; } - if (mImageArray[level].getWidth() != std::max(1, width >> level)) + if (mImageArray[level]->getWidth() != std::max(1, width >> level)) { return false; } - if (mImageArray[level].getHeight() != std::max(1, height >> level)) + if (mImageArray[level]->getHeight() != std::max(1, height >> level)) { return false; } @@ -2154,26 +694,20 @@ bool Texture2D::isDepth(GLint level) const return IsDepthTexture(getInternalFormat(level)); } -IDirect3DBaseTexture9 *Texture2D::getBaseTexture() const -{ - return mTexStorage ? mTexStorage->getBaseTexture() : NULL; -} - -// Constructs a Direct3D 9 texture resource from the texture images +// Constructs a native texture resource from the texture images void Texture2D::createTexture() { - GLsizei width = mImageArray[0].getWidth(); - GLsizei height = mImageArray[0].getHeight(); + GLsizei width = mImageArray[0]->getWidth(); + GLsizei height = mImageArray[0]->getHeight(); if (!(width > 0 && height > 0)) - return; // do not attempt to create d3d textures for nonexistant data + return; // do not attempt to create native textures for nonexistant data GLint levels = creationLevels(width, height); - D3DFORMAT d3dfmt = mImageArray[0].getD3DFormat(); - DWORD d3dusage = GetTextureUsage(d3dfmt, mUsage, false); + GLenum internalformat = mImageArray[0]->getInternalFormat(); delete mTexStorage; - mTexStorage = new TextureStorage2D(levels, d3dfmt, d3dusage, width, height); + mTexStorage = new rx::TextureStorageInterface2D(mRenderer, levels, internalformat, mUsage, false, width, height); if (mTexStorage->isManaged()) { @@ -2181,8 +715,7 @@ void Texture2D::createTexture() for (int level = 0; level < levels; level++) { - IDirect3DSurface9 *surface = mTexStorage->getSurfaceLevel(level, false); - mImageArray[level].setManagedSurface(surface); + mImageArray[level]->setManagedSurface(mTexStorage, level); } } @@ -2191,51 +724,40 @@ void Texture2D::createTexture() void Texture2D::updateTexture() { - int levels = levelCount(); + bool mipmapping = (isMipmapFiltered() && isMipmapComplete()); + + int levels = (mipmapping ? levelCount() : 1); for (int level = 0; level < levels; level++) { - Image *image = &mImageArray[level]; + rx::Image *image = mImageArray[level]; if (image->isDirty()) { - commitRect(level, 0, 0, mImageArray[level].getWidth(), mImageArray[level].getHeight()); + commitRect(level, 0, 0, mImageArray[level]->getWidth(), mImageArray[level]->getHeight()); } } } void Texture2D::convertToRenderTarget() { - TextureStorage2D *newTexStorage = NULL; + rx::TextureStorageInterface2D *newTexStorage = NULL; - if (mImageArray[0].getWidth() != 0 && mImageArray[0].getHeight() != 0) + if (mImageArray[0]->getWidth() != 0 && mImageArray[0]->getHeight() != 0) { - GLsizei width = mImageArray[0].getWidth(); - GLsizei height = mImageArray[0].getHeight(); - GLint levels = creationLevels(width, height); - D3DFORMAT d3dfmt = mImageArray[0].getD3DFormat(); - DWORD d3dusage = GetTextureUsage(d3dfmt, GL_FRAMEBUFFER_ATTACHMENT_ANGLE, true); + GLsizei width = mImageArray[0]->getWidth(); + GLsizei height = mImageArray[0]->getHeight(); + GLint levels = mTexStorage != NULL ? mTexStorage->levelCount() : creationLevels(width, height); + GLenum internalformat = mImageArray[0]->getInternalFormat(); - newTexStorage = new TextureStorage2D(levels, d3dfmt, d3dusage, width, height); + newTexStorage = new rx::TextureStorageInterface2D(mRenderer, levels, internalformat, GL_FRAMEBUFFER_ATTACHMENT_ANGLE, true, width, height); if (mTexStorage != NULL) { - int levels = levelCount(); - for (int i = 0; i < levels; i++) - { - IDirect3DSurface9 *source = mTexStorage->getSurfaceLevel(i, false); - IDirect3DSurface9 *dest = newTexStorage->getSurfaceLevel(i, true); - - if (!copyToRenderTarget(dest, source, mTexStorage->isManaged())) - { - delete newTexStorage; - if (source) source->Release(); - if (dest) dest->Release(); - return error(GL_OUT_OF_MEMORY); - } - - if (source) source->Release(); - if (dest) dest->Release(); + if (!mRenderer->copyToRenderTarget(newTexStorage, mTexStorage)) + { + delete newTexStorage; + return gl::error(GL_OUT_OF_MEMORY); } } } @@ -2248,53 +770,37 @@ void Texture2D::convertToRenderTarget() void Texture2D::generateMipmaps() { - if (!getContext()->supportsNonPower2Texture()) + if (!mRenderer->getNonPower2TextureSupport()) { - if (!isPow2(mImageArray[0].getWidth()) || !isPow2(mImageArray[0].getHeight())) + if (!isPow2(mImageArray[0]->getWidth()) || !isPow2(mImageArray[0]->getHeight())) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } } // Purge array levels 1 through q and reset them to represent the generated mipmap levels. - unsigned int q = log2(std::max(mImageArray[0].getWidth(), mImageArray[0].getHeight())); + unsigned int q = log2(std::max(mImageArray[0]->getWidth(), mImageArray[0]->getHeight())); for (unsigned int i = 1; i <= q; i++) { - redefineImage(i, mImageArray[0].getInternalFormat(), - std::max(mImageArray[0].getWidth() >> i, 1), - std::max(mImageArray[0].getHeight() >> i, 1)); + redefineImage(i, mImageArray[0]->getInternalFormat(), + std::max(mImageArray[0]->getWidth() >> i, 1), + std::max(mImageArray[0]->getHeight() >> i, 1)); } if (mTexStorage && mTexStorage->isRenderTarget()) { for (unsigned int i = 1; i <= q; i++) { - IDirect3DSurface9 *upper = mTexStorage->getSurfaceLevel(i - 1, false); - IDirect3DSurface9 *lower = mTexStorage->getSurfaceLevel(i, true); - - if (upper != NULL && lower != NULL) - { - getBlitter()->boxFilter(upper, lower); - } + mTexStorage->generateMipmap(i); - if (upper != NULL) upper->Release(); - if (lower != NULL) lower->Release(); - - mImageArray[i].markClean(); + mImageArray[i]->markClean(); } } else { for (unsigned int i = 1; i <= q; i++) { - if (mImageArray[i].getSurface() == NULL) - { - return error(GL_OUT_OF_MEMORY); - } - - GenerateMip(mImageArray[i].getSurface(), mImageArray[i - 1].getSurface()); - - mImageArray[i].markDirty(); + mRenderer->generateMipmap(mImageArray[i], mImageArray[i - 1]); } } } @@ -2303,20 +809,18 @@ Renderbuffer *Texture2D::getRenderbuffer(GLenum target) { if (target != GL_TEXTURE_2D) { - return error(GL_INVALID_OPERATION, (Renderbuffer *)NULL); + return gl::error(GL_INVALID_OPERATION, (Renderbuffer *)NULL); } if (mColorbufferProxy == NULL) { - mColorbufferProxy = new Renderbuffer(id(), new RenderbufferTexture2D(this, target)); + mColorbufferProxy = new Renderbuffer(mRenderer, id(), new RenderbufferTexture2D(this, target)); } return mColorbufferProxy; } -// Increments refcount on surface. -// caller must Release() the returned surface -IDirect3DSurface9 *Texture2D::getRenderTarget(GLenum target) +rx::RenderTarget *Texture2D::getRenderTarget(GLenum target) { ASSERT(target == GL_TEXTURE_2D); @@ -2333,12 +837,11 @@ IDirect3DSurface9 *Texture2D::getRenderTarget(GLenum target) { return NULL; } - return mTexStorage->getSurfaceLevel(0, false); + + return mTexStorage->getRenderTarget(); } -// Increments refcount on surface. -// caller must Release() the returned surface -IDirect3DSurface9 *Texture2D::getDepthStencil(GLenum target) +rx::RenderTarget *Texture2D::getDepthStencil(GLenum target) { ASSERT(target == GL_TEXTURE_2D); @@ -2355,10 +858,15 @@ IDirect3DSurface9 *Texture2D::getDepthStencil(GLenum target) { return NULL; } - return mTexStorage->getSurfaceLevel(0, false); + return mTexStorage->getRenderTarget(); } -TextureStorage *Texture2D::getStorage(bool renderTarget) +int Texture2D::levelCount() +{ + return mTexStorage ? mTexStorage->levelCount() : 0; +} + +rx::TextureStorageInterface *Texture2D::getStorage(bool renderTarget) { if (!mTexStorage || (renderTarget && !mTexStorage->isRenderTarget())) { @@ -2375,74 +883,18 @@ TextureStorage *Texture2D::getStorage(bool renderTarget) return mTexStorage; } -TextureStorageCubeMap::TextureStorageCubeMap(int levels, D3DFORMAT format, DWORD usage, int size) - : TextureStorage(usage), mFirstRenderTargetSerial(RenderbufferStorage::issueCubeSerials()) -{ - mTexture = NULL; - // if the size is not positive this should be treated as an incomplete texture - // we handle that here by skipping the d3d texture creation - if (size > 0) - { - IDirect3DDevice9 *device = getDevice(); - int height = size; - MakeValidSize(false, dx::IsCompressedFormat(format), &size, &height, &mLodOffset); - HRESULT result = device->CreateCubeTexture(size, levels ? levels + mLodOffset : 0, getUsage(), format, getPool(), &mTexture, NULL); - - if (FAILED(result)) - { - ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - error(GL_OUT_OF_MEMORY); - } - } -} - -TextureStorageCubeMap::~TextureStorageCubeMap() -{ - if (mTexture) - { - mTexture->Release(); - } -} - -// Increments refcount on surface. -// caller must Release() the returned surface -IDirect3DSurface9 *TextureStorageCubeMap::getCubeMapSurface(GLenum faceTarget, int level, bool dirty) -{ - IDirect3DSurface9 *surface = NULL; - - if (mTexture) - { - D3DCUBEMAP_FACES face = es2dx::ConvertCubeFace(faceTarget); - HRESULT result = mTexture->GetCubeMapSurface(face, level + mLodOffset, &surface); - ASSERT(SUCCEEDED(result)); - - // With managed textures the driver needs to be informed of updates to the lower mipmap levels - if (level != 0 && isManaged() && dirty) - { - mTexture->AddDirtyRect(face, NULL); - } - } - - return surface; -} - -IDirect3DBaseTexture9 *TextureStorageCubeMap::getBaseTexture() const -{ - return mTexture; -} - -unsigned int TextureStorageCubeMap::getRenderTargetSerial(GLenum target) const -{ - return mFirstRenderTargetSerial + TextureCubeMap::faceIndex(target); -} - -TextureCubeMap::TextureCubeMap(GLuint id) : Texture(id) +TextureCubeMap::TextureCubeMap(rx::Renderer *renderer, GLuint id) : Texture(renderer, id) { mTexStorage = NULL; for (int i = 0; i < 6; i++) { mFaceProxies[i] = NULL; mFaceProxyRefs[i] = 0; + + for (int j = 0; j < IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++j) + { + mImageArray[i][j] = renderer->createImage(); + } } } @@ -2451,6 +903,11 @@ TextureCubeMap::~TextureCubeMap() for (int i = 0; i < 6; i++) { mFaceProxies[i] = NULL; + + for (int j = 0; j < IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++j) + { + delete mImageArray[i][j]; + } } delete mTexStorage; @@ -2494,7 +951,7 @@ GLenum TextureCubeMap::getTarget() const GLsizei TextureCubeMap::getWidth(GLenum target, GLint level) const { if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) - return mImageArray[faceIndex(target)][level].getWidth(); + return mImageArray[faceIndex(target)][level]->getWidth(); else return 0; } @@ -2502,7 +959,7 @@ GLsizei TextureCubeMap::getWidth(GLenum target, GLint level) const GLsizei TextureCubeMap::getHeight(GLenum target, GLint level) const { if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) - return mImageArray[faceIndex(target)][level].getHeight(); + return mImageArray[faceIndex(target)][level]->getHeight(); else return 0; } @@ -2510,15 +967,15 @@ GLsizei TextureCubeMap::getHeight(GLenum target, GLint level) const GLenum TextureCubeMap::getInternalFormat(GLenum target, GLint level) const { if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) - return mImageArray[faceIndex(target)][level].getInternalFormat(); + return mImageArray[faceIndex(target)][level]->getInternalFormat(); else return GL_NONE; } -D3DFORMAT TextureCubeMap::getD3DFormat(GLenum target, GLint level) const +GLenum TextureCubeMap::getActualFormat(GLenum target, GLint level) const { if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) - return mImageArray[faceIndex(target)][level].getD3DFormat(); + return mImageArray[faceIndex(target)][level]->getActualFormat(); else return D3DFMT_UNKNOWN; } @@ -2558,32 +1015,22 @@ void TextureCubeMap::setCompressedImage(GLenum face, GLint level, GLenum format, // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly redefineImage(faceIndex(face), level, format, width, height); - Texture::setCompressedImage(imageSize, pixels, &mImageArray[faceIndex(face)][level]); + Texture::setCompressedImage(imageSize, pixels, mImageArray[faceIndex(face)][level]); } void TextureCubeMap::commitRect(int face, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) { - ASSERT(mImageArray[face][level].getSurface() != NULL); - if (level < levelCount()) { - IDirect3DSurface9 *destLevel = mTexStorage->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, true); - ASSERT(destLevel != NULL); - - if (destLevel != NULL) - { - Image *image = &mImageArray[face][level]; - image->updateSurface(destLevel, xoffset, yoffset, width, height); - - destLevel->Release(); + rx::Image *image = mImageArray[face][level]; + if (image->updateSurface(mTexStorage, face, level, xoffset, yoffset, width, height)) image->markClean(); - } } } void TextureCubeMap::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels) { - if (Texture::subImage(xoffset, yoffset, width, height, format, type, unpackAlignment, pixels, &mImageArray[faceIndex(target)][level])) + if (Texture::subImage(xoffset, yoffset, width, height, format, type, unpackAlignment, pixels, mImageArray[faceIndex(target)][level])) { commitRect(faceIndex(target), level, xoffset, yoffset, width, height); } @@ -2591,7 +1038,7 @@ void TextureCubeMap::subImage(GLenum target, GLint level, GLint xoffset, GLint y void TextureCubeMap::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels) { - if (Texture::subImageCompressed(xoffset, yoffset, width, height, format, imageSize, pixels, &mImageArray[faceIndex(target)][level])) + if (Texture::subImageCompressed(xoffset, yoffset, width, height, format, imageSize, pixels, mImageArray[faceIndex(target)][level])) { commitRect(faceIndex(target), level, xoffset, yoffset, width, height); } @@ -2600,39 +1047,24 @@ void TextureCubeMap::subImageCompressed(GLenum target, GLint level, GLint xoffse // Tests for cube map sampling completeness. [OpenGL ES 2.0.24] section 3.8.2 page 86. bool TextureCubeMap::isSamplerComplete() const { - int size = mImageArray[0][0].getWidth(); - - bool mipmapping; + int size = mImageArray[0][0]->getWidth(); - switch (mMinFilter) - { - case GL_NEAREST: - case GL_LINEAR: - mipmapping = false; - break; - case GL_NEAREST_MIPMAP_NEAREST: - case GL_LINEAR_MIPMAP_NEAREST: - case GL_NEAREST_MIPMAP_LINEAR: - case GL_LINEAR_MIPMAP_LINEAR: - mipmapping = true; - break; - default: - UNREACHABLE(); - return false; - } + bool mipmapping = isMipmapFiltered(); + bool filtering, renderable; - if ((gl::ExtractType(getInternalFormat(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0)) == GL_FLOAT && !getContext()->supportsFloat32LinearFilter()) || - (gl::ExtractType(getInternalFormat(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0) == GL_HALF_FLOAT_OES) && !getContext()->supportsFloat16LinearFilter())) + if ((gl::ExtractType(getInternalFormat(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0)) == GL_FLOAT && !mRenderer->getFloat32TextureSupport(&filtering, &renderable)) || + (gl::ExtractType(getInternalFormat(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0) == GL_HALF_FLOAT_OES) && !mRenderer->getFloat16TextureSupport(&filtering, &renderable))) { - if (mMagFilter != GL_NEAREST || (mMinFilter != GL_NEAREST && mMinFilter != GL_NEAREST_MIPMAP_NEAREST)) + if (mSamplerState.magFilter != GL_NEAREST || + (mSamplerState.minFilter != GL_NEAREST && mSamplerState.minFilter != GL_NEAREST_MIPMAP_NEAREST)) { return false; } } - if (!isPow2(size) && !getContext()->supportsNonPower2Texture()) + if (!isPow2(size) && !mRenderer->getNonPower2TextureSupport()) { - if (getWrapS() != GL_CLAMP_TO_EDGE || getWrapT() != GL_CLAMP_TO_EDGE || mipmapping) + if (mSamplerState.wrapS != GL_CLAMP_TO_EDGE || mSamplerState.wrapT != GL_CLAMP_TO_EDGE || mipmapping) { return false; } @@ -2659,16 +1091,16 @@ bool TextureCubeMap::isSamplerComplete() const // Tests for cube texture completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81. bool TextureCubeMap::isCubeComplete() const { - if (mImageArray[0][0].getWidth() <= 0 || mImageArray[0][0].getHeight() != mImageArray[0][0].getWidth()) + if (mImageArray[0][0]->getWidth() <= 0 || mImageArray[0][0]->getHeight() != mImageArray[0][0]->getWidth()) { return false; } for (unsigned int face = 1; face < 6; face++) { - if (mImageArray[face][0].getWidth() != mImageArray[0][0].getWidth() || - mImageArray[face][0].getWidth() != mImageArray[0][0].getHeight() || - mImageArray[face][0].getInternalFormat() != mImageArray[0][0].getInternalFormat()) + if (mImageArray[face][0]->getWidth() != mImageArray[0][0]->getWidth() || + mImageArray[face][0]->getWidth() != mImageArray[0][0]->getHeight() || + mImageArray[face][0]->getInternalFormat() != mImageArray[0][0]->getInternalFormat()) { return false; } @@ -2689,7 +1121,7 @@ bool TextureCubeMap::isMipmapCubeComplete() const return false; } - GLsizei size = mImageArray[0][0].getWidth(); + GLsizei size = mImageArray[0][0]->getWidth(); int q = log2(size); @@ -2697,12 +1129,12 @@ bool TextureCubeMap::isMipmapCubeComplete() const { for (int level = 1; level <= q; level++) { - if (mImageArray[face][level].getInternalFormat() != mImageArray[0][0].getInternalFormat()) + if (mImageArray[face][level]->getInternalFormat() != mImageArray[0][0]->getInternalFormat()) { return false; } - if (mImageArray[face][level].getWidth() != std::max(1, size >> level)) + if (mImageArray[face][level]->getWidth() != std::max(1, size >> level)) { return false; } @@ -2717,25 +1149,19 @@ bool TextureCubeMap::isCompressed(GLenum target, GLint level) const return IsCompressed(getInternalFormat(target, level)); } -IDirect3DBaseTexture9 *TextureCubeMap::getBaseTexture() const -{ - return mTexStorage ? mTexStorage->getBaseTexture() : NULL; -} - -// Constructs a Direct3D 9 texture resource from the texture images, or returns an existing one +// Constructs a native texture resource from the texture images, or returns an existing one void TextureCubeMap::createTexture() { - GLsizei size = mImageArray[0][0].getWidth(); + GLsizei size = mImageArray[0][0]->getWidth(); if (!(size > 0)) - return; // do not attempt to create d3d textures for nonexistant data + return; // do not attempt to create native textures for nonexistant data GLint levels = creationLevels(size); - D3DFORMAT d3dfmt = mImageArray[0][0].getD3DFormat(); - DWORD d3dusage = GetTextureUsage(d3dfmt, mUsage, false); + GLenum internalformat = mImageArray[0][0]->getInternalFormat(); delete mTexStorage; - mTexStorage = new TextureStorageCubeMap(levels, d3dfmt, d3dusage, size); + mTexStorage = new rx::TextureStorageInterfaceCube(mRenderer, levels, internalformat, mUsage, false, size); if (mTexStorage->isManaged()) { @@ -2745,8 +1171,7 @@ void TextureCubeMap::createTexture() { for (int level = 0; level < levels; level++) { - IDirect3DSurface9 *surface = mTexStorage->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, false); - mImageArray[face][level].setManagedSurface(surface); + mImageArray[face][level]->setManagedSurface(mTexStorage, face, level); } } } @@ -2756,12 +1181,15 @@ void TextureCubeMap::createTexture() void TextureCubeMap::updateTexture() { + bool mipmapping = isMipmapFiltered() && isMipmapCubeComplete(); + for (int face = 0; face < 6; face++) { - int levels = levelCount(); + int levels = (mipmapping ? levelCount() : 1); + for (int level = 0; level < levels; level++) { - Image *image = &mImageArray[face][level]; + rx::Image *image = mImageArray[face][level]; if (image->isDirty()) { @@ -2773,38 +1201,22 @@ void TextureCubeMap::updateTexture() void TextureCubeMap::convertToRenderTarget() { - TextureStorageCubeMap *newTexStorage = NULL; + rx::TextureStorageInterfaceCube *newTexStorage = NULL; - if (mImageArray[0][0].getWidth() != 0) + if (mImageArray[0][0]->getWidth() != 0) { - GLsizei size = mImageArray[0][0].getWidth(); - GLint levels = creationLevels(size); - D3DFORMAT d3dfmt = mImageArray[0][0].getD3DFormat(); - DWORD d3dusage = GetTextureUsage(d3dfmt, GL_FRAMEBUFFER_ATTACHMENT_ANGLE, true); + GLsizei size = mImageArray[0][0]->getWidth(); + GLint levels = mTexStorage != NULL ? mTexStorage->levelCount() : creationLevels(size); + GLenum internalformat = mImageArray[0][0]->getInternalFormat(); - newTexStorage = new TextureStorageCubeMap(levels, d3dfmt, d3dusage, size); + newTexStorage = new rx::TextureStorageInterfaceCube(mRenderer, levels, internalformat, GL_FRAMEBUFFER_ATTACHMENT_ANGLE, true, size); if (mTexStorage != NULL) { - int levels = levelCount(); - for (int f = 0; f < 6; f++) + if (!mRenderer->copyToRenderTarget(newTexStorage, mTexStorage)) { - for (int i = 0; i < levels; i++) - { - IDirect3DSurface9 *source = mTexStorage->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, false); - IDirect3DSurface9 *dest = newTexStorage->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, true); - - if (!copyToRenderTarget(dest, source, mTexStorage->isManaged())) - { - delete newTexStorage; - if (source) source->Release(); - if (dest) dest->Release(); - return error(GL_OUT_OF_MEMORY); - } - - if (source) source->Release(); - if (dest) dest->Release(); - } + delete newTexStorage; + return gl::error(GL_OUT_OF_MEMORY); } } } @@ -2820,7 +1232,7 @@ void TextureCubeMap::setImage(int faceIndex, GLint level, GLsizei width, GLsizei GLint internalformat = ConvertSizedInternalFormat(format, type); redefineImage(faceIndex, level, internalformat, width, height); - Texture::setImage(unpackAlignment, pixels, &mImageArray[faceIndex][level]); + Texture::setImage(unpackAlignment, pixels, mImageArray[faceIndex][level]); } unsigned int TextureCubeMap::faceIndex(GLenum face) @@ -2836,42 +1248,47 @@ unsigned int TextureCubeMap::faceIndex(GLenum face) void TextureCubeMap::redefineImage(int face, GLint level, GLint internalformat, GLsizei width, GLsizei height) { - bool redefined = mImageArray[face][level].redefine(internalformat, width, height, false); + // If there currently is a corresponding storage texture image, it has these parameters + const int storageWidth = std::max(1, mImageArray[0][0]->getWidth() >> level); + const int storageHeight = std::max(1, mImageArray[0][0]->getHeight() >> level); + const int storageFormat = mImageArray[0][0]->getInternalFormat(); - if (mTexStorage && redefined) + mImageArray[face][level]->redefine(mRenderer, internalformat, width, height, false); + + if (mTexStorage) { - for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) + const int storageLevels = mTexStorage->levelCount(); + + if ((level >= storageLevels && storageLevels != 0) || + width != storageWidth || + height != storageHeight || + internalformat != storageFormat) // Discard mismatched storage { - for (int f = 0; f < 6; f++) + for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) { - mImageArray[f][i].markDirty(); + for (int f = 0; f < 6; f++) + { + mImageArray[f][i]->markDirty(); + } } - } - delete mTexStorage; - mTexStorage = NULL; + delete mTexStorage; + mTexStorage = NULL; - mDirtyImages = true; + mDirtyImages = true; + } } } void TextureCubeMap::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source) { - IDirect3DSurface9 *renderTarget = source->getRenderTarget(); - - if (!renderTarget) - { - ERR("Failed to retrieve the render target."); - return error(GL_OUT_OF_MEMORY); - } - unsigned int faceindex = faceIndex(target); GLint internalformat = gl::ConvertSizedInternalFormat(format, GL_UNSIGNED_BYTE); redefineImage(faceindex, level, internalformat, width, height); - if (!mImageArray[faceindex][level].isRenderableFormat()) + if (!mImageArray[faceindex][level]->isRenderableFormat()) { - mImageArray[faceindex][level].copy(0, 0, x, y, width, height, renderTarget); + mImageArray[faceindex][level]->copy(0, 0, x, y, width, height, source); mDirtyImages = true; } else @@ -2881,53 +1298,37 @@ void TextureCubeMap::copyImage(GLenum target, GLint level, GLenum format, GLint convertToRenderTarget(); } - mImageArray[faceindex][level].markClean(); + mImageArray[faceindex][level]->markClean(); ASSERT(width == height); if (width > 0 && level < levelCount()) { - RECT sourceRect; - sourceRect.left = x; - sourceRect.right = x + width; - sourceRect.top = y; - sourceRect.bottom = y + height; + gl::Rectangle sourceRect; + sourceRect.x = x; + sourceRect.width = width; + sourceRect.y = y; + sourceRect.height = height; - IDirect3DSurface9 *dest = mTexStorage->getCubeMapSurface(target, level, true); - - if (dest) - { - getBlitter()->copy(renderTarget, sourceRect, format, 0, 0, dest); - dest->Release(); - } + mRenderer->copyImage(source, sourceRect, format, 0, 0, mTexStorage, target, level); } } - - renderTarget->Release(); } void TextureCubeMap::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source) { - GLsizei size = mImageArray[faceIndex(target)][level].getWidth(); + GLsizei size = mImageArray[faceIndex(target)][level]->getWidth(); if (xoffset + width > size || yoffset + height > size) { - return error(GL_INVALID_VALUE); - } - - IDirect3DSurface9 *renderTarget = source->getRenderTarget(); - - if (!renderTarget) - { - ERR("Failed to retrieve the render target."); - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_INVALID_VALUE); } unsigned int faceindex = faceIndex(target); - if (!mImageArray[faceindex][level].isRenderableFormat() || (!mTexStorage && !isSamplerComplete())) + if (!mImageArray[faceindex][level]->isRenderableFormat() || (!mTexStorage && !isSamplerComplete())) { - mImageArray[faceindex][level].copy(0, 0, x, y, width, height, renderTarget); + mImageArray[faceindex][level]->copy(0, 0, x, y, width, height, source); mDirtyImages = true; } else @@ -2941,39 +1342,29 @@ void TextureCubeMap::copySubImage(GLenum target, GLint level, GLint xoffset, GLi if (level < levelCount()) { - RECT sourceRect; - sourceRect.left = x; - sourceRect.right = x + width; - sourceRect.top = y; - sourceRect.bottom = y + height; + gl::Rectangle sourceRect; + sourceRect.x = x; + sourceRect.width = width; + sourceRect.y = y; + sourceRect.height = height; - IDirect3DSurface9 *dest = mTexStorage->getCubeMapSurface(target, level, true); - - if (dest) - { - getBlitter()->copy(renderTarget, sourceRect, gl::ExtractFormat(mImageArray[0][0].getInternalFormat()), xoffset, yoffset, dest); - dest->Release(); - } + mRenderer->copyImage(source, sourceRect, gl::ExtractFormat(mImageArray[0][0]->getInternalFormat()), + xoffset, yoffset, mTexStorage, target, level); } } - - renderTarget->Release(); } void TextureCubeMap::storage(GLsizei levels, GLenum internalformat, GLsizei size) { - D3DFORMAT d3dfmt = ConvertTextureInternalFormat(internalformat); - DWORD d3dusage = GetTextureUsage(d3dfmt, mUsage, false); - delete mTexStorage; - mTexStorage = new TextureStorageCubeMap(levels, d3dfmt, d3dusage, size); + mTexStorage = new rx::TextureStorageInterfaceCube(mRenderer, levels, internalformat, mUsage, false, size); mImmutable = true; for (int level = 0; level < levels; level++) { for (int face = 0; face < 6; face++) { - mImageArray[face][level].redefine(internalformat, size, size, true); + mImageArray[face][level]->redefine(mRenderer, internalformat, size, size, true); size = std::max(1, size >> 1); } } @@ -2982,7 +1373,7 @@ void TextureCubeMap::storage(GLsizei levels, GLenum internalformat, GLsizei size { for (int face = 0; face < 6; face++) { - mImageArray[face][level].redefine(GL_NONE, 0, 0, true); + mImageArray[face][level]->redefine(mRenderer, GL_NONE, 0, 0, true); } } @@ -2994,8 +1385,7 @@ void TextureCubeMap::storage(GLsizei levels, GLenum internalformat, GLsizei size { for (int level = 0; level < levels; level++) { - IDirect3DSurface9 *surface = mTexStorage->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, false); - mImageArray[face][level].setManagedSurface(surface); + mImageArray[face][level]->setManagedSurface(mTexStorage, face, level); } } } @@ -3005,26 +1395,26 @@ void TextureCubeMap::generateMipmaps() { if (!isCubeComplete()) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } - if (!getContext()->supportsNonPower2Texture()) + if (!mRenderer->getNonPower2TextureSupport()) { - if (!isPow2(mImageArray[0][0].getWidth())) + if (!isPow2(mImageArray[0][0]->getWidth())) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } } // Purge array levels 1 through q and reset them to represent the generated mipmap levels. - unsigned int q = log2(mImageArray[0][0].getWidth()); + unsigned int q = log2(mImageArray[0][0]->getWidth()); for (unsigned int f = 0; f < 6; f++) { for (unsigned int i = 1; i <= q; i++) { - redefineImage(f, i, mImageArray[f][0].getInternalFormat(), - std::max(mImageArray[f][0].getWidth() >> i, 1), - std::max(mImageArray[f][0].getWidth() >> i, 1)); + redefineImage(f, i, mImageArray[f][0]->getInternalFormat(), + std::max(mImageArray[f][0]->getWidth() >> i, 1), + std::max(mImageArray[f][0]->getWidth() >> i, 1)); } } @@ -3034,18 +1424,9 @@ void TextureCubeMap::generateMipmaps() { for (unsigned int i = 1; i <= q; i++) { - IDirect3DSurface9 *upper = mTexStorage->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i - 1, false); - IDirect3DSurface9 *lower = mTexStorage->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, true); - - if (upper != NULL && lower != NULL) - { - getBlitter()->boxFilter(upper, lower); - } + mTexStorage->generateMipmap(f, i); - if (upper != NULL) upper->Release(); - if (lower != NULL) lower->Release(); - - mImageArray[f][i].markClean(); + mImageArray[f][i]->markClean(); } } } @@ -3055,14 +1436,7 @@ void TextureCubeMap::generateMipmaps() { for (unsigned int i = 1; i <= q; i++) { - if (mImageArray[f][i].getSurface() == NULL) - { - return error(GL_OUT_OF_MEMORY); - } - - GenerateMip(mImageArray[f][i].getSurface(), mImageArray[f][i - 1].getSurface()); - - mImageArray[f][i].markDirty(); + mRenderer->generateMipmap(mImageArray[f][i], mImageArray[f][i - 1]); } } } @@ -3072,22 +1446,20 @@ Renderbuffer *TextureCubeMap::getRenderbuffer(GLenum target) { if (!IsCubemapTextureTarget(target)) { - return error(GL_INVALID_OPERATION, (Renderbuffer *)NULL); + return gl::error(GL_INVALID_OPERATION, (Renderbuffer *)NULL); } unsigned int face = faceIndex(target); if (mFaceProxies[face] == NULL) { - mFaceProxies[face] = new Renderbuffer(id(), new RenderbufferTextureCubeMap(this, target)); + mFaceProxies[face] = new Renderbuffer(mRenderer, id(), new RenderbufferTextureCubeMap(this, target)); } return mFaceProxies[face]; } -// Increments refcount on surface. -// caller must Release() the returned surface -IDirect3DSurface9 *TextureCubeMap::getRenderTarget(GLenum target) +rx::RenderTarget *TextureCubeMap::getRenderTarget(GLenum target) { ASSERT(IsCubemapTextureTarget(target)); @@ -3099,10 +1471,15 @@ IDirect3DSurface9 *TextureCubeMap::getRenderTarget(GLenum target) updateTexture(); - return mTexStorage->getCubeMapSurface(target, 0, false); + return mTexStorage->getRenderTarget(target); +} + +int TextureCubeMap::levelCount() +{ + return mTexStorage ? mTexStorage->levelCount() - getLodOffset() : 0; } -TextureStorage *TextureCubeMap::getStorage(bool renderTarget) +rx::TextureStorageInterface *TextureCubeMap::getStorage(bool renderTarget) { if (!mTexStorage || (renderTarget && !mTexStorage->isRenderTarget())) { diff --git a/src/3rdparty/angle/src/libGLESv2/Texture.h b/src/3rdparty/angle/src/libGLESv2/Texture.h index 7d7378f88b..4f5fab28d0 100644 --- a/src/3rdparty/angle/src/libGLESv2/Texture.h +++ b/src/3rdparty/angle/src/libGLESv2/Texture.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// 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. // @@ -15,22 +15,30 @@ #define GL_APICALL #include -#include #include "common/debug.h" #include "common/RefCountObject.h" -#include "libGLESv2/Renderbuffer.h" -#include "libGLESv2/utilities.h" +#include "libGLESv2/angletypes.h" namespace egl { class Surface; } +namespace rx +{ +class Renderer; +class TextureStorageInterface; +class TextureStorageInterface2D; +class TextureStorageInterfaceCube; +class RenderTarget; +class Image; +} + namespace gl { -class Blit; class Framebuffer; +class Renderbuffer; enum { @@ -43,132 +51,10 @@ enum IMPLEMENTATION_MAX_TEXTURE_LEVELS = 15 // 1+log2 of MAX_TEXTURE_SIZE }; -class Image -{ - public: - Image(); - ~Image(); - - bool redefine(GLint internalformat, GLsizei width, GLsizei height, bool forceRelease); - void markDirty() {mDirty = true;} - void markClean() {mDirty = false;} - - bool isRenderableFormat() const; - D3DFORMAT getD3DFormat() const; - - GLsizei getWidth() const {return mWidth;} - GLsizei getHeight() const {return mHeight;} - GLenum getInternalFormat() const {return mInternalFormat;} - bool isDirty() const {return mSurface && mDirty;} - IDirect3DSurface9 *getSurface(); - - void setManagedSurface(IDirect3DSurface9 *surface); - void updateSurface(IDirect3DSurface9 *dest, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); - - void loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, - GLint unpackAlignment, const void *input); - - void loadAlphaData(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const; - void loadAlphaDataSSE2(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const; - void loadAlphaFloatData(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const; - void loadAlphaHalfFloatData(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const; - void loadLuminanceData(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output, bool native) const; - void loadLuminanceFloatData(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const; - void loadLuminanceHalfFloatData(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const; - void loadLuminanceAlphaData(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output, bool native) const; - void loadLuminanceAlphaFloatData(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const; - void loadLuminanceAlphaHalfFloatData(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const; - void loadRGBUByteData(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const; - void loadRGB565Data(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const; - void loadRGBFloatData(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const; - void loadRGBHalfFloatData(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const; - void loadRGBAUByteDataSSE2(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const; - void loadRGBAUByteData(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const; - void loadRGBA4444Data(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const; - void loadRGBA5551Data(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const; - void loadRGBAFloatData(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const; - void loadRGBAHalfFloatData(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const; - void loadBGRAData(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const; - void loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, - const void *input); - - void copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, IDirect3DSurface9 *renderTarget); - - private: - DISALLOW_COPY_AND_ASSIGN(Image); - - void createSurface(); - - HRESULT lock(D3DLOCKED_RECT *lockedRect, const RECT *rect); - void unlock(); - - GLsizei mWidth; - GLsizei mHeight; - GLint mInternalFormat; - - bool mDirty; - - D3DPOOL mD3DPool; // can only be D3DPOOL_SYSTEMMEM or D3DPOOL_MANAGED since it needs to be lockable. - D3DFORMAT mD3DFormat; - - IDirect3DSurface9 *mSurface; -}; - -class TextureStorage -{ - public: - explicit TextureStorage(DWORD usage); - - virtual ~TextureStorage(); - - bool isRenderTarget() const; - bool isManaged() const; - D3DPOOL getPool() const; - DWORD getUsage() const; - unsigned int getTextureSerial() const; - virtual unsigned int getRenderTargetSerial(GLenum target) const = 0; - int getLodOffset() const; - - protected: - int mLodOffset; - - private: - DISALLOW_COPY_AND_ASSIGN(TextureStorage); - - const DWORD mD3DUsage; - const D3DPOOL mD3DPool; - - const unsigned int mTextureSerial; - static unsigned int issueTextureSerial(); - - static unsigned int mCurrentTextureSerial; -}; - class Texture : public RefCountObject { public: - explicit Texture(GLuint id); + Texture(rx::Renderer *renderer, GLuint id); virtual ~Texture(); @@ -189,11 +75,14 @@ class Texture : public RefCountObject GLenum getWrapS() const; GLenum getWrapT() const; float getMaxAnisotropy() const; + int getLodOffset(); + void getSamplerState(SamplerState *sampler); GLenum getUsage() const; + bool isMipmapFiltered() const; virtual bool isSamplerComplete() const = 0; - IDirect3DBaseTexture9 *getTexture(); + rx::TextureStorageInterface *getNativeTexture(); virtual Renderbuffer *getRenderbuffer(GLenum target) = 0; virtual void generateMipmaps() = 0; @@ -206,36 +95,28 @@ class Texture : public RefCountObject unsigned int getRenderTargetSerial(GLenum target); bool isImmutable() const; - int getLodOffset(); static const GLuint INCOMPLETE_TEXTURE_ID = static_cast(-1); // Every texture takes an id at creation time. The value is arbitrary because it is never registered with the resource manager. protected: - void setImage(GLint unpackAlignment, const void *pixels, Image *image); - bool subImage(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels, Image *image); - void setCompressedImage(GLsizei imageSize, const void *pixels, Image *image); - bool subImageCompressed(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels, Image *image); + void setImage(GLint unpackAlignment, const void *pixels, rx::Image *image); + bool subImage(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels, rx::Image *image); + void setCompressedImage(GLsizei imageSize, const void *pixels, rx::Image *image); + bool subImageCompressed(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels, rx::Image *image); GLint creationLevels(GLsizei width, GLsizei height) const; GLint creationLevels(GLsizei size) const; - virtual IDirect3DBaseTexture9 *getBaseTexture() const = 0; virtual void createTexture() = 0; virtual void updateTexture() = 0; virtual void convertToRenderTarget() = 0; - virtual IDirect3DSurface9 *getRenderTarget(GLenum target) = 0; + virtual rx::RenderTarget *getRenderTarget(GLenum target) = 0; - int levelCount(); + virtual int levelCount() = 0; - static Blit *getBlitter(); - static bool copyToRenderTarget(IDirect3DSurface9 *dest, IDirect3DSurface9 *source, bool fromManaged); + rx::Renderer *mRenderer; - GLenum mMinFilter; - GLenum mMagFilter; - GLenum mWrapS; - GLenum mWrapT; - float mMaxAnisotropy; - bool mDirtyParameters; + SamplerState mSamplerState; GLenum mUsage; bool mDirtyImages; @@ -245,33 +126,13 @@ class Texture : public RefCountObject private: DISALLOW_COPY_AND_ASSIGN(Texture); - virtual TextureStorage *getStorage(bool renderTarget) = 0; -}; - -class TextureStorage2D : public TextureStorage -{ - public: - explicit TextureStorage2D(IDirect3DTexture9 *surfaceTexture); - TextureStorage2D(int levels, D3DFORMAT format, DWORD usage, int width, int height); - - virtual ~TextureStorage2D(); - - IDirect3DSurface9 *getSurfaceLevel(int level, bool dirty); - IDirect3DBaseTexture9 *getBaseTexture() const; - - virtual unsigned int getRenderTargetSerial(GLenum target) const; - - private: - DISALLOW_COPY_AND_ASSIGN(TextureStorage2D); - - IDirect3DTexture9 *mTexture; - const unsigned int mRenderTargetSerial; + virtual rx::TextureStorageInterface *getStorage(bool renderTarget) = 0; }; class Texture2D : public Texture { public: - explicit Texture2D(GLuint id); + Texture2D(rx::Renderer *renderer, GLuint id); ~Texture2D(); @@ -283,7 +144,7 @@ class Texture2D : public Texture GLsizei getWidth(GLint level) const; GLsizei getHeight(GLint level) const; GLenum getInternalFormat(GLint level) const; - D3DFORMAT getD3DFormat(GLint level) const; + GLenum getActualFormat(GLint level) const; bool isCompressed(GLint level) const; bool isDepth(GLint level) const; @@ -305,26 +166,26 @@ class Texture2D : public Texture protected: friend class RenderbufferTexture2D; - virtual IDirect3DSurface9 *getRenderTarget(GLenum target); - virtual IDirect3DSurface9 *getDepthStencil(GLenum target); + virtual rx::RenderTarget *getRenderTarget(GLenum target); + virtual rx::RenderTarget *getDepthStencil(GLenum target); + virtual int levelCount(); private: DISALLOW_COPY_AND_ASSIGN(Texture2D); - virtual IDirect3DBaseTexture9 *getBaseTexture() const; virtual void createTexture(); virtual void updateTexture(); virtual void convertToRenderTarget(); - virtual TextureStorage *getStorage(bool renderTarget); + virtual rx::TextureStorageInterface *getStorage(bool renderTarget); bool isMipmapComplete() const; void redefineImage(GLint level, GLint internalformat, GLsizei width, GLsizei height); void commitRect(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); - Image mImageArray[IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + rx::Image *mImageArray[IMPLEMENTATION_MAX_TEXTURE_LEVELS]; - TextureStorage2D *mTexStorage; + rx::TextureStorageInterface2D *mTexStorage; egl::Surface *mSurface; // A specific internal reference count is kept for colorbuffer proxy references, @@ -336,29 +197,10 @@ class Texture2D : public Texture unsigned int mProxyRefs; }; -class TextureStorageCubeMap : public TextureStorage -{ - public: - TextureStorageCubeMap(int levels, D3DFORMAT format, DWORD usage, int size); - - virtual ~TextureStorageCubeMap(); - - IDirect3DSurface9 *getCubeMapSurface(GLenum faceTarget, int level, bool dirty); - IDirect3DBaseTexture9 *getBaseTexture() const; - - virtual unsigned int getRenderTargetSerial(GLenum target) const; - - private: - DISALLOW_COPY_AND_ASSIGN(TextureStorageCubeMap); - - IDirect3DCubeTexture9 *mTexture; - const unsigned int mFirstRenderTargetSerial; -}; - class TextureCubeMap : public Texture { public: - explicit TextureCubeMap(GLuint id); + TextureCubeMap(rx::Renderer *renderer, GLuint id); ~TextureCubeMap(); @@ -370,7 +212,7 @@ class TextureCubeMap : public Texture GLsizei getWidth(GLenum target, GLint level) const; GLsizei getHeight(GLenum target, GLint level) const; GLenum getInternalFormat(GLenum target, GLint level) const; - D3DFORMAT getD3DFormat(GLenum target, GLint level) const; + GLenum getActualFormat(GLenum target, GLint level) const; bool isCompressed(GLenum target, GLint level) const; void setImagePosX(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels); @@ -398,16 +240,16 @@ class TextureCubeMap : public Texture protected: friend class RenderbufferTextureCubeMap; - virtual IDirect3DSurface9 *getRenderTarget(GLenum target); + virtual rx::RenderTarget *getRenderTarget(GLenum target); + virtual int levelCount(); private: DISALLOW_COPY_AND_ASSIGN(TextureCubeMap); - virtual IDirect3DBaseTexture9 *getBaseTexture() const; virtual void createTexture(); virtual void updateTexture(); virtual void convertToRenderTarget(); - virtual TextureStorage *getStorage(bool renderTarget); + virtual rx::TextureStorageInterface *getStorage(bool renderTarget); bool isCubeComplete() const; bool isMipmapCubeComplete() const; @@ -416,9 +258,9 @@ class TextureCubeMap : public Texture void commitRect(int faceIndex, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); void redefineImage(int faceIndex, GLint level, GLint internalformat, GLsizei width, GLsizei height); - Image mImageArray[6][IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + rx::Image *mImageArray[6][IMPLEMENTATION_MAX_TEXTURE_LEVELS]; - TextureStorageCubeMap *mTexStorage; + rx::TextureStorageInterfaceCube *mTexStorage; // A specific internal reference count is kept for colorbuffer proxy references, // because, as the renderbuffer acting as proxy will maintain a binding pointer diff --git a/src/3rdparty/angle/src/libGLESv2/TextureSSE2.cpp b/src/3rdparty/angle/src/libGLESv2/TextureSSE2.cpp deleted file mode 100644 index 48ea6643bc..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/TextureSSE2.cpp +++ /dev/null @@ -1,100 +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. -// - -// TextureSSE2.cpp: Implements SSE2-based functions of gl::Image class. It's -// in a separated file for GCC, which can enable SSE usage only per-file, -// not for code blocks that use SSE2 explicitly. - -#include "libGLESv2/Texture.h" - -#include - -namespace gl -{ - -void Image::loadRGBAUByteDataSSE2(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const -{ - const unsigned int *source = NULL; - unsigned int *dest = NULL; - __m128i brMask = _mm_set1_epi32(0x00ff00ff); - - for (int y = 0; y < height; y++) - { - source = reinterpret_cast(static_cast(input) + y * inputPitch); - dest = reinterpret_cast(static_cast(output) + y * outputPitch); - int x = 0; - - // Make output writes aligned - for (x = 0; ((reinterpret_cast(&dest[x]) & 15) != 0) && x < width; x++) - { - unsigned int rgba = source[x]; - dest[x] = (_rotl(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00); - } - - for (; x + 3 < width; x += 4) - { - __m128i sourceData = _mm_loadu_si128(reinterpret_cast(&source[x])); - // Mask out g and a, which don't change - __m128i gaComponents = _mm_andnot_si128(brMask, sourceData); - // Mask out b and r - __m128i brComponents = _mm_and_si128(sourceData, brMask); - // Swap b and r - __m128i brSwapped = _mm_shufflehi_epi16(_mm_shufflelo_epi16(brComponents, _MM_SHUFFLE(2, 3, 0, 1)), _MM_SHUFFLE(2, 3, 0, 1)); - __m128i result = _mm_or_si128(gaComponents, brSwapped); - _mm_store_si128(reinterpret_cast<__m128i*>(&dest[x]), result); - } - - // Perform leftover writes - for (; x < width; x++) - { - unsigned int rgba = source[x]; - dest[x] = (_rotl(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00); - } - } -} - -void Image::loadAlphaDataSSE2(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) const -{ - const unsigned char *source = NULL; - unsigned int *dest = NULL; - __m128i zeroWide = _mm_setzero_si128(); - - for (int y = 0; y < height; y++) - { - source = static_cast(input) + y * inputPitch; - dest = reinterpret_cast(static_cast(output) + y * outputPitch); - - int x; - // Make output writes aligned - for (x = 0; ((reinterpret_cast(&dest[x]) & 0xF) != 0 && x < width); x++) - { - dest[x] = static_cast(source[x]) << 24; - } - - for (; x + 7 < width; x += 8) - { - __m128i sourceData = _mm_loadl_epi64(reinterpret_cast(&source[x])); - // Interleave each byte to 16bit, make the lower byte to zero - sourceData = _mm_unpacklo_epi8(zeroWide, sourceData); - // Interleave each 16bit to 32bit, make the lower 16bit to zero - __m128i lo = _mm_unpacklo_epi16(zeroWide, sourceData); - __m128i hi = _mm_unpackhi_epi16(zeroWide, sourceData); - - _mm_store_si128(reinterpret_cast<__m128i*>(&dest[x]), lo); - _mm_store_si128(reinterpret_cast<__m128i*>(&dest[x + 4]), hi); - } - - // Handle the remainder - for (; x < width; x++) - { - dest[x] = static_cast(source[x]) << 24; - } - } -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/Uniform.cpp b/src/3rdparty/angle/src/libGLESv2/Uniform.cpp new file mode 100644 index 0000000000..5424e271b5 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/Uniform.cpp @@ -0,0 +1,43 @@ +#include "precompiled.h" +// +// Copyright (c) 2010-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 "libGLESv2/Uniform.h" + +#include "libGLESv2/utilities.h" + +namespace gl +{ + +Uniform::Uniform(GLenum type, GLenum precision, const std::string &name, unsigned int arraySize) + : type(type), precision(precision), name(name), arraySize(arraySize) +{ + int bytes = gl::UniformInternalSize(type) * elementCount(); + data = new unsigned char[bytes]; + memset(data, 0, bytes); + dirty = true; + + psRegisterIndex = -1; + vsRegisterIndex = -1; + registerCount = VariableRowCount(type) * elementCount(); +} + +Uniform::~Uniform() +{ + delete[] data; +} + +bool Uniform::isArray() const +{ + return arraySize > 0; +} + +unsigned int Uniform::elementCount() const +{ + return arraySize > 0 ? arraySize : 1; +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/Uniform.h b/src/3rdparty/angle/src/libGLESv2/Uniform.h new file mode 100644 index 0000000000..8ab0fbe234 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/Uniform.h @@ -0,0 +1,48 @@ +// +// Copyright (c) 2010-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 LIBGLESV2_UNIFORM_H_ +#define LIBGLESV2_UNIFORM_H_ + +#include +#include + +#define GL_APICALL +#include + +#include "common/debug.h" + +namespace gl +{ + +// Helper struct representing a single shader uniform +struct Uniform +{ + Uniform(GLenum type, GLenum precision, const std::string &name, unsigned int arraySize); + + ~Uniform(); + + bool isArray() const; + unsigned int elementCount() const; + + const GLenum type; + const GLenum precision; + const std::string name; + const unsigned int arraySize; + + unsigned char *data; + bool dirty; + + int psRegisterIndex; + int vsRegisterIndex; + unsigned int registerCount; +}; + +typedef std::vector UniformArray; + +} + +#endif // LIBGLESV2_UNIFORM_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/VertexDataManager.cpp b/src/3rdparty/angle/src/libGLESv2/VertexDataManager.cpp deleted file mode 100644 index 32c40182d3..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/VertexDataManager.cpp +++ /dev/null @@ -1,783 +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. -// - -// VertexDataManager.h: Defines the VertexDataManager, a class that -// runs the Buffer translation process. - -#include "libGLESv2/VertexDataManager.h" - -#include "common/debug.h" - -#include "libGLESv2/Buffer.h" -#include "libGLESv2/Program.h" -#include "libGLESv2/ProgramBinary.h" -#include "libGLESv2/main.h" - -#include "libGLESv2/vertexconversion.h" -#include "libGLESv2/IndexDataManager.h" - -namespace -{ - enum { INITIAL_STREAM_BUFFER_SIZE = 1024*1024 }; - // This has to be at least 4k or else it fails on ATI cards. - enum { CONSTANT_VERTEX_BUFFER_SIZE = 4096 }; -} - -namespace gl -{ -unsigned int VertexBuffer::mCurrentSerial = 1; - -int elementsInBuffer(const VertexAttribute &attribute, int size) -{ - int stride = attribute.stride(); - return (size - attribute.mOffset % stride + (stride - attribute.typeSize())) / stride; -} - -VertexDataManager::VertexDataManager(Context *context, IDirect3DDevice9 *device) : mContext(context), mDevice(device) -{ - for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) - { - mDirtyCurrentValue[i] = true; - mCurrentValueBuffer[i] = NULL; - mCurrentValueOffsets[i] = 0; - } - - const D3DCAPS9 &caps = context->getDeviceCaps(); - checkVertexCaps(caps.DeclTypes); - - mStreamingBuffer = new StreamingVertexBuffer(mDevice, INITIAL_STREAM_BUFFER_SIZE); - - if (!mStreamingBuffer) - { - ERR("Failed to allocate the streaming vertex buffer."); - } -} - -VertexDataManager::~VertexDataManager() -{ - delete mStreamingBuffer; - - for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) - { - delete mCurrentValueBuffer[i]; - } -} - -std::size_t VertexDataManager::writeAttributeData(ArrayVertexBuffer *vertexBuffer, GLint start, GLsizei count, const VertexAttribute &attribute, GLsizei instances) -{ - Buffer *buffer = attribute.mBoundBuffer.get(); - - int inputStride = attribute.stride(); - int elementSize = attribute.typeSize(); - const FormatConverter &converter = formatConverter(attribute); - std::size_t streamOffset = 0; - - void *output = NULL; - - if (vertexBuffer) - { - output = vertexBuffer->map(attribute, spaceRequired(attribute, count, instances), &streamOffset); - } - - if (output == NULL) - { - ERR("Failed to map vertex buffer."); - return -1; - } - - const char *input = NULL; - - if (buffer) - { - int offset = attribute.mOffset; - - input = static_cast(buffer->data()) + offset; - } - else - { - input = static_cast(attribute.mPointer); - } - - if (instances == 0 || attribute.mDivisor == 0) - { - input += inputStride * start; - } - - if (converter.identity && inputStride == elementSize) - { - memcpy(output, input, count * inputStride); - } - else - { - converter.convertArray(input, inputStride, count, output); - } - - vertexBuffer->unmap(); - - return streamOffset; -} - -GLenum VertexDataManager::prepareVertexData(GLint start, GLsizei count, TranslatedAttribute *translated, GLsizei instances) -{ - if (!mStreamingBuffer) - { - return GL_OUT_OF_MEMORY; - } - - const VertexAttributeArray &attribs = mContext->getVertexAttributes(); - ProgramBinary *programBinary = mContext->getCurrentProgramBinary(); - - for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++) - { - translated[attributeIndex].active = (programBinary->getSemanticIndex(attributeIndex) != -1); - } - - // Determine the required storage size per used buffer, and invalidate static buffers that don't contain matching attributes - for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) - { - if (translated[i].active && attribs[i].mArrayEnabled) - { - Buffer *buffer = attribs[i].mBoundBuffer.get(); - StaticVertexBuffer *staticBuffer = buffer ? buffer->getStaticVertexBuffer() : NULL; - - if (staticBuffer) - { - if (staticBuffer->size() == 0) - { - int totalCount = elementsInBuffer(attribs[i], buffer->size()); - staticBuffer->addRequiredSpace(spaceRequired(attribs[i], totalCount, 0)); - } - else if (staticBuffer->lookupAttribute(attribs[i]) == -1) - { - // This static buffer doesn't have matching attributes, so fall back to using the streaming buffer - // Add the space of all previous attributes belonging to the invalidated static buffer to the streaming buffer - for (int previous = 0; previous < i; previous++) - { - if (translated[previous].active && attribs[previous].mArrayEnabled) - { - Buffer *previousBuffer = attribs[previous].mBoundBuffer.get(); - StaticVertexBuffer *previousStaticBuffer = previousBuffer ? previousBuffer->getStaticVertexBuffer() : NULL; - - if (staticBuffer == previousStaticBuffer) - { - mStreamingBuffer->addRequiredSpace(spaceRequired(attribs[previous], count, instances)); - } - } - } - - mStreamingBuffer->addRequiredSpace(spaceRequired(attribs[i], count, instances)); - - buffer->invalidateStaticData(); - } - } - else - { - mStreamingBuffer->addRequiredSpace(spaceRequired(attribs[i], count, instances)); - } - } - } - - // Reserve the required space per used buffer - for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) - { - if (translated[i].active && attribs[i].mArrayEnabled) - { - Buffer *buffer = attribs[i].mBoundBuffer.get(); - ArrayVertexBuffer *staticBuffer = buffer ? buffer->getStaticVertexBuffer() : NULL; - ArrayVertexBuffer *vertexBuffer = staticBuffer ? staticBuffer : mStreamingBuffer; - - if (vertexBuffer) - { - vertexBuffer->reserveRequiredSpace(); - } - } - } - - // Perform the vertex data translations - for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) - { - if (translated[i].active) - { - if (attribs[i].mArrayEnabled) - { - Buffer *buffer = attribs[i].mBoundBuffer.get(); - - if (!buffer && attribs[i].mPointer == NULL) - { - // This is an application error that would normally result in a crash, but we catch it and return an error - ERR("An enabled vertex array has no buffer and no pointer."); - return GL_INVALID_OPERATION; - } - - const FormatConverter &converter = formatConverter(attribs[i]); - - StaticVertexBuffer *staticBuffer = buffer ? buffer->getStaticVertexBuffer() : NULL; - ArrayVertexBuffer *vertexBuffer = staticBuffer ? staticBuffer : static_cast(mStreamingBuffer); - - std::size_t streamOffset = -1; - - if (staticBuffer) - { - streamOffset = staticBuffer->lookupAttribute(attribs[i]); - - if (streamOffset == -1) - { - // Convert the entire buffer - int totalCount = elementsInBuffer(attribs[i], buffer->size()); - int startIndex = attribs[i].mOffset / attribs[i].stride(); - - streamOffset = writeAttributeData(staticBuffer, -startIndex, totalCount, attribs[i], 0); - } - - if (streamOffset != -1) - { - streamOffset += (attribs[i].mOffset / attribs[i].stride()) * converter.outputElementSize; - - if (instances == 0 || attribs[i].mDivisor == 0) - { - streamOffset += start * converter.outputElementSize; - } - } - } - else - { - streamOffset = writeAttributeData(mStreamingBuffer, start, count, attribs[i], instances); - } - - if (streamOffset == -1) - { - return GL_OUT_OF_MEMORY; - } - - translated[i].vertexBuffer = vertexBuffer->getBuffer(); - translated[i].serial = vertexBuffer->getSerial(); - translated[i].divisor = attribs[i].mDivisor; - - translated[i].type = converter.d3dDeclType; - translated[i].stride = converter.outputElementSize; - translated[i].offset = streamOffset; - } - else - { - if (!mCurrentValueBuffer[i]) - { - mCurrentValueBuffer[i] = new StreamingVertexBuffer(mDevice, CONSTANT_VERTEX_BUFFER_SIZE); - } - - StreamingVertexBuffer *buffer = mCurrentValueBuffer[i]; - - if (mDirtyCurrentValue[i]) - { - const int requiredSpace = 4 * sizeof(float); - buffer->addRequiredSpace(requiredSpace); - buffer->reserveRequiredSpace(); - float *data = static_cast(buffer->map(VertexAttribute(), requiredSpace, &mCurrentValueOffsets[i])); - if (data) - { - data[0] = attribs[i].mCurrentValue[0]; - data[1] = attribs[i].mCurrentValue[1]; - data[2] = attribs[i].mCurrentValue[2]; - data[3] = attribs[i].mCurrentValue[3]; - buffer->unmap(); - mDirtyCurrentValue[i] = false; - } - } - - translated[i].vertexBuffer = mCurrentValueBuffer[i]->getBuffer(); - translated[i].serial = mCurrentValueBuffer[i]->getSerial(); - translated[i].divisor = 0; - - translated[i].type = D3DDECLTYPE_FLOAT4; - translated[i].stride = 0; - translated[i].offset = mCurrentValueOffsets[i]; - } - } - } - - for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) - { - if (translated[i].active && attribs[i].mArrayEnabled) - { - Buffer *buffer = attribs[i].mBoundBuffer.get(); - - if (buffer) - { - buffer->promoteStaticUsage(count * attribs[i].typeSize()); - } - } - } - - return GL_NO_ERROR; -} - -std::size_t VertexDataManager::spaceRequired(const VertexAttribute &attrib, std::size_t count, GLsizei instances) const -{ - size_t elementSize = formatConverter(attrib).outputElementSize; - - if (instances == 0 || attrib.mDivisor == 0) - { - return elementSize * count; - } - else - { - return elementSize * ((instances + attrib.mDivisor - 1) / attrib.mDivisor); - } -} - -// Mapping from OpenGL-ES vertex attrib type to D3D decl type: -// -// BYTE SHORT (Cast) -// BYTE-norm FLOAT (Normalize) (can't be exactly represented as SHORT-norm) -// UNSIGNED_BYTE UBYTE4 (Identity) or SHORT (Cast) -// UNSIGNED_BYTE-norm UBYTE4N (Identity) or FLOAT (Normalize) -// SHORT SHORT (Identity) -// SHORT-norm SHORT-norm (Identity) or FLOAT (Normalize) -// UNSIGNED_SHORT FLOAT (Cast) -// UNSIGNED_SHORT-norm USHORT-norm (Identity) or FLOAT (Normalize) -// FIXED (not in WebGL) FLOAT (FixedToFloat) -// FLOAT FLOAT (Identity) - -// GLToCType maps from GL type (as GLenum) to the C typedef. -template struct GLToCType { }; - -template <> struct GLToCType { typedef GLbyte type; }; -template <> struct GLToCType { typedef GLubyte type; }; -template <> struct GLToCType { typedef GLshort type; }; -template <> struct GLToCType { typedef GLushort type; }; -template <> struct GLToCType { typedef GLuint type; }; -template <> struct GLToCType { typedef GLfloat type; }; - -// This differs from D3DDECLTYPE in that it is unsized. (Size expansion is applied last.) -enum D3DVertexType -{ - D3DVT_FLOAT, - D3DVT_SHORT, - D3DVT_SHORT_NORM, - D3DVT_UBYTE, - D3DVT_UBYTE_NORM, - D3DVT_USHORT_NORM -}; - -// D3DToCType maps from D3D vertex type (as enum D3DVertexType) to the corresponding C type. -template struct D3DToCType { }; - -template <> struct D3DToCType { typedef float type; }; -template <> struct D3DToCType { typedef short type; }; -template <> struct D3DToCType { typedef short type; }; -template <> struct D3DToCType { typedef unsigned char type; }; -template <> struct D3DToCType { typedef unsigned char type; }; -template <> struct D3DToCType { typedef unsigned short type; }; - -// Encode the type/size combinations that D3D permits. For each type/size it expands to a widener that will provide the appropriate final size. -template -struct WidenRule -{ -}; - -template struct WidenRule : gl::NoWiden { }; -template struct WidenRule : gl::WidenToEven { }; -template struct WidenRule : gl::WidenToEven { }; -template struct WidenRule : gl::WidenToFour { }; -template struct WidenRule : gl::WidenToFour { }; -template struct WidenRule : gl::WidenToEven { }; - -// VertexTypeFlags encodes the D3DCAPS9::DeclType flag and vertex declaration flag for each D3D vertex type & size combination. -template -struct VertexTypeFlags -{ -}; - -template -struct VertexTypeFlagsHelper -{ - enum { capflag = _capflag }; - enum { declflag = _declflag }; -}; - -template <> struct VertexTypeFlags : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT1> { }; -template <> struct VertexTypeFlags : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT2> { }; -template <> struct VertexTypeFlags : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT3> { }; -template <> struct VertexTypeFlags : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT4> { }; -template <> struct VertexTypeFlags : VertexTypeFlagsHelper<0, D3DDECLTYPE_SHORT2> { }; -template <> struct VertexTypeFlags : VertexTypeFlagsHelper<0, D3DDECLTYPE_SHORT4> { }; -template <> struct VertexTypeFlags : VertexTypeFlagsHelper { }; -template <> struct VertexTypeFlags : VertexTypeFlagsHelper { }; -template <> struct VertexTypeFlags : VertexTypeFlagsHelper { }; -template <> struct VertexTypeFlags : VertexTypeFlagsHelper { }; -template <> struct VertexTypeFlags : VertexTypeFlagsHelper { }; -template <> struct VertexTypeFlags : VertexTypeFlagsHelper { }; - - -// VertexTypeMapping maps GL type & normalized flag to preferred and fallback D3D vertex types (as D3DVertexType enums). -template -struct VertexTypeMapping -{ -}; - -template -struct VertexTypeMappingBase -{ - enum { preferred = Preferred }; - enum { fallback = Fallback }; -}; - -template <> struct VertexTypeMapping : VertexTypeMappingBase { }; // Cast -template <> struct VertexTypeMapping : VertexTypeMappingBase { }; // Normalize -template <> struct VertexTypeMapping : VertexTypeMappingBase { }; // Identity, Cast -template <> struct VertexTypeMapping : VertexTypeMappingBase { }; // Identity, Normalize -template <> struct VertexTypeMapping : VertexTypeMappingBase { }; // Identity -template <> struct VertexTypeMapping : VertexTypeMappingBase { }; // Cast, Normalize -template <> struct VertexTypeMapping : VertexTypeMappingBase { }; // Cast -template <> struct VertexTypeMapping : VertexTypeMappingBase { }; // Cast, Normalize -template struct VertexTypeMapping : VertexTypeMappingBase { }; // FixedToFloat -template struct VertexTypeMapping : VertexTypeMappingBase { }; // Identity - - -// Given a GL type & norm flag and a D3D type, ConversionRule provides the type conversion rule (Cast, Normalize, Identity, FixedToFloat). -// The conversion rules themselves are defined in vertexconversion.h. - -// Almost all cases are covered by Cast (including those that are actually Identity since Cast knows it's an identity mapping). -template -struct ConversionRule : gl::Cast::type, typename D3DToCType::type> -{ -}; - -// All conversions from normalized types to float use the Normalize operator. -template struct ConversionRule : gl::Normalize::type> { }; - -// Use a full specialisation for this so that it preferentially matches ahead of the generic normalize-to-float rules. -template <> struct ConversionRule : gl::FixedToFloat { }; -template <> struct ConversionRule : gl::FixedToFloat { }; - -// A 2-stage construction is used for DefaultVertexValues because float must use SimpleDefaultValues (i.e. 0/1) -// whether it is normalized or not. -template -struct DefaultVertexValuesStage2 -{ -}; - -template struct DefaultVertexValuesStage2 : gl::NormalizedDefaultValues { }; -template struct DefaultVertexValuesStage2 : gl::SimpleDefaultValues { }; - -// Work out the default value rule for a D3D type (expressed as the C type) and -template -struct DefaultVertexValues : DefaultVertexValuesStage2 -{ -}; - -template struct DefaultVertexValues : gl::SimpleDefaultValues { }; - -// Policy rules for use with Converter, to choose whether to use the preferred or fallback conversion. -// The fallback conversion produces an output that all D3D9 devices must support. -template struct UsePreferred { enum { type = T::preferred }; }; -template struct UseFallback { enum { type = T::fallback }; }; - -// Converter ties it all together. Given an OpenGL type/norm/size and choice of preferred/fallback conversion, -// it provides all the members of the appropriate VertexDataConverter, the D3DCAPS9::DeclTypes flag in cap flag -// and the D3DDECLTYPE member needed for the vertex declaration in declflag. -template class PreferenceRule> -struct Converter - : gl::VertexDataConverter::type, - WidenRule >::type, size>, - ConversionRule >::type>, - DefaultVertexValues >::type>::type, normalized > > -{ -private: - enum { d3dtype = PreferenceRule< VertexTypeMapping >::type }; - enum { d3dsize = WidenRule::finalWidth }; - -public: - enum { capflag = VertexTypeFlags::capflag }; - enum { declflag = VertexTypeFlags::declflag }; -}; - -// Initialise a TranslationInfo -#define TRANSLATION(type, norm, size, preferred) \ - { \ - Converter::identity, \ - Converter::finalSize, \ - Converter::convertArray, \ - static_cast(Converter::declflag) \ - } - -#define TRANSLATION_FOR_TYPE_NORM_SIZE(type, norm, size) \ - { \ - Converter::capflag, \ - TRANSLATION(type, norm, size, UsePreferred), \ - TRANSLATION(type, norm, size, UseFallback) \ - } - -#define TRANSLATIONS_FOR_TYPE(type) \ - { \ - { TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 4) }, \ - { TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 4) }, \ - } - -#define TRANSLATIONS_FOR_TYPE_NO_NORM(type) \ - { \ - { TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 4) }, \ - { TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 4) }, \ - } - -const VertexDataManager::TranslationDescription VertexDataManager::mPossibleTranslations[NUM_GL_VERTEX_ATTRIB_TYPES][2][4] = // [GL types as enumerated by typeIndex()][normalized][size-1] -{ - TRANSLATIONS_FOR_TYPE(GL_BYTE), - TRANSLATIONS_FOR_TYPE(GL_UNSIGNED_BYTE), - TRANSLATIONS_FOR_TYPE(GL_SHORT), - TRANSLATIONS_FOR_TYPE(GL_UNSIGNED_SHORT), - TRANSLATIONS_FOR_TYPE_NO_NORM(GL_FIXED), - TRANSLATIONS_FOR_TYPE_NO_NORM(GL_FLOAT) -}; - -void VertexDataManager::checkVertexCaps(DWORD declTypes) -{ - for (unsigned int i = 0; i < NUM_GL_VERTEX_ATTRIB_TYPES; i++) - { - for (unsigned int j = 0; j < 2; j++) - { - for (unsigned int k = 0; k < 4; k++) - { - if (mPossibleTranslations[i][j][k].capsFlag == 0 || (declTypes & mPossibleTranslations[i][j][k].capsFlag) != 0) - { - mAttributeTypes[i][j][k] = mPossibleTranslations[i][j][k].preferredConversion; - } - else - { - mAttributeTypes[i][j][k] = mPossibleTranslations[i][j][k].fallbackConversion; - } - } - } - } -} - -// This is used to index mAttributeTypes and mPossibleTranslations. -unsigned int VertexDataManager::typeIndex(GLenum type) const -{ - switch (type) - { - case GL_BYTE: return 0; - case GL_UNSIGNED_BYTE: return 1; - case GL_SHORT: return 2; - case GL_UNSIGNED_SHORT: return 3; - case GL_FIXED: return 4; - case GL_FLOAT: return 5; - - default: UNREACHABLE(); return 5; - } -} - -VertexBuffer::VertexBuffer(IDirect3DDevice9 *device, std::size_t size, DWORD usageFlags) : mDevice(device), mVertexBuffer(NULL) -{ - if (size > 0) - { - D3DPOOL pool = getDisplay()->getBufferPool(usageFlags); - HRESULT result = device->CreateVertexBuffer(size, usageFlags, 0, pool, &mVertexBuffer, NULL); - mSerial = issueSerial(); - - if (FAILED(result)) - { - ERR("Out of memory allocating a vertex buffer of size %lu.", size); - } - } -} - -VertexBuffer::~VertexBuffer() -{ - if (mVertexBuffer) - { - mVertexBuffer->Release(); - } -} - -void VertexBuffer::unmap() -{ - if (mVertexBuffer) - { - mVertexBuffer->Unlock(); - } -} - -IDirect3DVertexBuffer9 *VertexBuffer::getBuffer() const -{ - return mVertexBuffer; -} - -unsigned int VertexBuffer::getSerial() const -{ - return mSerial; -} - -unsigned int VertexBuffer::issueSerial() -{ - return mCurrentSerial++; -} - -ArrayVertexBuffer::ArrayVertexBuffer(IDirect3DDevice9 *device, std::size_t size, DWORD usageFlags) : VertexBuffer(device, size, usageFlags) -{ - mBufferSize = size; - mWritePosition = 0; - mRequiredSpace = 0; -} - -ArrayVertexBuffer::~ArrayVertexBuffer() -{ -} - -void ArrayVertexBuffer::addRequiredSpace(UINT requiredSpace) -{ - mRequiredSpace += requiredSpace; -} - -StreamingVertexBuffer::StreamingVertexBuffer(IDirect3DDevice9 *device, std::size_t initialSize) : ArrayVertexBuffer(device, initialSize, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY) -{ -} - -StreamingVertexBuffer::~StreamingVertexBuffer() -{ -} - -void *StreamingVertexBuffer::map(const VertexAttribute &attribute, std::size_t requiredSpace, std::size_t *offset) -{ - void *mapPtr = NULL; - - if (mVertexBuffer) - { - HRESULT result = mVertexBuffer->Lock(mWritePosition, requiredSpace, &mapPtr, D3DLOCK_NOOVERWRITE); - - if (FAILED(result)) - { - ERR("Lock failed with error 0x%08x", result); - return NULL; - } - - *offset = mWritePosition; - mWritePosition += requiredSpace; - } - - return mapPtr; -} - -void StreamingVertexBuffer::reserveRequiredSpace() -{ - if (mRequiredSpace > mBufferSize) - { - if (mVertexBuffer) - { - mVertexBuffer->Release(); - mVertexBuffer = NULL; - } - - mBufferSize = std::max(mRequiredSpace, 3 * mBufferSize / 2); // 1.5 x mBufferSize is arbitrary and should be checked to see we don't have too many reallocations. - - D3DPOOL pool = getDisplay()->getBufferPool(D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY); - HRESULT result = mDevice->CreateVertexBuffer(mBufferSize, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, 0, pool, &mVertexBuffer, NULL); - mSerial = issueSerial(); - - if (FAILED(result)) - { - ERR("Out of memory allocating a vertex buffer of size %lu.", mBufferSize); - } - - mWritePosition = 0; - } - else if (mWritePosition + mRequiredSpace > mBufferSize) // Recycle - { - if (mVertexBuffer) - { - void *dummy; - mVertexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD); - mVertexBuffer->Unlock(); - } - - mWritePosition = 0; - } - - mRequiredSpace = 0; -} - -StaticVertexBuffer::StaticVertexBuffer(IDirect3DDevice9 *device) : ArrayVertexBuffer(device, 0, D3DUSAGE_WRITEONLY) -{ -} - -StaticVertexBuffer::~StaticVertexBuffer() -{ -} - -void *StaticVertexBuffer::map(const VertexAttribute &attribute, std::size_t requiredSpace, std::size_t *streamOffset) -{ - void *mapPtr = NULL; - - if (mVertexBuffer) - { - HRESULT result = mVertexBuffer->Lock(mWritePosition, requiredSpace, &mapPtr, 0); - - if (FAILED(result)) - { - ERR("Lock failed with error 0x%08x", result); - return NULL; - } - - int attributeOffset = attribute.mOffset % attribute.stride(); - VertexElement element = {attribute.mType, attribute.mSize, attribute.stride(), attribute.mNormalized, attributeOffset, mWritePosition}; - mCache.push_back(element); - - *streamOffset = mWritePosition; - mWritePosition += requiredSpace; - } - - return mapPtr; -} - -void StaticVertexBuffer::reserveRequiredSpace() -{ - if (!mVertexBuffer && mBufferSize == 0) - { - D3DPOOL pool = getDisplay()->getBufferPool(D3DUSAGE_WRITEONLY); - HRESULT result = mDevice->CreateVertexBuffer(mRequiredSpace, D3DUSAGE_WRITEONLY, 0, pool, &mVertexBuffer, NULL); - mSerial = issueSerial(); - - if (FAILED(result)) - { - ERR("Out of memory allocating a vertex buffer of size %lu.", mRequiredSpace); - } - - mBufferSize = mRequiredSpace; - } - else if (mVertexBuffer && mBufferSize >= mRequiredSpace) - { - // Already allocated - } - else UNREACHABLE(); // Static vertex buffers can't be resized - - mRequiredSpace = 0; -} - -std::size_t StaticVertexBuffer::lookupAttribute(const VertexAttribute &attribute) -{ - for (unsigned int element = 0; element < mCache.size(); element++) - { - if (mCache[element].type == attribute.mType && - mCache[element].size == attribute.mSize && - mCache[element].stride == attribute.stride() && - mCache[element].normalized == attribute.mNormalized) - { - if (mCache[element].attributeOffset == attribute.mOffset % attribute.stride()) - { - return mCache[element].streamOffset; - } - } - } - - return -1; -} - -const VertexDataManager::FormatConverter &VertexDataManager::formatConverter(const VertexAttribute &attribute) const -{ - return mAttributeTypes[typeIndex(attribute.mType)][attribute.mNormalized][attribute.mSize - 1]; -} -} diff --git a/src/3rdparty/angle/src/libGLESv2/VertexDataManager.h b/src/3rdparty/angle/src/libGLESv2/VertexDataManager.h deleted file mode 100644 index 857591ac29..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/VertexDataManager.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. -// - -// VertexDataManager.h: Defines the VertexDataManager, a class that -// runs the Buffer translation process. - -#ifndef LIBGLESV2_VERTEXDATAMANAGER_H_ -#define LIBGLESV2_VERTEXDATAMANAGER_H_ - -#include -#include - -#define GL_APICALL -#include - -#include "libGLESv2/Context.h" - -namespace gl -{ - -struct TranslatedAttribute -{ - bool active; - - D3DDECLTYPE type; - UINT offset; - UINT stride; // 0 means not to advance the read pointer at all - - IDirect3DVertexBuffer9 *vertexBuffer; - unsigned int serial; - unsigned int divisor; -}; - -class VertexBuffer -{ - public: - VertexBuffer(IDirect3DDevice9 *device, std::size_t size, DWORD usageFlags); - virtual ~VertexBuffer(); - - void unmap(); - - IDirect3DVertexBuffer9 *getBuffer() const; - unsigned int getSerial() const; - - protected: - IDirect3DDevice9 *const mDevice; - IDirect3DVertexBuffer9 *mVertexBuffer; - - unsigned int mSerial; - static unsigned int issueSerial(); - static unsigned int mCurrentSerial; - - private: - DISALLOW_COPY_AND_ASSIGN(VertexBuffer); -}; - -class ArrayVertexBuffer : public VertexBuffer -{ - public: - ArrayVertexBuffer(IDirect3DDevice9 *device, std::size_t size, DWORD usageFlags); - ~ArrayVertexBuffer(); - - std::size_t size() const { return mBufferSize; } - virtual void *map(const VertexAttribute &attribute, std::size_t requiredSpace, std::size_t *streamOffset) = 0; - virtual void reserveRequiredSpace() = 0; - void addRequiredSpace(UINT requiredSpace); - - protected: - std::size_t mBufferSize; - std::size_t mWritePosition; - std::size_t mRequiredSpace; -}; - -class StreamingVertexBuffer : public ArrayVertexBuffer -{ - public: - StreamingVertexBuffer(IDirect3DDevice9 *device, std::size_t initialSize); - ~StreamingVertexBuffer(); - - void *map(const VertexAttribute &attribute, std::size_t requiredSpace, std::size_t *streamOffset); - void reserveRequiredSpace(); -}; - -class StaticVertexBuffer : public ArrayVertexBuffer -{ - public: - explicit StaticVertexBuffer(IDirect3DDevice9 *device); - ~StaticVertexBuffer(); - - void *map(const VertexAttribute &attribute, std::size_t requiredSpace, std::size_t *streamOffset); - void reserveRequiredSpace(); - - std::size_t lookupAttribute(const VertexAttribute &attribute); // Returns the offset into the vertex buffer, or -1 if not found - - private: - struct VertexElement - { - GLenum type; - GLint size; - GLsizei stride; - bool normalized; - int attributeOffset; - - std::size_t streamOffset; - }; - - std::vector mCache; -}; - -class VertexDataManager -{ - public: - VertexDataManager(Context *context, IDirect3DDevice9 *backend); - virtual ~VertexDataManager(); - - void dirtyCurrentValue(int index) { mDirtyCurrentValue[index] = true; } - - GLenum prepareVertexData(GLint start, GLsizei count, TranslatedAttribute *outAttribs, GLsizei instances); - - private: - DISALLOW_COPY_AND_ASSIGN(VertexDataManager); - - std::size_t spaceRequired(const VertexAttribute &attrib, std::size_t count, GLsizei instances) const; - std::size_t writeAttributeData(ArrayVertexBuffer *vertexBuffer, GLint start, GLsizei count, const VertexAttribute &attribute, GLsizei instances); - - Context *const mContext; - IDirect3DDevice9 *const mDevice; - - StreamingVertexBuffer *mStreamingBuffer; - - bool mDirtyCurrentValue[MAX_VERTEX_ATTRIBS]; - StreamingVertexBuffer *mCurrentValueBuffer[MAX_VERTEX_ATTRIBS]; - std::size_t mCurrentValueOffsets[MAX_VERTEX_ATTRIBS]; - - // Attribute format conversion - struct FormatConverter - { - bool identity; - std::size_t outputElementSize; - void (*convertArray)(const void *in, std::size_t stride, std::size_t n, void *out); - D3DDECLTYPE d3dDeclType; - }; - - enum { NUM_GL_VERTEX_ATTRIB_TYPES = 6 }; - - FormatConverter mAttributeTypes[NUM_GL_VERTEX_ATTRIB_TYPES][2][4]; // [GL types as enumerated by typeIndex()][normalized][size - 1] - - struct TranslationDescription - { - DWORD capsFlag; - FormatConverter preferredConversion; - FormatConverter fallbackConversion; - }; - - // This table is used to generate mAttributeTypes. - static const TranslationDescription mPossibleTranslations[NUM_GL_VERTEX_ATTRIB_TYPES][2][4]; // [GL types as enumerated by typeIndex()][normalized][size - 1] - - void checkVertexCaps(DWORD declTypes); - - unsigned int typeIndex(GLenum type) const; - const FormatConverter &formatConverter(const VertexAttribute &attribute) const; -}; - -} - -#endif // LIBGLESV2_VERTEXDATAMANAGER_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/angletypes.h b/src/3rdparty/angle/src/libGLESv2/angletypes.h new file mode 100644 index 0000000000..37f67f41ac --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/angletypes.h @@ -0,0 +1,128 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// angletypes.h : Defines a variety of structures and enum types that are used throughout libGLESv2 + +#ifndef LIBGLESV2_ANGLETYPES_H_ +#define LIBGLESV2_ANGLETYPES_H_ + +namespace gl +{ + +enum TextureType +{ + TEXTURE_2D, + TEXTURE_CUBE, + + TEXTURE_TYPE_COUNT, + TEXTURE_UNKNOWN +}; + +enum SamplerType +{ + SAMPLER_PIXEL, + SAMPLER_VERTEX +}; + +struct Color +{ + float red; + float green; + float blue; + float alpha; +}; + +struct Rectangle +{ + int x; + int y; + int width; + int height; +}; + +struct RasterizerState +{ + bool cullFace; + GLenum cullMode; + GLenum frontFace; + + bool polygonOffsetFill; + GLfloat polygonOffsetFactor; + GLfloat polygonOffsetUnits; + + bool pointDrawMode; +}; + +struct BlendState +{ + bool blend; + GLenum sourceBlendRGB; + GLenum destBlendRGB; + GLenum sourceBlendAlpha; + GLenum destBlendAlpha; + GLenum blendEquationRGB; + GLenum blendEquationAlpha; + + bool colorMaskRed; + bool colorMaskGreen; + bool colorMaskBlue; + bool colorMaskAlpha; + + bool sampleAlphaToCoverage; + + bool dither; +}; + +struct DepthStencilState +{ + bool depthTest; + GLenum depthFunc; + bool depthMask; + + bool stencilTest; + GLenum stencilFunc; + GLuint stencilMask; + GLenum stencilFail; + GLenum stencilPassDepthFail; + GLenum stencilPassDepthPass; + GLuint stencilWritemask; + GLenum stencilBackFunc; + GLuint stencilBackMask; + GLenum stencilBackFail; + GLenum stencilBackPassDepthFail; + GLenum stencilBackPassDepthPass; + GLuint stencilBackWritemask; +}; + +struct SamplerState +{ + GLenum minFilter; + GLenum magFilter; + GLenum wrapS; + GLenum wrapT; + float maxAnisotropy; + int lodOffset; +}; + +struct ClearParameters +{ + GLbitfield mask; + + Color colorClearValue; + bool colorMaskRed; + bool colorMaskGreen; + bool colorMaskBlue; + bool colorMaskAlpha; + + float depthClearValue; + + GLint stencilClearValue; + GLuint stencilWriteMask; +}; + +} + +#endif // LIBGLESV2_ANGLETYPES_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/constants.h b/src/3rdparty/angle/src/libGLESv2/constants.h new file mode 100644 index 0000000000..9f24d66a7d --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/constants.h @@ -0,0 +1,34 @@ +// +// 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. +// + +// Contants.h: Defines some implementation specific and gl constants + +#ifndef LIBGLESV2_CONSTANTS_H_ +#define LIBGLESV2_CONSTANTS_H_ + +namespace gl +{ + +enum +{ + MAX_VERTEX_ATTRIBS = 16, + MAX_TEXTURE_IMAGE_UNITS = 16, + + // Implementation upper limits, real maximums depend on the hardware + IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS = 16, + IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS = MAX_TEXTURE_IMAGE_UNITS + IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS, + + IMPLEMENTATION_MAX_VARYING_VECTORS = 32, + IMPLEMENTATION_MAX_DRAW_BUFFERS = 8 +}; + +const float ALIASED_LINE_WIDTH_RANGE_MIN = 1.0f; +const float ALIASED_LINE_WIDTH_RANGE_MAX = 1.0f; +const float ALIASED_POINT_SIZE_RANGE_MIN = 1.0f; + +} + +#endif // LIBGLESV2_CONSTANTS_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp b/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp index 16d9c1775d..64f67d7d6d 100644 --- a/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp +++ b/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp @@ -1,3 +1,4 @@ +#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 @@ -6,29 +7,19 @@ // libGLESv2.cpp: Implements the exported OpenGL ES 2.0 functions. -#define GL_APICALL -#include -#include - -#include -#include - -#include "common/debug.h" #include "common/version.h" #include "libGLESv2/main.h" -#include "libGLESv2/mathutil.h" #include "libGLESv2/utilities.h" #include "libGLESv2/Buffer.h" -#include "libGLESv2/Context.h" #include "libGLESv2/Fence.h" #include "libGLESv2/Framebuffer.h" +#include "libGLESv2/Renderbuffer.h" #include "libGLESv2/Program.h" #include "libGLESv2/ProgramBinary.h" -#include "libGLESv2/Renderbuffer.h" -#include "libGLESv2/Shader.h" #include "libGLESv2/Texture.h" #include "libGLESv2/Query.h" +#include "libGLESv2/Context.h" bool validImageSize(GLint level, GLsizei width, GLsizei height) { @@ -71,7 +62,7 @@ bool checkTextureFormatType(GLenum format, GLenum type) case GL_DEPTH_STENCIL_OES: break; default: - return error(GL_INVALID_ENUM, false); + return gl::error(GL_INVALID_ENUM, false); } // invalid -> sets INVALID_ENUM @@ -89,7 +80,7 @@ bool checkTextureFormatType(GLenum format, GLenum type) case GL_LUMINANCE_ALPHA: return true; default: - return error(GL_INVALID_OPERATION, false); + return gl::error(GL_INVALID_OPERATION, false); } case GL_FLOAT: @@ -103,7 +94,7 @@ bool checkTextureFormatType(GLenum format, GLenum type) case GL_LUMINANCE_ALPHA: return true; default: - return error(GL_INVALID_OPERATION, false); + return gl::error(GL_INVALID_OPERATION, false); } case GL_UNSIGNED_SHORT_4_4_4_4: @@ -113,7 +104,7 @@ bool checkTextureFormatType(GLenum format, GLenum type) case GL_RGBA: return true; default: - return error(GL_INVALID_OPERATION, false); + return gl::error(GL_INVALID_OPERATION, false); } case GL_UNSIGNED_SHORT_5_6_5: @@ -122,7 +113,7 @@ bool checkTextureFormatType(GLenum format, GLenum type) case GL_RGB: return true; default: - return error(GL_INVALID_OPERATION, false); + return gl::error(GL_INVALID_OPERATION, false); } case GL_UNSIGNED_SHORT: @@ -132,7 +123,7 @@ bool checkTextureFormatType(GLenum format, GLenum type) case GL_DEPTH_COMPONENT: return true; default: - return error(GL_INVALID_OPERATION, false); + return gl::error(GL_INVALID_OPERATION, false); } case GL_UNSIGNED_INT_24_8_OES: @@ -141,11 +132,11 @@ bool checkTextureFormatType(GLenum format, GLenum type) case GL_DEPTH_STENCIL_OES: return true; default: - return error(GL_INVALID_OPERATION, false); + return gl::error(GL_INVALID_OPERATION, false); } default: - return error(GL_INVALID_ENUM, false); + return gl::error(GL_INVALID_ENUM, false); } } @@ -155,12 +146,12 @@ bool validateSubImageParams2D(bool compressed, GLsizei width, GLsizei height, { if (!texture) { - return error(GL_INVALID_OPERATION, false); + return gl::error(GL_INVALID_OPERATION, false); } if (compressed != texture->isCompressed(level)) { - return error(GL_INVALID_OPERATION, false); + return gl::error(GL_INVALID_OPERATION, false); } if (format != GL_NONE) @@ -168,7 +159,7 @@ bool validateSubImageParams2D(bool compressed, GLsizei width, GLsizei height, GLenum internalformat = gl::ConvertSizedInternalFormat(format, type); if (internalformat != texture->getInternalFormat(level)) { - return error(GL_INVALID_OPERATION, false); + return gl::error(GL_INVALID_OPERATION, false); } } @@ -177,14 +168,14 @@ bool validateSubImageParams2D(bool compressed, GLsizei width, GLsizei height, if ((width % 4 != 0 && width != texture->getWidth(0)) || (height % 4 != 0 && height != texture->getHeight(0))) { - return error(GL_INVALID_OPERATION, false); + return gl::error(GL_INVALID_OPERATION, false); } } if (xoffset + width > texture->getWidth(level) || yoffset + height > texture->getHeight(level)) { - return error(GL_INVALID_VALUE, false); + return gl::error(GL_INVALID_VALUE, false); } return true; @@ -196,12 +187,12 @@ bool validateSubImageParamsCube(bool compressed, GLsizei width, GLsizei height, { if (!texture) { - return error(GL_INVALID_OPERATION, false); + return gl::error(GL_INVALID_OPERATION, false); } if (compressed != texture->isCompressed(target, level)) { - return error(GL_INVALID_OPERATION, false); + return gl::error(GL_INVALID_OPERATION, false); } if (format != GL_NONE) @@ -209,7 +200,7 @@ bool validateSubImageParamsCube(bool compressed, GLsizei width, GLsizei height, GLenum internalformat = gl::ConvertSizedInternalFormat(format, type); if (internalformat != texture->getInternalFormat(target, level)) { - return error(GL_INVALID_OPERATION, false); + return gl::error(GL_INVALID_OPERATION, false); } } @@ -218,14 +209,14 @@ bool validateSubImageParamsCube(bool compressed, GLsizei width, GLsizei height, if ((width % 4 != 0 && width != texture->getWidth(target, 0)) || (height % 4 != 0 && height != texture->getHeight(target, 0))) { - return error(GL_INVALID_OPERATION, false); + return gl::error(GL_INVALID_OPERATION, false); } } if (xoffset + width > texture->getWidth(target, level) || yoffset + height > texture->getHeight(target, level)) { - return error(GL_INVALID_VALUE, false); + return gl::error(GL_INVALID_VALUE, false); } return true; @@ -277,7 +268,7 @@ void __stdcall glActiveTexture(GLenum texture) { if (texture < GL_TEXTURE0 || texture > GL_TEXTURE0 + context->getMaximumCombinedTextureImageUnits() - 1) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } context->setActiveSampler(texture - GL_TEXTURE0); @@ -285,7 +276,7 @@ void __stdcall glActiveTexture(GLenum texture) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -306,11 +297,11 @@ void __stdcall glAttachShader(GLuint program, GLuint shader) { if (context->getShader(program)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } else { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } } @@ -318,23 +309,23 @@ void __stdcall glAttachShader(GLuint program, GLuint shader) { if (context->getProgram(shader)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } else { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } } if (!programObject->attachShader(shaderObject)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -350,12 +341,12 @@ void __stdcall glBeginQueryEXT(GLenum target, GLuint id) case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT: break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } if (id == 0) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } gl::Context *context = gl::getNonLostContext(); @@ -367,7 +358,7 @@ void __stdcall glBeginQueryEXT(GLenum target, GLuint id) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -379,7 +370,7 @@ void __stdcall glBindAttribLocation(GLuint program, GLuint index, const GLchar* { if (index >= gl::MAX_VERTEX_ATTRIBS) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -392,17 +383,17 @@ void __stdcall glBindAttribLocation(GLuint program, GLuint index, const GLchar* { if (context->getShader(program)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } else { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } } if (strncmp(name, "gl_", 3) == 0) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } programObject->bindAttributeLocation(index, name); @@ -410,7 +401,7 @@ void __stdcall glBindAttribLocation(GLuint program, GLuint index, const GLchar* } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -433,13 +424,13 @@ void __stdcall glBindBuffer(GLenum target, GLuint buffer) context->bindElementArrayBuffer(buffer); return; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -451,7 +442,7 @@ void __stdcall glBindFramebuffer(GLenum target, GLuint framebuffer) { if (target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } gl::Context *context = gl::getNonLostContext(); @@ -471,7 +462,7 @@ void __stdcall glBindFramebuffer(GLenum target, GLuint framebuffer) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -483,7 +474,7 @@ void __stdcall glBindRenderbuffer(GLenum target, GLuint renderbuffer) { if (target != GL_RENDERBUFFER) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } gl::Context *context = gl::getNonLostContext(); @@ -495,7 +486,7 @@ void __stdcall glBindRenderbuffer(GLenum target, GLuint renderbuffer) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -513,7 +504,7 @@ void __stdcall glBindTexture(GLenum target, GLuint texture) if (textureObject && textureObject->getTarget() != target && texture != 0) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } switch (target) @@ -525,13 +516,13 @@ void __stdcall glBindTexture(GLenum target, GLuint texture) context->bindTextureCubeMap(texture); return; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -551,7 +542,7 @@ void __stdcall glBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclamp } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -573,7 +564,7 @@ void __stdcall glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha) case GL_FUNC_REVERSE_SUBTRACT: break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } switch (modeAlpha) @@ -583,7 +574,7 @@ void __stdcall glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha) case GL_FUNC_REVERSE_SUBTRACT: break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } gl::Context *context = gl::getNonLostContext(); @@ -595,7 +586,7 @@ void __stdcall glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -630,7 +621,7 @@ void __stdcall glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha case GL_SRC_ALPHA_SATURATE: break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } switch (dstRGB) @@ -651,7 +642,7 @@ void __stdcall glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha case GL_ONE_MINUS_CONSTANT_ALPHA: break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } switch (srcAlpha) @@ -673,7 +664,7 @@ void __stdcall glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha case GL_SRC_ALPHA_SATURATE: break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } switch (dstAlpha) @@ -694,7 +685,7 @@ void __stdcall glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha case GL_ONE_MINUS_CONSTANT_ALPHA: break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } bool constantColorUsed = (srcRGB == GL_CONSTANT_COLOR || srcRGB == GL_ONE_MINUS_CONSTANT_COLOR || @@ -706,7 +697,7 @@ void __stdcall glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha if (constantColorUsed && constantAlphaUsed) { ERR("Simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR invalid under WebGL"); - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } gl::Context *context = gl::getNonLostContext(); @@ -718,7 +709,7 @@ void __stdcall glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -731,7 +722,7 @@ void __stdcall glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, { if (size < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } switch (usage) @@ -741,7 +732,7 @@ void __stdcall glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, case GL_DYNAMIC_DRAW: break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } gl::Context *context = gl::getNonLostContext(); @@ -759,12 +750,12 @@ void __stdcall glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, buffer = context->getElementArrayBuffer(); break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } if (!buffer) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } buffer->bufferData(data, size, usage); @@ -772,7 +763,7 @@ void __stdcall glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -785,7 +776,7 @@ void __stdcall glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, { if (size < 0 || offset < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } if (data == NULL) @@ -808,17 +799,17 @@ void __stdcall glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, buffer = context->getElementArrayBuffer(); break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } if (!buffer) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } if ((size_t)size + offset > buffer->size()) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } buffer->bufferSubData(data, size, offset); @@ -826,7 +817,7 @@ void __stdcall glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -838,7 +829,7 @@ GLenum __stdcall glCheckFramebufferStatus(GLenum target) { if (target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE) { - return error(GL_INVALID_ENUM, 0); + return gl::error(GL_INVALID_ENUM, 0); } gl::Context *context = gl::getNonLostContext(); @@ -860,7 +851,7 @@ GLenum __stdcall glCheckFramebufferStatus(GLenum target) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY, 0); + return gl::error(GL_OUT_OF_MEMORY, 0); } return 0; @@ -881,7 +872,7 @@ void __stdcall glClear(GLbitfield mask) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -901,7 +892,7 @@ void __stdcall glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclamp } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -920,7 +911,7 @@ void __stdcall glClearDepthf(GLclampf depth) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -939,7 +930,7 @@ void __stdcall glClearStencil(GLint s) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -959,7 +950,7 @@ void __stdcall glColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboo } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -979,11 +970,11 @@ void __stdcall glCompileShader(GLuint shader) { if (context->getProgram(shader)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } else { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } } @@ -992,7 +983,7 @@ void __stdcall glCompileShader(GLuint shader) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -1007,7 +998,7 @@ void __stdcall glCompressedTexImage2D(GLenum target, GLint level, GLenum interna { if (!validImageSize(level, width, height) || border != 0 || imageSize < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } switch (internalformat) @@ -1018,12 +1009,22 @@ void __stdcall glCompressedTexImage2D(GLenum target, GLint level, GLenum interna case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } if (border != 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_OPERATION); + } + + if (width != 1 && width != 2 && width % 4 != 0) + { + return gl::error(GL_INVALID_OPERATION); + } + + if (height != 1 && height != 2 && height % 4 != 0) + { + return gl::error(GL_INVALID_OPERATION); } gl::Context *context = gl::getNonLostContext(); @@ -1032,7 +1033,7 @@ void __stdcall glCompressedTexImage2D(GLenum target, GLint level, GLenum interna { if (level > context->getMaximumTextureLevel()) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } switch (target) @@ -1041,7 +1042,7 @@ void __stdcall glCompressedTexImage2D(GLenum target, GLint level, GLenum interna if (width > (context->getMaximumTextureDimension() >> level) || height > (context->getMaximumTextureDimension() >> level)) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } break; case GL_TEXTURE_CUBE_MAP_POSITIVE_X: @@ -1052,17 +1053,17 @@ void __stdcall glCompressedTexImage2D(GLenum target, GLint level, GLenum interna case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: if (width != height) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } if (width > (context->getMaximumCubeTextureDimension() >> level) || height > (context->getMaximumCubeTextureDimension() >> level)) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } switch (internalformat) { @@ -1070,19 +1071,19 @@ void __stdcall glCompressedTexImage2D(GLenum target, GLint level, GLenum interna case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: if (!context->supportsDXT1Textures()) { - return error(GL_INVALID_ENUM); // in this case, it's as though the internal format switch failed + return gl::error(GL_INVALID_ENUM); // in this case, it's as though the internal format switch failed } break; case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: if (!context->supportsDXT3Textures()) { - return error(GL_INVALID_ENUM); // in this case, it's as though the internal format switch failed + return gl::error(GL_INVALID_ENUM); // in this case, it's as though the internal format switch failed } break; case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: if (!context->supportsDXT5Textures()) { - return error(GL_INVALID_ENUM); // in this case, it's as though the internal format switch failed + return gl::error(GL_INVALID_ENUM); // in this case, it's as though the internal format switch failed } break; default: UNREACHABLE(); @@ -1090,7 +1091,7 @@ void __stdcall glCompressedTexImage2D(GLenum target, GLint level, GLenum interna if (imageSize != gl::ComputeCompressedSize(width, height, internalformat)) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } if (target == GL_TEXTURE_2D) @@ -1099,12 +1100,12 @@ void __stdcall glCompressedTexImage2D(GLenum target, GLint level, GLenum interna if (!texture) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } if (texture->isImmutable()) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } texture->setCompressedImage(level, internalformat, width, height, imageSize, data); @@ -1115,12 +1116,12 @@ void __stdcall glCompressedTexImage2D(GLenum target, GLint level, GLenum interna if (!texture) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } if (texture->isImmutable()) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } switch (target) @@ -1141,7 +1142,7 @@ void __stdcall glCompressedTexImage2D(GLenum target, GLint level, GLenum interna } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -1157,12 +1158,12 @@ void __stdcall glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffs { if (!gl::IsInternalTextureTarget(target)) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } if (xoffset < 0 || yoffset < 0 || !validImageSize(level, width, height) || imageSize < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } switch (format) @@ -1173,7 +1174,7 @@ void __stdcall glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffs case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } if (width == 0 || height == 0 || data == NULL) @@ -1187,7 +1188,7 @@ void __stdcall glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffs { if (level > context->getMaximumTextureLevel()) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } switch (format) { @@ -1195,19 +1196,19 @@ void __stdcall glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffs case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: if (!context->supportsDXT1Textures()) { - return error(GL_INVALID_ENUM); // in this case, it's as though the internal format switch failed + return gl::error(GL_INVALID_ENUM); // in this case, it's as though the internal format switch failed } break; case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: if (!context->supportsDXT3Textures()) { - return error(GL_INVALID_ENUM); // in this case, it's as though the internal format switch failed + return gl::error(GL_INVALID_ENUM); // in this case, it's as though the internal format switch failed } break; case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: if (!context->supportsDXT5Textures()) { - return error(GL_INVALID_ENUM); // in this case, it's as though the internal format switch failed + return gl::error(GL_INVALID_ENUM); // in this case, it's as though the internal format switch failed } break; default: UNREACHABLE(); @@ -1215,12 +1216,12 @@ void __stdcall glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffs if (imageSize != gl::ComputeCompressedSize(width, height, format)) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } if (xoffset % 4 != 0 || yoffset % 4 != 0) { - return error(GL_INVALID_OPERATION); // we wait to check the offsets until this point, because the multiple-of-four restriction + return gl::error(GL_INVALID_OPERATION); // we wait to check the offsets until this point, because the multiple-of-four restriction // does not exist unless DXT textures are supported. } @@ -1248,7 +1249,7 @@ void __stdcall glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffs } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -1262,12 +1263,12 @@ void __stdcall glCopyTexImage2D(GLenum target, GLint level, GLenum internalforma { if (!validImageSize(level, width, height)) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } if (border != 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -1276,7 +1277,7 @@ void __stdcall glCopyTexImage2D(GLenum target, GLint level, GLenum internalforma { if (level > context->getMaximumTextureLevel()) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } switch (target) @@ -1285,7 +1286,7 @@ void __stdcall glCopyTexImage2D(GLenum target, GLint level, GLenum internalforma if (width > (context->getMaximumTextureDimension() >> level) || height > (context->getMaximumTextureDimension() >> level)) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } break; case GL_TEXTURE_CUBE_MAP_POSITIVE_X: @@ -1296,32 +1297,32 @@ void __stdcall glCopyTexImage2D(GLenum target, GLint level, GLenum internalforma case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: if (width != height) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } if (width > (context->getMaximumCubeTextureDimension() >> level) || height > (context->getMaximumCubeTextureDimension() >> level)) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } gl::Framebuffer *framebuffer = context->getReadFramebuffer(); if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE) { - return error(GL_INVALID_FRAMEBUFFER_OPERATION); + return gl::error(GL_INVALID_FRAMEBUFFER_OPERATION); } - if (context->getReadFramebufferHandle() != 0 && framebuffer->getColorbuffer()->getSamples() != 0) + if (context->getReadFramebufferHandle() != 0 && framebuffer->getSamples() != 0) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } - gl::Renderbuffer *source = framebuffer->getColorbuffer(); + gl::Renderbuffer *source = framebuffer->getReadColorbuffer(); GLenum colorbufferFormat = source->getInternalFormat(); // [OpenGL ES 2.0.24] table 3.9 @@ -1331,9 +1332,10 @@ void __stdcall glCopyTexImage2D(GLenum target, GLint level, GLenum internalforma if (colorbufferFormat != GL_ALPHA8_EXT && colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 && + colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } break; case GL_LUMINANCE: @@ -1342,49 +1344,51 @@ void __stdcall glCopyTexImage2D(GLenum target, GLint level, GLenum internalforma colorbufferFormat != GL_RGB8_OES && colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 && + colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } break; case GL_LUMINANCE_ALPHA: case GL_RGBA: if (colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 && + colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } break; case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: if (context->supportsDXT1Textures()) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } else { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } break; case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: if (context->supportsDXT3Textures()) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } else { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } break; case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: if (context->supportsDXT5Textures()) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } else { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } break; case GL_DEPTH_COMPONENT: @@ -1394,14 +1398,14 @@ void __stdcall glCopyTexImage2D(GLenum target, GLint level, GLenum internalforma case GL_DEPTH24_STENCIL8_OES: if (context->supportsDepthTextures()) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } else { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } if (target == GL_TEXTURE_2D) @@ -1410,12 +1414,12 @@ void __stdcall glCopyTexImage2D(GLenum target, GLint level, GLenum internalforma if (!texture) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } if (texture->isImmutable()) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } texture->copyImage(level, internalformat, x, y, width, height, framebuffer); @@ -1426,12 +1430,12 @@ void __stdcall glCopyTexImage2D(GLenum target, GLint level, GLenum internalforma if (!texture) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } if (texture->isImmutable()) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } texture->copyImage(target, level, internalformat, x, y, width, height, framebuffer); @@ -1441,7 +1445,7 @@ void __stdcall glCopyTexImage2D(GLenum target, GLint level, GLenum internalforma } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -1455,17 +1459,17 @@ void __stdcall glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GL { if (!gl::IsInternalTextureTarget(target)) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } if (level < 0 || xoffset < 0 || yoffset < 0 || width < 0 || height < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } if (std::numeric_limits::max() - xoffset < width || std::numeric_limits::max() - yoffset < height) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } if (width == 0 || height == 0) @@ -1479,22 +1483,22 @@ void __stdcall glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GL { if (level > context->getMaximumTextureLevel()) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Framebuffer *framebuffer = context->getReadFramebuffer(); if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE) { - return error(GL_INVALID_FRAMEBUFFER_OPERATION); + return gl::error(GL_INVALID_FRAMEBUFFER_OPERATION); } - if (context->getReadFramebufferHandle() != 0 && framebuffer->getColorbuffer()->getSamples() != 0) + if (context->getReadFramebufferHandle() != 0 && framebuffer->getSamples() != 0) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } - gl::Renderbuffer *source = framebuffer->getColorbuffer(); + gl::Renderbuffer *source = framebuffer->getReadColorbuffer(); GLenum colorbufferFormat = source->getInternalFormat(); gl::Texture *texture = NULL; GLenum textureFormat = GL_RGBA; @@ -1532,7 +1536,7 @@ void __stdcall glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GL colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } break; case GL_LUMINANCE: @@ -1543,7 +1547,7 @@ void __stdcall glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GL colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } break; case GL_LUMINANCE_ALPHA: @@ -1552,19 +1556,19 @@ void __stdcall glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GL colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } break; case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); case GL_DEPTH_COMPONENT: case GL_DEPTH_STENCIL_OES: - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); default: - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } texture->copySubImage(target, level, xoffset, yoffset, x, y, width, height, framebuffer); @@ -1573,7 +1577,7 @@ void __stdcall glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GL catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -1592,7 +1596,7 @@ GLuint __stdcall glCreateProgram(void) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY, 0); + return gl::error(GL_OUT_OF_MEMORY, 0); } return 0; @@ -1614,13 +1618,13 @@ GLuint __stdcall glCreateShader(GLenum type) case GL_VERTEX_SHADER: return context->createShader(type); default: - return error(GL_INVALID_ENUM, 0); + return gl::error(GL_INVALID_ENUM, 0); } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY, 0); + return gl::error(GL_OUT_OF_MEMORY, 0); } return 0; @@ -1647,12 +1651,12 @@ void __stdcall glCullFace(GLenum mode) } break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -1664,7 +1668,7 @@ void __stdcall glDeleteBuffers(GLsizei n, const GLuint* buffers) { if (n < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -1679,7 +1683,7 @@ void __stdcall glDeleteBuffers(GLsizei n, const GLuint* buffers) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -1691,7 +1695,7 @@ void __stdcall glDeleteFencesNV(GLsizei n, const GLuint* fences) { if (n < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -1706,7 +1710,7 @@ void __stdcall glDeleteFencesNV(GLsizei n, const GLuint* fences) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -1718,7 +1722,7 @@ void __stdcall glDeleteFramebuffers(GLsizei n, const GLuint* framebuffers) { if (n < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -1736,7 +1740,7 @@ void __stdcall glDeleteFramebuffers(GLsizei n, const GLuint* framebuffers) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -1759,11 +1763,11 @@ void __stdcall glDeleteProgram(GLuint program) { if(context->getShader(program)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } else { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } } @@ -1772,7 +1776,7 @@ void __stdcall glDeleteProgram(GLuint program) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -1784,7 +1788,7 @@ void __stdcall glDeleteQueriesEXT(GLsizei n, const GLuint *ids) { if (n < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -1799,7 +1803,7 @@ void __stdcall glDeleteQueriesEXT(GLsizei n, const GLuint *ids) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -1811,7 +1815,7 @@ void __stdcall glDeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers) { if (n < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -1826,7 +1830,7 @@ void __stdcall glDeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -1849,11 +1853,11 @@ void __stdcall glDeleteShader(GLuint shader) { if(context->getProgram(shader)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } else { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } } @@ -1862,7 +1866,7 @@ void __stdcall glDeleteShader(GLuint shader) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -1874,7 +1878,7 @@ void __stdcall glDeleteTextures(GLsizei n, const GLuint* textures) { if (n < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -1892,7 +1896,7 @@ void __stdcall glDeleteTextures(GLsizei n, const GLuint* textures) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -1914,7 +1918,7 @@ void __stdcall glDepthFunc(GLenum func) case GL_NOTEQUAL: break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } gl::Context *context = gl::getNonLostContext(); @@ -1926,7 +1930,7 @@ void __stdcall glDepthFunc(GLenum func) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -1945,7 +1949,7 @@ void __stdcall glDepthMask(GLboolean flag) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -1964,7 +1968,7 @@ void __stdcall glDepthRangef(GLclampf zNear, GLclampf zFar) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -1988,11 +1992,11 @@ void __stdcall glDetachShader(GLuint program, GLuint shader) shaderByProgramHandle = context->getShader(program); if (!shaderByProgramHandle) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } else { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } } @@ -2001,23 +2005,23 @@ void __stdcall glDetachShader(GLuint program, GLuint shader) gl::Program *programByShaderHandle = context->getProgram(shader); if (!programByShaderHandle) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } else { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } } if (!programObject->detachShader(shaderObject)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -2043,13 +2047,13 @@ void __stdcall glDisable(GLenum cap) case GL_BLEND: context->setBlend(false); break; case GL_DITHER: context->setDither(false); break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -2061,7 +2065,7 @@ void __stdcall glDisableVertexAttribArray(GLuint index) { if (index >= gl::MAX_VERTEX_ATTRIBS) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -2073,7 +2077,7 @@ void __stdcall glDisableVertexAttribArray(GLuint index) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -2085,7 +2089,7 @@ void __stdcall glDrawArrays(GLenum mode, GLint first, GLsizei count) { if (count < 0 || first < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -2097,7 +2101,7 @@ void __stdcall glDrawArrays(GLenum mode, GLint first, GLsizei count) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -2109,7 +2113,7 @@ void __stdcall glDrawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei coun { if (count < 0 || first < 0 || primcount < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } if (primcount > 0) @@ -2124,7 +2128,7 @@ void __stdcall glDrawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei coun } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -2137,7 +2141,7 @@ void __stdcall glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLv { if (count < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -2152,11 +2156,11 @@ void __stdcall glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLv case GL_UNSIGNED_INT: if (!context->supports32bitIndices()) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } context->drawElements(mode, count, type, indices, 0); @@ -2164,7 +2168,7 @@ void __stdcall glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLv } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -2177,7 +2181,7 @@ void __stdcall glDrawElementsInstancedANGLE(GLenum mode, GLsizei count, GLenum t { if (count < 0 || primcount < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } if (primcount > 0) @@ -2194,11 +2198,11 @@ void __stdcall glDrawElementsInstancedANGLE(GLenum mode, GLsizei count, GLenum t case GL_UNSIGNED_INT: if (!context->supports32bitIndices()) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } context->drawElements(mode, count, type, indices, primcount); @@ -2207,7 +2211,7 @@ void __stdcall glDrawElementsInstancedANGLE(GLenum mode, GLsizei count, GLenum t } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -2233,13 +2237,13 @@ void __stdcall glEnable(GLenum cap) case GL_BLEND: context->setBlend(true); break; case GL_DITHER: context->setDither(true); break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -2251,7 +2255,7 @@ void __stdcall glEnableVertexAttribArray(GLuint index) { if (index >= gl::MAX_VERTEX_ATTRIBS) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -2263,7 +2267,7 @@ void __stdcall glEnableVertexAttribArray(GLuint index) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -2279,7 +2283,7 @@ void __stdcall glEndQueryEXT(GLenum target) case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT: break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } gl::Context *context = gl::getNonLostContext(); @@ -2291,7 +2295,7 @@ void __stdcall glEndQueryEXT(GLenum target) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -2309,7 +2313,7 @@ void __stdcall glFinishFenceNV(GLuint fence) if (fenceObject == NULL) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } fenceObject->finishFence(); @@ -2317,7 +2321,7 @@ void __stdcall glFinishFenceNV(GLuint fence) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -2336,7 +2340,7 @@ void __stdcall glFinish(void) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -2355,7 +2359,7 @@ void __stdcall glFlush(void) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -2369,7 +2373,7 @@ void __stdcall glFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenu if ((target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE) || (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0)) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } gl::Context *context = gl::getNonLostContext(); @@ -2391,28 +2395,39 @@ void __stdcall glFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenu if (!framebuffer || (framebufferHandle == 0 && renderbuffer != 0)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } - switch (attachment) + if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT) { - case GL_COLOR_ATTACHMENT0: - framebuffer->setColorbuffer(GL_RENDERBUFFER, renderbuffer); - break; - case GL_DEPTH_ATTACHMENT: - framebuffer->setDepthbuffer(GL_RENDERBUFFER, renderbuffer); - break; - case GL_STENCIL_ATTACHMENT: - framebuffer->setStencilbuffer(GL_RENDERBUFFER, renderbuffer); - break; - default: - return error(GL_INVALID_ENUM); + const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT); + + if (colorAttachment >= context->getMaximumRenderTargets()) + { + return gl::error(GL_INVALID_VALUE); + } + + framebuffer->setColorbuffer(colorAttachment, GL_RENDERBUFFER, renderbuffer); + } + else + { + switch (attachment) + { + case GL_DEPTH_ATTACHMENT: + framebuffer->setDepthbuffer(GL_RENDERBUFFER, renderbuffer); + break; + case GL_STENCIL_ATTACHMENT: + framebuffer->setStencilbuffer(GL_RENDERBUFFER, renderbuffer); + break; + default: + return gl::error(GL_INVALID_ENUM); + } } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -2425,23 +2440,34 @@ void __stdcall glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum t { if (target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE) { - return error(GL_INVALID_ENUM); - } - - switch (attachment) - { - case GL_COLOR_ATTACHMENT0: - case GL_DEPTH_ATTACHMENT: - case GL_STENCIL_ATTACHMENT: - break; - default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } gl::Context *context = gl::getNonLostContext(); if (context) { + if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT) + { + const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT); + + if (colorAttachment >= context->getMaximumRenderTargets()) + { + return gl::error(GL_INVALID_VALUE); + } + } + else + { + switch (attachment) + { + case GL_DEPTH_ATTACHMENT: + case GL_STENCIL_ATTACHMENT: + break; + default: + return gl::error(GL_INVALID_ENUM); + } + } + if (texture == 0) { textarget = GL_NONE; @@ -2452,7 +2478,7 @@ void __stdcall glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum t if (tex == NULL) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } switch (textarget) @@ -2461,12 +2487,12 @@ void __stdcall glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum t { if (tex->getTarget() != GL_TEXTURE_2D) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } gl::Texture2D *tex2d = static_cast(tex); if (tex2d->isCompressed(0)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } break; } @@ -2480,23 +2506,23 @@ void __stdcall glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum t { if (tex->getTarget() != GL_TEXTURE_CUBE_MAP) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } gl::TextureCubeMap *texcube = static_cast(tex); if (texcube->isCompressed(textarget, level)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } break; } default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } if (level != 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } } @@ -2515,20 +2541,33 @@ void __stdcall glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum t if (framebufferHandle == 0 || !framebuffer) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } - switch (attachment) + if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT) { - case GL_COLOR_ATTACHMENT0: framebuffer->setColorbuffer(textarget, texture); break; - case GL_DEPTH_ATTACHMENT: framebuffer->setDepthbuffer(textarget, texture); break; - case GL_STENCIL_ATTACHMENT: framebuffer->setStencilbuffer(textarget, texture); break; + const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT); + + if (colorAttachment >= context->getMaximumRenderTargets()) + { + return gl::error(GL_INVALID_VALUE); + } + + framebuffer->setColorbuffer(colorAttachment, textarget, texture); + } + else + { + switch (attachment) + { + case GL_DEPTH_ATTACHMENT: framebuffer->setDepthbuffer(textarget, texture); break; + case GL_STENCIL_ATTACHMENT: framebuffer->setStencilbuffer(textarget, texture); break; + } } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -2552,12 +2591,12 @@ void __stdcall glFrontFace(GLenum mode) } break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -2569,7 +2608,7 @@ void __stdcall glGenBuffers(GLsizei n, GLuint* buffers) { if (n < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -2584,7 +2623,7 @@ void __stdcall glGenBuffers(GLsizei n, GLuint* buffers) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -2606,11 +2645,11 @@ void __stdcall glGenerateMipmap(GLenum target) if (tex2d->isCompressed(0)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } if (tex2d->isDepth(0)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } tex2d->generateMipmaps(); @@ -2623,7 +2662,7 @@ void __stdcall glGenerateMipmap(GLenum target) if (texcube->isCompressed(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } texcube->generateMipmaps(); @@ -2631,13 +2670,13 @@ void __stdcall glGenerateMipmap(GLenum target) } default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -2649,7 +2688,7 @@ void __stdcall glGenFencesNV(GLsizei n, GLuint* fences) { if (n < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -2664,7 +2703,7 @@ void __stdcall glGenFencesNV(GLsizei n, GLuint* fences) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -2676,7 +2715,7 @@ void __stdcall glGenFramebuffers(GLsizei n, GLuint* framebuffers) { if (n < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -2691,7 +2730,7 @@ void __stdcall glGenFramebuffers(GLsizei n, GLuint* framebuffers) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -2703,7 +2742,7 @@ void __stdcall glGenQueriesEXT(GLsizei n, GLuint* ids) { if (n < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -2718,7 +2757,7 @@ void __stdcall glGenQueriesEXT(GLsizei n, GLuint* ids) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -2730,7 +2769,7 @@ void __stdcall glGenRenderbuffers(GLsizei n, GLuint* renderbuffers) { if (n < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -2745,7 +2784,7 @@ void __stdcall glGenRenderbuffers(GLsizei n, GLuint* renderbuffers) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -2757,7 +2796,7 @@ void __stdcall glGenTextures(GLsizei n, GLuint* textures) { if (n < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -2772,7 +2811,7 @@ void __stdcall glGenTextures(GLsizei n, GLuint* textures) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -2786,7 +2825,7 @@ void __stdcall glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, { if (bufsize < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -2799,17 +2838,17 @@ void __stdcall glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, { if (context->getShader(program)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } else { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } } if (index >= (GLuint)programObject->getActiveAttributeCount()) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } programObject->getActiveAttribute(index, bufsize, length, size, type, name); @@ -2817,7 +2856,7 @@ void __stdcall glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -2831,7 +2870,7 @@ void __stdcall glGetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, { if (bufsize < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -2844,17 +2883,17 @@ void __stdcall glGetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, { if (context->getShader(program)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } else { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } } if (index >= (GLuint)programObject->getActiveUniformCount()) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } programObject->getActiveUniform(index, bufsize, length, size, type, name); @@ -2862,7 +2901,7 @@ void __stdcall glGetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -2875,7 +2914,7 @@ void __stdcall glGetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* c { if (maxcount < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -2888,11 +2927,11 @@ void __stdcall glGetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* c { if (context->getShader(program)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } else { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } } @@ -2901,7 +2940,7 @@ void __stdcall glGetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* c } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -2922,18 +2961,18 @@ int __stdcall glGetAttribLocation(GLuint program, const GLchar* name) { if (context->getShader(program)) { - return error(GL_INVALID_OPERATION, -1); + return gl::error(GL_INVALID_OPERATION, -1); } else { - return error(GL_INVALID_VALUE, -1); + return gl::error(GL_INVALID_VALUE, -1); } } gl::ProgramBinary *programBinary = programObject->getProgramBinary(); if (!programObject->isLinked() || !programBinary) { - return error(GL_INVALID_OPERATION, -1); + return gl::error(GL_INVALID_OPERATION, -1); } return programBinary->getAttributeLocation(name); @@ -2941,7 +2980,7 @@ int __stdcall glGetAttribLocation(GLuint program, const GLchar* name) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY, -1); + return gl::error(GL_OUT_OF_MEMORY, -1); } return -1; @@ -2962,7 +3001,7 @@ void __stdcall glGetBooleanv(GLenum pname, GLboolean* params) GLenum nativeType; unsigned int numParams = 0; if (!context->getQueryParameterInfo(pname, &nativeType, &numParams)) - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); if (numParams == 0) return; // it is known that the pname is valid, but there are no parameters to return @@ -3006,7 +3045,7 @@ void __stdcall glGetBooleanv(GLenum pname, GLboolean* params) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -3030,13 +3069,13 @@ void __stdcall glGetBufferParameteriv(GLenum target, GLenum pname, GLint* params case GL_ELEMENT_ARRAY_BUFFER: buffer = context->getElementArrayBuffer(); break; - default: return error(GL_INVALID_ENUM); + default: return gl::error(GL_INVALID_ENUM); } if (!buffer) { // A null buffer means that "0" is bound to the requested buffer target - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } switch (pname) @@ -3047,13 +3086,13 @@ void __stdcall glGetBufferParameteriv(GLenum target, GLenum pname, GLint* params case GL_BUFFER_SIZE: *params = buffer->size(); break; - default: return error(GL_INVALID_ENUM); + default: return gl::error(GL_INVALID_ENUM); } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -3086,7 +3125,7 @@ void __stdcall glGetFenceivNV(GLuint fence, GLenum pname, GLint *params) if (fenceObject == NULL) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } fenceObject->getFenceiv(pname, params); @@ -3094,7 +3133,7 @@ void __stdcall glGetFenceivNV(GLuint fence, GLenum pname, GLint *params) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -3113,7 +3152,7 @@ void __stdcall glGetFloatv(GLenum pname, GLfloat* params) GLenum nativeType; unsigned int numParams = 0; if (!context->getQueryParameterInfo(pname, &nativeType, &numParams)) - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); if (numParams == 0) return; // it is known that the pname is valid, but that there are no parameters to return. @@ -3154,7 +3193,7 @@ void __stdcall glGetFloatv(GLenum pname, GLfloat* params) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -3171,7 +3210,7 @@ void __stdcall glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attac { if (target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } gl::Framebuffer *framebuffer = NULL; @@ -3179,7 +3218,7 @@ void __stdcall glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attac { if(context->getReadFramebufferHandle() == 0) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } framebuffer = context->getReadFramebuffer(); @@ -3188,7 +3227,7 @@ void __stdcall glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attac { if (context->getDrawFramebufferHandle() == 0) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } framebuffer = context->getDrawFramebuffer(); @@ -3196,21 +3235,33 @@ void __stdcall glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attac GLenum attachmentType; GLuint attachmentHandle; - switch (attachment) + + if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT) { - case GL_COLOR_ATTACHMENT0: - attachmentType = framebuffer->getColorbufferType(); - attachmentHandle = framebuffer->getColorbufferHandle(); - break; - case GL_DEPTH_ATTACHMENT: - attachmentType = framebuffer->getDepthbufferType(); - attachmentHandle = framebuffer->getDepthbufferHandle(); - break; - case GL_STENCIL_ATTACHMENT: - attachmentType = framebuffer->getStencilbufferType(); - attachmentHandle = framebuffer->getStencilbufferHandle(); - break; - default: return error(GL_INVALID_ENUM); + const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT); + + if (colorAttachment >= context->getMaximumRenderTargets()) + { + return gl::error(GL_INVALID_ENUM); + } + + attachmentType = framebuffer->getColorbufferType(colorAttachment); + attachmentHandle = framebuffer->getColorbufferHandle(colorAttachment); + } + else + { + switch (attachment) + { + case GL_DEPTH_ATTACHMENT: + attachmentType = framebuffer->getDepthbufferType(); + attachmentHandle = framebuffer->getDepthbufferHandle(); + break; + case GL_STENCIL_ATTACHMENT: + attachmentType = framebuffer->getStencilbufferType(); + attachmentHandle = framebuffer->getStencilbufferHandle(); + break; + default: return gl::error(GL_INVALID_ENUM); + } } GLenum attachmentObjectType; // Type category @@ -3240,7 +3291,7 @@ void __stdcall glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attac } else { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } break; case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL: @@ -3250,7 +3301,7 @@ void __stdcall glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attac } else { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } break; case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE: @@ -3267,17 +3318,17 @@ void __stdcall glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attac } else { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -3317,7 +3368,7 @@ void __stdcall glGetIntegerv(GLenum pname, GLint* params) GLenum nativeType; unsigned int numParams = 0; if (!context->getQueryParameterInfo(pname, &nativeType, &numParams)) - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); if (numParams == 0) return; // it is known that pname is valid, but there are no parameters to return @@ -3363,7 +3414,7 @@ void __stdcall glGetIntegerv(GLenum pname, GLint* params) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -3381,7 +3432,7 @@ void __stdcall glGetProgramiv(GLuint program, GLenum pname, GLint* params) if (!programObject) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } switch (pname) @@ -3417,13 +3468,13 @@ void __stdcall glGetProgramiv(GLuint program, GLenum pname, GLint* params) *params = programObject->getProgramBinaryLength(); return; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -3436,7 +3487,7 @@ void __stdcall glGetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* len { if (bufsize < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -3447,7 +3498,7 @@ void __stdcall glGetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* len if (!programObject) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } programObject->getInfoLog(bufsize, length, infolog); @@ -3455,7 +3506,7 @@ void __stdcall glGetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* len } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -3470,7 +3521,7 @@ void __stdcall glGetQueryivEXT(GLenum target, GLenum pname, GLint *params) case GL_CURRENT_QUERY_EXT: break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } gl::Context *context = gl::getNonLostContext(); @@ -3482,7 +3533,7 @@ void __stdcall glGetQueryivEXT(GLenum target, GLenum pname, GLint *params) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -3498,7 +3549,7 @@ void __stdcall glGetQueryObjectuivEXT(GLuint id, GLenum pname, GLuint *params) case GL_QUERY_RESULT_AVAILABLE_EXT: break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } gl::Context *context = gl::getNonLostContext(); @@ -3508,12 +3559,12 @@ void __stdcall glGetQueryObjectuivEXT(GLuint id, GLenum pname, GLuint *params) if (!queryObject) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } if (context->getActiveQuery(queryObject->getType()) == id) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } switch(pname) @@ -3531,7 +3582,7 @@ void __stdcall glGetQueryObjectuivEXT(GLuint id, GLenum pname, GLuint *params) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -3547,12 +3598,12 @@ void __stdcall glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* { if (target != GL_RENDERBUFFER) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } if (context->getRenderbufferHandle() == 0) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } gl::Renderbuffer *renderbuffer = context->getRenderbuffer(context->getRenderbufferHandle()); @@ -3575,17 +3626,17 @@ void __stdcall glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* } else { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -3603,7 +3654,7 @@ void __stdcall glGetShaderiv(GLuint shader, GLenum pname, GLint* params) if (!shaderObject) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } switch (pname) @@ -3627,13 +3678,13 @@ void __stdcall glGetShaderiv(GLuint shader, GLenum pname, GLint* params) *params = shaderObject->getTranslatedSourceLength(); return; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -3646,7 +3697,7 @@ void __stdcall glGetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* lengt { if (bufsize < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -3657,7 +3708,7 @@ void __stdcall glGetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* lengt if (!shaderObject) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } shaderObject->getInfoLog(bufsize, length, infolog); @@ -3665,7 +3716,7 @@ void __stdcall glGetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* lengt } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -3682,7 +3733,7 @@ void __stdcall glGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontyp case GL_FRAGMENT_SHADER: break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } switch (precisiontype) @@ -3705,12 +3756,12 @@ void __stdcall glGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontyp *precision = 0; break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -3723,7 +3774,7 @@ void __stdcall glGetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length { if (bufsize < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -3734,7 +3785,7 @@ void __stdcall glGetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length if (!shaderObject) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } shaderObject->getSource(bufsize, length, source); @@ -3742,7 +3793,7 @@ void __stdcall glGetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -3755,7 +3806,7 @@ void __stdcall glGetTranslatedShaderSourceANGLE(GLuint shader, GLsizei bufsize, { if (bufsize < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -3766,7 +3817,7 @@ void __stdcall glGetTranslatedShaderSourceANGLE(GLuint shader, GLsizei bufsize, if (!shaderObject) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } shaderObject->getTranslatedSource(bufsize, length, source); @@ -3774,7 +3825,7 @@ void __stdcall glGetTranslatedShaderSourceANGLE(GLuint shader, GLsizei bufsize, } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -3799,12 +3850,12 @@ const GLubyte* __stdcall glGetString(GLenum name) case GL_EXTENSIONS: return (GLubyte*)((context != NULL) ? context->getExtensionString() : ""); default: - return error(GL_INVALID_ENUM, (GLubyte*)NULL); + return gl::error(GL_INVALID_ENUM, (GLubyte*)NULL); } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY, (GLubyte*)NULL); + return gl::error(GL_OUT_OF_MEMORY, (GLubyte*)NULL); } } @@ -3829,7 +3880,7 @@ void __stdcall glGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params) texture = context->getTextureCubeMap(); break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } switch (pname) @@ -3855,18 +3906,18 @@ void __stdcall glGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params) case GL_TEXTURE_MAX_ANISOTROPY_EXT: if (!context->supportsTextureFilterAnisotropy()) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } *params = (GLfloat)texture->getMaxAnisotropy(); break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -3891,7 +3942,7 @@ void __stdcall glGetTexParameteriv(GLenum target, GLenum pname, GLint* params) texture = context->getTextureCubeMap(); break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } switch (pname) @@ -3917,18 +3968,18 @@ void __stdcall glGetTexParameteriv(GLenum target, GLenum pname, GLint* params) case GL_TEXTURE_MAX_ANISOTROPY_EXT: if (!context->supportsTextureFilterAnisotropy()) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } *params = (GLint)texture->getMaxAnisotropy(); break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -3941,7 +3992,7 @@ void __stdcall glGetnUniformfvEXT(GLuint program, GLint location, GLsizei bufSiz { if (bufSize < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -3950,31 +4001,31 @@ void __stdcall glGetnUniformfvEXT(GLuint program, GLint location, GLsizei bufSiz { if (program == 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Program *programObject = context->getProgram(program); if (!programObject || !programObject->isLinked()) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } gl::ProgramBinary *programBinary = programObject->getProgramBinary(); if (!programBinary) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } if (!programBinary->getUniformfv(location, &bufSize, params)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -3990,31 +4041,31 @@ void __stdcall glGetUniformfv(GLuint program, GLint location, GLfloat* params) { if (program == 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Program *programObject = context->getProgram(program); if (!programObject || !programObject->isLinked()) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } gl::ProgramBinary *programBinary = programObject->getProgramBinary(); if (!programBinary) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } if (!programBinary->getUniformfv(location, NULL, params)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -4027,7 +4078,7 @@ void __stdcall glGetnUniformivEXT(GLuint program, GLint location, GLsizei bufSiz { if (bufSize < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -4036,31 +4087,31 @@ void __stdcall glGetnUniformivEXT(GLuint program, GLint location, GLsizei bufSiz { if (program == 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Program *programObject = context->getProgram(program); if (!programObject || !programObject->isLinked()) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } gl::ProgramBinary *programBinary = programObject->getProgramBinary(); if (!programBinary) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } if (!programBinary->getUniformiv(location, &bufSize, params)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -4076,31 +4127,31 @@ void __stdcall glGetUniformiv(GLuint program, GLint location, GLint* params) { if (program == 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Program *programObject = context->getProgram(program); if (!programObject || !programObject->isLinked()) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } gl::ProgramBinary *programBinary = programObject->getProgramBinary(); if (!programBinary) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } if (!programBinary->getUniformiv(location, NULL, params)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -4125,18 +4176,18 @@ int __stdcall glGetUniformLocation(GLuint program, const GLchar* name) { if (context->getShader(program)) { - return error(GL_INVALID_OPERATION, -1); + return gl::error(GL_INVALID_OPERATION, -1); } else { - return error(GL_INVALID_VALUE, -1); + return gl::error(GL_INVALID_VALUE, -1); } } gl::ProgramBinary *programBinary = programObject->getProgramBinary(); if (!programObject->isLinked() || !programBinary) { - return error(GL_INVALID_OPERATION, -1); + return gl::error(GL_INVALID_OPERATION, -1); } return programBinary->getUniformLocation(name); @@ -4144,7 +4195,7 @@ int __stdcall glGetUniformLocation(GLuint program, const GLchar* name) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY, -1); + return gl::error(GL_OUT_OF_MEMORY, -1); } return -1; @@ -4162,7 +4213,7 @@ void __stdcall glGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params) { if (index >= gl::MAX_VERTEX_ATTRIBS) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } const gl::VertexAttribute &attribState = context->getVertexAttribState(index); @@ -4196,13 +4247,13 @@ void __stdcall glGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params) case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE: *params = (GLfloat)attribState.mDivisor; break; - default: return error(GL_INVALID_ENUM); + default: return gl::error(GL_INVALID_ENUM); } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -4218,7 +4269,7 @@ void __stdcall glGetVertexAttribiv(GLuint index, GLenum pname, GLint* params) { if (index >= gl::MAX_VERTEX_ATTRIBS) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } const gl::VertexAttribute &attribState = context->getVertexAttribState(index); @@ -4253,13 +4304,13 @@ void __stdcall glGetVertexAttribiv(GLuint index, GLenum pname, GLint* params) case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE: *params = (GLint)attribState.mDivisor; break; - default: return error(GL_INVALID_ENUM); + default: return gl::error(GL_INVALID_ENUM); } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -4275,12 +4326,12 @@ void __stdcall glGetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid** po { if (index >= gl::MAX_VERTEX_ATTRIBS) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } *pointer = const_cast(context->getVertexAttribPointer(index)); @@ -4288,7 +4339,7 @@ void __stdcall glGetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid** po } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -4305,7 +4356,7 @@ void __stdcall glHint(GLenum target, GLenum mode) case GL_DONT_CARE: break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } gl::Context *context = gl::getNonLostContext(); @@ -4318,12 +4369,12 @@ void __stdcall glHint(GLenum target, GLenum mode) if (context) context->setFragmentShaderDerivativeHint(mode); break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -4347,7 +4398,7 @@ GLboolean __stdcall glIsBuffer(GLuint buffer) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY, GL_FALSE); + return gl::error(GL_OUT_OF_MEMORY, GL_FALSE); } return GL_FALSE; @@ -4375,13 +4426,13 @@ GLboolean __stdcall glIsEnabled(GLenum cap) case GL_BLEND: return context->isBlendEnabled(); case GL_DITHER: return context->isDitherEnabled(); default: - return error(GL_INVALID_ENUM, false); + return gl::error(GL_INVALID_ENUM, false); } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY, false); + return gl::error(GL_OUT_OF_MEMORY, false); } return false; @@ -4409,7 +4460,7 @@ GLboolean __stdcall glIsFenceNV(GLuint fence) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY, GL_FALSE); + return gl::error(GL_OUT_OF_MEMORY, GL_FALSE); } return GL_FALSE; @@ -4435,7 +4486,7 @@ GLboolean __stdcall glIsFramebuffer(GLuint framebuffer) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY, GL_FALSE); + return gl::error(GL_OUT_OF_MEMORY, GL_FALSE); } return GL_FALSE; @@ -4461,7 +4512,7 @@ GLboolean __stdcall glIsProgram(GLuint program) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY, GL_FALSE); + return gl::error(GL_OUT_OF_MEMORY, GL_FALSE); } return GL_FALSE; @@ -4492,7 +4543,7 @@ GLboolean __stdcall glIsQueryEXT(GLuint id) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY, GL_FALSE); + return gl::error(GL_OUT_OF_MEMORY, GL_FALSE); } return GL_FALSE; @@ -4518,7 +4569,7 @@ GLboolean __stdcall glIsRenderbuffer(GLuint renderbuffer) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY, GL_FALSE); + return gl::error(GL_OUT_OF_MEMORY, GL_FALSE); } return GL_FALSE; @@ -4544,7 +4595,7 @@ GLboolean __stdcall glIsShader(GLuint shader) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY, GL_FALSE); + return gl::error(GL_OUT_OF_MEMORY, GL_FALSE); } return GL_FALSE; @@ -4570,7 +4621,7 @@ GLboolean __stdcall glIsTexture(GLuint texture) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY, GL_FALSE); + return gl::error(GL_OUT_OF_MEMORY, GL_FALSE); } return GL_FALSE; @@ -4584,7 +4635,7 @@ void __stdcall glLineWidth(GLfloat width) { if (width <= 0.0f) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -4596,7 +4647,7 @@ void __stdcall glLineWidth(GLfloat width) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -4616,11 +4667,11 @@ void __stdcall glLinkProgram(GLuint program) { if (context->getShader(program)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } else { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } } @@ -4629,7 +4680,7 @@ void __stdcall glLinkProgram(GLuint program) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -4648,7 +4699,7 @@ void __stdcall glPixelStorei(GLenum pname, GLint param) case GL_UNPACK_ALIGNMENT: if (param != 1 && param != 2 && param != 4 && param != 8) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } context->setUnpackAlignment(param); @@ -4657,7 +4708,7 @@ void __stdcall glPixelStorei(GLenum pname, GLint param) case GL_PACK_ALIGNMENT: if (param != 1 && param != 2 && param != 4 && param != 8) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } context->setPackAlignment(param); @@ -4668,13 +4719,13 @@ void __stdcall glPixelStorei(GLenum pname, GLint param) break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -4693,7 +4744,7 @@ void __stdcall glPolygonOffset(GLfloat factor, GLfloat units) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -4709,7 +4760,7 @@ void __stdcall glReadnPixelsEXT(GLint x, GLint y, GLsizei width, GLsizei height, { if (width < 0 || height < 0 || bufSize < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -4726,7 +4777,7 @@ void __stdcall glReadnPixelsEXT(GLint x, GLint y, GLsizei width, GLsizei height, if (!(currentFormat == format && currentType == type) && !validReadFormatType(format, type)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } context->readPixels(x, y, width, height, format, type, &bufSize, data); @@ -4734,7 +4785,7 @@ void __stdcall glReadnPixelsEXT(GLint x, GLint y, GLsizei width, GLsizei height, } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -4749,7 +4800,7 @@ void __stdcall glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, { if (width < 0 || height < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -4766,7 +4817,7 @@ void __stdcall glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, if (!(currentFormat == format && currentType == type) && !validReadFormatType(format, type)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } context->readPixels(x, y, width, height, format, type, NULL, pixels); @@ -4774,7 +4825,7 @@ void __stdcall glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -4788,7 +4839,7 @@ void __stdcall glReleaseShaderCompiler(void) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -4804,17 +4855,17 @@ void __stdcall glRenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samp case GL_RENDERBUFFER: break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } if (!gl::IsColorRenderable(internalformat) && !gl::IsDepthRenderable(internalformat) && !gl::IsStencilRenderable(internalformat)) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } if (width < 0 || height < 0 || samples < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -4825,41 +4876,35 @@ void __stdcall glRenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samp height > context->getMaximumRenderbufferDimension() || samples > context->getMaxSupportedSamples()) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } GLuint handle = context->getRenderbufferHandle(); if (handle == 0) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } switch (internalformat) { case GL_DEPTH_COMPONENT16: - context->setRenderbufferStorage(new gl::Depthbuffer(width, height, samples)); - break; case GL_RGBA4: case GL_RGB5_A1: case GL_RGB565: case GL_RGB8_OES: case GL_RGBA8_OES: - context->setRenderbufferStorage(new gl::Colorbuffer(width, height, internalformat, samples)); - break; case GL_STENCIL_INDEX8: - context->setRenderbufferStorage(new gl::Stencilbuffer(width, height, samples)); - break; case GL_DEPTH24_STENCIL8_OES: - context->setRenderbufferStorage(new gl::DepthStencilbuffer(width, height, samples)); + context->setRenderbufferStorage(width, height, internalformat, samples); break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -4883,7 +4928,7 @@ void __stdcall glSampleCoverage(GLclampf value, GLboolean invert) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -4895,7 +4940,7 @@ void __stdcall glSetFenceNV(GLuint fence, GLenum condition) { if (condition != GL_ALL_COMPLETED_NV) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } gl::Context *context = gl::getNonLostContext(); @@ -4906,7 +4951,7 @@ void __stdcall glSetFenceNV(GLuint fence, GLenum condition) if (fenceObject == NULL) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } fenceObject->setFence(condition); @@ -4914,7 +4959,7 @@ void __stdcall glSetFenceNV(GLuint fence, GLenum condition) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -4926,7 +4971,7 @@ void __stdcall glScissor(GLint x, GLint y, GLsizei width, GLsizei height) { if (width < 0 || height < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context* context = gl::getNonLostContext(); @@ -4938,7 +4983,7 @@ void __stdcall glScissor(GLint x, GLint y, GLsizei width, GLsizei height) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -4951,11 +4996,11 @@ void __stdcall glShaderBinary(GLsizei n, const GLuint* shaders, GLenum binaryfor try { // No binary shader formats are supported. - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -4968,7 +5013,7 @@ void __stdcall glShaderSource(GLuint shader, GLsizei count, const GLchar** strin { if (count < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -4981,11 +5026,11 @@ void __stdcall glShaderSource(GLuint shader, GLsizei count, const GLchar** strin { if (context->getProgram(shader)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } else { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } } @@ -4994,7 +5039,7 @@ void __stdcall glShaderSource(GLuint shader, GLsizei count, const GLchar** strin } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -5016,7 +5061,7 @@ void __stdcall glStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint case GL_FRONT_AND_BACK: break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } switch (func) @@ -5031,7 +5076,7 @@ void __stdcall glStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint case GL_NOTEQUAL: break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } gl::Context *context = gl::getNonLostContext(); @@ -5051,7 +5096,7 @@ void __stdcall glStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -5073,7 +5118,7 @@ void __stdcall glStencilMaskSeparate(GLenum face, GLuint mask) case GL_FRONT_AND_BACK: break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } gl::Context *context = gl::getNonLostContext(); @@ -5093,7 +5138,7 @@ void __stdcall glStencilMaskSeparate(GLenum face, GLuint mask) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -5116,7 +5161,7 @@ void __stdcall glStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenu case GL_FRONT_AND_BACK: break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } switch (fail) @@ -5131,7 +5176,7 @@ void __stdcall glStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenu case GL_DECR_WRAP: break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } switch (zfail) @@ -5146,7 +5191,7 @@ void __stdcall glStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenu case GL_DECR_WRAP: break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } switch (zpass) @@ -5161,7 +5206,7 @@ void __stdcall glStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenu case GL_DECR_WRAP: break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } gl::Context *context = gl::getNonLostContext(); @@ -5181,7 +5226,7 @@ void __stdcall glStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenu } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -5199,7 +5244,7 @@ GLboolean __stdcall glTestFenceNV(GLuint fence) if (fenceObject == NULL) { - return error(GL_INVALID_OPERATION, GL_TRUE); + return gl::error(GL_INVALID_OPERATION, GL_TRUE); } return fenceObject->testFence(); @@ -5207,7 +5252,7 @@ GLboolean __stdcall glTestFenceNV(GLuint fence) } catch(std::bad_alloc&) { - error(GL_OUT_OF_MEMORY); + gl::error(GL_OUT_OF_MEMORY); } return GL_TRUE; @@ -5224,12 +5269,12 @@ void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GL { if (!validImageSize(level, width, height)) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } if (internalformat != GLint(format)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } // validate by itself (used as secondary key below) @@ -5246,7 +5291,7 @@ void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GL case GL_FLOAT: break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } // validate + combinations @@ -5264,7 +5309,7 @@ void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GL case GL_HALF_FLOAT_OES: break; default: - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } break; case GL_RGB: @@ -5276,7 +5321,7 @@ void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GL case GL_HALF_FLOAT_OES: break; default: - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } break; case GL_RGBA: @@ -5289,7 +5334,7 @@ void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GL case GL_HALF_FLOAT_OES: break; default: - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } break; case GL_BGRA_EXT: @@ -5298,7 +5343,7 @@ void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GL case GL_UNSIGNED_BYTE: break; default: - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } break; case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: // error cases for compressed textures are handled below @@ -5313,7 +5358,7 @@ void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GL case GL_UNSIGNED_INT: break; default: - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } break; case GL_DEPTH_STENCIL_OES: @@ -5322,16 +5367,16 @@ void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GL case GL_UNSIGNED_INT_24_8_OES: break; default: - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } if (border != 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -5340,7 +5385,7 @@ void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GL { if (level > context->getMaximumTextureLevel()) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } switch (target) @@ -5349,7 +5394,7 @@ void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GL if (width > (context->getMaximumTextureDimension() >> level) || height > (context->getMaximumTextureDimension() >> level)) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } break; case GL_TEXTURE_CUBE_MAP_POSITIVE_X: @@ -5360,17 +5405,17 @@ void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GL case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: if (width != height) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } if (width > (context->getMaximumCubeTextureDimension() >> level) || height > (context->getMaximumCubeTextureDimension() >> level)) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } switch (format) { @@ -5378,48 +5423,48 @@ void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GL case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: if (context->supportsDXT1Textures()) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } else { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } break; case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: if (context->supportsDXT3Textures()) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } else { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } break; case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: if (context->supportsDXT5Textures()) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } else { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } break; case GL_DEPTH_COMPONENT: case GL_DEPTH_STENCIL_OES: if (!context->supportsDepthTextures()) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } if (target != GL_TEXTURE_2D) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } // OES_depth_texture supports loading depth data and multiple levels, // but ANGLE_depth_texture does not if (pixels != NULL || level != 0) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } break; default: @@ -5430,14 +5475,14 @@ void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GL { if (!context->supportsFloat32Textures()) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } } else if (type == GL_HALF_FLOAT_OES) { if (!context->supportsFloat16Textures()) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } } @@ -5447,12 +5492,12 @@ void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GL if (!texture) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } if (texture->isImmutable()) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } texture->setImage(level, width, height, format, type, context->getUnpackAlignment(), pixels); @@ -5463,12 +5508,12 @@ void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GL if (!texture) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } if (texture->isImmutable()) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } switch (target) @@ -5498,7 +5543,7 @@ void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GL } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -5523,7 +5568,7 @@ void __stdcall glTexParameterf(GLenum target, GLenum pname, GLfloat param) texture = context->getTextureCubeMap(); break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } switch (pname) @@ -5531,51 +5576,51 @@ void __stdcall glTexParameterf(GLenum target, GLenum pname, GLfloat param) case GL_TEXTURE_WRAP_S: if (!texture->setWrapS((GLenum)param)) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } break; case GL_TEXTURE_WRAP_T: if (!texture->setWrapT((GLenum)param)) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } break; case GL_TEXTURE_MIN_FILTER: if (!texture->setMinFilter((GLenum)param)) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } break; case GL_TEXTURE_MAG_FILTER: if (!texture->setMagFilter((GLenum)param)) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } break; case GL_TEXTURE_USAGE_ANGLE: if (!texture->setUsage((GLenum)param)) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } break; case GL_TEXTURE_MAX_ANISOTROPY_EXT: if (!context->supportsTextureFilterAnisotropy()) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } if (!texture->setMaxAnisotropy((float)param, context->getTextureMaxAnisotropy())) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -5605,7 +5650,7 @@ void __stdcall glTexParameteri(GLenum target, GLenum pname, GLint param) texture = context->getTextureCubeMap(); break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } switch (pname) @@ -5613,51 +5658,51 @@ void __stdcall glTexParameteri(GLenum target, GLenum pname, GLint param) case GL_TEXTURE_WRAP_S: if (!texture->setWrapS((GLenum)param)) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } break; case GL_TEXTURE_WRAP_T: if (!texture->setWrapT((GLenum)param)) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } break; case GL_TEXTURE_MIN_FILTER: if (!texture->setMinFilter((GLenum)param)) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } break; case GL_TEXTURE_MAG_FILTER: if (!texture->setMagFilter((GLenum)param)) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } break; case GL_TEXTURE_USAGE_ANGLE: if (!texture->setUsage((GLenum)param)) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } break; case GL_TEXTURE_MAX_ANISOTROPY_EXT: if (!context->supportsTextureFilterAnisotropy()) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } if (!texture->setMaxAnisotropy((float)param, context->getTextureMaxAnisotropy())) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -5675,22 +5720,22 @@ void __stdcall glTexStorage2DEXT(GLenum target, GLsizei levels, GLenum internalf { if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } if (width < 1 || height < 1 || levels < 1) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } if (target == GL_TEXTURE_CUBE_MAP && width != height) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } if (levels != 1 && levels != gl::log2(std::max(width, height)) + 1) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } GLenum format = gl::ExtractFormat(internalformat); @@ -5698,7 +5743,7 @@ void __stdcall glTexStorage2DEXT(GLenum target, GLsizei levels, GLenum internalf if (format == GL_NONE || type == GL_NONE) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } gl::Context *context = gl::getNonLostContext(); @@ -5711,25 +5756,25 @@ void __stdcall glTexStorage2DEXT(GLenum target, GLsizei levels, GLenum internalf if (width > context->getMaximumTextureDimension() || height > context->getMaximumTextureDimension()) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } break; case GL_TEXTURE_CUBE_MAP: if (width > context->getMaximumCubeTextureDimension() || height > context->getMaximumCubeTextureDimension()) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } if (levels != 1 && !context->supportsNonPower2Texture()) { if (!gl::isPow2(width) || !gl::isPow2(height)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } } @@ -5739,19 +5784,19 @@ void __stdcall glTexStorage2DEXT(GLenum target, GLsizei levels, GLenum internalf case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: if (!context->supportsDXT1Textures()) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } break; case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: if (!context->supportsDXT3Textures()) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } break; case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: if (!context->supportsDXT5Textures()) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } break; case GL_RGBA32F_EXT: @@ -5761,7 +5806,7 @@ void __stdcall glTexStorage2DEXT(GLenum target, GLsizei levels, GLenum internalf case GL_LUMINANCE_ALPHA32F_EXT: if (!context->supportsFloat32Textures()) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } break; case GL_RGBA16F_EXT: @@ -5771,7 +5816,7 @@ void __stdcall glTexStorage2DEXT(GLenum target, GLsizei levels, GLenum internalf case GL_LUMINANCE_ALPHA16F_EXT: if (!context->supportsFloat16Textures()) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } break; case GL_DEPTH_COMPONENT16: @@ -5779,16 +5824,16 @@ void __stdcall glTexStorage2DEXT(GLenum target, GLsizei levels, GLenum internalf case GL_DEPTH24_STENCIL8_OES: if (!context->supportsDepthTextures()) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } if (target != GL_TEXTURE_2D) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } // ANGLE_depth_texture only supports 1-level textures if (levels != 1) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } break; default: @@ -5801,12 +5846,12 @@ void __stdcall glTexStorage2DEXT(GLenum target, GLsizei levels, GLenum internalf if (!texture || texture->id() == 0) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } if (texture->isImmutable()) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } texture->storage(levels, internalformat, width, height); @@ -5817,12 +5862,12 @@ void __stdcall glTexStorage2DEXT(GLenum target, GLsizei levels, GLenum internalf if (!texture || texture->id() == 0) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } if (texture->isImmutable()) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } texture->storage(levels, internalformat, width); @@ -5832,7 +5877,7 @@ void __stdcall glTexStorage2DEXT(GLenum target, GLsizei levels, GLenum internalf } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -5848,17 +5893,17 @@ void __stdcall glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint { if (!gl::IsInternalTextureTarget(target)) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } if (level < 0 || xoffset < 0 || yoffset < 0 || width < 0 || height < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } if (std::numeric_limits::max() - xoffset < width || std::numeric_limits::max() - yoffset < height) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } if (!checkTextureFormatType(format, type)) @@ -5872,35 +5917,35 @@ void __stdcall glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint { if (level > context->getMaximumTextureLevel()) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } if (format == GL_FLOAT) { if (!context->supportsFloat32Textures()) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } } else if (format == GL_HALF_FLOAT_OES) { if (!context->supportsFloat16Textures()) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } } else if (gl::IsDepthTexture(format)) { if (!context->supportsDepthTextures()) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } if (target != GL_TEXTURE_2D) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } // OES_depth_texture supports loading depth data, but ANGLE_depth_texture does not - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } if (width == 0 || height == 0 || pixels == NULL) @@ -5932,7 +5977,7 @@ void __stdcall glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -5949,7 +5994,7 @@ void __stdcall glUniform1fv(GLint location, GLsizei count, const GLfloat* v) { if (count < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } if (location == -1) @@ -5964,18 +6009,18 @@ void __stdcall glUniform1fv(GLint location, GLsizei count, const GLfloat* v) gl::ProgramBinary *programBinary = context->getCurrentProgramBinary(); if (!programBinary) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } if (!programBinary->setUniform1fv(location, count, v)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -5992,7 +6037,7 @@ void __stdcall glUniform1iv(GLint location, GLsizei count, const GLint* v) { if (count < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } if (location == -1) @@ -6007,18 +6052,18 @@ void __stdcall glUniform1iv(GLint location, GLsizei count, const GLint* v) gl::ProgramBinary *programBinary = context->getCurrentProgramBinary(); if (!programBinary) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } if (!programBinary->setUniform1iv(location, count, v)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -6037,7 +6082,7 @@ void __stdcall glUniform2fv(GLint location, GLsizei count, const GLfloat* v) { if (count < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } if (location == -1) @@ -6052,18 +6097,18 @@ void __stdcall glUniform2fv(GLint location, GLsizei count, const GLfloat* v) gl::ProgramBinary *programBinary = context->getCurrentProgramBinary(); if (!programBinary) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } if (!programBinary->setUniform2fv(location, count, v)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -6082,7 +6127,7 @@ void __stdcall glUniform2iv(GLint location, GLsizei count, const GLint* v) { if (count < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } if (location == -1) @@ -6097,18 +6142,18 @@ void __stdcall glUniform2iv(GLint location, GLsizei count, const GLint* v) gl::ProgramBinary *programBinary = context->getCurrentProgramBinary(); if (!programBinary) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } if (!programBinary->setUniform2iv(location, count, v)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -6127,7 +6172,7 @@ void __stdcall glUniform3fv(GLint location, GLsizei count, const GLfloat* v) { if (count < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } if (location == -1) @@ -6142,18 +6187,18 @@ void __stdcall glUniform3fv(GLint location, GLsizei count, const GLfloat* v) gl::ProgramBinary *programBinary = context->getCurrentProgramBinary(); if (!programBinary) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } if (!programBinary->setUniform3fv(location, count, v)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -6172,7 +6217,7 @@ void __stdcall glUniform3iv(GLint location, GLsizei count, const GLint* v) { if (count < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } if (location == -1) @@ -6187,18 +6232,18 @@ void __stdcall glUniform3iv(GLint location, GLsizei count, const GLint* v) gl::ProgramBinary *programBinary = context->getCurrentProgramBinary(); if (!programBinary) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } if (!programBinary->setUniform3iv(location, count, v)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -6217,7 +6262,7 @@ void __stdcall glUniform4fv(GLint location, GLsizei count, const GLfloat* v) { if (count < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } if (location == -1) @@ -6232,18 +6277,18 @@ void __stdcall glUniform4fv(GLint location, GLsizei count, const GLfloat* v) gl::ProgramBinary *programBinary = context->getCurrentProgramBinary(); if (!programBinary) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } if (!programBinary->setUniform4fv(location, count, v)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -6262,7 +6307,7 @@ void __stdcall glUniform4iv(GLint location, GLsizei count, const GLint* v) { if (count < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } if (location == -1) @@ -6277,18 +6322,18 @@ void __stdcall glUniform4iv(GLint location, GLsizei count, const GLint* v) gl::ProgramBinary *programBinary = context->getCurrentProgramBinary(); if (!programBinary) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } if (!programBinary->setUniform4iv(location, count, v)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -6301,7 +6346,7 @@ void __stdcall glUniformMatrix2fv(GLint location, GLsizei count, GLboolean trans { if (count < 0 || transpose != GL_FALSE) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } if (location == -1) @@ -6316,18 +6361,18 @@ void __stdcall glUniformMatrix2fv(GLint location, GLsizei count, GLboolean trans gl::ProgramBinary *programBinary = context->getCurrentProgramBinary(); if (!programBinary) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } if (!programBinary->setUniformMatrix2fv(location, count, value)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -6340,7 +6385,7 @@ void __stdcall glUniformMatrix3fv(GLint location, GLsizei count, GLboolean trans { if (count < 0 || transpose != GL_FALSE) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } if (location == -1) @@ -6355,18 +6400,18 @@ void __stdcall glUniformMatrix3fv(GLint location, GLsizei count, GLboolean trans gl::ProgramBinary *programBinary = context->getCurrentProgramBinary(); if (!programBinary) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } if (!programBinary->setUniformMatrix3fv(location, count, value)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -6379,7 +6424,7 @@ void __stdcall glUniformMatrix4fv(GLint location, GLsizei count, GLboolean trans { if (count < 0 || transpose != GL_FALSE) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } if (location == -1) @@ -6394,18 +6439,18 @@ void __stdcall glUniformMatrix4fv(GLint location, GLsizei count, GLboolean trans gl::ProgramBinary *programBinary = context->getCurrentProgramBinary(); if (!programBinary) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } if (!programBinary->setUniformMatrix4fv(location, count, value)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } } } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -6425,17 +6470,17 @@ void __stdcall glUseProgram(GLuint program) { if (context->getShader(program)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } else { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } } if (program != 0 && !programObject->isLinked()) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } context->useProgram(program); @@ -6443,7 +6488,7 @@ void __stdcall glUseProgram(GLuint program) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -6463,11 +6508,11 @@ void __stdcall glValidateProgram(GLuint program) { if (context->getShader(program)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } else { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } } @@ -6476,7 +6521,7 @@ void __stdcall glValidateProgram(GLuint program) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -6488,7 +6533,7 @@ void __stdcall glVertexAttrib1f(GLuint index, GLfloat x) { if (index >= gl::MAX_VERTEX_ATTRIBS) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -6501,7 +6546,7 @@ void __stdcall glVertexAttrib1f(GLuint index, GLfloat x) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -6513,7 +6558,7 @@ void __stdcall glVertexAttrib1fv(GLuint index, const GLfloat* values) { if (index >= gl::MAX_VERTEX_ATTRIBS) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -6526,7 +6571,7 @@ void __stdcall glVertexAttrib1fv(GLuint index, const GLfloat* values) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -6538,7 +6583,7 @@ void __stdcall glVertexAttrib2f(GLuint index, GLfloat x, GLfloat y) { if (index >= gl::MAX_VERTEX_ATTRIBS) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -6551,7 +6596,7 @@ void __stdcall glVertexAttrib2f(GLuint index, GLfloat x, GLfloat y) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -6563,7 +6608,7 @@ void __stdcall glVertexAttrib2fv(GLuint index, const GLfloat* values) { if (index >= gl::MAX_VERTEX_ATTRIBS) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -6576,7 +6621,7 @@ void __stdcall glVertexAttrib2fv(GLuint index, const GLfloat* values) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -6588,7 +6633,7 @@ void __stdcall glVertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z) { if (index >= gl::MAX_VERTEX_ATTRIBS) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -6601,7 +6646,7 @@ void __stdcall glVertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -6613,7 +6658,7 @@ void __stdcall glVertexAttrib3fv(GLuint index, const GLfloat* values) { if (index >= gl::MAX_VERTEX_ATTRIBS) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -6626,7 +6671,7 @@ void __stdcall glVertexAttrib3fv(GLuint index, const GLfloat* values) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -6638,7 +6683,7 @@ void __stdcall glVertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, G { if (index >= gl::MAX_VERTEX_ATTRIBS) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -6651,7 +6696,7 @@ void __stdcall glVertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, G } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -6663,7 +6708,7 @@ void __stdcall glVertexAttrib4fv(GLuint index, const GLfloat* values) { if (index >= gl::MAX_VERTEX_ATTRIBS) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -6675,7 +6720,7 @@ void __stdcall glVertexAttrib4fv(GLuint index, const GLfloat* values) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -6687,7 +6732,7 @@ void __stdcall glVertexAttribDivisorANGLE(GLuint index, GLuint divisor) { if (index >= gl::MAX_VERTEX_ATTRIBS) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -6699,7 +6744,7 @@ void __stdcall glVertexAttribDivisorANGLE(GLuint index, GLuint divisor) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -6713,12 +6758,12 @@ void __stdcall glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLbo { if (index >= gl::MAX_VERTEX_ATTRIBS) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } if (size < 1 || size > 4) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } switch (type) @@ -6731,12 +6776,12 @@ void __stdcall glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLbo case GL_FLOAT: break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } if (stride < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -6748,7 +6793,7 @@ void __stdcall glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLbo } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -6760,7 +6805,7 @@ void __stdcall glViewport(GLint x, GLint y, GLsizei width, GLsizei height) { if (width < 0 || height < 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } gl::Context *context = gl::getNonLostContext(); @@ -6772,7 +6817,7 @@ void __stdcall glViewport(GLint x, GLint y, GLsizei width, GLsizei height) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -6791,18 +6836,18 @@ void __stdcall glBlitFramebufferANGLE(GLint srcX0, GLint srcY0, GLint srcX1, GLi case GL_NEAREST: break; default: - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0) { - return error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE); } if (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0) { ERR("Scaling and flipping in BlitFramebufferANGLE not supported by this implementation"); - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } gl::Context *context = gl::getNonLostContext(); @@ -6812,7 +6857,7 @@ void __stdcall glBlitFramebufferANGLE(GLint srcX0, GLint srcY0, GLint srcX1, GLi if (context->getReadFramebufferHandle() == context->getDrawFramebufferHandle()) { ERR("Blits with the same source and destination framebuffer are not supported by this implementation."); - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask); @@ -6820,7 +6865,7 @@ void __stdcall glBlitFramebufferANGLE(GLint srcX0, GLint srcY0, GLint srcX1, GLi } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -6838,7 +6883,7 @@ void __stdcall glTexImage3DOES(GLenum target, GLint level, GLenum internalformat } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -6858,19 +6903,19 @@ void __stdcall glGetProgramBinaryOES(GLuint program, GLsizei bufSize, GLsizei *l if (!programObject || !programObject->isLinked()) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } gl::ProgramBinary *programBinary = programObject->getProgramBinary(); if (!programBinary) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } if (!programBinary->save(binary, bufSize, length)) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } *binaryFormat = GL_PROGRAM_BINARY_ANGLE; @@ -6878,7 +6923,7 @@ void __stdcall glGetProgramBinaryOES(GLuint program, GLsizei bufSize, GLsizei *l } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); } } @@ -6896,14 +6941,14 @@ void __stdcall glProgramBinaryOES(GLuint program, GLenum binaryFormat, { if (binaryFormat != GL_PROGRAM_BINARY_ANGLE) { - return error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } gl::Program *programObject = context->getProgram(program); if (!programObject) { - return error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION); } context->setProgramBinary(program, binary, length); @@ -6911,7 +6956,63 @@ void __stdcall glProgramBinaryOES(GLuint program, GLenum binaryFormat, } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY); + return gl::error(GL_OUT_OF_MEMORY); + } +} + +void __stdcall glDrawBuffersEXT(GLsizei n, const GLenum *bufs) +{ + EVENT("(GLenum n = %d, bufs = 0x%0.8p)", n, bufs); + + try + { + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (n < 0 || (unsigned int)n > context->getMaximumRenderTargets()) + { + return gl::error(GL_INVALID_VALUE); + } + + if (context->getDrawFramebufferHandle() == 0) + { + if (n > 1) + { + return gl::error(GL_INVALID_OPERATION); + } + + if (n == 1) + { + if (bufs[0] != GL_NONE && bufs[0] != GL_BACK) + { + return gl::error(GL_INVALID_OPERATION); + } + } + } + else + { + for (int colorAttachment = 0; colorAttachment < n; colorAttachment++) + { + const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment; + if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment) + { + return gl::error(GL_INVALID_OPERATION); + } + } + } + + gl::Framebuffer *framebuffer = context->getDrawFramebuffer(); + + for (int colorAttachment = 0; colorAttachment < n; colorAttachment++) + { + framebuffer->setDrawBufferState(colorAttachment, bufs[colorAttachment]); + } + } + } + catch (std::bad_alloc&) + { + return gl::error(GL_OUT_OF_MEMORY); } } @@ -6948,13 +7049,14 @@ __eglMustCastToProperFunctionPointerType __stdcall glGetProcAddress(const char * {"glEndQueryEXT", (__eglMustCastToProperFunctionPointerType)glEndQueryEXT}, {"glGetQueryivEXT", (__eglMustCastToProperFunctionPointerType)glGetQueryivEXT}, {"glGetQueryObjectuivEXT", (__eglMustCastToProperFunctionPointerType)glGetQueryObjectuivEXT}, + {"glDrawBuffersEXT", (__eglMustCastToProperFunctionPointerType)glDrawBuffersEXT}, {"glVertexAttribDivisorANGLE", (__eglMustCastToProperFunctionPointerType)glVertexAttribDivisorANGLE}, {"glDrawArraysInstancedANGLE", (__eglMustCastToProperFunctionPointerType)glDrawArraysInstancedANGLE}, {"glDrawElementsInstancedANGLE", (__eglMustCastToProperFunctionPointerType)glDrawElementsInstancedANGLE}, {"glGetProgramBinaryOES", (__eglMustCastToProperFunctionPointerType)glGetProgramBinaryOES}, {"glProgramBinaryOES", (__eglMustCastToProperFunctionPointerType)glProgramBinaryOES}, }; - for (int ext = 0; ext < sizeof(glExtensions) / sizeof(Extension); ext++) + for (unsigned int ext = 0; ext < ArraySize(glExtensions); ext++) { if (strcmp(procname, glExtensions[ext].name) == 0) { @@ -6993,7 +7095,7 @@ bool __stdcall glBindTexImage(egl::Surface *surface) } catch(std::bad_alloc&) { - return error(GL_OUT_OF_MEMORY, false); + return gl::error(GL_OUT_OF_MEMORY, false); } return true; diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2.def b/src/3rdparty/angle/src/libGLESv2/libGLESv2.def index 5f935c3733..71398b3142 100644 --- a/src/3rdparty/angle/src/libGLESv2/libGLESv2.def +++ b/src/3rdparty/angle/src/libGLESv2/libGLESv2.def @@ -172,6 +172,7 @@ EXPORTS glDrawElementsInstancedANGLE @174 glProgramBinaryOES @175 glGetProgramBinaryOES @176 + glDrawBuffersEXT @179 ; EGL dependencies glCreateContext @144 NONAME @@ -180,3 +181,5 @@ EXPORTS glGetCurrentContext @147 NONAME glGetProcAddress @148 NONAME glBindTexImage @158 NONAME + glCreateRenderer @177 NONAME + glDestroyRenderer @178 NONAME \ No newline at end of file diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2d.def b/src/3rdparty/angle/src/libGLESv2/libGLESv2d.def index c20864aa31..2b3b34009e 100644 --- a/src/3rdparty/angle/src/libGLESv2/libGLESv2d.def +++ b/src/3rdparty/angle/src/libGLESv2/libGLESv2d.def @@ -180,3 +180,5 @@ EXPORTS glGetCurrentContext @147 NONAME glGetProcAddress @148 NONAME glBindTexImage @158 NONAME + glCreateRenderer @177 NONAME + glDestroyRenderer @178 NONAME diff --git a/src/3rdparty/angle/src/libGLESv2/main.cpp b/src/3rdparty/angle/src/libGLESv2/main.cpp index 3853e41c23..5d23e8e70f 100644 --- a/src/3rdparty/angle/src/libGLESv2/main.cpp +++ b/src/3rdparty/angle/src/libGLESv2/main.cpp @@ -1,3 +1,4 @@ +#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 @@ -7,12 +8,8 @@ // main.cpp: DLL entry point and management of thread-local data. #include "libGLESv2/main.h" -#include "libGLESv2/utilities.h" -#include "common/debug.h" -#include "libEGL/Surface.h" - -#include "libGLESv2/Framebuffer.h" +#include "libGLESv2/Context.h" #ifndef QT_OPENGL_ES_2_ANGLE_STATIC @@ -101,7 +98,7 @@ void makeCurrent(Context *context, egl::Display *display, egl::Surface *surface) if (context && display && surface) { - context->makeCurrent(display, surface); + context->makeCurrent(surface); } } @@ -118,7 +115,7 @@ Context *getNonLostContext() { if (context->isContextLost()) { - error(GL_OUT_OF_MEMORY); + gl::error(GL_OUT_OF_MEMORY); return NULL; } else @@ -134,27 +131,6 @@ egl::Display *getDisplay() return current()->display; } -IDirect3DDevice9 *getDevice() -{ - egl::Display *display = getDisplay(); - - return display->getDevice(); -} - -bool checkDeviceLost(HRESULT errorCode) -{ - egl::Display *display = NULL; - - if (isDeviceLostError(errorCode)) - { - display = gl::getDisplay(); - display->notifyDeviceLost(); - return true; - } - return false; -} -} - // Records an error code void error(GLenum errorCode) { @@ -188,3 +164,6 @@ void error(GLenum errorCode) } } } + +} + diff --git a/src/3rdparty/angle/src/libGLESv2/main.h b/src/3rdparty/angle/src/libGLESv2/main.h index 504848aa65..9168a2212e 100644 --- a/src/3rdparty/angle/src/libGLESv2/main.h +++ b/src/3rdparty/angle/src/libGLESv2/main.h @@ -9,17 +9,19 @@ #ifndef LIBGLESV2_MAIN_H_ #define LIBGLESV2_MAIN_H_ -#define GL_APICALL -#include -#include - #include "common/debug.h" -#include "libEGL/Display.h" +#include "common/system.h" -#include "libGLESv2/Context.h" +namespace egl +{ +class Display; +class Surface; +} namespace gl { +class Context; + struct Current { Context *context; @@ -32,11 +34,6 @@ Context *getContext(); Context *getNonLostContext(); egl::Display *getDisplay(); -IDirect3DDevice9 *getDevice(); - -bool checkDeviceLost(HRESULT errorCode); -} - void error(GLenum errorCode); template @@ -47,4 +44,25 @@ const T &error(GLenum errorCode, const T &returnValue) return returnValue; } +} + +namespace rx +{ +class Renderer; +} + +extern "C" +{ +// Exported functions for use by EGL +gl::Context *glCreateContext(const gl::Context *shareContext, rx::Renderer *renderer, bool notifyResets, bool robustAccess); +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, bool softwareDevice); +void glDestroyRenderer(rx::Renderer *renderer); + +__eglMustCastToProperFunctionPointerType __stdcall glGetProcAddress(const char *procname); +bool __stdcall glBindTexImage(egl::Surface *surface); +} + #endif // LIBGLESV2_MAIN_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/mathutil.h b/src/3rdparty/angle/src/libGLESv2/mathutil.h index 790ecd89fa..672c443c11 100644 --- a/src/3rdparty/angle/src/libGLESv2/mathutil.h +++ b/src/3rdparty/angle/src/libGLESv2/mathutil.h @@ -9,9 +9,8 @@ #ifndef LIBGLESV2_MATHUTIL_H_ #define LIBGLESV2_MATHUTIL_H_ -#include -#include -#include +#include "common/system.h" +#include "common/debug.h" namespace gl { @@ -54,7 +53,8 @@ inline unsigned int ceilPow2(unsigned int x) template inline T clamp(T x, MIN min, MAX max) { - return x < min ? min : (x > max ? max : x); + // Since NaNs fail all comparison tests, a NaN value will default to min + return x > min ? (x > max ? max : x) : min; } inline float clamp01(float x) @@ -142,4 +142,18 @@ float float16ToFloat32(unsigned short h); } +namespace rx +{ + +struct Range +{ + Range() {} + Range(int lo, int hi) : start(lo), end(hi) { ASSERT(lo <= hi); } + + int start; + int end; +}; + +} + #endif // LIBGLESV2_MATHUTIL_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/precompiled.cpp b/src/3rdparty/angle/src/libGLESv2/precompiled.cpp new file mode 100644 index 0000000000..2621cd6ce3 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/precompiled.cpp @@ -0,0 +1,9 @@ +// +// 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. +// + +// precompiled.cpp: Precompiled header source file for libGLESv2. + +#include "precompiled.h" diff --git a/src/3rdparty/angle/src/libGLESv2/precompiled.h b/src/3rdparty/angle/src/libGLESv2/precompiled.h new file mode 100644 index 0000000000..b8b043c964 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/precompiled.h @@ -0,0 +1,45 @@ +// +// 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. +// + +// precompiled.h: Precompiled header file for libGLESv2. + +#define GL_APICALL +#include +#include + +#define EGLAPI +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include // for std::min and std::max +#include +#include +#include +#include +#include +#include +#include + +#if defined(ANGLE_ENABLE_D3D11) +# include +# include +#else +# include +#endif +#include + +#ifdef _MSC_VER +#include +#endif diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Blit.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/Blit.cpp new file mode 100644 index 0000000000..2a3ce39c63 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/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/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 new file mode 100644 index 0000000000..3718028e66 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/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/BufferStorage.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage.cpp new file mode 100644 index 0000000000..a49b7bab84 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage.cpp @@ -0,0 +1,40 @@ +#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. +// + +// BufferStorage.cpp Defines the abstract BufferStorage class. + +#include "libGLESv2/renderer/BufferStorage.h" + +namespace rx +{ + +unsigned int BufferStorage::mNextSerial = 1; + +BufferStorage::BufferStorage() +{ + updateSerial(); +} + +BufferStorage::~BufferStorage() +{ +} + +unsigned int BufferStorage::getSerial() const +{ + return mSerial; +} + +void BufferStorage::updateSerial() +{ + mSerial = mNextSerial++; +} + +void BufferStorage::markBufferUsage() +{ +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage.h b/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage.h new file mode 100644 index 0000000000..ace1a11bae --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage.h @@ -0,0 +1,44 @@ +// +// 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. +// + +// BufferStorage.h Defines the abstract BufferStorage class. + +#ifndef LIBGLESV2_RENDERER_BUFFERSTORAGE_H_ +#define LIBGLESV2_RENDERER_BUFFERSTORAGE_H_ + +#include "common/angleutils.h" + +namespace rx +{ + +class BufferStorage +{ + public: + BufferStorage(); + virtual ~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) = 0; + virtual void clear() = 0; + virtual unsigned int getSize() const = 0; + virtual bool supportsDirectBinding() const = 0; + virtual void markBufferUsage(); + unsigned int getSerial() const; + + protected: + void updateSerial(); + + private: + DISALLOW_COPY_AND_ASSIGN(BufferStorage); + + unsigned int mSerial; + static unsigned int mNextSerial; +}; + +} + +#endif // LIBGLESV2_RENDERER_BUFFERSTORAGE_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage11.cpp new file mode 100644 index 0000000000..4c37bdbf60 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage11.cpp @@ -0,0 +1,342 @@ +#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) +{ + 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; + + D3D11_SUBRESOURCE_DATA initialData; + initialData.pSysMem = data; + initialData.SysMemPitch = size; + initialData.SysMemSlicePitch = 0; + + result = device->CreateBuffer(&bufferDesc, &initialData, &mStagingBuffer); + if (FAILED(result)) + { + return gl::error(GL_OUT_OF_MEMORY); + } + + mStagingBufferSize = size; + } + else + { + 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; + bufferDesc.BindFlags = 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; + } + + D3D11_SUBRESOURCE_DATA initialData; + initialData.pSysMem = data; + initialData.SysMemPitch = size; + initialData.SysMemSlicePitch = 0; + + result = device->CreateBuffer(&bufferDesc, &initialData, &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 true; +} + +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 new file mode 100644 index 0000000000..b62348b0c9 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage11.h @@ -0,0 +1,56 @@ +// +// 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); + 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 new file mode 100644 index 0000000000..7fc14fc073 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage9.cpp @@ -0,0 +1,75 @@ +#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) +{ + 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); + 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 new file mode 100644 index 0000000000..3e803969bc --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/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/Fence11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/Fence11.cpp new file mode 100644 index 0000000000..9d11c9a0fc --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/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/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 new file mode 100644 index 0000000000..a5398bca14 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/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/Fence9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/Fence9.cpp new file mode 100644 index 0000000000..86064d7e52 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/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/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 new file mode 100644 index 0000000000..9f17641e51 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/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/FenceImpl.h b/src/3rdparty/angle/src/libGLESv2/renderer/FenceImpl.h new file mode 100644 index 0000000000..d7f2102a2e --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/FenceImpl.h @@ -0,0 +1,45 @@ +// +// 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. +// + +// FenceImpl.h: Defines the rx::FenceImpl class. + +#ifndef LIBGLESV2_RENDERER_FENCEIMPL_H_ +#define LIBGLESV2_RENDERER_FENCEIMPL_H_ + +#include "common/angleutils.h" + +namespace rx +{ + +class FenceImpl +{ + public: + FenceImpl() : mStatus(GL_FALSE), mCondition(GL_NONE) { }; + virtual ~FenceImpl() { }; + + virtual GLboolean isFence() = 0; + virtual void setFence(GLenum condition) = 0; + virtual GLboolean testFence() = 0; + virtual void finishFence() = 0; + virtual void getFenceiv(GLenum pname, GLint *params) = 0; + + protected: + void setStatus(GLboolean status) { mStatus = status; } + GLboolean getStatus() const { return mStatus; } + + void setCondition(GLuint condition) { mCondition = condition; } + GLuint getCondition() const { return mCondition; } + + private: + DISALLOW_COPY_AND_ASSIGN(FenceImpl); + + GLboolean mStatus; + GLenum mCondition; +}; + +} + +#endif // LIBGLESV2_RENDERER_FENCEIMPL_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Image.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/Image.cpp new file mode 100644 index 0000000000..57239ef74f --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/Image.cpp @@ -0,0 +1,548 @@ +#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. +// + +// Image.h: Implements the rx::Image class, an abstract base class for the +// renderer-specific classes which will define the interface to the underlying +// surfaces or resources. + +#include "libGLESv2/renderer/Image.h" + +namespace rx +{ + +Image::Image() +{ + mWidth = 0; + mHeight = 0; + mInternalFormat = GL_NONE; + mActualFormat = GL_NONE; +} + +void Image::loadAlphaDataToBGRA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) +{ + const unsigned char *source = NULL; + unsigned char *dest = NULL; + + for (int y = 0; y < height; y++) + { + source = static_cast(input) + y * inputPitch; + dest = static_cast(output) + y * outputPitch; + for (int x = 0; x < width; x++) + { + dest[4 * x + 0] = 0; + dest[4 * x + 1] = 0; + dest[4 * x + 2] = 0; + dest[4 * x + 3] = source[x]; + } + } +} + +void Image::loadAlphaDataToNative(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) +{ + const unsigned char *source = NULL; + unsigned char *dest = NULL; + + for (int y = 0; y < height; y++) + { + source = static_cast(input) + y * inputPitch; + dest = static_cast(output) + y * outputPitch; + memcpy(dest, source, width); + } +} + +void Image::loadAlphaFloatDataToRGBA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) +{ + const float *source = NULL; + float *dest = NULL; + + for (int y = 0; y < height; y++) + { + source = reinterpret_cast(static_cast(input) + y * inputPitch); + dest = reinterpret_cast(static_cast(output) + y * outputPitch); + for (int x = 0; x < width; x++) + { + dest[4 * x + 0] = 0; + dest[4 * x + 1] = 0; + dest[4 * x + 2] = 0; + dest[4 * x + 3] = source[x]; + } + } +} + +void Image::loadAlphaHalfFloatDataToRGBA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) +{ + const unsigned short *source = NULL; + unsigned short *dest = NULL; + + for (int y = 0; y < height; y++) + { + source = reinterpret_cast(static_cast(input) + y * inputPitch); + dest = reinterpret_cast(static_cast(output) + y * outputPitch); + for (int x = 0; x < width; x++) + { + dest[4 * x + 0] = 0; + dest[4 * x + 1] = 0; + dest[4 * x + 2] = 0; + dest[4 * x + 3] = source[x]; + } + } +} + +void Image::loadLuminanceDataToNativeOrBGRA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output, bool native) +{ + const unsigned char *source = NULL; + unsigned char *dest = NULL; + + for (int y = 0; y < height; y++) + { + source = static_cast(input) + y * inputPitch; + dest = static_cast(output) + y * outputPitch; + + if (!native) // BGRA8 destination format + { + for (int x = 0; x < width; x++) + { + dest[4 * x + 0] = source[x]; + dest[4 * x + 1] = source[x]; + dest[4 * x + 2] = source[x]; + dest[4 * x + 3] = 0xFF; + } + } + else // L8 destination format + { + memcpy(dest, source, width); + } + } +} + +void Image::loadLuminanceFloatDataToRGBA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) +{ + const float *source = NULL; + float *dest = NULL; + + for (int y = 0; y < height; y++) + { + source = reinterpret_cast(static_cast(input) + y * inputPitch); + dest = reinterpret_cast(static_cast(output) + y * outputPitch); + for (int x = 0; x < width; x++) + { + dest[4 * x + 0] = source[x]; + dest[4 * x + 1] = source[x]; + dest[4 * x + 2] = source[x]; + dest[4 * x + 3] = 1.0f; + } + } +} + +void Image::loadLuminanceFloatDataToRGB(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) +{ + const float *source = NULL; + float *dest = NULL; + + for (int y = 0; y < height; y++) + { + source = reinterpret_cast(static_cast(input) + y * inputPitch); + dest = reinterpret_cast(static_cast(output) + y * outputPitch); + for (int x = 0; x < width; x++) + { + dest[3 * x + 0] = source[x]; + dest[3 * x + 1] = source[x]; + dest[3 * x + 2] = source[x]; + } + } +} + +void Image::loadLuminanceHalfFloatDataToRGBA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) +{ + const unsigned short *source = NULL; + unsigned short *dest = NULL; + + for (int y = 0; y < height; y++) + { + source = reinterpret_cast(static_cast(input) + y * inputPitch); + dest = reinterpret_cast(static_cast(output) + y * outputPitch); + for (int x = 0; x < width; x++) + { + dest[4 * x + 0] = source[x]; + dest[4 * x + 1] = source[x]; + dest[4 * x + 2] = source[x]; + dest[4 * x + 3] = 0x3C00; // SEEEEEMMMMMMMMMM, S = 0, E = 15, M = 0: 16bit flpt representation of 1 + } + } +} + +void Image::loadLuminanceAlphaDataToNativeOrBGRA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output, bool native) +{ + const unsigned char *source = NULL; + unsigned char *dest = NULL; + + for (int y = 0; y < height; y++) + { + source = static_cast(input) + y * inputPitch; + dest = static_cast(output) + y * outputPitch; + + if (!native) // BGRA8 destination format + { + for (int x = 0; x < width; x++) + { + dest[4 * x + 0] = source[2*x+0]; + dest[4 * x + 1] = source[2*x+0]; + dest[4 * x + 2] = source[2*x+0]; + dest[4 * x + 3] = source[2*x+1]; + } + } + else + { + memcpy(dest, source, width * 2); + } + } +} + +void Image::loadLuminanceAlphaFloatDataToRGBA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) +{ + const float *source = NULL; + float *dest = NULL; + + for (int y = 0; y < height; y++) + { + source = reinterpret_cast(static_cast(input) + y * inputPitch); + dest = reinterpret_cast(static_cast(output) + y * outputPitch); + for (int x = 0; x < width; x++) + { + dest[4 * x + 0] = source[2*x+0]; + dest[4 * x + 1] = source[2*x+0]; + dest[4 * x + 2] = source[2*x+0]; + dest[4 * x + 3] = source[2*x+1]; + } + } +} + +void Image::loadLuminanceAlphaHalfFloatDataToRGBA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) +{ + const unsigned short *source = NULL; + unsigned short *dest = NULL; + + for (int y = 0; y < height; y++) + { + source = reinterpret_cast(static_cast(input) + y * inputPitch); + dest = reinterpret_cast(static_cast(output) + y * outputPitch); + for (int x = 0; x < width; x++) + { + dest[4 * x + 0] = source[2*x+0]; + dest[4 * x + 1] = source[2*x+0]; + dest[4 * x + 2] = source[2*x+0]; + dest[4 * x + 3] = source[2*x+1]; + } + } +} + +void Image::loadRGBUByteDataToBGRX(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) +{ + const unsigned char *source = NULL; + unsigned char *dest = NULL; + + for (int y = 0; y < height; y++) + { + source = static_cast(input) + y * inputPitch; + dest = static_cast(output) + y * outputPitch; + for (int x = 0; x < width; x++) + { + dest[4 * x + 0] = source[x * 3 + 2]; + dest[4 * x + 1] = source[x * 3 + 1]; + dest[4 * x + 2] = source[x * 3 + 0]; + dest[4 * x + 3] = 0xFF; + } + } +} + +void Image::loadRGBUByteDataToRGBA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) +{ + const unsigned char *source = NULL; + unsigned char *dest = NULL; + + for (int y = 0; y < height; y++) + { + source = static_cast(input) + y * inputPitch; + dest = static_cast(output) + y * outputPitch; + for (int x = 0; x < width; x++) + { + dest[4 * x + 0] = source[x * 3 + 0]; + dest[4 * x + 1] = source[x * 3 + 1]; + dest[4 * x + 2] = source[x * 3 + 2]; + dest[4 * x + 3] = 0xFF; + } + } +} + +void Image::loadRGB565DataToBGRA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) +{ + const unsigned short *source = NULL; + unsigned char *dest = NULL; + + for (int y = 0; y < height; y++) + { + source = reinterpret_cast(static_cast(input) + y * inputPitch); + dest = static_cast(output) + y * outputPitch; + for (int x = 0; x < width; x++) + { + unsigned short rgba = source[x]; + dest[4 * x + 0] = ((rgba & 0x001F) << 3) | ((rgba & 0x001F) >> 2); + dest[4 * x + 1] = ((rgba & 0x07E0) >> 3) | ((rgba & 0x07E0) >> 9); + dest[4 * x + 2] = ((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13); + dest[4 * x + 3] = 0xFF; + } + } +} + +void Image::loadRGB565DataToRGBA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) +{ + const unsigned short *source = NULL; + unsigned char *dest = NULL; + + for (int y = 0; y < height; y++) + { + source = reinterpret_cast(static_cast(input) + y * inputPitch); + dest = static_cast(output) + y * outputPitch; + for (int x = 0; x < width; x++) + { + unsigned short rgba = source[x]; + dest[4 * x + 0] = ((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13); + dest[4 * x + 1] = ((rgba & 0x07E0) >> 3) | ((rgba & 0x07E0) >> 9); + dest[4 * x + 2] = ((rgba & 0x001F) << 3) | ((rgba & 0x001F) >> 2); + dest[4 * x + 3] = 0xFF; + } + } +} + +void Image::loadRGBFloatDataToRGBA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) +{ + const float *source = NULL; + float *dest = NULL; + + for (int y = 0; y < height; y++) + { + source = reinterpret_cast(static_cast(input) + y * inputPitch); + dest = reinterpret_cast(static_cast(output) + y * outputPitch); + for (int x = 0; x < width; x++) + { + dest[4 * x + 0] = source[x * 3 + 0]; + dest[4 * x + 1] = source[x * 3 + 1]; + dest[4 * x + 2] = source[x * 3 + 2]; + dest[4 * x + 3] = 1.0f; + } + } +} + +void Image::loadRGBFloatDataToNative(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) +{ + const float *source = NULL; + float *dest = NULL; + + for (int y = 0; y < height; y++) + { + source = reinterpret_cast(static_cast(input) + y * inputPitch); + dest = reinterpret_cast(static_cast(output) + y * outputPitch); + memcpy(dest, source, width * 12); + } +} + +void Image::loadRGBHalfFloatDataToRGBA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) +{ + const unsigned short *source = NULL; + unsigned short *dest = NULL; + + for (int y = 0; y < height; y++) + { + source = reinterpret_cast(static_cast(input) + y * inputPitch); + dest = reinterpret_cast(static_cast(output) + y * outputPitch); + for (int x = 0; x < width; x++) + { + dest[4 * x + 0] = source[x * 3 + 0]; + dest[4 * x + 1] = source[x * 3 + 1]; + dest[4 * x + 2] = source[x * 3 + 2]; + dest[4 * x + 3] = 0x3C00; // SEEEEEMMMMMMMMMM, S = 0, E = 15, M = 0: 16bit flpt representation of 1 + } + } +} + +void Image::loadRGBAUByteDataToBGRA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) +{ + const unsigned int *source = NULL; + unsigned int *dest = NULL; + for (int y = 0; y < height; y++) + { + source = reinterpret_cast(static_cast(input) + y * inputPitch); + dest = reinterpret_cast(static_cast(output) + y * outputPitch); + + for (int x = 0; x < width; x++) + { + unsigned int rgba = source[x]; + dest[x] = (_rotl(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00); + } + } +} + +void Image::loadRGBAUByteDataToNative(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) +{ + const unsigned int *source = NULL; + unsigned int *dest = NULL; + for (int y = 0; y < height; y++) + { + source = reinterpret_cast(static_cast(input) + y * inputPitch); + dest = reinterpret_cast(static_cast(output) + y * outputPitch); + + memcpy(dest, source, width * 4); + } +} + +void Image::loadRGBA4444DataToBGRA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) +{ + const unsigned short *source = NULL; + unsigned char *dest = NULL; + + for (int y = 0; y < height; y++) + { + source = reinterpret_cast(static_cast(input) + y * inputPitch); + dest = static_cast(output) + y * outputPitch; + for (int x = 0; x < width; x++) + { + unsigned short rgba = source[x]; + dest[4 * x + 0] = ((rgba & 0x00F0) << 0) | ((rgba & 0x00F0) >> 4); + dest[4 * x + 1] = ((rgba & 0x0F00) >> 4) | ((rgba & 0x0F00) >> 8); + dest[4 * x + 2] = ((rgba & 0xF000) >> 8) | ((rgba & 0xF000) >> 12); + dest[4 * x + 3] = ((rgba & 0x000F) << 4) | ((rgba & 0x000F) >> 0); + } + } +} + +void Image::loadRGBA4444DataToRGBA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) +{ + const unsigned short *source = NULL; + unsigned char *dest = NULL; + + for (int y = 0; y < height; y++) + { + source = reinterpret_cast(static_cast(input) + y * inputPitch); + dest = static_cast(output) + y * outputPitch; + for (int x = 0; x < width; x++) + { + unsigned short rgba = source[x]; + dest[4 * x + 0] = ((rgba & 0xF000) >> 8) | ((rgba & 0xF000) >> 12); + dest[4 * x + 1] = ((rgba & 0x0F00) >> 4) | ((rgba & 0x0F00) >> 8); + dest[4 * x + 2] = ((rgba & 0x00F0) << 0) | ((rgba & 0x00F0) >> 4); + dest[4 * x + 3] = ((rgba & 0x000F) << 4) | ((rgba & 0x000F) >> 0); + } + } +} + +void Image::loadRGBA5551DataToBGRA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) +{ + const unsigned short *source = NULL; + unsigned char *dest = NULL; + + for (int y = 0; y < height; y++) + { + source = reinterpret_cast(static_cast(input) + y * inputPitch); + dest = static_cast(output) + y * outputPitch; + for (int x = 0; x < width; x++) + { + unsigned short rgba = source[x]; + dest[4 * x + 0] = ((rgba & 0x003E) << 2) | ((rgba & 0x003E) >> 3); + dest[4 * x + 1] = ((rgba & 0x07C0) >> 3) | ((rgba & 0x07C0) >> 8); + dest[4 * x + 2] = ((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13); + dest[4 * x + 3] = (rgba & 0x0001) ? 0xFF : 0; + } + } +} + +void Image::loadRGBA5551DataToRGBA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) +{ + const unsigned short *source = NULL; + unsigned char *dest = NULL; + + for (int y = 0; y < height; y++) + { + source = reinterpret_cast(static_cast(input) + y * inputPitch); + dest = static_cast(output) + y * outputPitch; + for (int x = 0; x < width; x++) + { + unsigned short rgba = source[x]; + dest[4 * x + 0] = ((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13); + dest[4 * x + 1] = ((rgba & 0x07C0) >> 3) | ((rgba & 0x07C0) >> 8); + dest[4 * x + 2] = ((rgba & 0x003E) << 2) | ((rgba & 0x003E) >> 3); + dest[4 * x + 3] = (rgba & 0x0001) ? 0xFF : 0; + } + } +} + +void Image::loadRGBAFloatDataToRGBA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) +{ + const float *source = NULL; + float *dest = NULL; + + for (int y = 0; y < height; y++) + { + source = reinterpret_cast(static_cast(input) + y * inputPitch); + dest = reinterpret_cast(static_cast(output) + y * outputPitch); + memcpy(dest, source, width * 16); + } +} + +void Image::loadRGBAHalfFloatDataToRGBA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) +{ + const unsigned char *source = NULL; + unsigned char *dest = NULL; + + for (int y = 0; y < height; y++) + { + source = static_cast(input) + y * inputPitch; + dest = static_cast(output) + y * outputPitch; + memcpy(dest, source, width * 8); + } +} + +void Image::loadBGRADataToBGRA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) +{ + const unsigned char *source = NULL; + unsigned char *dest = NULL; + + for (int y = 0; y < height; y++) + { + source = static_cast(input) + y * inputPitch; + dest = static_cast(output) + y * outputPitch; + memcpy(dest, source, width*4); + } +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Image.h b/src/3rdparty/angle/src/libGLESv2/renderer/Image.h new file mode 100644 index 0000000000..454e83e21e --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/Image.h @@ -0,0 +1,131 @@ +// +// 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. +// + +// Image.h: Defines the rx::Image class, an abstract base class for the +// renderer-specific classes which will define the interface to the underlying +// surfaces or resources. + +#ifndef LIBGLESV2_RENDERER_IMAGE_H_ +#define LIBGLESV2_RENDERER_IMAGE_H_ + +#include "common/debug.h" + +namespace gl +{ +class Framebuffer; +} + +namespace rx +{ +class Renderer; +class TextureStorageInterface2D; +class TextureStorageInterfaceCube; + +class Image +{ + public: + Image(); + virtual ~Image() {}; + + GLsizei getWidth() const { return mWidth; } + GLsizei getHeight() const { return mHeight; } + GLenum getInternalFormat() const { return mInternalFormat; } + GLenum getActualFormat() const { return mActualFormat; } + + void markDirty() {mDirty = true;} + void markClean() {mDirty = false;} + virtual bool isDirty() const = 0; + + 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) = 0; + virtual bool updateSurface(TextureStorageInterfaceCube *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) = 0; + + virtual bool redefine(Renderer *renderer, GLint internalformat, GLsizei width, GLsizei height, bool forceRelease) = 0; + + virtual bool isRenderableFormat() const = 0; + + virtual void loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + GLint unpackAlignment, const void *input) = 0; + virtual void loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + const void *input) = 0; + + virtual void copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) = 0; + + static void loadAlphaDataToBGRA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output); + static void loadAlphaDataToNative(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output); + static void loadAlphaDataToBGRASSE2(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output); + static void loadAlphaFloatDataToRGBA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output); + static void loadAlphaHalfFloatDataToRGBA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output); + static void loadLuminanceDataToNativeOrBGRA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output, bool native); + static void loadLuminanceFloatDataToRGBA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output); + static void loadLuminanceFloatDataToRGB(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output); + static void loadLuminanceHalfFloatDataToRGBA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output); + static void loadLuminanceAlphaDataToNativeOrBGRA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output, bool native); + static void loadLuminanceAlphaFloatDataToRGBA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output); + static void loadLuminanceAlphaHalfFloatDataToRGBA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output); + static void loadRGBUByteDataToBGRX(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output); + static void loadRGBUByteDataToRGBA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output); + static void loadRGB565DataToBGRA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output); + static void loadRGB565DataToRGBA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output); + static void loadRGBFloatDataToRGBA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output); + static void loadRGBFloatDataToNative(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output); + static void loadRGBHalfFloatDataToRGBA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output); + static void loadRGBAUByteDataToBGRASSE2(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output); + static void loadRGBAUByteDataToBGRA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output); + static void loadRGBAUByteDataToNative(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output); + static void loadRGBA4444DataToBGRA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output); + static void loadRGBA4444DataToRGBA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output); + static void loadRGBA5551DataToBGRA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output); + static void loadRGBA5551DataToRGBA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output); + static void loadRGBAFloatDataToRGBA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output); + static void loadRGBAHalfFloatDataToRGBA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output); + static void loadBGRADataToBGRA(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output); + + protected: + GLsizei mWidth; + GLsizei mHeight; + GLint mInternalFormat; + GLenum mActualFormat; + + bool mDirty; + + private: + DISALLOW_COPY_AND_ASSIGN(Image); +}; + +} + +#endif // LIBGLESV2_RENDERER_IMAGE_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Image11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/Image11.cpp new file mode 100644 index 0000000000..8c78c7d750 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/Image11.cpp @@ -0,0 +1,457 @@ +#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(&destMapped); + src->map(&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); + 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(&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: + loadAlphaDataToNative(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: + loadLuminanceFloatDataToRGB(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: + loadRGBFloatDataToNative(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(&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(&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_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_MAPPED_SUBRESOURCE *map) +{ + createStagingTexture(); + + HRESULT result = E_FAIL; + + if (mStagingTexture) + { + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + result = deviceContext->Map(mStagingTexture, mStagingSubresource, D3D11_MAP_WRITE, 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 new file mode 100644 index 0000000000..4d5f1c1780 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/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_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 new file mode 100644 index 0000000000..53030b7f1e --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/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/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 new file mode 100644 index 0000000000..2fbbca3124 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/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/ImageSSE2.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/ImageSSE2.cpp new file mode 100644 index 0000000000..b2a90ca961 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/ImageSSE2.cpp @@ -0,0 +1,100 @@ +#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. +// + +// ImageSSE2.cpp: Implements SSE2-based functions of rx::Image class. It's +// in a separated file for GCC, which can enable SSE usage only per-file, +// not for code blocks that use SSE2 explicitly. + +#include "libGLESv2/Texture.h" +#include "libGLESv2/renderer/Image.h" + +namespace rx +{ + +void Image::loadRGBAUByteDataToBGRASSE2(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) +{ + const unsigned int *source = NULL; + unsigned int *dest = NULL; + __m128i brMask = _mm_set1_epi32(0x00ff00ff); + + for (int y = 0; y < height; y++) + { + source = reinterpret_cast(static_cast(input) + y * inputPitch); + dest = reinterpret_cast(static_cast(output) + y * outputPitch); + int x = 0; + + // Make output writes aligned + for (x = 0; ((reinterpret_cast(&dest[x]) & 15) != 0) && x < width; x++) + { + unsigned int rgba = source[x]; + dest[x] = (_rotl(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00); + } + + for (; x + 3 < width; x += 4) + { + __m128i sourceData = _mm_loadu_si128(reinterpret_cast(&source[x])); + // Mask out g and a, which don't change + __m128i gaComponents = _mm_andnot_si128(brMask, sourceData); + // Mask out b and r + __m128i brComponents = _mm_and_si128(sourceData, brMask); + // Swap b and r + __m128i brSwapped = _mm_shufflehi_epi16(_mm_shufflelo_epi16(brComponents, _MM_SHUFFLE(2, 3, 0, 1)), _MM_SHUFFLE(2, 3, 0, 1)); + __m128i result = _mm_or_si128(gaComponents, brSwapped); + _mm_store_si128(reinterpret_cast<__m128i*>(&dest[x]), result); + } + + // Perform leftover writes + for (; x < width; x++) + { + unsigned int rgba = source[x]; + dest[x] = (_rotl(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00); + } + } +} + +void Image::loadAlphaDataToBGRASSE2(GLsizei width, GLsizei height, + int inputPitch, const void *input, size_t outputPitch, void *output) +{ + const unsigned char *source = NULL; + unsigned int *dest = NULL; + __m128i zeroWide = _mm_setzero_si128(); + + for (int y = 0; y < height; y++) + { + source = static_cast(input) + y * inputPitch; + dest = reinterpret_cast(static_cast(output) + y * outputPitch); + + int x; + // Make output writes aligned + for (x = 0; ((reinterpret_cast(&dest[x]) & 0xF) != 0 && x < width); x++) + { + dest[x] = static_cast(source[x]) << 24; + } + + for (; x + 7 < width; x += 8) + { + __m128i sourceData = _mm_loadl_epi64(reinterpret_cast(&source[x])); + // Interleave each byte to 16bit, make the lower byte to zero + sourceData = _mm_unpacklo_epi8(zeroWide, sourceData); + // Interleave each 16bit to 32bit, make the lower 16bit to zero + __m128i lo = _mm_unpacklo_epi16(zeroWide, sourceData); + __m128i hi = _mm_unpackhi_epi16(zeroWide, sourceData); + + _mm_store_si128(reinterpret_cast<__m128i*>(&dest[x]), lo); + _mm_store_si128(reinterpret_cast<__m128i*>(&dest[x + 4]), hi); + } + + // Handle the remainder + for (; x < width; x++) + { + dest[x] = static_cast(source[x]) << 24; + } + } +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer.cpp new file mode 100644 index 0000000000..16fd782315 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer.cpp @@ -0,0 +1,202 @@ +#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. +// + +// IndexBuffer.cpp: Defines the abstract IndexBuffer class and IndexBufferInterface +// class with derivations, classes that perform graphics API agnostic index buffer operations. + +#include "libGLESv2/renderer/IndexBuffer.h" +#include "libGLESv2/renderer/Renderer.h" + +namespace rx +{ + +unsigned int IndexBuffer::mNextSerial = 1; + +IndexBuffer::IndexBuffer() +{ + updateSerial(); +} + +IndexBuffer::~IndexBuffer() +{ +} + +unsigned int IndexBuffer::getSerial() const +{ + return mSerial; +} + +void IndexBuffer::updateSerial() +{ + mSerial = mNextSerial++; +} + + +IndexBufferInterface::IndexBufferInterface(Renderer *renderer, bool dynamic) : mRenderer(renderer) +{ + mIndexBuffer = renderer->createIndexBuffer(); + + mDynamic = dynamic; + mWritePosition = 0; +} + +IndexBufferInterface::~IndexBufferInterface() +{ + if (mIndexBuffer) + { + delete mIndexBuffer; + } +} + +GLenum IndexBufferInterface::getIndexType() const +{ + return mIndexBuffer->getIndexType(); +} + +unsigned int IndexBufferInterface::getBufferSize() const +{ + return mIndexBuffer->getBufferSize(); +} + +unsigned int IndexBufferInterface::getSerial() const +{ + return mIndexBuffer->getSerial(); +} + +int IndexBufferInterface::mapBuffer(unsigned int size, void** outMappedMemory) +{ + if (!mIndexBuffer->mapBuffer(mWritePosition, size, outMappedMemory)) + { + *outMappedMemory = NULL; + return -1; + } + + int oldWritePos = static_cast(mWritePosition); + mWritePosition += size; + + return oldWritePos; +} + +bool IndexBufferInterface::unmapBuffer() +{ + return mIndexBuffer->unmapBuffer(); +} + +IndexBuffer * IndexBufferInterface::getIndexBuffer() const +{ + return mIndexBuffer; +} + +unsigned int IndexBufferInterface::getWritePosition() const +{ + return mWritePosition; +} + +void IndexBufferInterface::setWritePosition(unsigned int writePosition) +{ + mWritePosition = writePosition; +} + +bool IndexBufferInterface::discard() +{ + return mIndexBuffer->discard(); +} + +bool IndexBufferInterface::setBufferSize(unsigned int bufferSize, GLenum indexType) +{ + if (mIndexBuffer->getBufferSize() == 0) + { + return mIndexBuffer->initialize(bufferSize, indexType, mDynamic); + } + else + { + return mIndexBuffer->setSize(bufferSize, indexType); + } +} + +StreamingIndexBufferInterface::StreamingIndexBufferInterface(Renderer *renderer) : IndexBufferInterface(renderer, true) +{ +} + +StreamingIndexBufferInterface::~StreamingIndexBufferInterface() +{ +} + +bool StreamingIndexBufferInterface::reserveBufferSpace(unsigned int size, GLenum indexType) +{ + bool result = true; + unsigned int curBufferSize = getBufferSize(); + if (size > curBufferSize) + { + result = setBufferSize(std::max(size, 2 * curBufferSize), indexType); + setWritePosition(0); + } + else if (getWritePosition() + size > curBufferSize) + { + if (!discard()) + { + return false; + } + setWritePosition(0); + } + + return result; +} + + +StaticIndexBufferInterface::StaticIndexBufferInterface(Renderer *renderer) : IndexBufferInterface(renderer, false) +{ +} + +StaticIndexBufferInterface::~StaticIndexBufferInterface() +{ +} + +bool StaticIndexBufferInterface::reserveBufferSpace(unsigned int size, GLenum indexType) +{ + unsigned int curSize = getBufferSize(); + if (curSize == 0) + { + return setBufferSize(size, indexType); + } + else if (curSize >= size && indexType == getIndexType()) + { + return true; + } + else + { + ERR("Static index buffers can't be resized"); + UNREACHABLE(); + return false; + } +} + +unsigned int StaticIndexBufferInterface::lookupRange(intptr_t offset, GLsizei count, unsigned int *minIndex, unsigned int *maxIndex) +{ + IndexRange range = {offset, count}; + + std::map::iterator res = mCache.find(range); + + if (res == mCache.end()) + { + return -1; + } + + *minIndex = res->second.minIndex; + *maxIndex = res->second.maxIndex; + return res->second.streamOffset; +} + +void StaticIndexBufferInterface::addRange(intptr_t offset, GLsizei count, unsigned int minIndex, unsigned int maxIndex, unsigned int streamOffset) +{ + IndexRange indexRange = {offset, count}; + IndexResult indexResult = {minIndex, maxIndex, streamOffset}; + mCache[indexRange] = indexResult; +} + +} + diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer.h b/src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer.h new file mode 100644 index 0000000000..1afbd626fa --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer.h @@ -0,0 +1,137 @@ +// +// 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. +// + +// IndexBuffer.h: Defines the abstract IndexBuffer class and IndexBufferInterface +// class with derivations, classes that perform graphics API agnostic index buffer operations. + +#ifndef LIBGLESV2_RENDERER_INDEXBUFFER_H_ +#define LIBGLESV2_RENDERER_INDEXBUFFER_H_ + +#include "common/angleutils.h" + +namespace rx +{ +class Renderer; + +class IndexBuffer +{ + public: + IndexBuffer(); + virtual ~IndexBuffer(); + + virtual bool initialize(unsigned int bufferSize, GLenum indexType, bool dynamic) = 0; + + virtual bool mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory) = 0; + virtual bool unmapBuffer() = 0; + + virtual bool discard() = 0; + + virtual GLenum getIndexType() const = 0; + virtual unsigned int getBufferSize() const = 0; + virtual bool setSize(unsigned int bufferSize, GLenum indexType) = 0; + + unsigned int getSerial() const; + + protected: + void updateSerial(); + + private: + DISALLOW_COPY_AND_ASSIGN(IndexBuffer); + + unsigned int mSerial; + static unsigned int mNextSerial; +}; + +class IndexBufferInterface +{ + public: + IndexBufferInterface(Renderer *renderer, bool dynamic); + virtual ~IndexBufferInterface(); + + virtual bool reserveBufferSpace(unsigned int size, GLenum indexType) = 0; + + GLenum getIndexType() const; + unsigned int getBufferSize() const; + + unsigned int getSerial() const; + + int mapBuffer(unsigned int size, void** outMappedMemory); + bool unmapBuffer(); + + IndexBuffer *getIndexBuffer() const; + + protected: + unsigned int getWritePosition() const; + void setWritePosition(unsigned int writePosition); + + bool discard(); + + bool setBufferSize(unsigned int bufferSize, GLenum indexType); + + private: + DISALLOW_COPY_AND_ASSIGN(IndexBufferInterface); + + rx::Renderer *const mRenderer; + + IndexBuffer* mIndexBuffer; + + unsigned int mWritePosition; + bool mDynamic; +}; + +class StreamingIndexBufferInterface : public IndexBufferInterface +{ + public: + StreamingIndexBufferInterface(Renderer *renderer); + ~StreamingIndexBufferInterface(); + + virtual bool reserveBufferSpace(unsigned int size, GLenum indexType); +}; + +class StaticIndexBufferInterface : public IndexBufferInterface +{ + public: + explicit StaticIndexBufferInterface(Renderer *renderer); + ~StaticIndexBufferInterface(); + + virtual bool reserveBufferSpace(unsigned int size, GLenum indexType); + + unsigned int lookupRange(intptr_t offset, GLsizei count, unsigned int *minIndex, unsigned int *maxIndex); // Returns the offset into the index buffer, or -1 if not found + void addRange(intptr_t offset, GLsizei count, unsigned int minIndex, unsigned int maxIndex, unsigned int streamOffset); + + private: + struct IndexRange + { + intptr_t offset; + GLsizei count; + + bool operator<(const IndexRange& rhs) const + { + if (offset != rhs.offset) + { + return offset < rhs.offset; + } + if (count != rhs.count) + { + return count < rhs.count; + } + return false; + } + }; + + struct IndexResult + { + unsigned int minIndex; + unsigned int maxIndex; + unsigned int streamOffset; + }; + + std::map mCache; +}; + +} + +#endif // LIBGLESV2_RENDERER_INDEXBUFFER_H_ \ No newline at end of file diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer11.cpp new file mode 100644 index 0000000000..2a442ecd1a --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer11.cpp @@ -0,0 +1,182 @@ +#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) + { + if (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/IndexBuffer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer11.h new file mode 100644 index 0000000000..39a61946ad --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/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/IndexBuffer9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer9.cpp new file mode 100644 index 0000000000..c6d83c5dca --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/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/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 new file mode 100644 index 0000000000..6801867532 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/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/IndexDataManager.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/IndexDataManager.cpp new file mode 100644 index 0000000000..84b79b4109 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/IndexDataManager.cpp @@ -0,0 +1,316 @@ +#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. +// + +// IndexDataManager.cpp: Defines the IndexDataManager, a class that +// runs the Buffer translation process for index buffers. + +#include "libGLESv2/renderer/IndexDataManager.h" +#include "libGLESv2/renderer/BufferStorage.h" + +#include "libGLESv2/Buffer.h" +#include "libGLESv2/main.h" +#include "libGLESv2/renderer/IndexBuffer.h" + +namespace rx +{ + +IndexDataManager::IndexDataManager(Renderer *renderer) : mRenderer(renderer) +{ + mStreamingBufferShort = new StreamingIndexBufferInterface(mRenderer); + if (!mStreamingBufferShort->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_SHORT)) + { + delete mStreamingBufferShort; + mStreamingBufferShort = NULL; + } + + mStreamingBufferInt = new StreamingIndexBufferInterface(mRenderer); + if (!mStreamingBufferInt->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT)) + { + delete mStreamingBufferInt; + mStreamingBufferInt = NULL; + } + + if (!mStreamingBufferShort) + { + // Make sure both buffers are deleted. + delete mStreamingBufferInt; + mStreamingBufferInt = NULL; + + ERR("Failed to allocate the streaming index buffer(s)."); + } + + mCountingBuffer = NULL; +} + +IndexDataManager::~IndexDataManager() +{ + delete mStreamingBufferShort; + delete mStreamingBufferInt; + delete mCountingBuffer; +} + +static unsigned int indexTypeSize(GLenum type) +{ + switch (type) + { + case GL_UNSIGNED_INT: return sizeof(GLuint); + case GL_UNSIGNED_SHORT: return sizeof(GLushort); + case GL_UNSIGNED_BYTE: return sizeof(GLubyte); + default: UNREACHABLE(); return sizeof(GLushort); + } +} + +static void convertIndices(GLenum type, const void *input, GLsizei count, void *output) +{ + if (type == GL_UNSIGNED_BYTE) + { + const GLubyte *in = static_cast(input); + GLushort *out = static_cast(output); + + for (GLsizei i = 0; i < count; i++) + { + out[i] = in[i]; + } + } + else if (type == GL_UNSIGNED_INT) + { + memcpy(output, input, count * sizeof(GLuint)); + } + else if (type == GL_UNSIGNED_SHORT) + { + memcpy(output, input, count * sizeof(GLushort)); + } + else UNREACHABLE(); +} + +template +static void computeRange(const IndexType *indices, GLsizei count, GLuint *minIndex, GLuint *maxIndex) +{ + *minIndex = indices[0]; + *maxIndex = indices[0]; + + for (GLsizei i = 0; i < count; i++) + { + if (*minIndex > indices[i]) *minIndex = indices[i]; + if (*maxIndex < indices[i]) *maxIndex = indices[i]; + } +} + +static void computeRange(GLenum type, const GLvoid *indices, GLsizei count, GLuint *minIndex, GLuint *maxIndex) +{ + if (type == GL_UNSIGNED_BYTE) + { + computeRange(static_cast(indices), count, minIndex, maxIndex); + } + else if (type == GL_UNSIGNED_INT) + { + computeRange(static_cast(indices), count, minIndex, maxIndex); + } + else if (type == GL_UNSIGNED_SHORT) + { + computeRange(static_cast(indices), count, minIndex, maxIndex); + } + else UNREACHABLE(); +} + +GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer *buffer, const GLvoid *indices, TranslatedIndexData *translated) +{ + if (!mStreamingBufferShort) + { + return GL_OUT_OF_MEMORY; + } + + GLenum destinationIndexType = (type == GL_UNSIGNED_INT) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT; + intptr_t offset = reinterpret_cast(indices); + bool alignedOffset = false; + + BufferStorage *storage = NULL; + + if (buffer != NULL) + { + storage = buffer->getStorage(); + + switch (type) + { + case GL_UNSIGNED_BYTE: alignedOffset = (offset % sizeof(GLubyte) == 0); break; + case GL_UNSIGNED_SHORT: alignedOffset = (offset % sizeof(GLushort) == 0); break; + case GL_UNSIGNED_INT: alignedOffset = (offset % sizeof(GLuint) == 0); break; + default: UNREACHABLE(); alignedOffset = false; + } + + if (indexTypeSize(type) * count + offset > storage->getSize()) + { + return GL_INVALID_OPERATION; + } + + indices = static_cast(storage->getData()) + offset; + } + + StreamingIndexBufferInterface *streamingBuffer = (type == GL_UNSIGNED_INT) ? mStreamingBufferInt : mStreamingBufferShort; + + StaticIndexBufferInterface *staticBuffer = buffer ? buffer->getStaticIndexBuffer() : NULL; + IndexBufferInterface *indexBuffer = streamingBuffer; + bool directStorage = alignedOffset && storage && storage->supportsDirectBinding() && + destinationIndexType == type; + UINT streamOffset = 0; + + if (directStorage) + { + indexBuffer = streamingBuffer; + streamOffset = offset; + storage->markBufferUsage(); + computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex); + } + else if (staticBuffer && staticBuffer->getBufferSize() != 0 && staticBuffer->getIndexType() == type && alignedOffset) + { + indexBuffer = staticBuffer; + streamOffset = staticBuffer->lookupRange(offset, count, &translated->minIndex, &translated->maxIndex); + + if (streamOffset == -1) + { + streamOffset = (offset / indexTypeSize(type)) * indexTypeSize(destinationIndexType); + computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex); + staticBuffer->addRange(offset, count, translated->minIndex, translated->maxIndex, streamOffset); + } + } + else + { + int convertCount = count; + + if (staticBuffer) + { + if (staticBuffer->getBufferSize() == 0 && alignedOffset) + { + indexBuffer = staticBuffer; + convertCount = storage->getSize() / indexTypeSize(type); + } + else + { + buffer->invalidateStaticData(); + staticBuffer = NULL; + } + } + + if (!indexBuffer) + { + ERR("No valid index buffer."); + return GL_INVALID_OPERATION; + } + + unsigned int bufferSizeRequired = convertCount * indexTypeSize(destinationIndexType); + indexBuffer->reserveBufferSpace(bufferSizeRequired, type); + + void* output = NULL; + streamOffset = indexBuffer->mapBuffer(bufferSizeRequired, &output); + if (streamOffset == -1 || output == NULL) + { + ERR("Failed to map index buffer."); + return GL_OUT_OF_MEMORY; + } + + convertIndices(type, staticBuffer ? storage->getData() : indices, convertCount, output); + + if (!indexBuffer->unmapBuffer()) + { + ERR("Failed to unmap index buffer."); + return GL_OUT_OF_MEMORY; + } + + computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex); + + if (staticBuffer) + { + streamOffset = (offset / indexTypeSize(type)) * indexTypeSize(destinationIndexType); + staticBuffer->addRange(offset, count, translated->minIndex, translated->maxIndex, streamOffset); + } + } + + translated->storage = directStorage ? storage : NULL; + translated->indexBuffer = indexBuffer->getIndexBuffer(); + translated->serial = directStorage ? storage->getSerial() : indexBuffer->getSerial(); + translated->startIndex = streamOffset / indexTypeSize(destinationIndexType); + translated->startOffset = streamOffset; + + if (buffer) + { + buffer->promoteStaticUsage(count * indexTypeSize(type)); + } + + return GL_NO_ERROR; +} + +StaticIndexBufferInterface *IndexDataManager::getCountingIndices(GLsizei count) +{ + if (count <= 65536) // 16-bit indices + { + const unsigned int spaceNeeded = count * sizeof(unsigned short); + + if (!mCountingBuffer || mCountingBuffer->getBufferSize() < spaceNeeded) + { + delete mCountingBuffer; + mCountingBuffer = new StaticIndexBufferInterface(mRenderer); + mCountingBuffer->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_SHORT); + + void* mappedMemory = NULL; + if (mCountingBuffer->mapBuffer(spaceNeeded, &mappedMemory) == -1 || mappedMemory == NULL) + { + ERR("Failed to map counting buffer."); + return NULL; + } + + unsigned short *data = reinterpret_cast(mappedMemory); + for(int i = 0; i < count; i++) + { + data[i] = i; + } + + if (!mCountingBuffer->unmapBuffer()) + { + ERR("Failed to unmap counting buffer."); + return NULL; + } + } + } + else if (mStreamingBufferInt) // 32-bit indices supported + { + const unsigned int spaceNeeded = count * sizeof(unsigned int); + + if (!mCountingBuffer || mCountingBuffer->getBufferSize() < spaceNeeded) + { + delete mCountingBuffer; + mCountingBuffer = new StaticIndexBufferInterface(mRenderer); + mCountingBuffer->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT); + + void* mappedMemory = NULL; + if (mCountingBuffer->mapBuffer(spaceNeeded, &mappedMemory) == -1 || mappedMemory == NULL) + { + ERR("Failed to map counting buffer."); + return NULL; + } + + unsigned int *data = reinterpret_cast(mappedMemory); + for(int i = 0; i < count; i++) + { + data[i] = i; + } + + if (!mCountingBuffer->unmapBuffer()) + { + ERR("Failed to unmap counting buffer."); + return NULL; + } + } + } + else + { + return NULL; + } + + return mCountingBuffer; +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/IndexDataManager.h b/src/3rdparty/angle/src/libGLESv2/renderer/IndexDataManager.h new file mode 100644 index 0000000000..0e77c81d1b --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/IndexDataManager.h @@ -0,0 +1,66 @@ +// +// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// IndexDataManager.h: Defines the IndexDataManager, a class that +// runs the Buffer translation process for index buffers. + +#ifndef LIBGLESV2_INDEXDATAMANAGER_H_ +#define LIBGLESV2_INDEXDATAMANAGER_H_ + +#include "common/angleutils.h" + +namespace +{ + enum { INITIAL_INDEX_BUFFER_SIZE = 4096 * sizeof(GLuint) }; +} + +namespace gl +{ +class Buffer; +} + +namespace rx +{ +class StaticIndexBufferInterface; +class StreamingIndexBufferInterface; +class IndexBuffer; +class BufferStorage; +class Renderer; + +struct TranslatedIndexData +{ + unsigned int minIndex; + unsigned int maxIndex; + unsigned int startIndex; + unsigned int startOffset; // In bytes + + IndexBuffer *indexBuffer; + BufferStorage *storage; + unsigned int serial; +}; + +class IndexDataManager +{ + public: + explicit IndexDataManager(Renderer *renderer); + virtual ~IndexDataManager(); + + GLenum prepareIndexData(GLenum type, GLsizei count, gl::Buffer *arrayElementBuffer, const GLvoid *indices, TranslatedIndexData *translated); + StaticIndexBufferInterface *getCountingIndices(GLsizei count); + + private: + DISALLOW_COPY_AND_ASSIGN(IndexDataManager); + + Renderer *const mRenderer; + + StreamingIndexBufferInterface *mStreamingBufferShort; + StreamingIndexBufferInterface *mStreamingBufferInt; + StaticIndexBufferInterface *mCountingBuffer; +}; + +} + +#endif // LIBGLESV2_INDEXDATAMANAGER_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/InputLayoutCache.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/InputLayoutCache.cpp new file mode 100644 index 0000000000..0402bb35ac --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/InputLayoutCache.cpp @@ -0,0 +1,166 @@ +#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; +} + +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(); +} + +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 }; + 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.glslElementType[ilKey.elementCount], NULL); + + ilKey.elements[ilKey.elementCount].SemanticName = semanticName; + ilKey.elements[ilKey.elementCount].SemanticIndex = sortedSemanticIndices[i]; + ilKey.elements[ilKey.elementCount].Format = attributes[i].attribute->mArrayEnabled ? vertexBuffer->getDXGIFormat(*attributes[i].attribute) : DXGI_FORMAT_R32G32B32A32_FLOAT; + ilKey.elements[ilKey.elementCount].InputSlot = i; + ilKey.elements[ilKey.elementCount].AlignedByteOffset = 0; + ilKey.elements[ilKey.elementCount].InputSlotClass = inputClass; + ilKey.elements[ilKey.elementCount].InstanceDataStepRate = attributes[i].divisor; + ilKey.elementCount++; + + vertexBuffers[i] = bufferStorage ? bufferStorage->getBuffer() : vertexBuffer->getBuffer(); + 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()); + + HRESULT result = mDevice->CreateInputLayout(ilKey.elements, 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)); + } + + mDeviceContext->IASetInputLayout(inputLayout); + mDeviceContext->IASetVertexBuffers(0, gl::MAX_VERTEX_ATTRIBS, vertexBuffers, vertexStrides, vertexOffsets); + + 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, sizeof(InputLayoutKey), seed, &hash); + return hash; +} + +bool InputLayoutCache::compareInputLayouts(const InputLayoutKey &a, const InputLayoutKey &b) +{ + return memcmp(&a, &b, sizeof(InputLayoutKey)) == 0; +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/InputLayoutCache.h b/src/3rdparty/angle/src/libGLESv2/renderer/InputLayoutCache.h new file mode 100644 index 0000000000..d95f39fae4 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/InputLayoutCache.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. +// + +// 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(); + + GLenum applyVertexBuffers(TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS], + gl::ProgramBinary *programBinary); + + private: + DISALLOW_COPY_AND_ASSIGN(InputLayoutCache); + + struct InputLayoutKey + { + unsigned int elementCount; + D3D11_INPUT_ELEMENT_DESC elements[gl::MAX_VERTEX_ATTRIBS]; + GLenum glslElementType[gl::MAX_VERTEX_ATTRIBS]; + }; + + struct InputLayoutCounterPair + { + ID3D11InputLayout *inputLayout; + unsigned long long lastUsedTime; + }; + + 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 new file mode 100644 index 0000000000..13210fc929 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/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/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 new file mode 100644 index 0000000000..0a03de77ca --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/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/Query9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/Query9.cpp new file mode 100644 index 0000000000..ef694267dd --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/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/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 new file mode 100644 index 0000000000..47eef89336 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/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/QueryImpl.h b/src/3rdparty/angle/src/libGLESv2/renderer/QueryImpl.h new file mode 100644 index 0000000000..a874047b0c --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/QueryImpl.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. +// + +// QueryImpl.h: Defines the abstract rx::QueryImpl class. + +#ifndef LIBGLESV2_RENDERER_QUERYIMPL_H_ +#define LIBGLESV2_RENDERER_QUERYIMPL_H_ + +#include "common/angleutils.h" + +namespace rx +{ + +class QueryImpl +{ + public: + explicit QueryImpl(GLenum type) : mType(type), mStatus(GL_FALSE), mResult(0) { } + virtual ~QueryImpl() { } + + virtual void begin() = 0; + virtual void end() = 0; + virtual GLuint getResult() = 0; + virtual GLboolean isResultAvailable() = 0; + + GLenum getType() const { return mType; } + + protected: + GLuint mResult; + GLboolean mStatus; + + private: + DISALLOW_COPY_AND_ASSIGN(QueryImpl); + + GLenum mType; +}; + +} + +#endif // LIBGLESV2_RENDERER_QUERYIMPL_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/RenderStateCache.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/RenderStateCache.cpp new file mode 100644 index 0000000000..f60a88f97a --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/RenderStateCache.cpp @@ -0,0 +1,406 @@ +#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 = TRUE; + 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 = gl_d3d11::ConvertMaxLOD(samplerState.minFilter, samplerState.lodOffset); + + 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 new file mode 100644 index 0000000000..f8b5111de4 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/RenderStateCache.h @@ -0,0 +1,101 @@ +// +// 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/RenderTarget.h b/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget.h new file mode 100644 index 0000000000..80de39f4f7 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget.h @@ -0,0 +1,56 @@ +// +// 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. +// + +// RenderTarget.h: Defines an abstract wrapper class to manage IDirect3DSurface9 +// and ID3D11View objects belonging to renderbuffers. + +#ifndef LIBGLESV2_RENDERER_RENDERTARGET_H_ +#define LIBGLESV2_RENDERER_RENDERTARGET_H_ + +#include "common/angleutils.h" + +namespace rx +{ +class RenderTarget +{ + public: + RenderTarget() + { + mWidth = 0; + mHeight = 0; + mInternalFormat = GL_NONE; + mActualFormat = GL_NONE; + mSamples = 0; + } + + virtual ~RenderTarget() {}; + + GLsizei getWidth() { return mWidth; } + GLsizei getHeight() { return mHeight; } + GLenum getInternalFormat() { return mInternalFormat; } + GLenum getActualFormat() { return mActualFormat; } + GLsizei getSamples() { return mSamples; } + + struct Desc { + GLsizei width; + GLsizei height; + GLenum format; + }; + + protected: + GLsizei mWidth; + GLsizei mHeight; + GLenum mInternalFormat; + GLenum mActualFormat; + GLsizei mSamples; + + private: + DISALLOW_COPY_AND_ASSIGN(RenderTarget); +}; + +} + +#endif // LIBGLESV2_RENDERTARGET_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget11.cpp new file mode 100644 index 0000000000..cf226de17b --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget11.cpp @@ -0,0 +1,378 @@ +#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 +{ + if (mTexture) + { + mTexture->AddRef(); + } + + return mTexture; +} + +// Adds reference, caller must call Release +ID3D11RenderTargetView *RenderTarget11::getRenderTargetView() const +{ + if (mRenderTarget) + { + mRenderTarget->AddRef(); + } + + return mRenderTarget; +} + +// Adds reference, caller must call Release +ID3D11DepthStencilView *RenderTarget11::getDepthStencilView() const +{ + if (mDepthStencil) + { + mDepthStencil->AddRef(); + } + + return mDepthStencil; +} + +// Adds reference, caller must call Release +ID3D11ShaderResourceView *RenderTarget11::getShaderResourceView() const +{ + if (mShaderResource) + { + mShaderResource->AddRef(); + } + + 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 new file mode 100644 index 0000000000..dc697cf0e3 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget11.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. +// + +// 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); + + // Adds reference, caller must call Release + ID3D11Texture2D *getTexture() const; + + // Adds reference, caller must call Release + ID3D11RenderTargetView *getRenderTargetView() const; + + // Adds reference, caller must call Release + ID3D11DepthStencilView *getDepthStencilView() const; + + // Adds reference, caller must call Release + 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 new file mode 100644 index 0000000000..a84c709059 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/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/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 new file mode 100644 index 0000000000..faf8ad1c6d --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/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/Renderer.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp new file mode 100644 index 0000000000..41cdb8b278 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp @@ -0,0 +1,201 @@ +#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. +// + +// Renderer.cpp: Implements EGL dependencies for creating and destroying Renderer instances. + +#include "libGLESv2/main.h" +#include "libGLESv2/Program.h" +#include "libGLESv2/renderer/Renderer.h" +#if defined(ANGLE_ENABLE_D3D11) +# include "libGLESv2/renderer/Renderer11.h" +# define D3DERR_OUTOFVIDEOMEMORY MAKE_HRESULT( 1, 0x876, 380 ) +#else +# include "libGLESv2/renderer/Renderer9.h" +#endif +#include "libGLESv2/utilities.h" + +#if !defined(ANGLE_COMPILE_OPTIMIZATION_LEVEL) +#define ANGLE_COMPILE_OPTIMIZATION_LEVEL D3DCOMPILE_OPTIMIZATION_LEVEL3 +#endif + +namespace rx +{ + +Renderer::Renderer(egl::Display *display) : mDisplay(display) +{ + mD3dCompilerModule = NULL; + mD3DCompileFunc = NULL; +} + +Renderer::~Renderer() +{ + if (mD3dCompilerModule) + { + FreeLibrary(mD3dCompilerModule); + mD3dCompilerModule = NULL; + } +} + +bool Renderer::initializeCompiler() +{ +#if defined(ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES) + // Find a D3DCompiler module that had already been loaded based on a predefined list of versions. + static TCHAR* d3dCompilerNames[] = ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES; + + for (size_t i = 0; i < ArraySize(d3dCompilerNames); ++i) + { + if (GetModuleHandleEx(0, d3dCompilerNames[i], &mD3dCompilerModule)) + { + break; + } + } +#else + // Load the version of the D3DCompiler DLL associated with the Direct3D version ANGLE was built with. + mD3dCompilerModule = LoadLibrary(D3DCOMPILER_DLL); +#endif // ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES + + if (!mD3dCompilerModule) + { + ERR("No D3D compiler module found - aborting!\n"); + return false; + } + + mD3DCompileFunc = reinterpret_cast(GetProcAddress(mD3dCompilerModule, "D3DCompile")); + ASSERT(mD3DCompileFunc); + + return mD3DCompileFunc != NULL; +} + +// Compiles HLSL code into executable binaries +ShaderBlob *Renderer::compileToBinary(gl::InfoLog &infoLog, const char *hlsl, const char *profile, UINT optimizationFlags, bool alternateFlags) +{ + if (!hlsl) + { + return NULL; + } + + HRESULT result = S_OK; + UINT flags = 0; + std::string sourceText; + if (gl::perfActive()) + { + flags |= D3DCOMPILE_DEBUG; + +#ifdef NDEBUG + flags |= optimizationFlags; +#else + flags |= D3DCOMPILE_SKIP_OPTIMIZATION; +#endif + + std::string sourcePath = getTempPath(); + sourceText = std::string("#line 2 \"") + sourcePath + std::string("\"\n\n") + std::string(hlsl); + writeFile(sourcePath.c_str(), sourceText.c_str(), sourceText.size()); + } + else + { + flags |= optimizationFlags; + sourceText = hlsl; + } + + // Sometimes D3DCompile will fail with the default compilation flags for complicated shaders when it would otherwise pass with alternative options. + // Try the default flags first and if compilation fails, try some alternatives. + const static UINT extraFlags[] = + { + 0, + D3DCOMPILE_AVOID_FLOW_CONTROL, + D3DCOMPILE_PREFER_FLOW_CONTROL + }; + + const static char * const extraFlagNames[] = + { + "default", + "avoid flow control", + "prefer flow control" + }; + + int attempts = alternateFlags ? ArraySize(extraFlags) : 1; + pD3DCompile compileFunc = reinterpret_cast(mD3DCompileFunc); + for (int i = 0; i < attempts; ++i) + { + ID3DBlob *errorMessage = NULL; + ID3DBlob *binary = NULL; + + result = compileFunc(hlsl, strlen(hlsl), gl::g_fakepath, NULL, NULL, + "main", profile, flags | extraFlags[i], 0, &binary, &errorMessage); + if (errorMessage) + { + const char *message = (const char*)errorMessage->GetBufferPointer(); + + infoLog.appendSanitized(message); + TRACE("\n%s", hlsl); + TRACE("\n%s", message); + + errorMessage->Release(); + errorMessage = NULL; + } + + if (SUCCEEDED(result)) + { + return (ShaderBlob*)binary; + } + else + { + if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY) + { + return gl::error(GL_OUT_OF_MEMORY, (ShaderBlob*) NULL); + } + + infoLog.append("Warning: D3D shader compilation failed with "); + infoLog.append(extraFlagNames[i]); + infoLog.append(" flags."); + if (i + 1 < attempts) + { + infoLog.append(" Retrying with "); + infoLog.append(extraFlagNames[i + 1]); + infoLog.append(".\n"); + } + } + } + + return NULL; +} + +} + +extern "C" +{ + +rx::Renderer *glCreateRenderer(egl::Display *display, HDC hDc, bool softwareDevice) +{ + rx::Renderer *renderer = NULL; + EGLint status = EGL_BAD_ALLOC; + +#if defined(ANGLE_ENABLE_D3D11) + renderer = new rx::Renderer11(display, hDc); +#else + renderer = new rx::Renderer9(display, hDc, softwareDevice); +#endif + + if (renderer) + { + status = renderer->initialize(); + } + + if (status == EGL_SUCCESS) + { + return renderer; + } + + return NULL; +} + +void glDestroyRenderer(rx::Renderer *renderer) +{ + delete renderer; +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h new file mode 100644 index 0000000000..656cb0f1bf --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h @@ -0,0 +1,238 @@ +// +// 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. +// + +// Renderer.h: Defines a back-end specific class that hides the details of the +// implementation-specific renderer. + +#ifndef LIBGLESV2_RENDERER_RENDERER_H_ +#define LIBGLESV2_RENDERER_RENDERER_H_ + +#include "libGLESv2/Uniform.h" +#include "libGLESv2/angletypes.h" + +const int versionWindowsVista = MAKEWORD(0x00, 0x06); +const int versionWindows7 = MAKEWORD(0x01, 0x06); + +// Return the version of the operating system in a format suitable for ordering +// comparison. +inline int getComparableOSVersion() +{ + DWORD version = GetVersion(); + int majorVersion = LOBYTE(LOWORD(version)); + int minorVersion = HIBYTE(LOWORD(version)); + return MAKEWORD(minorVersion, majorVersion); +} + +namespace egl +{ +class Display; +} + +namespace gl +{ +class InfoLog; +class ProgramBinary; +class VertexAttribute; +class Buffer; +class Texture; +class Framebuffer; +} + +namespace rx +{ +class TextureStorageInterface2D; +class TextureStorageInterfaceCube; +class VertexBuffer; +class IndexBuffer; +class QueryImpl; +class FenceImpl; +class BufferStorage; +class Blit; +struct TranslatedIndexData; +class ShaderExecutable; +class SwapChain; +class RenderTarget; +class Image; +class TextureStorage; + +typedef void * ShaderBlob; +typedef void (*pCompileFunc)(); + +struct ConfigDesc +{ + GLenum renderTargetFormat; + GLenum depthStencilFormat; + GLint multiSample; + bool fastConfig; +}; + +struct dx_VertexConstants +{ + float depthRange[4]; + float viewAdjust[4]; +}; + +struct dx_PixelConstants +{ + float depthRange[4]; + float viewCoords[4]; + float depthFront[4]; +}; + +enum ShaderType +{ + SHADER_VERTEX, + SHADER_PIXEL, + SHADER_GEOMETRY +}; + +class Renderer +{ + public: + explicit Renderer(egl::Display *display); + virtual ~Renderer(); + + virtual EGLint initialize() = 0; + virtual bool resetDevice() = 0; + + virtual int generateConfigs(ConfigDesc **configDescList) = 0; + virtual void deleteConfigs(ConfigDesc *configDescList) = 0; + + virtual void sync(bool block) = 0; + + virtual SwapChain *createSwapChain(HWND window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) = 0; + + virtual void setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &sampler) = 0; + 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, + unsigned int sampleMask) = 0; + virtual void setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef, + int stencilBackRef, bool frontFaceCCW) = 0; + + virtual void setScissorRectangle(const gl::Rectangle &scissor, bool enabled) = 0; + virtual bool setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace, + bool ignoreViewport) = 0; + + virtual bool applyRenderTarget(gl::Framebuffer *frameBuffer) = 0; + virtual void applyShaders(gl::ProgramBinary *programBinary) = 0; + virtual void applyUniforms(gl::ProgramBinary *programBinary, gl::UniformArray *uniformArray) = 0; + virtual bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount) = 0; + virtual GLenum applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], GLint first, GLsizei count, GLsizei instances) = 0; + virtual GLenum applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo) = 0; + + virtual void drawArrays(GLenum mode, GLsizei count, GLsizei instances) = 0; + virtual void drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances) = 0; + + virtual void clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer) = 0; + + virtual void markAllStateDirty() = 0; + + // lost device + virtual void notifyDeviceLost() = 0; + virtual bool isDeviceLost() = 0; + virtual bool testDeviceLost(bool notify) = 0; + virtual bool testDeviceResettable() = 0; + + // Renderer capabilities + virtual DWORD getAdapterVendor() const = 0; + virtual std::string getRendererDescription() const = 0; + virtual GUID getAdapterIdentifier() const = 0; + + virtual bool getBGRATextureSupport() const = 0; + virtual bool getDXT1TextureSupport() = 0; + virtual bool getDXT3TextureSupport() = 0; + virtual bool getDXT5TextureSupport() = 0; + virtual bool getEventQuerySupport() = 0; + virtual bool getFloat32TextureSupport(bool *filtering, bool *renderable) = 0; + virtual bool getFloat16TextureSupport(bool *filtering, bool *renderable) = 0; + virtual bool getLuminanceTextureSupport() = 0; + virtual bool getLuminanceAlphaTextureSupport() = 0; + bool getVertexTextureSupport() const { return getMaxVertexTextureImageUnits() > 0; } + virtual unsigned int getMaxVertexTextureImageUnits() const = 0; + virtual unsigned int getMaxCombinedTextureImageUnits() const = 0; + virtual unsigned int getReservedVertexUniformVectors() const = 0; + virtual unsigned int getReservedFragmentUniformVectors() const = 0; + virtual unsigned int getMaxVertexUniformVectors() const = 0; + virtual unsigned int getMaxFragmentUniformVectors() const = 0; + virtual unsigned int getMaxVaryingVectors() const = 0; + virtual bool getNonPower2TextureSupport() const = 0; + virtual bool getDepthTextureSupport() const = 0; + virtual bool getOcclusionQuerySupport() const = 0; + virtual bool getInstancingSupport() const = 0; + virtual bool getTextureFilterAnisotropySupport() const = 0; + virtual float getTextureMaxAnisotropy() const = 0; + virtual bool getShareHandleSupport() const = 0; + virtual bool getDerivativeInstructionSupport() const = 0; + virtual bool getPostSubBufferSupport() const = 0; + + virtual int getMajorShaderModel() const = 0; + virtual float getMaxPointSize() const = 0; + virtual int getMaxViewportDimension() const = 0; + virtual int getMaxTextureWidth() const = 0; + virtual int getMaxTextureHeight() const = 0; + virtual bool get32BitIndexSupport() const = 0; + virtual int getMinSwapInterval() const = 0; + virtual int getMaxSwapInterval() const = 0; + + virtual GLsizei getMaxSupportedSamples() const = 0; + + virtual unsigned int getMaxRenderTargets() const = 0; + + // Pixel operations + virtual bool copyToRenderTarget(TextureStorageInterface2D *dest, TextureStorageInterface2D *source) = 0; + virtual bool copyToRenderTarget(TextureStorageInterfaceCube *dest, TextureStorageInterfaceCube *source) = 0; + + virtual bool copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + GLint xoffset, GLint yoffset, TextureStorageInterface2D *storage, GLint level) = 0; + virtual bool copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + GLint xoffset, GLint yoffset, TextureStorageInterfaceCube *storage, GLenum target, GLint level) = 0; + + virtual bool blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &readRect, gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect, + bool blitRenderTarget, bool blitDepthStencil) = 0; + 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) = 0; + + // RenderTarget creation + virtual RenderTarget *createRenderTarget(SwapChain *swapChain, bool depth) = 0; + virtual RenderTarget *createRenderTarget(int width, int height, GLenum format, GLsizei samples, bool depth) = 0; + + // 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; + + // Image operations + virtual Image *createImage() = 0; + virtual void generateMipmap(Image *dest, Image *source) = 0; + virtual TextureStorage *createTextureStorage2D(SwapChain *swapChain) = 0; + virtual TextureStorage *createTextureStorage2D(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height) = 0; + virtual TextureStorage *createTextureStorageCube(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size) = 0; + + // Buffer creation + virtual VertexBuffer *createVertexBuffer() = 0; + virtual IndexBuffer *createIndexBuffer() = 0; + virtual BufferStorage *createBufferStorage() = 0; + + // Query and Fence creation + virtual QueryImpl *createQuery(GLenum type) = 0; + virtual FenceImpl *createFence() = 0; + + protected: + bool initializeCompiler(); + ShaderBlob *compileToBinary(gl::InfoLog &infoLog, const char *hlsl, const char *profile, UINT optimizationFlags, bool alternateFlags); + + egl::Display *mDisplay; + + private: + DISALLOW_COPY_AND_ASSIGN(Renderer); + + HMODULE mD3dCompilerModule; + pCompileFunc mD3DCompileFunc; +}; + +} +#endif // LIBGLESV2_RENDERER_RENDERER_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer11.cpp new file mode 100644 index 0000000000..cf083963e1 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer11.cpp @@ -0,0 +1,3531 @@ +#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/clear11ps.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; + mClearPS = 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; + } + + 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; + } + + D3D_FEATURE_LEVEL featureLevels[] = + { + D3D_FEATURE_LEVEL_11_0, + D3D_FEATURE_LEVEL_10_1, + D3D_FEATURE_LEVEL_10_0, + }; + + 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, + &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 + } + + IDXGIDevice *dxgiDevice = NULL; + result = mDevice->QueryInterface(__uuidof(IDXGIDevice), (void**)&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_R32G32B32_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(HWND 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."); + } + + const float blendColors[] = { blendColor.red, blendColor.green, blendColor.blue, 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; + + switch (mode) + { + case GL_POINTS: primitiveTopology = D3D11_PRIMITIVE_TOPOLOGY_POINTLIST; break; + case GL_LINES: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINELIST; break; + case GL_LINE_LOOP: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP; break; + case GL_LINE_STRIP: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP; break; + case GL_TRIANGLES: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; break; + case GL_TRIANGLE_STRIP: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP; break; + // emulate fans via rewriting index buffer + case GL_TRIANGLE_FAN: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; break; + default: + return gl::error(GL_INVALID_ENUM, false); + } + + mDeviceContext->IASetPrimitiveTopology(primitiveTopology); + + return count > 0; +} + +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; + } + + SafeRelease(framebufferRTVs); + SafeRelease(framebufferDSV); + + 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)); + } +} + +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); + } + } + + const int spaceNeeded = (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; + int offset = mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory); + if (offset == -1 || mappedMemory == NULL) + { + 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 = static_cast(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); + } + } + + const int numTris = count - 2; + const 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; + int offset = mTriangleFanIB->mapBuffer(spaceNeeded, &mappedMemory); + if (offset == -1 || mappedMemory == NULL) + { + 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 = static_cast(offset); + + switch (type) + { + case GL_NONE: // Non-indexed draw + for (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 (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 (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 (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); + } + + mDeviceContext->VSSetConstantBuffers(0, 1, &vertexConstantBuffer); + mDeviceContext->PSSetConstantBuffers(0, 1, &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 + mDeviceContext->GSSetConstantBuffers(0, 1, &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); + } + 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); + + framebufferRTV->Release(); + } + } + } + } + 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); + + framebufferDSV->Release(); + } + } + } +} + +void Renderer11::maskedClear(const gl::ClearParameters &clearParams) +{ + HRESULT result; + + if (!mClearResourcesInitialized) + { + ASSERT(!mClearVB && !mClearVS && !mClearPS && !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_Clear, sizeof(g_PS_Clear), NULL, &mClearPS); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mClearPS, "Renderer11 masked clear pixel shader"); + + 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 + mDeviceContext->IASetInputLayout(mClearIL); + mDeviceContext->VSSetShader(mClearVS, NULL, 0); + mDeviceContext->PSSetShader(mClearPS, 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)); +} + +void Renderer11::releaseDeviceResources() +{ + mStateCache.clear(); + mInputLayoutCache.clear(); + + delete mVertexDataManager; + mVertexDataManager = NULL; + + delete mIndexDataManager; + mIndexDataManager = NULL; + + delete mLineLoopIB; + mLineLoopIB = NULL; + + delete mTriangleFanIB; + mTriangleFanIB = NULL; + + if (mCopyVB) + { + mCopyVB->Release(); + mCopyVB = NULL; + } + + if (mCopySampler) + { + mCopySampler->Release(); + mCopySampler = NULL; + } + + if (mCopyIL) + { + mCopyIL->Release(); + mCopyIL = NULL; + } + + if (mCopyVS) + { + mCopyVS->Release(); + mCopyVS = NULL; + } + + if (mCopyRGBAPS) + { + mCopyRGBAPS->Release(); + mCopyRGBAPS = NULL; + } + + if (mCopyRGBPS) + { + mCopyRGBPS->Release(); + mCopyRGBPS = NULL; + } + + if (mCopyLumPS) + { + mCopyLumPS->Release(); + mCopyLumPS = NULL; + } + + if (mCopyLumAlphaPS) + { + mCopyLumAlphaPS->Release(); + mCopyLumAlphaPS = NULL; + } + + mCopyResourcesInitialized = false; + + if (mClearVB) + { + mClearVB->Release(); + mClearVB = NULL; + } + + if (mClearIL) + { + mClearIL->Release(); + mClearIL = NULL; + } + + if (mClearVS) + { + mClearVS->Release(); + mClearVS = NULL; + } + + if (mClearPS) + { + mClearPS->Release(); + mClearPS = NULL; + } + + if (mClearScissorRS) + { + mClearScissorRS->Release(); + mClearScissorRS = NULL; + } + + if (mClearNoScissorRS) + { + mClearNoScissorRS->Release(); + mClearNoScissorRS = NULL; + } + + mClearResourcesInitialized = false; + + if (mDriverConstantBufferVS) + { + mDriverConstantBufferVS->Release(); + mDriverConstantBufferVS = NULL; + } + + if (mDriverConstantBufferPS) + { + mDriverConstantBufferPS->Release(); + mDriverConstantBufferPS = NULL; + } + + if (mSyncQuery) + { + mSyncQuery->Release(); + mSyncQuery = NULL; + } +} + +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, + }; + + 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; + 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); + 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; + 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_10_0); + 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_10_0); + 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; + 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; + 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; + 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: + return true; + 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; + 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 + 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 + 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 + 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 + 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 + 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 + 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); + + 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: + return D3D10_SIMULTANEOUS_RENDER_TARGET_COUNT; // 8 + 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) + { + source->Release(); + 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) + { + source->Release(); + 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) + { + source->Release(); + 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); + + source->Release(); + dest->Release(); + + 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) + { + source->Release(); + 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) + { + source->Release(); + 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) + { + source->Release(); + 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); + + source->Release(); + dest->Release(); + + 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) +{ + const char *profile = NULL; + + 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; + } + + ID3DBlob *binary = (ID3DBlob*)compileToBinary(infoLog, shaderHLSL, profile, 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); + colorBufferRTV->Release(); + + 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 *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) + { + ID3D11Texture2D *unresolvedTexture = readRenderTarget11->getTexture(); + + readTexture = resolveMultisampledTexture(unresolvedTexture, readRenderTarget11->getSubresourceIndex()); + readSubresource = 0; + + unresolvedTexture->Release(); + } + else + { + readTexture = readRenderTarget11->getTexture(); + 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); + } + + RenderTarget11 *drawRenderTarget11 = RenderTarget11::makeRenderTarget11(drawRenderTarget); + if (!drawRenderTarget) + { + readTexture->Release(); + 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(); + + 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); + + readTexture->Release(); + drawTexture->Release(); + + 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; + } +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer11.h new file mode 100644 index 0000000000..a3e42e9048 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer11.h @@ -0,0 +1,348 @@ +// +// 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_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(HWND 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; }; + + bool getRenderTargetResource(gl::Renderbuffer *colorbuffer, unsigned int *subresourceIndex, ID3D11Texture2D **resource); + void unapplyRenderTargets(); + void setOneTimeRenderTarget(ID3D11RenderTargetView *renderTargetView); + + 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); + 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; + + unsigned int mAppliedIBSerial; + unsigned int mAppliedStorageIBSerial; + unsigned int mAppliedIBOffset; + + unsigned int mAppliedProgramBinarySerial; + bool mIsGeometryShaderActive; + + dx_VertexConstants mVertexConstants; + dx_VertexConstants mAppliedVertexConstants; + ID3D11Buffer *mDriverConstantBufferVS; + + dx_PixelConstants mPixelConstants; + dx_PixelConstants mAppliedPixelConstants; + ID3D11Buffer *mDriverConstantBufferPS; + + // 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 *mClearPS; + 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 new file mode 100644 index 0000000000..8acbce4be7 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer9.cpp @@ -0,0 +1,3211 @@ +#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" + +// 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) + +#if !defined(ANGLE_COMPILE_OPTIMIZATION_LEVEL) +#define ANGLE_COMPILE_OPTIMIZATION_LEVEL D3DCOMPILE_OPTIMIZATION_LEVEL3 +#endif + +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) + { + mD3d9Module = GetModuleHandle(TEXT("swiftshader_d3d9.dll")); + } + else + { + 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))) + { + ASSERT(mD3d9Ex); + mD3d9Ex->QueryInterface(IID_IDirect3D9, reinterpret_cast(&mD3d9)); + ASSERT(mD3d9); + } + else + { + 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. + 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; + } + + 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; + 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; + } + } + } + + 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"); + + 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; + + 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)) + { + 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) + { + result = mDevice->QueryInterface(IID_IDirect3DDevice9Ex, (void**) &mDeviceEx); + ASSERT(SUCCEEDED(result)); + } + + mVertexShaderCache.initialize(mDevice); + mPixelShaderCache.initialize(mDevice); + + // Check occlusion query support + IDirect3DQuery9 *occlusionQuery = NULL; + if (SUCCEEDED(mDevice->CreateQuery(D3DQUERYTYPE_OCCLUSION, &occlusionQuery)) && occlusionQuery) + { + occlusionQuery->Release(); + mOcclusionQuerySupport = true; + } + else + { + mOcclusionQuerySupport = false; + } + + // Check event query support + IDirect3DQuery9 *eventQuery = NULL; + 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 + } + + bool viewportChanged = mForceSetViewport || memcmp(&actualViewport, &mCurViewport, sizeof(gl::Rectangle)) != 0 || + actualZNear != mCurNear || actualZFar != mCurFar; + if (viewportChanged) + { + mDevice->SetViewport(&dxViewport); + + mCurViewport = actualViewport; + mCurNear = actualZNear; + mCurFar = actualZFar; + + 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] = !gl::IsTriangleMode(drawMode) ? 0.0f : (frontFace == GL_CCW ? 1.0f : -1.0f);; + + 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; + } + + UINT 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); + } + } + + const int spaceNeeded = (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; + int offset = mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory); + if (offset == -1 || mappedMemory == NULL) + { + 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); + } + } + + const int spaceNeeded = (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; + int offset = mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory); + if (offset == -1 || mappedMemory == NULL) + { + 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); + + if (status == S_PRESENT_MODE_CHANGED) + { + // Reset the device so that D3D stops reporting S_PRESENT_MODE_CHANGED. Otherwise it will report + // it continuously, potentially masking a lost device. D3D resources are not lost on a mode change with WDDM. + D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters(); + mDeviceEx->Reset(&presentParameters); + + // Existing swap chains sometimes crash on the next present after a reset. + mDisplay->recreateSwapChains(); + + // Reset will not always cause the device loss to be reported so issue a dummy present. + mDeviceEx->Present(NULL, NULL, NULL, NULL); + + // Retest the device status to see if the mode change really indicated a lost device. + 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); +} + +} \ No newline at end of file diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer9.h b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer9.h new file mode 100644 index 0000000000..527a5010ae --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer9.h @@ -0,0 +1,347 @@ +// +// 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; + + 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; + + 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/ShaderCache.h b/src/3rdparty/angle/src/libGLESv2/renderer/ShaderCache.h new file mode 100644 index 0000000000..4391ac271a --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/ShaderCache.h @@ -0,0 +1,110 @@ +// +// 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. +// + +// ShaderCache: Defines rx::ShaderCache, a cache of Direct3D shader objects +// keyed by their byte code. + +#ifndef LIBGLESV2_RENDERER_SHADER_CACHE_H_ +#define LIBGLESV2_RENDERER_SHADER_CACHE_H_ + +#include "common/debug.h" + +namespace rx +{ +template +class ShaderCache +{ + public: + ShaderCache() : mDevice(NULL) + { + } + + ~ShaderCache() + { + // Call clear while the device is still valid. + ASSERT(mMap.empty()); + } + + void initialize(IDirect3DDevice9* device) + { + mDevice = device; + } + + ShaderObject *create(const DWORD *function, size_t length) + { + std::string key(reinterpret_cast(function), length); + typename Map::iterator it = mMap.find(key); + if (it != mMap.end()) + { + it->second->AddRef(); + return it->second; + } + + ShaderObject *shader; + HRESULT result = createShader(function, &shader); + if (FAILED(result)) + { + return NULL; + } + + // Random eviction policy. + if (mMap.size() >= kMaxMapSize) + { + mMap.begin()->second->Release(); + mMap.erase(mMap.begin()); + } + + shader->AddRef(); + mMap[key] = shader; + + return shader; + } + + void clear() + { + for (typename Map::iterator it = mMap.begin(); it != mMap.end(); ++it) + { + it->second->Release(); + } + + mMap.clear(); + } + + private: + DISALLOW_COPY_AND_ASSIGN(ShaderCache); + + const static size_t kMaxMapSize = 100; + + HRESULT createShader(const DWORD *function, IDirect3DVertexShader9 **shader) + { + return mDevice->CreateVertexShader(function, shader); + } + + HRESULT createShader(const DWORD *function, IDirect3DPixelShader9 **shader) + { + return mDevice->CreatePixelShader(function, shader); + } + +#ifndef HASH_MAP +# ifdef _MSC_VER +# define HASH_MAP stdext::hash_map +# else +# define HASH_MAP std::unordered_map +# endif +#endif + + typedef HASH_MAP Map; + Map mMap; + + IDirect3DDevice9 *mDevice; +}; + +typedef ShaderCache VertexShaderCache; +typedef ShaderCache PixelShaderCache; + +} + +#endif // LIBGLESV2_RENDERER_SHADER_CACHE_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable.h b/src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable.h new file mode 100644 index 0000000000..128d123fbe --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable.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. +// + +// ShaderExecutable.h: Defines a renderer-agnostic class to contain shader +// executable implementation details. + +#ifndef LIBGLESV2_RENDERER_SHADEREXECUTABLE_H_ +#define LIBGLESV2_RENDERER_SHADEREXECUTABLE_H_ + +#include "common/angleutils.h" + +namespace rx +{ + +class ShaderExecutable +{ + public: + ShaderExecutable(const void *function, size_t length) : mLength(length) + { + mFunction = new char[length]; + memcpy(mFunction, function, length); + } + + virtual ~ShaderExecutable() + { + delete mFunction; + } + + void *getFunction() const + { + return mFunction; + } + + size_t getLength() const + { + return mLength; + } + + private: + DISALLOW_COPY_AND_ASSIGN(ShaderExecutable); + + void *mFunction; + const size_t mLength; +}; + +} + +#endif // LIBGLESV2_RENDERER_SHADEREXECUTABLE9_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable11.cpp new file mode 100644 index 0000000000..e1eb560334 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/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/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 new file mode 100644 index 0000000000..c6ec1cf7d2 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/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/ShaderExecutable9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable9.cpp new file mode 100644 index 0000000000..98868a3fbf --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/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/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 new file mode 100644 index 0000000000..fa1e6c2844 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/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/SwapChain.h b/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.h new file mode 100644 index 0000000000..14c0515fc8 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.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. +// + +// SwapChain.h: Defines a back-end specific class that hides the details of the +// implementation-specific swapchain. + +#ifndef LIBGLESV2_RENDERER_SWAPCHAIN_H_ +#define LIBGLESV2_RENDERER_SWAPCHAIN_H_ + +#include "common/angleutils.h" + +namespace rx +{ + +class SwapChain +{ + public: + SwapChain(HWND window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) + : mWindow(window), mShareHandle(shareHandle), mBackBufferFormat(backBufferFormat), mDepthBufferFormat(depthBufferFormat) + { + } + + virtual ~SwapChain() {}; + + virtual EGLint resize(EGLint backbufferWidth, EGLint backbufferSize) = 0; + virtual EGLint reset(EGLint backbufferWidth, EGLint backbufferHeight, EGLint swapInterval) = 0; + virtual EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height) = 0; + virtual void recreate() = 0; + + virtual HANDLE getShareHandle() {return mShareHandle;}; + + protected: + const HWND mWindow; // Window that the surface is created for. + const GLenum mBackBufferFormat; + const GLenum mDepthBufferFormat; + + HANDLE mShareHandle; +}; + +} +#endif // LIBGLESV2_RENDERER_SWAPCHAIN_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain11.cpp new file mode 100644 index 0000000000..87422be727 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain11.cpp @@ -0,0 +1,767 @@ +#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, HWND 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); + + 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; + } + + // 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) + { + // 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.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapChainDesc.Flags = 0; + swapChainDesc.OutputWindow = mWindow; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.Windowed = TRUE; + + HRESULT result = factory->CreateSwapChain(device, &swapChainDesc, &mSwapChain); + + 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 new file mode 100644 index 0000000000..800104602e --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/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, HWND 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 new file mode 100644 index 0000000000..f57a874688 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain9.cpp @@ -0,0 +1,449 @@ +#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 new file mode 100644 index 0000000000..16a62bd86f --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/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/TextureStorage.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage.cpp new file mode 100644 index 0000000000..00b316f1cc --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage.cpp @@ -0,0 +1,122 @@ +#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. +// + +// TextureStorage.cpp: Implements the abstract rx::TextureStorageInterface class and its concrete derived +// classes TextureStorageInterface2D and TextureStorageInterfaceCube, which act as the interface to the +// GPU-side texture. + +#include "libGLESv2/renderer/TextureStorage.h" +#include "libGLESv2/renderer/Renderer.h" +#include "libGLESv2/Renderbuffer.h" +#include "libGLESv2/Texture.h" + +#include "common/debug.h" + +namespace rx +{ +unsigned int TextureStorageInterface::mCurrentTextureSerial = 1; + +TextureStorageInterface::TextureStorageInterface() + : mTextureSerial(issueTextureSerial()), + mInstance(NULL) +{ +} + +TextureStorageInterface::~TextureStorageInterface() +{ + delete mInstance; +} + +bool TextureStorageInterface::isRenderTarget() const +{ + return mInstance->isRenderTarget(); +} + + +bool TextureStorageInterface::isManaged() const +{ + return mInstance->isManaged(); +} + +unsigned int TextureStorageInterface::getTextureSerial() const +{ + return mTextureSerial; +} + +unsigned int TextureStorageInterface::issueTextureSerial() +{ + return mCurrentTextureSerial++; +} + +int TextureStorageInterface::getLodOffset() const +{ + return mInstance->getLodOffset(); +} + + +int TextureStorageInterface::levelCount() +{ + return mInstance->levelCount(); +} + +TextureStorageInterface2D::TextureStorageInterface2D(Renderer *renderer, SwapChain *swapchain) + : mRenderTargetSerial(gl::RenderbufferStorage::issueSerial()) +{ + mInstance = renderer->createTextureStorage2D(swapchain); +} + +TextureStorageInterface2D::TextureStorageInterface2D(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height) + : mRenderTargetSerial(gl::RenderbufferStorage::issueSerial()) +{ + mInstance = renderer->createTextureStorage2D(levels, internalformat, usage, forceRenderable, width, height); +} + +TextureStorageInterface2D::~TextureStorageInterface2D() +{ +} + +RenderTarget *TextureStorageInterface2D::getRenderTarget() const +{ + return mInstance->getRenderTarget(); +} + +void TextureStorageInterface2D::generateMipmap(int level) +{ + mInstance->generateMipmap(level); +} + +unsigned int TextureStorageInterface2D::getRenderTargetSerial(GLenum target) const +{ + return mRenderTargetSerial; +} + +TextureStorageInterfaceCube::TextureStorageInterfaceCube(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size) + : mFirstRenderTargetSerial(gl::RenderbufferStorage::issueCubeSerials()) +{ + mInstance = renderer->createTextureStorageCube(levels, internalformat, usage, forceRenderable, size); +} + +TextureStorageInterfaceCube::~TextureStorageInterfaceCube() +{ +} + +RenderTarget *TextureStorageInterfaceCube::getRenderTarget(GLenum faceTarget) const +{ + return mInstance->getRenderTarget(faceTarget); +} + +void TextureStorageInterfaceCube::generateMipmap(int face, int level) +{ + mInstance->generateMipmap(face, level); +} + +unsigned int TextureStorageInterfaceCube::getRenderTargetSerial(GLenum target) const +{ + return mFirstRenderTargetSerial + gl::TextureCubeMap::faceIndex(target); +} + +} \ No newline at end of file diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage.h b/src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage.h new file mode 100644 index 0000000000..edddb75f3f --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage.h @@ -0,0 +1,110 @@ +// +// 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. +// + +// TextureStorage.h: Defines the abstract rx::TextureStorageInterface class and its concrete derived +// classes TextureStorageInterface2D and TextureStorageInterfaceCube, which act as the interface to the +// GPU-side texture. + +#ifndef LIBGLESV2_RENDERER_TEXTURESTORAGE_H_ +#define LIBGLESV2_RENDERER_TEXTURESTORAGE_H_ + +#include "common/debug.h" + +namespace rx +{ +class Renderer; +class SwapChain; +class RenderTarget; +class Blit; + +class TextureStorage +{ + public: + TextureStorage() {}; + virtual ~TextureStorage() {}; + + virtual int getLodOffset() const = 0; + virtual bool isRenderTarget() const = 0; + virtual bool isManaged() const = 0; + virtual int levelCount() = 0; + + virtual RenderTarget *getRenderTarget() = 0; + virtual RenderTarget *getRenderTarget(GLenum faceTarget) = 0; + virtual void generateMipmap(int level) = 0; + virtual void generateMipmap(int face, int level) = 0; + + private: + DISALLOW_COPY_AND_ASSIGN(TextureStorage); + +}; + +class TextureStorageInterface +{ + public: + TextureStorageInterface(); + virtual ~TextureStorageInterface(); + + TextureStorage *getStorageInstance() { return mInstance; } + + unsigned int getTextureSerial() const; + virtual unsigned int getRenderTargetSerial(GLenum target) const = 0; + + virtual int getLodOffset() const; + virtual bool isRenderTarget() const; + virtual bool isManaged() const; + virtual int levelCount(); + + protected: + TextureStorage *mInstance; + + private: + DISALLOW_COPY_AND_ASSIGN(TextureStorageInterface); + + const unsigned int mTextureSerial; + static unsigned int issueTextureSerial(); + + static unsigned int mCurrentTextureSerial; +}; + +class TextureStorageInterface2D : public TextureStorageInterface +{ + public: + TextureStorageInterface2D(Renderer *renderer, SwapChain *swapchain); + TextureStorageInterface2D(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height); + virtual ~TextureStorageInterface2D(); + + void generateMipmap(int level); + RenderTarget *getRenderTarget() const; + + virtual unsigned int getRenderTargetSerial(GLenum target) const; + + private: + DISALLOW_COPY_AND_ASSIGN(TextureStorageInterface2D); + + const unsigned int mRenderTargetSerial; +}; + +class TextureStorageInterfaceCube : public TextureStorageInterface +{ + public: + TextureStorageInterfaceCube(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size); + virtual ~TextureStorageInterfaceCube(); + + void generateMipmap(int face, int level); + RenderTarget *getRenderTarget(GLenum faceTarget) const; + + virtual unsigned int getRenderTargetSerial(GLenum target) const; + + private: + DISALLOW_COPY_AND_ASSIGN(TextureStorageInterfaceCube); + + const unsigned int mFirstRenderTargetSerial; +}; + +} + +#endif // LIBGLESV2_RENDERER_TEXTURESTORAGE_H_ + diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage11.cpp new file mode 100644 index 0000000000..667dbff175 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage11.cpp @@ -0,0 +1,676 @@ +#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_R32G32B32_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: + 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); + } + + if (sourceSRV) + { + sourceSRV->Release(); + } + if (destRTV) + { + destRTV->Release(); + } + } +} + +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), usage, forceRenderable)) +{ + for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) + { + mRenderTarget[i] = NULL; + } + + DXGI_FORMAT convertedFormat = gl_d3d11::ConvertTextureFormat(internalformat); + 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), 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); + 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 new file mode 100644 index 0000000000..3c5ded05b8 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/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/TextureStorage9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage9.cpp new file mode 100644 index 0000000000..8aa74a7cba --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/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/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 new file mode 100644 index 0000000000..86f551a131 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/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/VertexBuffer.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer.cpp new file mode 100644 index 0000000000..16e1486511 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer.cpp @@ -0,0 +1,229 @@ +#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. +// + +// VertexBuffer.cpp: Defines the abstract VertexBuffer class and VertexBufferInterface +// class with derivations, classes that perform graphics API agnostic vertex buffer operations. + +#include "libGLESv2/renderer/VertexBuffer.h" +#include "libGLESv2/renderer/Renderer.h" +#include "libGLESv2/Context.h" + +namespace rx +{ + +unsigned int VertexBuffer::mNextSerial = 1; + +VertexBuffer::VertexBuffer() +{ + updateSerial(); +} + +VertexBuffer::~VertexBuffer() +{ +} + +void VertexBuffer::updateSerial() +{ + mSerial = mNextSerial++; +} + +unsigned int VertexBuffer::getSerial() const +{ + return mSerial; +} + +VertexBufferInterface::VertexBufferInterface(rx::Renderer *renderer, bool dynamic) : mRenderer(renderer) +{ + mDynamic = dynamic; + mWritePosition = 0; + mReservedSpace = 0; + + mVertexBuffer = renderer->createVertexBuffer(); +} + +VertexBufferInterface::~VertexBufferInterface() +{ + delete mVertexBuffer; +} + +unsigned int VertexBufferInterface::getSerial() const +{ + return mVertexBuffer->getSerial(); +} + +unsigned int VertexBufferInterface::getBufferSize() const +{ + return mVertexBuffer->getBufferSize(); +} + +bool VertexBufferInterface::setBufferSize(unsigned int size) +{ + if (mVertexBuffer->getBufferSize() == 0) + { + return mVertexBuffer->initialize(size, mDynamic); + } + else + { + return mVertexBuffer->setBufferSize(size); + } +} + +unsigned int VertexBufferInterface::getWritePosition() const +{ + return mWritePosition; +} + +void VertexBufferInterface::setWritePosition(unsigned int writePosition) +{ + mWritePosition = writePosition; +} + +bool VertexBufferInterface::discard() +{ + return mVertexBuffer->discard(); +} + +int VertexBufferInterface::storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, GLsizei instances) +{ + if (!reserveSpace(mReservedSpace)) + { + return -1; + } + mReservedSpace = 0; + + if (!mVertexBuffer->storeVertexAttributes(attrib, start, count, instances, mWritePosition)) + { + return -1; + } + + int oldWritePos = static_cast(mWritePosition); + mWritePosition += mVertexBuffer->getSpaceRequired(attrib, count, instances); + + return oldWritePos; +} + +int VertexBufferInterface::storeRawData(const void* data, unsigned int size) +{ + if (!reserveSpace(mReservedSpace)) + { + return -1; + } + mReservedSpace = 0; + + if (!mVertexBuffer->storeRawData(data, size, mWritePosition)) + { + return -1; + } + + int oldWritePos = static_cast(mWritePosition); + mWritePosition += size; + + return oldWritePos; +} + +void VertexBufferInterface::reserveVertexSpace(const gl::VertexAttribute &attribute, GLsizei count, GLsizei instances) +{ + mReservedSpace += mVertexBuffer->getSpaceRequired(attribute, count, instances); +} + +void VertexBufferInterface::reserveRawDataSpace(unsigned int size) +{ + mReservedSpace += size; +} + +VertexBuffer* VertexBufferInterface::getVertexBuffer() const +{ + return mVertexBuffer; +} + + +StreamingVertexBufferInterface::StreamingVertexBufferInterface(rx::Renderer *renderer, std::size_t initialSize) : VertexBufferInterface(renderer, true) +{ + setBufferSize(initialSize); +} + +StreamingVertexBufferInterface::~StreamingVertexBufferInterface() +{ +} + +bool StreamingVertexBufferInterface::reserveSpace(unsigned int size) +{ + bool result = true; + unsigned int curBufferSize = getBufferSize(); + if (size > curBufferSize) + { + result = setBufferSize(std::max(size, 3 * curBufferSize / 2)); + setWritePosition(0); + } + else if (getWritePosition() + size > curBufferSize) + { + if (!discard()) + { + return false; + } + setWritePosition(0); + } + + return result; +} + +StaticVertexBufferInterface::StaticVertexBufferInterface(rx::Renderer *renderer) : VertexBufferInterface(renderer, false) +{ +} + +StaticVertexBufferInterface::~StaticVertexBufferInterface() +{ +} + +int StaticVertexBufferInterface::lookupAttribute(const gl::VertexAttribute &attribute) +{ + for (unsigned int element = 0; element < mCache.size(); element++) + { + if (mCache[element].type == attribute.mType && + mCache[element].size == attribute.mSize && + mCache[element].stride == attribute.stride() && + mCache[element].normalized == attribute.mNormalized) + { + if (mCache[element].attributeOffset == attribute.mOffset % attribute.stride()) + { + return mCache[element].streamOffset; + } + } + } + + return -1; +} + +bool StaticVertexBufferInterface::reserveSpace(unsigned int size) +{ + unsigned int curSize = getBufferSize(); + if (curSize == 0) + { + setBufferSize(size); + return true; + } + else if (curSize >= size) + { + return true; + } + else + { + UNREACHABLE(); // Static vertex buffers can't be resized + return false; + } +} + +int StaticVertexBufferInterface::storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, GLsizei instances) +{ + int attributeOffset = attrib.mOffset % attrib.stride(); + VertexElement element = { attrib.mType, attrib.mSize, attrib.stride(), attrib.mNormalized, attributeOffset, getWritePosition() }; + mCache.push_back(element); + + return VertexBufferInterface::storeVertexAttributes(attrib, start, count, instances); +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer.h b/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer.h new file mode 100644 index 0000000000..6ecffd0c0b --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer.h @@ -0,0 +1,138 @@ +// +// 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. +// + +// VertexBuffer.h: Defines the abstract VertexBuffer class and VertexBufferInterface +// class with derivations, classes that perform graphics API agnostic vertex buffer operations. + +#ifndef LIBGLESV2_RENDERER_VERTEXBUFFER_H_ +#define LIBGLESV2_RENDERER_VERTEXBUFFER_H_ + +#include "common/angleutils.h" + +namespace gl +{ +class VertexAttribute; +} + +namespace rx +{ +class Renderer; + +class VertexBuffer +{ + public: + VertexBuffer(); + virtual ~VertexBuffer(); + + virtual bool initialize(unsigned int size, bool dynamicUsage) = 0; + + virtual bool storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, + GLsizei instances, unsigned int offset) = 0; + virtual bool storeRawData(const void* data, unsigned int size, unsigned int offset) = 0; + + virtual unsigned int getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, + GLsizei instances) const = 0; + + virtual bool requiresConversion(const gl::VertexAttribute &attrib) const = 0; + + virtual unsigned int getBufferSize() const = 0; + virtual bool setBufferSize(unsigned int size) = 0; + virtual bool discard() = 0; + + unsigned int getSerial() const; + + protected: + void updateSerial(); + + private: + DISALLOW_COPY_AND_ASSIGN(VertexBuffer); + + unsigned int mSerial; + static unsigned int mNextSerial; +}; + +class VertexBufferInterface +{ + public: + VertexBufferInterface(rx::Renderer *renderer, bool dynamic); + virtual ~VertexBufferInterface(); + + void reserveVertexSpace(const gl::VertexAttribute &attribute, GLsizei count, GLsizei instances); + void reserveRawDataSpace(unsigned int size); + + unsigned int getBufferSize() const; + + unsigned int getSerial() const; + + virtual int storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, GLsizei instances); + virtual int storeRawData(const void* data, unsigned int size); + + VertexBuffer* getVertexBuffer() const; + + protected: + virtual bool reserveSpace(unsigned int size) = 0; + + unsigned int getWritePosition() const; + void setWritePosition(unsigned int writePosition); + + bool discard(); + + bool setBufferSize(unsigned int size); + + private: + DISALLOW_COPY_AND_ASSIGN(VertexBufferInterface); + + rx::Renderer *const mRenderer; + + VertexBuffer* mVertexBuffer; + + unsigned int mWritePosition; + unsigned int mReservedSpace; + bool mDynamic; +}; + +class StreamingVertexBufferInterface : public VertexBufferInterface +{ + public: + StreamingVertexBufferInterface(rx::Renderer *renderer, std::size_t initialSize); + ~StreamingVertexBufferInterface(); + + protected: + bool reserveSpace(unsigned int size); +}; + +class StaticVertexBufferInterface : public VertexBufferInterface +{ + public: + explicit StaticVertexBufferInterface(rx::Renderer *renderer); + ~StaticVertexBufferInterface(); + + int storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, GLsizei instances); + + // Returns the offset into the vertex buffer, or -1 if not found + int lookupAttribute(const gl::VertexAttribute &attribute); + + protected: + bool reserveSpace(unsigned int size); + + private: + struct VertexElement + { + GLenum type; + GLint size; + GLsizei stride; + bool normalized; + int attributeOffset; + + unsigned int streamOffset; + }; + + std::vector mCache; +}; + +} + +#endif // LIBGLESV2_RENDERER_VERTEXBUFFER_H_ \ No newline at end of file diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer11.cpp new file mode 100644 index 0000000000..92c8755e22 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer11.cpp @@ -0,0 +1,418 @@ +#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; + } +} + +unsigned int VertexBuffer11::getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, + GLsizei instances) const +{ + unsigned int elementSize = getVertexConversion(attrib).outputElementSize; + + if (instances == 0 || attrib.mDivisor == 0) + { + return elementSize * count; + } + else + { + return elementSize * ((instances + attrib.mDivisor - 1) / attrib.mDivisor); + } +} + +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 new file mode 100644 index 0000000000..75e025075e --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer11.h @@ -0,0 +1,73 @@ +// +// 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 unsigned int getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances) 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_ \ No newline at end of file diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer9.cpp new file mode 100644 index 0000000000..76dc73e391 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer9.cpp @@ -0,0 +1,486 @@ +#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; + HRESULT result = mVertexBuffer->Lock(offset, spaceRequired(attrib, count, instances), &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; + } +} + +unsigned int VertexBuffer9::getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances) const +{ + return spaceRequired(attrib, count, instances); +} + +bool VertexBuffer9::requiresConversion(const gl::VertexAttribute &attrib) const +{ + return formatConverter(attrib).identity; +} + +unsigned int VertexBuffer9::getVertexSize(const gl::VertexAttribute &attrib) const +{ + return spaceRequired(attrib, 1, 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]; +} + +unsigned int VertexBuffer9::spaceRequired(const gl::VertexAttribute &attrib, std::size_t count, GLsizei instances) +{ + unsigned int elementSize = formatConverter(attrib).outputElementSize; + + if (instances == 0 || attrib.mDivisor == 0) + { + return elementSize * count; + } + else + { + return elementSize * ((instances + attrib.mDivisor - 1) / attrib.mDivisor); + } +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer9.h b/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer9.h new file mode 100644 index 0000000000..f771635bda --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer9.h @@ -0,0 +1,90 @@ +// +// 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 unsigned int getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances) 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 unsigned int spaceRequired(const gl::VertexAttribute &attrib, std::size_t count, GLsizei instances); +}; + +} + +#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 new file mode 100644 index 0000000000..ec85857264 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/VertexDataManager.cpp @@ -0,0 +1,258 @@ +#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. +// + +// VertexDataManager.h: Defines the VertexDataManager, a class that +// runs the Buffer translation process. + +#include "libGLESv2/renderer/VertexDataManager.h" +#include "libGLESv2/renderer/BufferStorage.h" + +#include "libGLESv2/Buffer.h" +#include "libGLESv2/ProgramBinary.h" +#include "libGLESv2/Context.h" +#include "libGLESv2/renderer/VertexBuffer.h" + +namespace +{ + enum { INITIAL_STREAM_BUFFER_SIZE = 1024*1024 }; + // This has to be at least 4k or else it fails on ATI cards. + enum { CONSTANT_VERTEX_BUFFER_SIZE = 4096 }; +} + +namespace rx +{ + +static int elementsInBuffer(const gl::VertexAttribute &attribute, int size) +{ + int stride = attribute.stride(); + return (size - attribute.mOffset % stride + (stride - attribute.typeSize())) / stride; +} + +VertexDataManager::VertexDataManager(Renderer *renderer) : mRenderer(renderer) +{ + for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + mCurrentValue[i][0] = std::numeric_limits::quiet_NaN(); + mCurrentValue[i][1] = std::numeric_limits::quiet_NaN(); + mCurrentValue[i][2] = std::numeric_limits::quiet_NaN(); + mCurrentValue[i][3] = std::numeric_limits::quiet_NaN(); + mCurrentValueBuffer[i] = NULL; + mCurrentValueOffsets[i] = 0; + } + + mStreamingBuffer = new StreamingVertexBufferInterface(renderer, INITIAL_STREAM_BUFFER_SIZE); + + if (!mStreamingBuffer) + { + ERR("Failed to allocate the streaming vertex buffer."); + } +} + +VertexDataManager::~VertexDataManager() +{ + delete mStreamingBuffer; + + for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + delete mCurrentValueBuffer[i]; + } +} + +static bool directStoragePossible(VertexBufferInterface* vb, const gl::VertexAttribute& attrib) +{ + gl::Buffer *buffer = attrib.mBoundBuffer.get(); + BufferStorage *storage = buffer ? buffer->getStorage() : NULL; + + const bool isAligned = (attrib.stride() % 4 == 0) && (attrib.mOffset % 4 == 0); + + return storage && storage->supportsDirectBinding() && !vb->getVertexBuffer()->requiresConversion(attrib) && isAligned; +} + +GLenum VertexDataManager::prepareVertexData(const gl::VertexAttribute attribs[], gl::ProgramBinary *programBinary, GLint start, GLsizei count, TranslatedAttribute *translated, GLsizei instances) +{ + if (!mStreamingBuffer) + { + return GL_OUT_OF_MEMORY; + } + + for (int attributeIndex = 0; attributeIndex < gl::MAX_VERTEX_ATTRIBS; attributeIndex++) + { + translated[attributeIndex].active = (programBinary->getSemanticIndex(attributeIndex) != -1); + } + + // Invalidate static buffers that don't contain matching attributes + for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + if (translated[i].active && attribs[i].mArrayEnabled) + { + gl::Buffer *buffer = attribs[i].mBoundBuffer.get(); + StaticVertexBufferInterface *staticBuffer = buffer ? buffer->getStaticVertexBuffer() : NULL; + + if (staticBuffer && staticBuffer->getBufferSize() > 0 && staticBuffer->lookupAttribute(attribs[i]) == -1 && + !directStoragePossible(staticBuffer, attribs[i])) + { + buffer->invalidateStaticData(); + } + } + } + + // Reserve the required space in the buffers + for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + if (translated[i].active && attribs[i].mArrayEnabled) + { + gl::Buffer *buffer = attribs[i].mBoundBuffer.get(); + StaticVertexBufferInterface *staticBuffer = buffer ? buffer->getStaticVertexBuffer() : NULL; + VertexBufferInterface *vertexBuffer = staticBuffer ? staticBuffer : static_cast(mStreamingBuffer); + + if (!directStoragePossible(vertexBuffer, attribs[i])) + { + if (staticBuffer) + { + if (staticBuffer->getBufferSize() == 0) + { + int totalCount = elementsInBuffer(attribs[i], buffer->size()); + staticBuffer->reserveVertexSpace(attribs[i], totalCount, 0); + } + } + else + { + mStreamingBuffer->reserveVertexSpace(attribs[i], count, instances); + } + } + } + } + + // Perform the vertex data translations + for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + if (translated[i].active) + { + if (attribs[i].mArrayEnabled) + { + gl::Buffer *buffer = attribs[i].mBoundBuffer.get(); + + if (!buffer && attribs[i].mPointer == NULL) + { + // This is an application error that would normally result in a crash, but we catch it and return an error + ERR("An enabled vertex array has no buffer and no pointer."); + return GL_INVALID_OPERATION; + } + + StaticVertexBufferInterface *staticBuffer = buffer ? buffer->getStaticVertexBuffer() : NULL; + VertexBufferInterface *vertexBuffer = staticBuffer ? staticBuffer : static_cast(mStreamingBuffer); + + BufferStorage *storage = buffer ? buffer->getStorage() : NULL; + bool directStorage = directStoragePossible(vertexBuffer, attribs[i]); + + std::size_t streamOffset = -1; + unsigned int outputElementSize = 0; + + if (directStorage) + { + outputElementSize = attribs[i].stride(); + streamOffset = attribs[i].mOffset + outputElementSize * start; + storage->markBufferUsage(); + } + else if (staticBuffer) + { + streamOffset = staticBuffer->lookupAttribute(attribs[i]); + outputElementSize = staticBuffer->getVertexBuffer()->getSpaceRequired(attribs[i], 1, 0); + + if (streamOffset == -1) + { + // Convert the entire buffer + int totalCount = elementsInBuffer(attribs[i], storage->getSize()); + int startIndex = attribs[i].mOffset / attribs[i].stride(); + + streamOffset = staticBuffer->storeVertexAttributes(attribs[i], -startIndex, totalCount, 0); + } + + if (streamOffset != -1) + { + streamOffset += (attribs[i].mOffset / attribs[i].stride()) * outputElementSize; + + if (instances == 0 || attribs[i].mDivisor == 0) + { + streamOffset += start * outputElementSize; + } + } + } + else + { + outputElementSize = mStreamingBuffer->getVertexBuffer()->getSpaceRequired(attribs[i], 1, 0); + streamOffset = mStreamingBuffer->storeVertexAttributes(attribs[i], start, count, instances); + } + + if (streamOffset == -1) + { + return GL_OUT_OF_MEMORY; + } + + translated[i].storage = directStorage ? storage : NULL; + translated[i].vertexBuffer = vertexBuffer->getVertexBuffer(); + translated[i].serial = directStorage ? storage->getSerial() : vertexBuffer->getSerial(); + translated[i].divisor = attribs[i].mDivisor; + + translated[i].attribute = &attribs[i]; + translated[i].stride = outputElementSize; + translated[i].offset = streamOffset; + } + else + { + if (!mCurrentValueBuffer[i]) + { + mCurrentValueBuffer[i] = new StreamingVertexBufferInterface(mRenderer, CONSTANT_VERTEX_BUFFER_SIZE); + } + + StreamingVertexBufferInterface *buffer = mCurrentValueBuffer[i]; + + if (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]) + { + unsigned int requiredSpace = sizeof(float) * 4; + buffer->reserveRawDataSpace(requiredSpace); + int streamOffset = buffer->storeRawData(attribs[i].mCurrentValue, requiredSpace); + if (streamOffset == -1) + { + return GL_OUT_OF_MEMORY; + } + + mCurrentValueOffsets[i] = streamOffset; + } + + translated[i].storage = NULL; + translated[i].vertexBuffer = mCurrentValueBuffer[i]->getVertexBuffer(); + translated[i].serial = mCurrentValueBuffer[i]->getSerial(); + translated[i].divisor = 0; + + translated[i].attribute = &attribs[i]; + translated[i].stride = 0; + translated[i].offset = mCurrentValueOffsets[i]; + } + } + } + + for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + if (translated[i].active && attribs[i].mArrayEnabled) + { + gl::Buffer *buffer = attribs[i].mBoundBuffer.get(); + + if (buffer) + { + buffer->promoteStaticUsage(count * attribs[i].typeSize()); + } + } + } + + return GL_NO_ERROR; +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/VertexDataManager.h b/src/3rdparty/angle/src/libGLESv2/renderer/VertexDataManager.h new file mode 100644 index 0000000000..28387e6baf --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/VertexDataManager.h @@ -0,0 +1,65 @@ +// +// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// VertexDataManager.h: Defines the VertexDataManager, a class that +// runs the Buffer translation process. + +#ifndef LIBGLESV2_RENDERER_VERTEXDATAMANAGER_H_ +#define LIBGLESV2_RENDERER_VERTEXDATAMANAGER_H_ + +#include "libGLESv2/Constants.h" +#include "common/angleutils.h" + +namespace gl +{ +class VertexAttribute; +class ProgramBinary; +} + +namespace rx +{ +class BufferStorage; +class StreamingVertexBufferInterface; +class VertexBuffer; +class Renderer; + +struct TranslatedAttribute +{ + bool active; + + const gl::VertexAttribute *attribute; + UINT offset; + UINT stride; // 0 means not to advance the read pointer at all + + VertexBuffer *vertexBuffer; + BufferStorage *storage; + unsigned int serial; + unsigned int divisor; +}; + +class VertexDataManager +{ + public: + VertexDataManager(rx::Renderer *renderer); + virtual ~VertexDataManager(); + + GLenum prepareVertexData(const gl::VertexAttribute attribs[], gl::ProgramBinary *programBinary, GLint start, GLsizei count, TranslatedAttribute *outAttribs, GLsizei instances); + + private: + DISALLOW_COPY_AND_ASSIGN(VertexDataManager); + + rx::Renderer *const mRenderer; + + StreamingVertexBufferInterface *mStreamingBuffer; + + float mCurrentValue[gl::MAX_VERTEX_ATTRIBS][4]; + StreamingVertexBufferInterface *mCurrentValueBuffer[gl::MAX_VERTEX_ATTRIBS]; + std::size_t mCurrentValueOffsets[gl::MAX_VERTEX_ATTRIBS]; +}; + +} + +#endif // LIBGLESV2_RENDERER_VERTEXDATAMANAGER_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/VertexDeclarationCache.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/VertexDeclarationCache.cpp new file mode 100644 index 0000000000..9b83a6476e --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/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/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 new file mode 100644 index 0000000000..3fc024a9ba --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/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/generatemip.h b/src/3rdparty/angle/src/libGLESv2/renderer/generatemip.h new file mode 100644 index 0000000000..8e1973605b --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/generatemip.h @@ -0,0 +1,203 @@ +// +// 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. +// + +// generatemip.h: Defines the GenerateMip function, templated on the format +// type of the image for which mip levels are being generated. + +#ifndef LIBGLESV2_RENDERER_GENERATEMIP_H_ +#define LIBGLESV2_RENDERER_GENERATEMIP_H_ + +#include "libGLESv2/mathutil.h" + +namespace rx +{ +struct L8 +{ + unsigned char L; + + static void average(L8 *dst, const L8 *src1, const L8 *src2) + { + dst->L = ((src1->L ^ src2->L) >> 1) + (src1->L & src2->L); + } +}; + +typedef L8 R8; // R8 type is functionally equivalent for mip purposes +typedef L8 A8; // A8 type is functionally equivalent for mip purposes + +struct A8L8 +{ + unsigned char L; + unsigned char A; + + static void average(A8L8 *dst, const A8L8 *src1, const A8L8 *src2) + { + *(unsigned short*)dst = (((*(unsigned short*)src1 ^ *(unsigned short*)src2) & 0xFEFE) >> 1) + (*(unsigned short*)src1 & *(unsigned short*)src2); + } +}; + +typedef A8L8 R8G8; // R8G8 type is functionally equivalent for mip purposes + +struct A8R8G8B8 +{ + unsigned char B; + unsigned char G; + unsigned char R; + unsigned char A; + + static void average(A8R8G8B8 *dst, const A8R8G8B8 *src1, const A8R8G8B8 *src2) + { + *(unsigned int*)dst = (((*(unsigned int*)src1 ^ *(unsigned int*)src2) & 0xFEFEFEFE) >> 1) + (*(unsigned int*)src1 & *(unsigned int*)src2); + } +}; + +typedef A8R8G8B8 R8G8B8A8; // R8G8B8A8 type is functionally equivalent for mip purposes + +struct A16B16G16R16F +{ + unsigned short R; + unsigned short G; + unsigned short B; + unsigned short A; + + static void average(A16B16G16R16F *dst, const A16B16G16R16F *src1, const A16B16G16R16F *src2) + { + dst->R = gl::float32ToFloat16((gl::float16ToFloat32(src1->R) + gl::float16ToFloat32(src2->R)) * 0.5f); + dst->G = gl::float32ToFloat16((gl::float16ToFloat32(src1->G) + gl::float16ToFloat32(src2->G)) * 0.5f); + dst->B = gl::float32ToFloat16((gl::float16ToFloat32(src1->B) + gl::float16ToFloat32(src2->B)) * 0.5f); + dst->A = gl::float32ToFloat16((gl::float16ToFloat32(src1->A) + gl::float16ToFloat32(src2->A)) * 0.5f); + } +}; + +struct R16F +{ + unsigned short R; + + static void average(R16F *dst, const R16F *src1, const R16F *src2) + { + dst->R = gl::float32ToFloat16((gl::float16ToFloat32(src1->R) + gl::float16ToFloat32(src2->R)) * 0.5f); + } +}; + +struct R16G16F +{ + unsigned short R; + unsigned short G; + + static void average(R16G16F *dst, const R16G16F *src1, const R16G16F *src2) + { + dst->R = gl::float32ToFloat16((gl::float16ToFloat32(src1->R) + gl::float16ToFloat32(src2->R)) * 0.5f); + dst->G = gl::float32ToFloat16((gl::float16ToFloat32(src1->G) + gl::float16ToFloat32(src2->G)) * 0.5f); + } +}; + +struct A32B32G32R32F +{ + float R; + float G; + float B; + float A; + + static void average(A32B32G32R32F *dst, const A32B32G32R32F *src1, const A32B32G32R32F *src2) + { + dst->R = (src1->R + src2->R) * 0.5f; + dst->G = (src1->G + src2->G) * 0.5f; + dst->B = (src1->B + src2->B) * 0.5f; + dst->A = (src1->A + src2->A) * 0.5f; + } +}; + +struct R32F +{ + float R; + + static void average(R32F *dst, const R32F *src1, const R32F *src2) + { + dst->R = (src1->R + src2->R) * 0.5f; + } +}; + +struct R32G32F +{ + float R; + float G; + + static void average(R32G32F *dst, const R32G32F *src1, const R32G32F *src2) + { + dst->R = (src1->R + src2->R) * 0.5f; + dst->G = (src1->G + src2->G) * 0.5f; + } +}; + +struct R32G32B32F +{ + float R; + float G; + float B; + + static void average(R32G32B32F *dst, const R32G32B32F *src1, const R32G32B32F *src2) + { + dst->R = (src1->R + src2->R) * 0.5f; + dst->G = (src1->G + src2->G) * 0.5f; + dst->B = (src1->B + src2->B) * 0.5f; + } +}; + +template +static void GenerateMip(unsigned int sourceWidth, unsigned int sourceHeight, + const unsigned char *sourceData, int sourcePitch, + unsigned char *destData, int destPitch) +{ + unsigned int mipWidth = std::max(1U, sourceWidth >> 1); + unsigned int mipHeight = std::max(1U, sourceHeight >> 1); + + if (sourceHeight == 1) + { + ASSERT(sourceWidth != 1); + + const T *src = (const T*)sourceData; + T *dst = (T*)destData; + + for (unsigned int x = 0; x < mipWidth; x++) + { + T::average(&dst[x], &src[x * 2], &src[x * 2 + 1]); + } + } + else if (sourceWidth == 1) + { + ASSERT(sourceHeight != 1); + + for (unsigned int y = 0; y < mipHeight; y++) + { + const T *src0 = (const T*)(sourceData + y * 2 * sourcePitch); + const T *src1 = (const T*)(sourceData + y * 2 * sourcePitch + sourcePitch); + T *dst = (T*)(destData + y * destPitch); + + T::average(dst, src0, src1); + } + } + else + { + for (unsigned int y = 0; y < mipHeight; y++) + { + const T *src0 = (const T*)(sourceData + y * 2 * sourcePitch); + const T *src1 = (const T*)(sourceData + y * 2 * sourcePitch + sourcePitch); + T *dst = (T*)(destData + y * destPitch); + + for (unsigned int x = 0; x < mipWidth; x++) + { + T tmp0; + T tmp1; + + T::average(&tmp0, &src0[x * 2], &src0[x * 2 + 1]); + T::average(&tmp1, &src1[x * 2], &src1[x * 2 + 1]); + T::average(&dst[x], &tmp0, &tmp1); + } + } + } +} +} + +#endif // LIBGLESV2_RENDERER_GENERATEMIP_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/renderer11_utils.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/renderer11_utils.cpp new file mode 100644 index 0000000000..5f01dc12ed --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/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/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) +{ + 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 DXGI_FORMAT_A8_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_R32G32B32_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 new file mode 100644 index 0000000000..1bc48c1a13 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/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); +} + +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 new file mode 100644 index 0000000000..da75d465e3 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/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/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 new file mode 100644 index 0000000000..bf6cdf1ea6 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/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/shaders/Blit.ps b/src/3rdparty/angle/src/libGLESv2/renderer/shaders/Blit.ps new file mode 100644 index 0000000000..dcb3bd0e76 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/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/shaders/Blit.vs b/src/3rdparty/angle/src/libGLESv2/renderer/shaders/Blit.vs new file mode 100644 index 0000000000..3a36980b93 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/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/shaders/Clear11.hlsl b/src/3rdparty/angle/src/libGLESv2/renderer/shaders/Clear11.hlsl new file mode 100644 index 0000000000..d2752601e9 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/shaders/Clear11.hlsl @@ -0,0 +1,33 @@ +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_Output +{ + float4 color0 : SV_TARGET0; + float4 color1 : SV_TARGET1; + float4 color2 : SV_TARGET2; + float4 color3 : SV_TARGET3; + float4 color4 : SV_TARGET4; + float4 color5 : SV_TARGET5; + float4 color6 : SV_TARGET6; + float4 color7 : SV_TARGET7; +}; + +PS_Output PS_Clear(in float4 inPosition : SV_POSITION, in float4 inColor : COLOR) +{ + PS_Output outColor; + outColor.color0 = inColor; + outColor.color1 = inColor; + outColor.color2 = inColor; + outColor.color3 = inColor; + outColor.color4 = inColor; + outColor.color5 = inColor; + outColor.color6 = inColor; + outColor.color7 = inColor; + return outColor; +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/shaders/Passthrough11.hlsl b/src/3rdparty/angle/src/libGLESv2/renderer/shaders/Passthrough11.hlsl new file mode 100644 index 0000000000..43b7801efc --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/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/vertexconversion.h b/src/3rdparty/angle/src/libGLESv2/renderer/vertexconversion.h new file mode 100644 index 0000000000..590b9d48a3 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/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/shaders/Blit.ps b/src/3rdparty/angle/src/libGLESv2/shaders/Blit.ps deleted file mode 100644 index dcb3bd0e76..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/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/shaders/Blit.vs b/src/3rdparty/angle/src/libGLESv2/shaders/Blit.vs deleted file mode 100644 index 3a36980b93..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/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/utilities.cpp b/src/3rdparty/angle/src/libGLESv2/utilities.cpp index a3eb27d392..9809b9d8e8 100644 --- a/src/3rdparty/angle/src/libGLESv2/utilities.cpp +++ b/src/3rdparty/angle/src/libGLESv2/utilities.cpp @@ -1,5 +1,6 @@ +#include "precompiled.h" // -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// 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. // @@ -7,21 +8,12 @@ // utilities.cpp: Conversion functions and other utility routines. #include "libGLESv2/utilities.h" - -#include -#include -#include - -#include "common/debug.h" - #include "libGLESv2/mathutil.h" -#include "libGLESv2/Context.h" namespace gl { -// This is how much data the application expects for a uniform -int UniformExternalComponentCount(GLenum type) +int UniformComponentCount(GLenum type) { switch (type) { @@ -55,42 +47,6 @@ int UniformExternalComponentCount(GLenum type) return 0; } -// This is how much data we actually store for a uniform -int UniformInternalComponentCount(GLenum type) -{ - switch (type) - { - case GL_BOOL: - case GL_INT: - case GL_SAMPLER_2D: - case GL_SAMPLER_CUBE: - return 1; - case GL_BOOL_VEC2: - case GL_INT_VEC2: - return 2; - case GL_INT_VEC3: - case GL_BOOL_VEC3: - return 3; - case GL_FLOAT: - case GL_FLOAT_VEC2: - case GL_FLOAT_VEC3: - case GL_BOOL_VEC4: - case GL_FLOAT_VEC4: - case GL_INT_VEC4: - return 4; - case GL_FLOAT_MAT2: - return 8; - case GL_FLOAT_MAT3: - return 12; - case GL_FLOAT_MAT4: - return 16; - default: - UNREACHABLE(); - } - - return 0; -} - GLenum UniformComponentType(GLenum type) { switch(type) @@ -137,12 +93,13 @@ size_t UniformComponentSize(GLenum type) size_t UniformInternalSize(GLenum type) { - return UniformComponentSize(UniformComponentType(type)) * UniformInternalComponentCount(type); + // Expanded to 4-element vectors + return UniformComponentSize(UniformComponentType(type)) * VariableRowCount(type) * 4; } size_t UniformExternalSize(GLenum type) { - return UniformComponentSize(UniformComponentType(type)) * UniformExternalComponentCount(type); + return UniformComponentSize(UniformComponentType(type)) * UniformComponentCount(type); } int VariableRowCount(GLenum type) @@ -163,6 +120,8 @@ int VariableRowCount(GLenum type) case GL_BOOL_VEC4: case GL_FLOAT_VEC4: case GL_INT_VEC4: + case GL_SAMPLER_2D: + case GL_SAMPLER_CUBE: return 1; case GL_FLOAT_MAT2: return 2; @@ -186,6 +145,8 @@ int VariableColumnCount(GLenum type) case GL_BOOL: case GL_FLOAT: case GL_INT: + case GL_SAMPLER_2D: + case GL_SAMPLER_CUBE: return 1; case GL_BOOL_VEC2: case GL_FLOAT_VEC2: @@ -297,6 +258,27 @@ bool IsStencilTexture(GLenum format) return false; } +void MakeValidSize(bool isImage, bool isCompressed, GLsizei *requestWidth, GLsizei *requestHeight, int *levelOffset) +{ + int upsampleCount = 0; + + if (isCompressed) + { + // Don't expand the size of full textures that are at least 4x4 + // already. + if (isImage || *requestWidth < 4 || *requestHeight < 4) + { + while (*requestWidth % 4 != 0 || *requestHeight % 4 != 0) + { + *requestWidth <<= 1; + *requestHeight <<= 1; + upsampleCount++; + } + } + } + *levelOffset = upsampleCount; +} + // Returns the size, in bytes, of a single texel in an Image int ComputePixelSize(GLint internalformat) { @@ -510,6 +492,8 @@ bool IsColorRenderable(GLenum internalformat) case GL_STENCIL_INDEX8: case GL_DEPTH24_STENCIL8_OES: return false; + case GL_BGRA8_EXT: + return true; default: UNIMPLEMENTED(); } @@ -589,597 +573,141 @@ bool IsFloat16Format(GLint internalformat) } } -} - -namespace es2dx -{ - -D3DCMPFUNC ConvertComparison(GLenum comparison) -{ - D3DCMPFUNC d3dComp = D3DCMP_ALWAYS; - switch (comparison) - { - case GL_NEVER: d3dComp = D3DCMP_NEVER; break; - case GL_ALWAYS: d3dComp = D3DCMP_ALWAYS; break; - case GL_LESS: d3dComp = D3DCMP_LESS; break; - case GL_LEQUAL: d3dComp = D3DCMP_LESSEQUAL; break; - case GL_EQUAL: d3dComp = D3DCMP_EQUAL; break; - case GL_GREATER: d3dComp = D3DCMP_GREATER; break; - case GL_GEQUAL: d3dComp = D3DCMP_GREATEREQUAL; break; - case GL_NOTEQUAL: d3dComp = D3DCMP_NOTEQUAL; break; - default: UNREACHABLE(); - } - - return d3dComp; -} - -D3DCOLOR ConvertColor(gl::Color color) -{ - return D3DCOLOR_RGBA(gl::unorm<8>(color.red), - gl::unorm<8>(color.green), - gl::unorm<8>(color.blue), - gl::unorm<8>(color.alpha)); -} - -D3DBLEND ConvertBlendFunc(GLenum blend) -{ - D3DBLEND d3dBlend = D3DBLEND_ZERO; - - switch (blend) - { - case GL_ZERO: d3dBlend = D3DBLEND_ZERO; break; - case GL_ONE: d3dBlend = D3DBLEND_ONE; break; - case GL_SRC_COLOR: d3dBlend = D3DBLEND_SRCCOLOR; break; - case GL_ONE_MINUS_SRC_COLOR: d3dBlend = D3DBLEND_INVSRCCOLOR; break; - case GL_DST_COLOR: d3dBlend = D3DBLEND_DESTCOLOR; break; - case GL_ONE_MINUS_DST_COLOR: d3dBlend = D3DBLEND_INVDESTCOLOR; break; - case GL_SRC_ALPHA: d3dBlend = D3DBLEND_SRCALPHA; break; - case GL_ONE_MINUS_SRC_ALPHA: d3dBlend = D3DBLEND_INVSRCALPHA; break; - case GL_DST_ALPHA: d3dBlend = D3DBLEND_DESTALPHA; break; - case GL_ONE_MINUS_DST_ALPHA: d3dBlend = D3DBLEND_INVDESTALPHA; break; - case GL_CONSTANT_COLOR: d3dBlend = D3DBLEND_BLENDFACTOR; break; - case GL_ONE_MINUS_CONSTANT_COLOR: d3dBlend = D3DBLEND_INVBLENDFACTOR; break; - case GL_CONSTANT_ALPHA: d3dBlend = D3DBLEND_BLENDFACTOR; break; - case GL_ONE_MINUS_CONSTANT_ALPHA: d3dBlend = D3DBLEND_INVBLENDFACTOR; break; - case GL_SRC_ALPHA_SATURATE: d3dBlend = D3DBLEND_SRCALPHASAT; break; - default: UNREACHABLE(); - } - - return d3dBlend; -} - -D3DBLENDOP ConvertBlendOp(GLenum blendOp) -{ - D3DBLENDOP d3dBlendOp = D3DBLENDOP_ADD; - - switch (blendOp) - { - case GL_FUNC_ADD: d3dBlendOp = D3DBLENDOP_ADD; break; - case GL_FUNC_SUBTRACT: d3dBlendOp = D3DBLENDOP_SUBTRACT; break; - case GL_FUNC_REVERSE_SUBTRACT: d3dBlendOp = D3DBLENDOP_REVSUBTRACT; break; - default: UNREACHABLE(); - } - - return d3dBlendOp; -} - -D3DSTENCILOP ConvertStencilOp(GLenum stencilOp) -{ - D3DSTENCILOP d3dStencilOp = D3DSTENCILOP_KEEP; - - switch (stencilOp) - { - case GL_ZERO: d3dStencilOp = D3DSTENCILOP_ZERO; break; - case GL_KEEP: d3dStencilOp = D3DSTENCILOP_KEEP; break; - case GL_REPLACE: d3dStencilOp = D3DSTENCILOP_REPLACE; break; - case GL_INCR: d3dStencilOp = D3DSTENCILOP_INCRSAT; break; - case GL_DECR: d3dStencilOp = D3DSTENCILOP_DECRSAT; break; - case GL_INVERT: d3dStencilOp = D3DSTENCILOP_INVERT; break; - case GL_INCR_WRAP: d3dStencilOp = D3DSTENCILOP_INCR; break; - case GL_DECR_WRAP: d3dStencilOp = D3DSTENCILOP_DECR; break; - default: UNREACHABLE(); - } - - return d3dStencilOp; -} - -D3DTEXTUREADDRESS ConvertTextureWrap(GLenum wrap) -{ - D3DTEXTUREADDRESS d3dWrap = D3DTADDRESS_WRAP; - - switch (wrap) - { - case GL_REPEAT: d3dWrap = D3DTADDRESS_WRAP; break; - case GL_CLAMP_TO_EDGE: d3dWrap = D3DTADDRESS_CLAMP; break; - case GL_MIRRORED_REPEAT: d3dWrap = D3DTADDRESS_MIRROR; break; - default: UNREACHABLE(); - } - - return d3dWrap; -} - -D3DCULL ConvertCullMode(GLenum cullFace, GLenum frontFace) -{ - D3DCULL cull = D3DCULL_CCW; - switch (cullFace) - { - case GL_FRONT: - cull = (frontFace == GL_CCW ? D3DCULL_CW : D3DCULL_CCW); - break; - case GL_BACK: - cull = (frontFace == GL_CCW ? D3DCULL_CCW : D3DCULL_CW); - break; - case GL_FRONT_AND_BACK: - cull = D3DCULL_NONE; // culling will be handled during draw - break; - default: UNREACHABLE(); - } - - return cull; -} - -D3DCUBEMAP_FACES ConvertCubeFace(GLenum cubeFace) -{ - D3DCUBEMAP_FACES face = D3DCUBEMAP_FACE_POSITIVE_X; - - switch (cubeFace) - { - case GL_TEXTURE_CUBE_MAP_POSITIVE_X: - face = D3DCUBEMAP_FACE_POSITIVE_X; - break; - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: - face = D3DCUBEMAP_FACE_NEGATIVE_X; - break; - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: - face = D3DCUBEMAP_FACE_POSITIVE_Y; - break; - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: - face = D3DCUBEMAP_FACE_NEGATIVE_Y; - break; - case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: - face = D3DCUBEMAP_FACE_POSITIVE_Z; - break; - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: - face = D3DCUBEMAP_FACE_NEGATIVE_Z; - break; - default: UNREACHABLE(); - } - - return face; -} - -DWORD ConvertColorMask(bool red, bool green, bool blue, bool alpha) -{ - return (red ? D3DCOLORWRITEENABLE_RED : 0) | - (green ? D3DCOLORWRITEENABLE_GREEN : 0) | - (blue ? D3DCOLORWRITEENABLE_BLUE : 0) | - (alpha ? D3DCOLORWRITEENABLE_ALPHA : 0); -} - -D3DTEXTUREFILTERTYPE ConvertMagFilter(GLenum magFilter, float maxAnisotropy) -{ - if (maxAnisotropy > 1.0f) - { - return D3DTEXF_ANISOTROPIC; - } - - D3DTEXTUREFILTERTYPE d3dMagFilter = D3DTEXF_POINT; - switch (magFilter) - { - case GL_NEAREST: d3dMagFilter = D3DTEXF_POINT; break; - case GL_LINEAR: d3dMagFilter = D3DTEXF_LINEAR; break; - default: UNREACHABLE(); - } - - return d3dMagFilter; -} - -void ConvertMinFilter(GLenum minFilter, D3DTEXTUREFILTERTYPE *d3dMinFilter, D3DTEXTUREFILTERTYPE *d3dMipFilter, float maxAnisotropy) -{ - switch (minFilter) - { - case GL_NEAREST: - *d3dMinFilter = D3DTEXF_POINT; - *d3dMipFilter = D3DTEXF_NONE; - break; - case GL_LINEAR: - *d3dMinFilter = D3DTEXF_LINEAR; - *d3dMipFilter = D3DTEXF_NONE; - break; - case GL_NEAREST_MIPMAP_NEAREST: - *d3dMinFilter = D3DTEXF_POINT; - *d3dMipFilter = D3DTEXF_POINT; - break; - case GL_LINEAR_MIPMAP_NEAREST: - *d3dMinFilter = D3DTEXF_LINEAR; - *d3dMipFilter = D3DTEXF_POINT; - break; - case GL_NEAREST_MIPMAP_LINEAR: - *d3dMinFilter = D3DTEXF_POINT; - *d3dMipFilter = D3DTEXF_LINEAR; - break; - case GL_LINEAR_MIPMAP_LINEAR: - *d3dMinFilter = D3DTEXF_LINEAR; - *d3dMipFilter = D3DTEXF_LINEAR; - break; - default: - *d3dMinFilter = D3DTEXF_POINT; - *d3dMipFilter = D3DTEXF_NONE; - UNREACHABLE(); - } - - if (maxAnisotropy > 1.0f) - { - *d3dMinFilter = D3DTEXF_ANISOTROPIC; - } -} - -bool ConvertPrimitiveType(GLenum primitiveType, GLsizei elementCount, - D3DPRIMITIVETYPE *d3dPrimitiveType, int *d3dPrimitiveCount) -{ - switch (primitiveType) - { - case GL_POINTS: - *d3dPrimitiveType = D3DPT_POINTLIST; - *d3dPrimitiveCount = elementCount; - break; - case GL_LINES: - *d3dPrimitiveType = D3DPT_LINELIST; - *d3dPrimitiveCount = elementCount / 2; - break; - case GL_LINE_LOOP: - *d3dPrimitiveType = D3DPT_LINESTRIP; - *d3dPrimitiveCount = elementCount - 1; // D3D doesn't support line loops, so we draw the last line separately - break; - case GL_LINE_STRIP: - *d3dPrimitiveType = D3DPT_LINESTRIP; - *d3dPrimitiveCount = elementCount - 1; - break; - case GL_TRIANGLES: - *d3dPrimitiveType = D3DPT_TRIANGLELIST; - *d3dPrimitiveCount = elementCount / 3; - break; - case GL_TRIANGLE_STRIP: - *d3dPrimitiveType = D3DPT_TRIANGLESTRIP; - *d3dPrimitiveCount = elementCount - 2; - break; - case GL_TRIANGLE_FAN: - *d3dPrimitiveType = D3DPT_TRIANGLEFAN; - *d3dPrimitiveCount = elementCount - 2; - break; - default: - return false; - } - - return true; -} - -D3DFORMAT ConvertRenderbufferFormat(GLenum format) -{ - switch (format) - { - case GL_NONE: return D3DFMT_NULL; - case GL_RGBA4: - case GL_RGB5_A1: - case GL_RGBA8_OES: return D3DFMT_A8R8G8B8; - case GL_RGB565: return D3DFMT_R5G6B5; - case GL_RGB8_OES: return D3DFMT_X8R8G8B8; - case GL_DEPTH_COMPONENT16: - case GL_STENCIL_INDEX8: - case GL_DEPTH24_STENCIL8_OES: return D3DFMT_D24S8; - default: UNREACHABLE(); return D3DFMT_A8R8G8B8; - } -} - -D3DMULTISAMPLE_TYPE GetMultisampleTypeFromSamples(GLsizei samples) -{ - if (samples <= 1) - return D3DMULTISAMPLE_NONE; - else - return (D3DMULTISAMPLE_TYPE)samples; -} - -} - -namespace dx2es -{ - -unsigned int GetStencilSize(D3DFORMAT stencilFormat) -{ - if (stencilFormat == D3DFMT_INTZ) - { - return 8; - } - switch(stencilFormat) - { - case D3DFMT_D24FS8: - case D3DFMT_D24S8: - return 8; - case D3DFMT_D24X4S4: - return 4; - case D3DFMT_D15S1: - return 1; - case D3DFMT_D16_LOCKABLE: - case D3DFMT_D32: - case D3DFMT_D24X8: - case D3DFMT_D32F_LOCKABLE: - case D3DFMT_D16: - return 0; - //case D3DFMT_D32_LOCKABLE: return 0; // DirectX 9Ex only - //case D3DFMT_S8_LOCKABLE: return 8; // DirectX 9Ex only - default: - return 0; - } -} - -unsigned int GetAlphaSize(D3DFORMAT colorFormat) +unsigned int GetAlphaSize(GLenum colorFormat) { switch (colorFormat) { - case D3DFMT_A16B16G16R16F: + case GL_RGBA16F_EXT: return 16; - case D3DFMT_A32B32G32R32F: + case GL_RGBA32F_EXT: return 32; - case D3DFMT_A2R10G10B10: - return 2; - case D3DFMT_A8R8G8B8: + case GL_RGBA4: + return 4; + case GL_RGBA8_OES: + case GL_BGRA8_EXT: return 8; - case D3DFMT_A1R5G5B5: + case GL_RGB5_A1: return 1; - case D3DFMT_X8R8G8B8: - case D3DFMT_R5G6B5: + case GL_RGB8_OES: + case GL_RGB565: + case GL_RGB32F_EXT: + case GL_RGB16F_EXT: return 0; default: return 0; } } -unsigned int GetRedSize(D3DFORMAT colorFormat) +unsigned int GetRedSize(GLenum colorFormat) { switch (colorFormat) { - case D3DFMT_A16B16G16R16F: + case GL_RGBA16F_EXT: + case GL_RGB16F_EXT: return 16; - case D3DFMT_A32B32G32R32F: + case GL_RGBA32F_EXT: + case GL_RGB32F_EXT: return 32; - case D3DFMT_A2R10G10B10: - return 10; - case D3DFMT_A8R8G8B8: - case D3DFMT_X8R8G8B8: + case GL_RGBA4: + return 4; + case GL_RGBA8_OES: + case GL_BGRA8_EXT: + case GL_RGB8_OES: return 8; - case D3DFMT_A1R5G5B5: - case D3DFMT_R5G6B5: + case GL_RGB5_A1: + case GL_RGB565: return 5; default: return 0; } } -unsigned int GetGreenSize(D3DFORMAT colorFormat) +unsigned int GetGreenSize(GLenum colorFormat) { switch (colorFormat) { - case D3DFMT_A16B16G16R16F: + case GL_RGBA16F_EXT: + case GL_RGB16F_EXT: return 16; - case D3DFMT_A32B32G32R32F: + case GL_RGBA32F_EXT: + case GL_RGB32F_EXT: return 32; - case D3DFMT_A2R10G10B10: - return 10; - case D3DFMT_A8R8G8B8: - case D3DFMT_X8R8G8B8: + case GL_RGBA4: + return 4; + case GL_RGBA8_OES: + case GL_BGRA8_EXT: + case GL_RGB8_OES: return 8; - case D3DFMT_A1R5G5B5: + case GL_RGB5_A1: return 5; - case D3DFMT_R5G6B5: + case GL_RGB565: return 6; default: return 0; } } -unsigned int GetBlueSize(D3DFORMAT colorFormat) +unsigned int GetBlueSize(GLenum colorFormat) { switch (colorFormat) { - case D3DFMT_A16B16G16R16F: + case GL_RGBA16F_EXT: + case GL_RGB16F_EXT: return 16; - case D3DFMT_A32B32G32R32F: + case GL_RGBA32F_EXT: + case GL_RGB32F_EXT: return 32; - case D3DFMT_A2R10G10B10: - return 10; - case D3DFMT_A8R8G8B8: - case D3DFMT_X8R8G8B8: + case GL_RGBA4: + return 4; + case GL_RGBA8_OES: + case GL_BGRA8_EXT: + case GL_RGB8_OES: return 8; - case D3DFMT_A1R5G5B5: - case D3DFMT_R5G6B5: + case GL_RGB5_A1: + case GL_RGB565: return 5; default: return 0; } } -unsigned int GetDepthSize(D3DFORMAT depthFormat) +unsigned int GetDepthSize(GLenum depthFormat) { - if (depthFormat == D3DFMT_INTZ) - { - return 24; - } switch (depthFormat) { - case D3DFMT_D16_LOCKABLE: return 16; - case D3DFMT_D32: return 32; - case D3DFMT_D15S1: return 15; - case D3DFMT_D24S8: return 24; - case D3DFMT_D24X8: return 24; - case D3DFMT_D24X4S4: return 24; - case D3DFMT_D16: return 16; - case D3DFMT_D32F_LOCKABLE: return 32; - case D3DFMT_D24FS8: return 24; - //case D3DFMT_D32_LOCKABLE: return 32; // D3D9Ex only - //case D3DFMT_S8_LOCKABLE: return 0; // D3D9Ex only - default: return 0; - } -} - -GLsizei GetSamplesFromMultisampleType(D3DMULTISAMPLE_TYPE type) -{ - if (type == D3DMULTISAMPLE_NONMASKABLE) - return 0; - else - return type; -} - -bool IsFormatChannelEquivalent(D3DFORMAT d3dformat, GLenum format) -{ - switch (d3dformat) - { - case D3DFMT_L8: - return (format == GL_LUMINANCE); - case D3DFMT_A8L8: - return (format == GL_LUMINANCE_ALPHA); - case D3DFMT_DXT1: - return (format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT || format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT); - case D3DFMT_DXT3: - return (format == GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE); - case D3DFMT_DXT5: - return (format == GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE); - case D3DFMT_A8R8G8B8: - case D3DFMT_A16B16G16R16F: - case D3DFMT_A32B32G32R32F: - return (format == GL_RGBA || format == GL_BGRA_EXT); - case D3DFMT_X8R8G8B8: - return (format == GL_RGB); - default: - if (d3dformat == D3DFMT_INTZ && gl::IsDepthTexture(format)) - return true; - return false; - } -} - -bool ConvertReadBufferFormat(D3DFORMAT d3dformat, GLenum *format, GLenum *type) -{ - switch (d3dformat) - { - case D3DFMT_A8R8G8B8: - *type = GL_UNSIGNED_BYTE; - *format = GL_BGRA_EXT; - break; - case D3DFMT_X8R8G8B8: - *type = GL_UNSIGNED_BYTE; - *format = GL_RGB; - break; - case D3DFMT_R5G6B5: - *type = GL_UNSIGNED_SHORT_5_6_5; - *format = GL_RGB; - break; - case D3DFMT_A16B16G16R16F: - *type = GL_HALF_FLOAT_OES; - *format = GL_RGBA; - break; - case D3DFMT_A32B32G32R32F: - *type = GL_FLOAT; - *format = GL_RGBA; - break; - case D3DFMT_A4R4G4B4: - *type = GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT; - *format = GL_BGRA_EXT; - break; - case D3DFMT_A1R5G5B5: - *type = GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT; - *format = GL_BGRA_EXT; - break; - default: - *type = GL_NONE; - *format = GL_NONE; - return false; - } - return true; -} - -GLenum ConvertBackBufferFormat(D3DFORMAT format) -{ - switch (format) - { - case D3DFMT_A4R4G4B4: return GL_RGBA4; - case D3DFMT_A8R8G8B8: return GL_RGBA8_OES; - case D3DFMT_A1R5G5B5: return GL_RGB5_A1; - case D3DFMT_R5G6B5: return GL_RGB565; - case D3DFMT_X8R8G8B8: return GL_RGB8_OES; - default: - UNREACHABLE(); + case GL_DEPTH_COMPONENT16: return 16; + case GL_DEPTH_COMPONENT32_OES: return 32; + case GL_DEPTH24_STENCIL8_OES: return 24; + default: return 0; } - - return GL_RGBA4; } -GLenum ConvertDepthStencilFormat(D3DFORMAT format) +unsigned int GetStencilSize(GLenum stencilFormat) { - if (format == D3DFMT_INTZ) + switch (stencilFormat) { - return GL_DEPTH24_STENCIL8_OES; + case GL_DEPTH24_STENCIL8_OES: return 8; + default: return 0; } - switch (format) - { - case D3DFMT_D16: - case D3DFMT_D24X8: - return GL_DEPTH_COMPONENT16; - case D3DFMT_D24S8: - return GL_DEPTH24_STENCIL8_OES; - default: - UNREACHABLE(); - } - - return GL_DEPTH24_STENCIL8_OES; } -} - -namespace dx -{ - -bool IsCompressedFormat(D3DFORMAT surfaceFormat) +bool IsTriangleMode(GLenum drawMode) { - switch(surfaceFormat) + switch (drawMode) { - case D3DFMT_DXT1: - case D3DFMT_DXT2: - case D3DFMT_DXT3: - case D3DFMT_DXT4: - case D3DFMT_DXT5: + case GL_TRIANGLES: + case GL_TRIANGLE_FAN: + case GL_TRIANGLE_STRIP: return true; - default: + case GL_POINTS: + case GL_LINES: + case GL_LINE_LOOP: + case GL_LINE_STRIP: return false; + default: UNREACHABLE(); } -} -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; - } + return false; } } diff --git a/src/3rdparty/angle/src/libGLESv2/utilities.h b/src/3rdparty/angle/src/libGLESv2/utilities.h index 29ad207313..7a10767086 100644 --- a/src/3rdparty/angle/src/libGLESv2/utilities.h +++ b/src/3rdparty/angle/src/libGLESv2/utilities.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// 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. // @@ -12,20 +12,15 @@ #define GL_APICALL #include #include -#include #include -const D3DFORMAT D3DFMT_INTZ = ((D3DFORMAT)(MAKEFOURCC('I','N','T','Z'))); -const D3DFORMAT D3DFMT_NULL = ((D3DFORMAT)(MAKEFOURCC('N','U','L','L'))); - namespace gl { struct Color; -int UniformExternalComponentCount(GLenum type); -int UniformInternalComponentCount(GLenum type); +int UniformComponentCount(GLenum type); GLenum UniformComponentType(GLenum type); size_t UniformInternalSize(GLenum type); size_t UniformExternalSize(GLenum type); @@ -34,6 +29,7 @@ int VariableColumnCount(GLenum type); int AllocateFirstFreeBits(unsigned int *bits, unsigned int allocationSize, unsigned int bitsSize); +void MakeValidSize(bool isImage, bool isCompressed, GLsizei *requestWidth, GLsizei *requestHeight, int *levelOffset); int ComputePixelSize(GLint internalformat); GLsizei ComputePitch(GLsizei width, GLint internalformat, GLint alignment); GLsizei ComputeCompressedPitch(GLsizei width, GLenum format); @@ -53,69 +49,18 @@ bool IsStencilRenderable(GLenum internalformat); bool IsFloat32Format(GLint internalformat); bool IsFloat16Format(GLint internalformat); -} - -namespace es2dx -{ - -D3DCMPFUNC ConvertComparison(GLenum comparison); -D3DCOLOR ConvertColor(gl::Color color); -D3DBLEND ConvertBlendFunc(GLenum blend); -D3DBLENDOP ConvertBlendOp(GLenum blendOp); -D3DSTENCILOP ConvertStencilOp(GLenum stencilOp); -D3DTEXTUREADDRESS ConvertTextureWrap(GLenum wrap); -D3DCULL ConvertCullMode(GLenum cullFace, GLenum frontFace); -D3DCUBEMAP_FACES ConvertCubeFace(GLenum cubeFace); -DWORD ConvertColorMask(bool red, bool green, bool blue, bool alpha); -D3DTEXTUREFILTERTYPE ConvertMagFilter(GLenum magFilter, float maxAnisotropy); -void ConvertMinFilter(GLenum minFilter, D3DTEXTUREFILTERTYPE *d3dMinFilter, D3DTEXTUREFILTERTYPE *d3dMipFilter, float maxAnisotropy); -bool ConvertPrimitiveType(GLenum primitiveType, GLsizei elementCount, - D3DPRIMITIVETYPE *d3dPrimitiveType, int *d3dPrimitiveCount); -D3DFORMAT ConvertRenderbufferFormat(GLenum format); -D3DMULTISAMPLE_TYPE GetMultisampleTypeFromSamples(GLsizei samples); - -} - -namespace dx2es -{ - -GLuint GetAlphaSize(D3DFORMAT colorFormat); -GLuint GetRedSize(D3DFORMAT colorFormat); -GLuint GetGreenSize(D3DFORMAT colorFormat); -GLuint GetBlueSize(D3DFORMAT colorFormat); -GLuint GetDepthSize(D3DFORMAT depthFormat); -GLuint GetStencilSize(D3DFORMAT stencilFormat); - -GLsizei GetSamplesFromMultisampleType(D3DMULTISAMPLE_TYPE type); - -bool IsFormatChannelEquivalent(D3DFORMAT d3dformat, GLenum format); -bool ConvertReadBufferFormat(D3DFORMAT d3dformat, GLenum *format, GLenum *type); -GLenum ConvertBackBufferFormat(D3DFORMAT format); -GLenum ConvertDepthStencilFormat(D3DFORMAT format); -} +GLuint GetAlphaSize(GLenum colorFormat); +GLuint GetRedSize(GLenum colorFormat); +GLuint GetGreenSize(GLenum colorFormat); +GLuint GetBlueSize(GLenum colorFormat); +GLuint GetDepthSize(GLenum depthFormat); +GLuint GetStencilSize(GLenum stencilFormat); +bool IsTriangleMode(GLenum drawMode); -namespace dx -{ -bool IsCompressedFormat(D3DFORMAT format); -size_t ComputeRowSize(D3DFORMAT format, unsigned int width); } std::string getTempPath(); void writeFile(const char* path, const void* data, size_t size); -inline bool isDeviceLostError(HRESULT errorCode) -{ - switch (errorCode) - { - case D3DERR_DRIVERINTERNALERROR: - case D3DERR_DEVICELOST: - case D3DERR_DEVICEHUNG: - case D3DERR_DEVICEREMOVED: - return true; - default: - return false; - } -}; - #endif // LIBGLESV2_UTILITIES_H diff --git a/src/3rdparty/angle/src/libGLESv2/vertexconversion.h b/src/3rdparty/angle/src/libGLESv2/vertexconversion.h deleted file mode 100644 index 5bb8b8995e..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/vertexconversion.h +++ /dev/null @@ -1,208 +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_ - -#include -#include - -#include "libGLESv2/Context.h" // Defines Index - -namespace gl -{ - -// Conversion types: -// static const bool identity: true if this is an identity transform, false otherwise -// static U convert(T): convert a single element from the input type to the output type -// typedef ... OutputType: the type produced by this conversion - -template -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/third_party/compiler/ArrayBoundsClamper.cpp b/src/3rdparty/angle/src/third_party/compiler/ArrayBoundsClamper.cpp new file mode 100644 index 0000000000..288f5529ad --- /dev/null +++ b/src/3rdparty/angle/src/third_party/compiler/ArrayBoundsClamper.cpp @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2012 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "third_party/compiler/ArrayBoundsClamper.h" + +// The built-in 'clamp' instruction only accepts floats and returns a float. I +// iterated a few times with our driver team who examined the output from our +// compiler - they said the multiple casts generates more code than a single +// function call. An inline ternary operator might have been better, but since +// the index value might be an expression itself, we'd have to make temporary +// variables to avoid evaluating the expression multiple times. And making +// temporary variables was difficult because ANGLE would then need to make more +// brutal changes to the expression tree. + +const char* kIntClampBegin = "// BEGIN: Generated code for array bounds clamping\n\n"; +const char* kIntClampEnd = "// END: Generated code for array bounds clamping\n\n"; +const char* kIntClampDefinition = "int webgl_int_clamp(int value, int minValue, int maxValue) { return ((value < minValue) ? minValue : ((value > maxValue) ? maxValue : value)); }\n\n"; + +namespace { + +class ArrayBoundsClamperMarker : public TIntermTraverser { +public: + ArrayBoundsClamperMarker() + : mNeedsClamp(false) + { + } + + virtual bool visitBinary(Visit visit, TIntermBinary* node) + { + if (node->getOp() == EOpIndexIndirect) + { + TIntermTyped* left = node->getLeft(); + if (left->isArray() || left->isVector() || left->isMatrix()) + { + node->setAddIndexClamp(); + mNeedsClamp = true; + } + } + return true; + } + + bool GetNeedsClamp() { return mNeedsClamp; } + +private: + bool mNeedsClamp; +}; + +} // anonymous namespace + +ArrayBoundsClamper::ArrayBoundsClamper() + : mClampingStrategy(SH_CLAMP_WITH_CLAMP_INTRINSIC) + , mArrayBoundsClampDefinitionNeeded(false) +{ +} + +void ArrayBoundsClamper::SetClampingStrategy(ShArrayIndexClampingStrategy clampingStrategy) +{ + mClampingStrategy = clampingStrategy; +} + +void ArrayBoundsClamper::MarkIndirectArrayBoundsForClamping(TIntermNode* root) +{ + ASSERT(root); + + ArrayBoundsClamperMarker clamper; + root->traverse(&clamper); + if (clamper.GetNeedsClamp()) + { + SetArrayBoundsClampDefinitionNeeded(); + } +} + +void ArrayBoundsClamper::OutputClampingFunctionDefinition(TInfoSinkBase& out) const +{ + if (!mArrayBoundsClampDefinitionNeeded) + { + return; + } + if (mClampingStrategy != SH_CLAMP_WITH_USER_DEFINED_INT_CLAMP_FUNCTION) + { + return; + } + out << kIntClampBegin << kIntClampDefinition << kIntClampEnd; +} diff --git a/src/3rdparty/angle/src/third_party/compiler/ArrayBoundsClamper.h b/src/3rdparty/angle/src/third_party/compiler/ArrayBoundsClamper.h new file mode 100644 index 0000000000..0d4e1a374c --- /dev/null +++ b/src/3rdparty/angle/src/third_party/compiler/ArrayBoundsClamper.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2012 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef THIRD_PARTY_COMPILER_ARRAY_BOUNDS_CLAMPER_H_ +#define THIRD_PARTY_COMPILER_ARRAY_BOUNDS_CLAMPER_H_ + +#include "GLSLANG/ShaderLang.h" + +#include "compiler/InfoSink.h" +#include "compiler/intermediate.h" + +class ArrayBoundsClamper { +public: + ArrayBoundsClamper(); + + // Must be set before compiling any shaders to ensure consistency + // between the translated shaders and any necessary prequel. + void SetClampingStrategy(ShArrayIndexClampingStrategy clampingStrategy); + + // Marks nodes in the tree that index arrays indirectly as + // requiring clamping. + void MarkIndirectArrayBoundsForClamping(TIntermNode* root); + + // If necessary, output array clamp function source into the shader source. + void OutputClampingFunctionDefinition(TInfoSinkBase& out) const; + + void Cleanup() + { + mArrayBoundsClampDefinitionNeeded = false; + } + +private: + bool GetArrayBoundsClampDefinitionNeeded() const { return mArrayBoundsClampDefinitionNeeded; } + void SetArrayBoundsClampDefinitionNeeded() { mArrayBoundsClampDefinitionNeeded = true; } + + ShArrayIndexClampingStrategy mClampingStrategy; + bool mArrayBoundsClampDefinitionNeeded; +}; + +#endif // THIRD_PARTY_COMPILER_ARRAY_BOUNDS_CLAMPER_H_ diff --git a/src/3rdparty/angle/src/third_party/compiler/LICENSE b/src/3rdparty/angle/src/third_party/compiler/LICENSE new file mode 100644 index 0000000000..c2cb2125e9 --- /dev/null +++ b/src/3rdparty/angle/src/third_party/compiler/LICENSE @@ -0,0 +1,22 @@ +Copyright (C) 2012 Apple Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY APPLE, INC. ``AS IS'' AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE, INC. OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/src/3rdparty/angle/src/third_party/compiler/README.angle b/src/3rdparty/angle/src/third_party/compiler/README.angle new file mode 100644 index 0000000000..4fdf757ef4 --- /dev/null +++ b/src/3rdparty/angle/src/third_party/compiler/README.angle @@ -0,0 +1,12 @@ +Name: ANGLE array bounds clamper from WebKit +Short Name: WebKit +URL: http://webkit.org +Version: 0 +License: BSD +Security Critical: yes + +Description: +Implements clamping of array indexing expressions during shader translation. + +Local Modifications: +None diff --git a/src/3rdparty/angle/src/third_party/murmurhash/LICENSE b/src/3rdparty/angle/src/third_party/murmurhash/LICENSE new file mode 100644 index 0000000000..6a385f0f07 --- /dev/null +++ b/src/3rdparty/angle/src/third_party/murmurhash/LICENSE @@ -0,0 +1,2 @@ +// MurmurHash3 was written by Austin Appleby, and is placed in the public +// domain. The author hereby disclaims copyright to this source code. \ No newline at end of file diff --git a/src/3rdparty/angle/src/third_party/murmurhash/MurmurHash3.cpp b/src/3rdparty/angle/src/third_party/murmurhash/MurmurHash3.cpp new file mode 100644 index 0000000000..dd86292649 --- /dev/null +++ b/src/3rdparty/angle/src/third_party/murmurhash/MurmurHash3.cpp @@ -0,0 +1,334 @@ +//----------------------------------------------------------------------------- +// MurmurHash3 was written by Austin Appleby, and is placed in the public +// domain. The author hereby disclaims copyright to this source code. + +// Note - The x86 and x64 versions do _not_ produce the same results, as the +// algorithms are optimized for their respective platforms. You can still +// compile and run any of them on any platform, but your performance with the +// non-native version will be less than optimal. + +#include "MurmurHash3.h" + +//----------------------------------------------------------------------------- +// Platform-specific functions and macros + +// Microsoft Visual Studio + +#if defined(_MSC_VER) + +#define FORCE_INLINE __forceinline + +#include + +#define ROTL32(x,y) _rotl(x,y) +#define ROTL64(x,y) _rotl64(x,y) + +#define BIG_CONSTANT(x) (x) + +// Other compilers + +#else // defined(_MSC_VER) + +#define FORCE_INLINE __attribute__((always_inline)) + +inline uint32_t rotl32 ( uint32_t x, int8_t r ) +{ + return (x << r) | (x >> (32 - r)); +} + +inline uint64_t rotl64 ( uint64_t x, int8_t r ) +{ + return (x << r) | (x >> (64 - r)); +} + +#define ROTL32(x,y) rotl32(x,y) +#define ROTL64(x,y) rotl64(x,y) + +#define BIG_CONSTANT(x) (x##LLU) + +#endif // !defined(_MSC_VER) + +//----------------------------------------------------------------------------- +// Block read - if your platform needs to do endian-swapping or can only +// handle aligned reads, do the conversion here + +FORCE_INLINE uint32_t getblock ( const uint32_t * p, int i ) +{ + return p[i]; +} + +FORCE_INLINE uint64_t getblock ( const uint64_t * p, int i ) +{ + return p[i]; +} + +//----------------------------------------------------------------------------- +// Finalization mix - force all bits of a hash block to avalanche + +FORCE_INLINE uint32_t fmix ( uint32_t h ) +{ + h ^= h >> 16; + h *= 0x85ebca6b; + h ^= h >> 13; + h *= 0xc2b2ae35; + h ^= h >> 16; + + return h; +} + +//---------- + +FORCE_INLINE uint64_t fmix ( uint64_t k ) +{ + k ^= k >> 33; + k *= BIG_CONSTANT(0xff51afd7ed558ccd); + k ^= k >> 33; + k *= BIG_CONSTANT(0xc4ceb9fe1a85ec53); + k ^= k >> 33; + + return k; +} + +//----------------------------------------------------------------------------- + +void MurmurHash3_x86_32 ( const void * key, int len, + uint32_t seed, void * out ) +{ + const uint8_t * data = (const uint8_t*)key; + const int nblocks = len / 4; + + uint32_t h1 = seed; + + const uint32_t c1 = 0xcc9e2d51; + const uint32_t c2 = 0x1b873593; + + //---------- + // body + + const uint32_t * blocks = (const uint32_t *)(data + nblocks*4); + + for(int i = -nblocks; i; i++) + { + uint32_t k1 = getblock(blocks,i); + + k1 *= c1; + k1 = ROTL32(k1,15); + k1 *= c2; + + h1 ^= k1; + h1 = ROTL32(h1,13); + h1 = h1*5+0xe6546b64; + } + + //---------- + // tail + + const uint8_t * tail = (const uint8_t*)(data + nblocks*4); + + uint32_t k1 = 0; + + switch(len & 3) + { + case 3: k1 ^= tail[2] << 16; + case 2: k1 ^= tail[1] << 8; + case 1: k1 ^= tail[0]; + k1 *= c1; k1 = ROTL32(k1,15); k1 *= c2; h1 ^= k1; + }; + + //---------- + // finalization + + h1 ^= len; + + h1 = fmix(h1); + + *(uint32_t*)out = h1; +} + +//----------------------------------------------------------------------------- + +void MurmurHash3_x86_128 ( const void * key, const int len, + uint32_t seed, void * out ) +{ + const uint8_t * data = (const uint8_t*)key; + const int nblocks = len / 16; + + uint32_t h1 = seed; + uint32_t h2 = seed; + uint32_t h3 = seed; + uint32_t h4 = seed; + + const uint32_t c1 = 0x239b961b; + const uint32_t c2 = 0xab0e9789; + const uint32_t c3 = 0x38b34ae5; + const uint32_t c4 = 0xa1e38b93; + + //---------- + // body + + const uint32_t * blocks = (const uint32_t *)(data + nblocks*16); + + for(int i = -nblocks; i; i++) + { + uint32_t k1 = getblock(blocks,i*4+0); + uint32_t k2 = getblock(blocks,i*4+1); + uint32_t k3 = getblock(blocks,i*4+2); + uint32_t k4 = getblock(blocks,i*4+3); + + k1 *= c1; k1 = ROTL32(k1,15); k1 *= c2; h1 ^= k1; + + h1 = ROTL32(h1,19); h1 += h2; h1 = h1*5+0x561ccd1b; + + k2 *= c2; k2 = ROTL32(k2,16); k2 *= c3; h2 ^= k2; + + h2 = ROTL32(h2,17); h2 += h3; h2 = h2*5+0x0bcaa747; + + k3 *= c3; k3 = ROTL32(k3,17); k3 *= c4; h3 ^= k3; + + h3 = ROTL32(h3,15); h3 += h4; h3 = h3*5+0x96cd1c35; + + k4 *= c4; k4 = ROTL32(k4,18); k4 *= c1; h4 ^= k4; + + h4 = ROTL32(h4,13); h4 += h1; h4 = h4*5+0x32ac3b17; + } + + //---------- + // tail + + const uint8_t * tail = (const uint8_t*)(data + nblocks*16); + + uint32_t k1 = 0; + uint32_t k2 = 0; + uint32_t k3 = 0; + uint32_t k4 = 0; + + switch(len & 15) + { + case 15: k4 ^= tail[14] << 16; + case 14: k4 ^= tail[13] << 8; + case 13: k4 ^= tail[12] << 0; + k4 *= c4; k4 = ROTL32(k4,18); k4 *= c1; h4 ^= k4; + + case 12: k3 ^= tail[11] << 24; + case 11: k3 ^= tail[10] << 16; + case 10: k3 ^= tail[ 9] << 8; + case 9: k3 ^= tail[ 8] << 0; + k3 *= c3; k3 = ROTL32(k3,17); k3 *= c4; h3 ^= k3; + + case 8: k2 ^= tail[ 7] << 24; + case 7: k2 ^= tail[ 6] << 16; + case 6: k2 ^= tail[ 5] << 8; + case 5: k2 ^= tail[ 4] << 0; + k2 *= c2; k2 = ROTL32(k2,16); k2 *= c3; h2 ^= k2; + + case 4: k1 ^= tail[ 3] << 24; + case 3: k1 ^= tail[ 2] << 16; + case 2: k1 ^= tail[ 1] << 8; + case 1: k1 ^= tail[ 0] << 0; + k1 *= c1; k1 = ROTL32(k1,15); k1 *= c2; h1 ^= k1; + }; + + //---------- + // finalization + + h1 ^= len; h2 ^= len; h3 ^= len; h4 ^= len; + + h1 += h2; h1 += h3; h1 += h4; + h2 += h1; h3 += h1; h4 += h1; + + h1 = fmix(h1); + h2 = fmix(h2); + h3 = fmix(h3); + h4 = fmix(h4); + + h1 += h2; h1 += h3; h1 += h4; + h2 += h1; h3 += h1; h4 += h1; + + ((uint32_t*)out)[0] = h1; + ((uint32_t*)out)[1] = h2; + ((uint32_t*)out)[2] = h3; + ((uint32_t*)out)[3] = h4; +} + +//----------------------------------------------------------------------------- + +void MurmurHash3_x64_128 ( const void * key, const int len, + const uint32_t seed, void * out ) +{ + const uint8_t * data = (const uint8_t*)key; + const int nblocks = len / 16; + + uint64_t h1 = seed; + uint64_t h2 = seed; + + const uint64_t c1 = BIG_CONSTANT(0x87c37b91114253d5); + const uint64_t c2 = BIG_CONSTANT(0x4cf5ad432745937f); + + //---------- + // body + + const uint64_t * blocks = (const uint64_t *)(data); + + for(int i = 0; i < nblocks; i++) + { + uint64_t k1 = getblock(blocks,i*2+0); + uint64_t k2 = getblock(blocks,i*2+1); + + k1 *= c1; k1 = ROTL64(k1,31); k1 *= c2; h1 ^= k1; + + h1 = ROTL64(h1,27); h1 += h2; h1 = h1*5+0x52dce729; + + k2 *= c2; k2 = ROTL64(k2,33); k2 *= c1; h2 ^= k2; + + h2 = ROTL64(h2,31); h2 += h1; h2 = h2*5+0x38495ab5; + } + + //---------- + // tail + + const uint8_t * tail = (const uint8_t*)(data + nblocks*16); + + uint64_t k1 = 0; + uint64_t k2 = 0; + + switch(len & 15) + { + case 15: k2 ^= uint64_t(tail[14]) << 48; + case 14: k2 ^= uint64_t(tail[13]) << 40; + case 13: k2 ^= uint64_t(tail[12]) << 32; + case 12: k2 ^= uint64_t(tail[11]) << 24; + case 11: k2 ^= uint64_t(tail[10]) << 16; + case 10: k2 ^= uint64_t(tail[ 9]) << 8; + case 9: k2 ^= uint64_t(tail[ 8]) << 0; + k2 *= c2; k2 = ROTL64(k2,33); k2 *= c1; h2 ^= k2; + + case 8: k1 ^= uint64_t(tail[ 7]) << 56; + case 7: k1 ^= uint64_t(tail[ 6]) << 48; + case 6: k1 ^= uint64_t(tail[ 5]) << 40; + case 5: k1 ^= uint64_t(tail[ 4]) << 32; + case 4: k1 ^= uint64_t(tail[ 3]) << 24; + case 3: k1 ^= uint64_t(tail[ 2]) << 16; + case 2: k1 ^= uint64_t(tail[ 1]) << 8; + case 1: k1 ^= uint64_t(tail[ 0]) << 0; + k1 *= c1; k1 = ROTL64(k1,31); k1 *= c2; h1 ^= k1; + }; + + //---------- + // finalization + + h1 ^= len; h2 ^= len; + + h1 += h2; + h2 += h1; + + h1 = fmix(h1); + h2 = fmix(h2); + + h1 += h2; + h2 += h1; + + ((uint64_t*)out)[0] = h1; + ((uint64_t*)out)[1] = h2; +} + +//----------------------------------------------------------------------------- diff --git a/src/3rdparty/angle/src/third_party/murmurhash/MurmurHash3.h b/src/3rdparty/angle/src/third_party/murmurhash/MurmurHash3.h new file mode 100644 index 0000000000..c08f4f2585 --- /dev/null +++ b/src/3rdparty/angle/src/third_party/murmurhash/MurmurHash3.h @@ -0,0 +1,37 @@ +//----------------------------------------------------------------------------- +// MurmurHash3 was written by Austin Appleby, and is placed in the public +// domain. The author hereby disclaims copyright to this source code. + +#ifndef _MURMURHASH3_H_ +#define _MURMURHASH3_H_ + +//----------------------------------------------------------------------------- +// Platform-specific functions and macros + +// Microsoft Visual Studio + +#if defined(_MSC_VER) + +typedef unsigned char uint8_t; +typedef unsigned long uint32_t; +typedef unsigned __int64 uint64_t; + +// Other compilers + +#else // defined(_MSC_VER) + +#include + +#endif // !defined(_MSC_VER) + +//----------------------------------------------------------------------------- + +void MurmurHash3_x86_32 ( const void * key, int len, uint32_t seed, void * out ); + +void MurmurHash3_x86_128 ( const void * key, int len, uint32_t seed, void * out ); + +void MurmurHash3_x64_128 ( const void * key, int len, uint32_t seed, void * out ); + +//----------------------------------------------------------------------------- + +#endif // _MURMURHASH3_H_ \ No newline at end of file -- cgit v1.2.3