From a218a252c4200cfe7048de81a46f7e48349084d5 Mon Sep 17 00:00:00 2001 From: Andrew Knight Date: Wed, 8 Apr 2015 17:04:36 +0300 Subject: Upgrade ANGLE to 2.1~99f075dade7c This aligns with Chromium branch 2356. This version brings more complete OpenGL ES 3 support as well as various bug fixes and performance improvements. The following changes were made to earlier patches: -0000-General-fixes-for-ANGLE-2.1 Removed. All changes are now handled elsewhere. +0001-ANGLE-Improve-Windows-Phone-support Consolidated remaining parts from 0009/0010. +0002-ANGLE-Fix-compilation-with-MinGW Remaining issues from patch 0016. +0003-ANGLE-Fix-compilation-with-MSVC2010 Remaining issues from patch 0015. +0004-ANGLE-Dynamically-load-D3D-compiler-from-list Renamed from patch 0008. +0005-ANGLE-Add-support-for-querying-platform-device Renamed from patch 0013. -0004-Make-it-possible-to-link-ANGLE-statically-for-single Removed. Fixed by adding defines to project files. -0008-ANGLE-Dynamically-load-D3D-compiler-from-a-list-or-t Renamed to patch 0005. -0009-ANGLE-Support-WinRT Removed. Mostly fixed upstream; remaining parts in patch 0001. -0010-ANGLE-Enable-D3D11-for-feature-level-9-cards Removed. Mostly fixed upstream; remaining parts in patch 0001. -0012-ANGLE-fix-semantic-index-lookup Removed. Fixed upstream. -0013-ANGLE-Add-support-for-querying-platform-device Renamed to patch 0005. -0014-Let-ANGLE-use-multithreaded-devices-if-necessary Removed. No longer needed. -0015-ANGLE-Fix-angle-d3d11-on-MSVC2010 Moved remaining parts to patch 0003. -0016-ANGLE-Fix-compilation-with-MinGW-D3D11 Moved remaining parts to patch 0002. -0017-ANGLE-Fix-compilation-with-D3D9 Removed. Fixed upstream. -0018-ANGLE-Fix-releasing-textures-after-we-kill-D3D11 Removed. Fixed upstream. -0019-ANGLE-Fix-handling-of-shader-source-with-fixed-lengt Removed. Fixed upstream. -0020-ANGLE-Do-not-use-std-strlen Removed. Fixed upstream. -0020-ANGLE-Fix-compilation-with-MSVC2013-Update4 Removed. Fixed upstream. [ChangeLog][Third-party libraries] ANGLE was updated to Chromium branch 2356 (2.1~99f075dade7c). Change-Id: I32ccbfe95e10986bd94be7191dfd53445ea09158 Task-number: QTBUG-44815 Task-number: QTBUG-37660 Task-number: QTBUG-44694 Task-number: QTBUG-42443 Reviewed-by: Andrew Knight Reviewed-by: Friedemann Kleint --- mkspecs/features/win32/opengl.prf | 2 +- src/3rdparty/angle/.gitignore | 15 +- src/3rdparty/angle/AUTHORS | 6 + src/3rdparty/angle/CONTRIBUTORS | 21 +- src/3rdparty/angle/include/EGL/egl.h | 9 +- src/3rdparty/angle/include/EGL/eglext.h | 24 +- src/3rdparty/angle/include/EGL/eglplatform.h | 17 +- src/3rdparty/angle/include/GLSLANG/ShaderLang.h | 30 +- src/3rdparty/angle/include/GLSLANG/ShaderVars.h | 9 +- src/3rdparty/angle/include/KHR/khrplatform.h | 2 +- src/3rdparty/angle/include/angle_gl.h | 6 +- src/3rdparty/angle/include/export.h | 28 + src/3rdparty/angle/include/platform/Platform.h | 112 + src/3rdparty/angle/src/commit.h | 12 - src/3rdparty/angle/src/common/MemoryBuffer.cpp | 80 + src/3rdparty/angle/src/common/MemoryBuffer.h | 38 + src/3rdparty/angle/src/common/NativeWindow.h | 82 - src/3rdparty/angle/src/common/Optional.h | 61 + src/3rdparty/angle/src/common/RefCountObject.cpp | 47 - src/3rdparty/angle/src/common/RefCountObject.h | 95 - src/3rdparty/angle/src/common/angleutils.cpp | 3 +- src/3rdparty/angle/src/common/angleutils.h | 35 +- src/3rdparty/angle/src/common/blocklayout.cpp | 251 - src/3rdparty/angle/src/common/blocklayout.h | 127 - src/3rdparty/angle/src/common/debug.cpp | 263 +- src/3rdparty/angle/src/common/debug.h | 82 +- src/3rdparty/angle/src/common/event_tracer.cpp | 38 + src/3rdparty/angle/src/common/event_tracer.h | 34 + src/3rdparty/angle/src/common/features.h | 35 - src/3rdparty/angle/src/common/mathutil.h | 61 +- src/3rdparty/angle/src/common/platform.h | 109 +- src/3rdparty/angle/src/common/tls.h | 4 +- src/3rdparty/angle/src/common/utilities.cpp | 40 +- src/3rdparty/angle/src/common/utilities.h | 18 +- src/3rdparty/angle/src/common/version.h | 13 +- .../angle/src/common/win32/NativeWindow.cpp | 66 - .../src/common/winrt/CoreWindowNativeWindow.cpp | 200 - .../src/common/winrt/CoreWindowNativeWindow.h | 39 - .../src/common/winrt/InspectableNativeWindow.cpp | 274 - .../src/common/winrt/InspectableNativeWindow.h | 91 - .../common/winrt/SwapChainPanelNativeWindow.cpp | 226 - .../src/common/winrt/SwapChainPanelNativeWindow.h | 79 - .../src/compiler/preprocessor/DiagnosticsBase.h | 7 +- .../compiler/preprocessor/DirectiveHandlerBase.h | 7 +- .../src/compiler/preprocessor/DirectiveParser.h | 6 +- .../src/compiler/preprocessor/ExpressionParser.h | 7 +- .../src/compiler/preprocessor/ExpressionParser.y | 4 +- .../angle/src/compiler/preprocessor/Input.h | 2 +- .../angle/src/compiler/preprocessor/Lexer.h | 2 +- .../angle/src/compiler/preprocessor/Macro.h | 1 + .../src/compiler/preprocessor/MacroExpander.h | 6 +- .../angle/src/compiler/preprocessor/Preprocessor.h | 2 +- .../src/compiler/preprocessor/SourceLocation.h | 7 +- .../angle/src/compiler/preprocessor/Token.h | 1 + .../angle/src/compiler/preprocessor/Tokenizer.h | 2 +- .../angle/src/compiler/preprocessor/Tokenizer.l | 4 +- .../angle/src/compiler/preprocessor/numeric_lex.h | 7 +- .../angle/src/compiler/translator/BaseTypes.h | 49 +- .../translator/BuiltInFunctionEmulator.cpp | 415 +- .../compiler/translator/BuiltInFunctionEmulator.h | 112 +- .../translator/BuiltInFunctionEmulatorGLSL.cpp | 37 + .../translator/BuiltInFunctionEmulatorGLSL.h | 19 + .../translator/BuiltInFunctionEmulatorHLSL.cpp | 410 + .../translator/BuiltInFunctionEmulatorHLSL.h | 16 + .../angle/src/compiler/translator/CodeGen.cpp | 22 +- .../angle/src/compiler/translator/Common.h | 6 +- .../angle/src/compiler/translator/Compiler.cpp | 107 +- .../angle/src/compiler/translator/Compiler.h | 29 +- .../angle/src/compiler/translator/ConstantUnion.h | 13 +- .../src/compiler/translator/DetectCallDepth.cpp | 6 +- .../src/compiler/translator/DetectCallDepth.h | 6 +- .../src/compiler/translator/DetectDiscontinuity.h | 6 +- .../angle/src/compiler/translator/Diagnostics.h | 9 +- .../src/compiler/translator/DirectiveHandler.cpp | 13 +- .../src/compiler/translator/DirectiveHandler.h | 13 +- .../src/compiler/translator/EmulatePrecision.cpp | 528 ++ .../src/compiler/translator/EmulatePrecision.h | 74 + .../src/compiler/translator/ExtensionBehavior.h | 6 +- .../src/compiler/translator/FlagStd140Structs.h | 6 +- .../angle/src/compiler/translator/ForLoopUnroll.h | 6 +- .../angle/src/compiler/translator/HashNames.h | 6 +- .../angle/src/compiler/translator/InfoSink.h | 6 +- .../angle/src/compiler/translator/Initialize.cpp | 703 +- .../angle/src/compiler/translator/Initialize.h | 12 +- .../angle/src/compiler/translator/InitializeDll.h | 6 +- .../src/compiler/translator/InitializeGlobals.h | 6 +- .../compiler/translator/InitializeParseContext.h | 6 +- .../src/compiler/translator/InitializeVariables.h | 6 +- .../angle/src/compiler/translator/IntermNode.cpp | 311 +- .../angle/src/compiler/translator/IntermNode.h | 287 +- .../src/compiler/translator/IntermTraverse.cpp | 54 + .../angle/src/compiler/translator/Intermediate.cpp | 114 +- .../angle/src/compiler/translator/Intermediate.h | 71 + .../angle/src/compiler/translator/LoopInfo.h | 6 +- src/3rdparty/angle/src/compiler/translator/MMap.h | 6 +- .../angle/src/compiler/translator/NodeSearch.h | 6 +- .../angle/src/compiler/translator/Operator.cpp | 195 + .../angle/src/compiler/translator/Operator.h | 226 + .../angle/src/compiler/translator/OutputESSL.cpp | 23 +- .../angle/src/compiler/translator/OutputESSL.h | 11 +- .../angle/src/compiler/translator/OutputGLSL.cpp | 52 +- .../angle/src/compiler/translator/OutputGLSL.h | 13 +- .../src/compiler/translator/OutputGLSLBase.cpp | 216 +- .../angle/src/compiler/translator/OutputGLSLBase.h | 18 +- .../angle/src/compiler/translator/OutputHLSL.cpp | 991 ++- .../angle/src/compiler/translator/OutputHLSL.h | 113 +- .../angle/src/compiler/translator/ParseContext.cpp | 626 +- .../angle/src/compiler/translator/ParseContext.h | 61 +- .../angle/src/compiler/translator/PoolAlloc.h | 6 +- .../angle/src/compiler/translator/Pragma.h | 13 +- .../src/compiler/translator/QualifierAlive.cpp | 2 +- .../angle/src/compiler/translator/QualifierAlive.h | 5 + .../compiler/translator/RegenerateStructNames.h | 6 +- .../translator/RemoveSwitchFallThrough.cpp | 157 + .../compiler/translator/RemoveSwitchFallThrough.h | 43 + .../angle/src/compiler/translator/RemoveTree.cpp | 29 - .../angle/src/compiler/translator/RemoveTree.h | 7 - .../angle/src/compiler/translator/RenameFunction.h | 6 +- .../src/compiler/translator/RewriteElseBlocks.h | 6 +- .../translator/ScalarizeVecAndMatConstructorArgs.h | 6 +- .../angle/src/compiler/translator/SearchSymbol.cpp | 1 - .../angle/src/compiler/translator/SearchSymbol.h | 6 +- .../angle/src/compiler/translator/ShaderLang.cpp | 16 + .../angle/src/compiler/translator/ShaderVars.cpp | 18 +- .../translator/SimplifyArrayAssignment.cpp | 38 + .../compiler/translator/SimplifyArrayAssignment.h | 25 + .../src/compiler/translator/StructureHLSL.cpp | 22 +- .../angle/src/compiler/translator/StructureHLSL.h | 14 +- .../angle/src/compiler/translator/SymbolTable.cpp | 218 +- .../angle/src/compiler/translator/SymbolTable.h | 70 +- .../src/compiler/translator/TranslatorESSL.cpp | 69 +- .../angle/src/compiler/translator/TranslatorESSL.h | 19 +- .../src/compiler/translator/TranslatorGLSL.cpp | 114 +- .../angle/src/compiler/translator/TranslatorGLSL.h | 12 +- .../src/compiler/translator/TranslatorHLSL.cpp | 16 +- .../angle/src/compiler/translator/TranslatorHLSL.h | 8 +- .../angle/src/compiler/translator/Types.cpp | 18 +- src/3rdparty/angle/src/compiler/translator/Types.h | 38 +- .../src/compiler/translator/UnfoldShortCircuit.cpp | 6 +- .../src/compiler/translator/UnfoldShortCircuit.h | 9 +- .../compiler/translator/UnfoldShortCircuitAST.cpp | 28 +- .../compiler/translator/UnfoldShortCircuitAST.h | 29 +- .../angle/src/compiler/translator/UniformHLSL.cpp | 17 +- .../angle/src/compiler/translator/UniformHLSL.h | 12 +- .../angle/src/compiler/translator/UtilsHLSL.cpp | 7 + .../angle/src/compiler/translator/UtilsHLSL.h | 6 +- .../compiler/translator/ValidateLimitations.cpp | 87 - .../src/compiler/translator/ValidateLimitations.h | 4 + .../src/compiler/translator/ValidateOutputs.h | 5 + .../src/compiler/translator/ValidateSwitch.cpp | 200 + .../angle/src/compiler/translator/ValidateSwitch.h | 52 + .../angle/src/compiler/translator/VariableInfo.cpp | 36 +- .../angle/src/compiler/translator/VariableInfo.h | 8 +- .../angle/src/compiler/translator/VariablePacker.h | 6 +- .../angle/src/compiler/translator/VersionGLSL.cpp | 19 +- .../angle/src/compiler/translator/VersionGLSL.h | 18 +- .../angle/src/compiler/translator/blocklayout.cpp | 123 + .../angle/src/compiler/translator/blocklayout.h | 94 + .../src/compiler/translator/blocklayoutHLSL.cpp | 165 + .../src/compiler/translator/blocklayoutHLSL.h | 62 + .../angle/src/compiler/translator/compilerdebug.h | 6 +- .../compiler/translator/depgraph/DependencyGraph.h | 8 +- .../translator/depgraph/DependencyGraphBuilder.h | 12 +- .../translator/depgraph/DependencyGraphOutput.h | 25 +- .../angle/src/compiler/translator/glslang.h | 4 + .../angle/src/compiler/translator/glslang.l | 19 +- .../angle/src/compiler/translator/glslang.y | 427 +- .../angle/src/compiler/translator/intermOut.cpp | 110 +- .../angle/src/compiler/translator/intermediate.h | 67 - .../angle/src/compiler/translator/length_limits.h | 6 +- .../timing/RestrictFragmentShaderTiming.h | 33 +- .../translator/timing/RestrictVertexShaderTiming.h | 6 +- .../angle/src/compiler/translator/util.cpp | 2 +- src/3rdparty/angle/src/compiler/translator/util.h | 10 +- src/3rdparty/angle/src/id/commit.h | 3 + src/3rdparty/angle/src/libANGLE/AttributeMap.cpp | 53 + src/3rdparty/angle/src/libANGLE/AttributeMap.h | 39 + src/3rdparty/angle/src/libANGLE/BinaryStream.h | 218 + src/3rdparty/angle/src/libANGLE/Buffer.cpp | 121 + src/3rdparty/angle/src/libANGLE/Buffer.h | 70 + src/3rdparty/angle/src/libANGLE/Caps.cpp | 527 ++ src/3rdparty/angle/src/libANGLE/Caps.h | 374 + src/3rdparty/angle/src/libANGLE/Compiler.cpp | 38 + src/3rdparty/angle/src/libANGLE/Compiler.h | 39 + src/3rdparty/angle/src/libANGLE/Config.cpp | 275 + src/3rdparty/angle/src/libANGLE/Config.h | 91 + src/3rdparty/angle/src/libANGLE/Constants.h | 44 + src/3rdparty/angle/src/libANGLE/Context.cpp | 1587 ++++ src/3rdparty/angle/src/libANGLE/Context.h | 277 + src/3rdparty/angle/src/libANGLE/Data.cpp | 51 + src/3rdparty/angle/src/libANGLE/Data.h | 38 + src/3rdparty/angle/src/libANGLE/Display.cpp | 675 ++ src/3rdparty/angle/src/libANGLE/Display.h | 124 + src/3rdparty/angle/src/libANGLE/Error.cpp | 86 + src/3rdparty/angle/src/libANGLE/Error.h | 83 + src/3rdparty/angle/src/libANGLE/Error.inl | 163 + src/3rdparty/angle/src/libANGLE/Fence.cpp | 117 + src/3rdparty/angle/src/libANGLE/Fence.h | 71 + .../angle/src/libANGLE/Float16ToFloat32.cpp | 2203 +++++ src/3rdparty/angle/src/libANGLE/Framebuffer.cpp | 658 ++ src/3rdparty/angle/src/libANGLE/Framebuffer.h | 144 + .../angle/src/libANGLE/FramebufferAttachment.cpp | 302 + .../angle/src/libANGLE/FramebufferAttachment.h | 154 + .../angle/src/libANGLE/HandleAllocator.cpp | 133 + src/3rdparty/angle/src/libANGLE/HandleAllocator.h | 63 + src/3rdparty/angle/src/libANGLE/ImageIndex.cpp | 170 + src/3rdparty/angle/src/libANGLE/ImageIndex.h | 79 + src/3rdparty/angle/src/libANGLE/Platform.cpp | 35 + src/3rdparty/angle/src/libANGLE/Program.cpp | 1617 ++++ src/3rdparty/angle/src/libANGLE/Program.h | 276 + src/3rdparty/angle/src/libANGLE/Query.cpp | 50 + src/3rdparty/angle/src/libANGLE/Query.h | 47 + src/3rdparty/angle/src/libANGLE/RefCountObject.cpp | 39 + src/3rdparty/angle/src/libANGLE/RefCountObject.h | 110 + src/3rdparty/angle/src/libANGLE/Renderbuffer.cpp | 130 + src/3rdparty/angle/src/libANGLE/Renderbuffer.h | 69 + .../angle/src/libANGLE/ResourceManager.cpp | 456 ++ src/3rdparty/angle/src/libANGLE/ResourceManager.h | 114 + src/3rdparty/angle/src/libANGLE/Sampler.cpp | 43 + src/3rdparty/angle/src/libANGLE/Sampler.h | 60 + src/3rdparty/angle/src/libANGLE/Shader.cpp | 243 + src/3rdparty/angle/src/libANGLE/Shader.h | 118 + src/3rdparty/angle/src/libANGLE/State.cpp | 1470 ++++ src/3rdparty/angle/src/libANGLE/State.h | 335 + src/3rdparty/angle/src/libANGLE/Surface.cpp | 166 + src/3rdparty/angle/src/libANGLE/Surface.h | 98 + src/3rdparty/angle/src/libANGLE/Texture.cpp | 573 ++ src/3rdparty/angle/src/libANGLE/Texture.h | 156 + .../angle/src/libANGLE/TransformFeedback.cpp | 71 + .../angle/src/libANGLE/TransformFeedback.h | 50 + src/3rdparty/angle/src/libANGLE/Uniform.cpp | 107 + src/3rdparty/angle/src/libANGLE/Uniform.h | 77 + src/3rdparty/angle/src/libANGLE/VertexArray.cpp | 101 + src/3rdparty/angle/src/libANGLE/VertexArray.h | 66 + .../angle/src/libANGLE/VertexAttribute.cpp | 73 + src/3rdparty/angle/src/libANGLE/VertexAttribute.h | 122 + src/3rdparty/angle/src/libANGLE/angletypes.cpp | 246 + src/3rdparty/angle/src/libANGLE/angletypes.h | 323 + src/3rdparty/angle/src/libANGLE/features.h | 40 + src/3rdparty/angle/src/libANGLE/formatutils.cpp | 650 ++ src/3rdparty/angle/src/libANGLE/formatutils.h | 81 + .../angle/src/libANGLE/queryconversions.cpp | 147 + src/3rdparty/angle/src/libANGLE/queryconversions.h | 17 + .../angle/src/libANGLE/renderer/BufferImpl.h | 38 + .../angle/src/libANGLE/renderer/CompilerImpl.h | 30 + .../angle/src/libANGLE/renderer/DisplayImpl.cpp | 58 + .../angle/src/libANGLE/renderer/DisplayImpl.h | 99 + .../angle/src/libANGLE/renderer/FenceNVImpl.h | 34 + .../angle/src/libANGLE/renderer/FenceSyncImpl.h | 35 + .../angle/src/libANGLE/renderer/FramebufferImpl.h | 68 + src/3rdparty/angle/src/libANGLE/renderer/Image.h | 77 + .../angle/src/libANGLE/renderer/ImplFactory.h | 68 + .../src/libANGLE/renderer/IndexRangeCache.cpp | 114 + .../angle/src/libANGLE/renderer/IndexRangeCache.h | 53 + .../angle/src/libANGLE/renderer/ProgramImpl.cpp | 152 + .../angle/src/libANGLE/renderer/ProgramImpl.h | 137 + .../angle/src/libANGLE/renderer/QueryImpl.h | 40 + .../src/libANGLE/renderer/RenderbufferImpl.cpp | 21 + .../angle/src/libANGLE/renderer/RenderbufferImpl.h | 33 + .../angle/src/libANGLE/renderer/Renderer.cpp | 72 + .../angle/src/libANGLE/renderer/Renderer.h | 91 + .../angle/src/libANGLE/renderer/ShaderImpl.h | 57 + .../angle/src/libANGLE/renderer/SurfaceImpl.cpp | 22 + .../angle/src/libANGLE/renderer/SurfaceImpl.h | 48 + .../angle/src/libANGLE/renderer/TextureImpl.h | 72 + .../src/libANGLE/renderer/TransformFeedbackImpl.h | 31 + .../angle/src/libANGLE/renderer/VertexArrayImpl.h | 32 + .../angle/src/libANGLE/renderer/Workarounds.h | 74 + .../angle/src/libANGLE/renderer/d3d/BufferD3D.cpp | 80 + .../angle/src/libANGLE/renderer/d3d/BufferD3D.h | 56 + .../src/libANGLE/renderer/d3d/CompilerD3D.cpp | 128 + .../angle/src/libANGLE/renderer/d3d/CompilerD3D.h | 48 + .../angle/src/libANGLE/renderer/d3d/DisplayD3D.cpp | 357 + .../angle/src/libANGLE/renderer/d3d/DisplayD3D.h | 61 + .../src/libANGLE/renderer/d3d/DynamicHLSL.cpp | 1265 +++ .../angle/src/libANGLE/renderer/d3d/DynamicHLSL.h | 99 + .../src/libANGLE/renderer/d3d/FramebufferD3D.cpp | 463 ++ .../src/libANGLE/renderer/d3d/FramebufferD3D.h | 111 + .../src/libANGLE/renderer/d3d/HLSLCompiler.cpp | 340 + .../angle/src/libANGLE/renderer/d3d/HLSLCompiler.h | 54 + .../angle/src/libANGLE/renderer/d3d/ImageD3D.cpp | 47 + .../angle/src/libANGLE/renderer/d3d/ImageD3D.h | 84 + .../src/libANGLE/renderer/d3d/IndexBuffer.cpp | 196 + .../angle/src/libANGLE/renderer/d3d/IndexBuffer.h | 101 + .../src/libANGLE/renderer/d3d/IndexDataManager.cpp | 267 + .../src/libANGLE/renderer/d3d/IndexDataManager.h | 70 + .../angle/src/libANGLE/renderer/d3d/ProgramD3D.cpp | 2005 +++++ .../angle/src/libANGLE/renderer/d3d/ProgramD3D.h | 244 + .../src/libANGLE/renderer/d3d/RenderTargetD3D.cpp | 36 + .../src/libANGLE/renderer/d3d/RenderTargetD3D.h | 42 + .../src/libANGLE/renderer/d3d/RenderbufferD3D.cpp | 73 + .../src/libANGLE/renderer/d3d/RenderbufferD3D.h | 43 + .../src/libANGLE/renderer/d3d/RendererD3D.cpp | 628 ++ .../angle/src/libANGLE/renderer/d3d/RendererD3D.h | 241 + .../angle/src/libANGLE/renderer/d3d/ShaderD3D.cpp | 388 + .../angle/src/libANGLE/renderer/d3d/ShaderD3D.h | 89 + .../libANGLE/renderer/d3d/ShaderExecutableD3D.cpp | 61 + .../libANGLE/renderer/d3d/ShaderExecutableD3D.h | 54 + .../angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp | 396 + .../angle/src/libANGLE/renderer/d3d/SurfaceD3D.h | 92 + .../angle/src/libANGLE/renderer/d3d/SwapChainD3D.h | 63 + .../angle/src/libANGLE/renderer/d3d/TextureD3D.cpp | 2916 +++++++ .../angle/src/libANGLE/renderer/d3d/TextureD3D.h | 364 + .../src/libANGLE/renderer/d3d/TextureStorage.cpp | 39 + .../src/libANGLE/renderer/d3d/TextureStorage.h | 67 + .../libANGLE/renderer/d3d/TransformFeedbackD3D.cpp | 38 + .../libANGLE/renderer/d3d/TransformFeedbackD3D.h | 32 + .../src/libANGLE/renderer/d3d/VertexBuffer.cpp | 311 + .../angle/src/libANGLE/renderer/d3d/VertexBuffer.h | 143 + .../libANGLE/renderer/d3d/VertexDataManager.cpp | 396 + .../src/libANGLE/renderer/d3d/VertexDataManager.h | 95 + .../angle/src/libANGLE/renderer/d3d/copyimage.cpp | 22 + .../angle/src/libANGLE/renderer/d3d/copyimage.h | 35 + .../angle/src/libANGLE/renderer/d3d/copyimage.inl | 32 + .../src/libANGLE/renderer/d3d/d3d11/Blit11.cpp | 1059 +++ .../angle/src/libANGLE/renderer/d3d/d3d11/Blit11.h | 121 + .../src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp | 1070 +++ .../src/libANGLE/renderer/d3d/d3d11/Buffer11.h | 103 + .../src/libANGLE/renderer/d3d/d3d11/Clear11.cpp | 614 ++ .../src/libANGLE/renderer/d3d/d3d11/Clear11.h | 86 + .../renderer/d3d/d3d11/DebugAnnotator11.cpp | 119 + .../libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h | 39 + .../src/libANGLE/renderer/d3d/d3d11/Fence11.cpp | 231 + .../src/libANGLE/renderer/d3d/d3d11/Fence11.h | 59 + .../libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp | 270 + .../libANGLE/renderer/d3d/d3d11/Framebuffer11.h | 45 + .../src/libANGLE/renderer/d3d/d3d11/Image11.cpp | 664 ++ .../src/libANGLE/renderer/d3d/d3d11/Image11.h | 84 + .../libANGLE/renderer/d3d/d3d11/IndexBuffer11.cpp | 162 + .../libANGLE/renderer/d3d/d3d11/IndexBuffer11.h | 51 + .../renderer/d3d/d3d11/InputLayoutCache.cpp | 430 + .../libANGLE/renderer/d3d/d3d11/InputLayoutCache.h | 103 + .../src/libANGLE/renderer/d3d/d3d11/NativeWindow.h | 80 + .../renderer/d3d/d3d11/PixelTransfer11.cpp | 302 + .../libANGLE/renderer/d3d/d3d11/PixelTransfer11.h | 89 + .../src/libANGLE/renderer/d3d/d3d11/Query11.cpp | 164 + .../src/libANGLE/renderer/d3d/d3d11/Query11.h | 42 + .../renderer/d3d/d3d11/RenderStateCache.cpp | 452 ++ .../libANGLE/renderer/d3d/d3d11/RenderStateCache.h | 111 + .../libANGLE/renderer/d3d/d3d11/RenderTarget11.cpp | 394 + .../libANGLE/renderer/d3d/d3d11/RenderTarget11.h | 110 + .../src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp | 3585 +++++++++ .../src/libANGLE/renderer/d3d/d3d11/Renderer11.h | 400 + .../renderer/d3d/d3d11/ShaderExecutable11.cpp | 110 + .../renderer/d3d/d3d11/ShaderExecutable11.h | 59 + .../libANGLE/renderer/d3d/d3d11/SwapChain11.cpp | 711 ++ .../src/libANGLE/renderer/d3d/d3d11/SwapChain11.h | 87 + .../renderer/d3d/d3d11/TextureStorage11.cpp | 2676 +++++++ .../libANGLE/renderer/d3d/d3d11/TextureStorage11.h | 326 + .../src/libANGLE/renderer/d3d/d3d11/Trim11.cpp | 95 + .../angle/src/libANGLE/renderer/d3d/d3d11/Trim11.h | 43 + .../libANGLE/renderer/d3d/d3d11/VertexArray11.h | 40 + .../libANGLE/renderer/d3d/d3d11/VertexBuffer11.cpp | 244 + .../libANGLE/renderer/d3d/d3d11/VertexBuffer11.h | 58 + .../src/libANGLE/renderer/d3d/d3d11/copyvertex.h | 40 + .../src/libANGLE/renderer/d3d/d3d11/copyvertex.inl | 377 + .../libANGLE/renderer/d3d/d3d11/formatutils11.cpp | 1328 +++ .../libANGLE/renderer/d3d/d3d11/formatutils11.h | 93 + .../renderer/d3d/d3d11/renderer11_utils.cpp | 1378 ++++ .../libANGLE/renderer/d3d/d3d11/renderer11_utils.h | 190 + .../d3d/d3d11/shaders/BufferToTexture11.hlsl | 77 + .../renderer/d3d/d3d11/shaders/Clear11.hlsl | 119 + .../d3d/d3d11/shaders/Passthrough2D11.hlsl | 111 + .../d3d/d3d11/shaders/Passthrough3D11.hlsl | 146 + .../renderer/d3d/d3d11/shaders/Swizzle11.hlsl | 99 + .../renderer/d3d/d3d11/win32/NativeWindow.cpp | 68 + .../d3d/d3d11/winrt/CoreWindowNativeWindow.cpp | 214 + .../d3d/d3d11/winrt/CoreWindowNativeWindow.h | 110 + .../d3d/d3d11/winrt/InspectableNativeWindow.cpp | 291 + .../d3d/d3d11/winrt/InspectableNativeWindow.h | 105 + .../d3d/d3d11/winrt/SwapChainPanelNativeWindow.cpp | 228 + .../d3d/d3d11/winrt/SwapChainPanelNativeWindow.h | 79 + .../angle/src/libANGLE/renderer/d3d/d3d9/Blit9.cpp | 679 ++ .../angle/src/libANGLE/renderer/d3d/d3d9/Blit9.h | 97 + .../src/libANGLE/renderer/d3d/d3d9/Buffer9.cpp | 116 + .../angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.h | 49 + .../libANGLE/renderer/d3d/d3d9/DebugAnnotator9.cpp | 36 + .../libANGLE/renderer/d3d/d3d9/DebugAnnotator9.h | 29 + .../src/libANGLE/renderer/d3d/d3d9/Fence9.cpp | 90 + .../angle/src/libANGLE/renderer/d3d/d3d9/Fence9.h | 36 + .../libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp | 422 + .../src/libANGLE/renderer/d3d/d3d9/Framebuffer9.h | 41 + .../src/libANGLE/renderer/d3d/d3d9/Image9.cpp | 788 ++ .../angle/src/libANGLE/renderer/d3d/d3d9/Image9.h | 73 + .../libANGLE/renderer/d3d/d3d9/IndexBuffer9.cpp | 173 + .../src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.h | 51 + .../src/libANGLE/renderer/d3d/d3d9/Query9.cpp | 144 + .../angle/src/libANGLE/renderer/d3d/d3d9/Query9.h | 41 + .../libANGLE/renderer/d3d/d3d9/RenderTarget9.cpp | 139 + .../src/libANGLE/renderer/d3d/d3d9/RenderTarget9.h | 84 + .../src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp | 2933 +++++++ .../src/libANGLE/renderer/d3d/d3d9/Renderer9.h | 377 + .../src/libANGLE/renderer/d3d/d3d9/ShaderCache.h | 108 + .../renderer/d3d/d3d9/ShaderExecutable9.cpp | 53 + .../libANGLE/renderer/d3d/d3d9/ShaderExecutable9.h | 37 + .../src/libANGLE/renderer/d3d/d3d9/SwapChain9.cpp | 425 + .../src/libANGLE/renderer/d3d/d3d9/SwapChain9.h | 63 + .../libANGLE/renderer/d3d/d3d9/TextureStorage9.cpp | 472 ++ .../libANGLE/renderer/d3d/d3d9/TextureStorage9.h | 108 + .../src/libANGLE/renderer/d3d/d3d9/VertexArray9.h | 41 + .../libANGLE/renderer/d3d/d3d9/VertexBuffer9.cpp | 239 + .../src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.h | 52 + .../renderer/d3d/d3d9/VertexDeclarationCache.cpp | 237 + .../renderer/d3d/d3d9/VertexDeclarationCache.h | 60 + .../libANGLE/renderer/d3d/d3d9/formatutils9.cpp | 602 ++ .../src/libANGLE/renderer/d3d/d3d9/formatutils9.h | 86 + .../libANGLE/renderer/d3d/d3d9/renderer9_utils.cpp | 597 ++ .../libANGLE/renderer/d3d/d3d9/renderer9_utils.h | 86 + .../src/libANGLE/renderer/d3d/d3d9/shaders/Blit.ps | 33 + .../src/libANGLE/renderer/d3d/d3d9/shaders/Blit.vs | 43 + .../libANGLE/renderer/d3d/d3d9/vertexconversion.h | 197 + .../src/libANGLE/renderer/d3d/formatutilsD3D.cpp | 147 + .../src/libANGLE/renderer/d3d/formatutilsD3D.h | 50 + .../angle/src/libANGLE/renderer/d3d/generatemip.h | 28 + .../src/libANGLE/renderer/d3d/generatemip.inl | 266 + .../angle/src/libANGLE/renderer/d3d/imageformats.h | 2031 +++++ .../angle/src/libANGLE/renderer/d3d/loadimage.cpp | 662 ++ .../angle/src/libANGLE/renderer/d3d/loadimage.h | 193 + .../angle/src/libANGLE/renderer/d3d/loadimage.inl | 156 + .../src/libANGLE/renderer/d3d/loadimageSSE2.cpp | 125 + src/3rdparty/angle/src/libANGLE/validationEGL.cpp | 503 ++ src/3rdparty/angle/src/libANGLE/validationEGL.h | 49 + src/3rdparty/angle/src/libANGLE/validationES.cpp | 1882 +++++ src/3rdparty/angle/src/libANGLE/validationES.h | 94 + src/3rdparty/angle/src/libANGLE/validationES2.cpp | 882 ++ src/3rdparty/angle/src/libANGLE/validationES2.h | 34 + src/3rdparty/angle/src/libANGLE/validationES3.cpp | 1282 +++ src/3rdparty/angle/src/libANGLE/validationES3.h | 49 + src/3rdparty/angle/src/libEGL/AttributeMap.cpp | 40 - src/3rdparty/angle/src/libEGL/AttributeMap.h | 33 - src/3rdparty/angle/src/libEGL/Config.cpp | 353 - src/3rdparty/angle/src/libEGL/Config.h | 114 - src/3rdparty/angle/src/libEGL/Display.cpp | 648 -- src/3rdparty/angle/src/libEGL/Display.h | 104 - src/3rdparty/angle/src/libEGL/Error.cpp | 48 - src/3rdparty/angle/src/libEGL/Error.h | 39 - src/3rdparty/angle/src/libEGL/Surface.cpp | 505 -- src/3rdparty/angle/src/libEGL/Surface.h | 120 - src/3rdparty/angle/src/libEGL/libEGL.cpp | 1235 +-- src/3rdparty/angle/src/libEGL/libEGL.def | 12 + src/3rdparty/angle/src/libEGL/libEGL.rc | 103 - src/3rdparty/angle/src/libEGL/libEGL_mingw32.def | 12 + src/3rdparty/angle/src/libEGL/libEGLd.def | 12 + src/3rdparty/angle/src/libEGL/main.cpp | 203 - src/3rdparty/angle/src/libEGL/main.h | 45 - src/3rdparty/angle/src/libGLESv2/BinaryStream.h | 208 - src/3rdparty/angle/src/libGLESv2/Buffer.cpp | 128 - src/3rdparty/angle/src/libGLESv2/Buffer.h | 74 - src/3rdparty/angle/src/libGLESv2/Caps.cpp | 425 - src/3rdparty/angle/src/libGLESv2/Caps.h | 273 - src/3rdparty/angle/src/libGLESv2/Context.cpp | 1769 ---- src/3rdparty/angle/src/libGLESv2/Context.h | 291 - src/3rdparty/angle/src/libGLESv2/Data.cpp | 51 - src/3rdparty/angle/src/libGLESv2/Data.h | 38 - src/3rdparty/angle/src/libGLESv2/Error.cpp | 48 - src/3rdparty/angle/src/libGLESv2/Error.h | 39 - src/3rdparty/angle/src/libGLESv2/Fence.cpp | 116 - src/3rdparty/angle/src/libGLESv2/Fence.h | 75 - .../angle/src/libGLESv2/Float16ToFloat32.cpp | 2203 ----- .../angle/src/libGLESv2/Float16ToFloat32.py | 78 - src/3rdparty/angle/src/libGLESv2/Framebuffer.cpp | 672 -- src/3rdparty/angle/src/libGLESv2/Framebuffer.h | 126 - .../angle/src/libGLESv2/FramebufferAttachment.cpp | 230 - .../angle/src/libGLESv2/FramebufferAttachment.h | 132 - .../angle/src/libGLESv2/HandleAllocator.cpp | 63 - src/3rdparty/angle/src/libGLESv2/HandleAllocator.h | 44 - src/3rdparty/angle/src/libGLESv2/ImageIndex.cpp | 148 - src/3rdparty/angle/src/libGLESv2/ImageIndex.h | 68 - src/3rdparty/angle/src/libGLESv2/Program.cpp | 668 -- src/3rdparty/angle/src/libGLESv2/Program.h | 151 - src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp | 1233 --- src/3rdparty/angle/src/libGLESv2/ProgramBinary.h | 237 - src/3rdparty/angle/src/libGLESv2/Query.cpp | 50 - src/3rdparty/angle/src/libGLESv2/Query.h | 48 - src/3rdparty/angle/src/libGLESv2/Renderbuffer.cpp | 119 - src/3rdparty/angle/src/libGLESv2/Renderbuffer.h | 71 - .../angle/src/libGLESv2/ResourceManager.cpp | 427 - src/3rdparty/angle/src/libGLESv2/ResourceManager.h | 115 - src/3rdparty/angle/src/libGLESv2/Sampler.cpp | 43 - src/3rdparty/angle/src/libGLESv2/Sampler.h | 60 - src/3rdparty/angle/src/libGLESv2/Shader.cpp | 219 - src/3rdparty/angle/src/libGLESv2/Shader.h | 118 - src/3rdparty/angle/src/libGLESv2/State.cpp | 1464 ---- src/3rdparty/angle/src/libGLESv2/State.h | 325 - src/3rdparty/angle/src/libGLESv2/Texture.cpp | 1012 --- src/3rdparty/angle/src/libGLESv2/Texture.h | 241 - .../angle/src/libGLESv2/TransformFeedback.cpp | 71 - .../angle/src/libGLESv2/TransformFeedback.h | 51 - src/3rdparty/angle/src/libGLESv2/Uniform.cpp | 105 - src/3rdparty/angle/src/libGLESv2/Uniform.h | 79 - src/3rdparty/angle/src/libGLESv2/VertexArray.cpp | 96 - src/3rdparty/angle/src/libGLESv2/VertexArray.h | 62 - .../angle/src/libGLESv2/VertexAttribute.cpp | 55 - src/3rdparty/angle/src/libGLESv2/VertexAttribute.h | 119 - src/3rdparty/angle/src/libGLESv2/angletypes.cpp | 210 - src/3rdparty/angle/src/libGLESv2/angletypes.h | 257 - src/3rdparty/angle/src/libGLESv2/constants.h | 44 - .../angle/src/libGLESv2/entry_points_egl.cpp | 1127 +++ .../angle/src/libGLESv2/entry_points_egl.h | 74 + .../angle/src/libGLESv2/entry_points_egl_ext.cpp | 271 + .../angle/src/libGLESv2/entry_points_egl_ext.h | 30 + .../angle/src/libGLESv2/entry_points_gles_2_0.cpp | 4318 ++++++++++ .../angle/src/libGLESv2/entry_points_gles_2_0.h | 163 + .../src/libGLESv2/entry_points_gles_2_0_ext.cpp | 1058 +++ .../src/libGLESv2/entry_points_gles_2_0_ext.h | 78 + .../angle/src/libGLESv2/entry_points_gles_3_0.cpp | 3394 ++++++++ .../angle/src/libGLESv2/entry_points_gles_3_0.h | 125 + .../src/libGLESv2/entry_points_gles_3_0_ext.cpp | 14 + .../src/libGLESv2/entry_points_gles_3_0_ext.h | 23 + src/3rdparty/angle/src/libGLESv2/formatutils.cpp | 629 -- src/3rdparty/angle/src/libGLESv2/formatutils.h | 106 - src/3rdparty/angle/src/libGLESv2/global_state.cpp | 235 + src/3rdparty/angle/src/libGLESv2/global_state.h | 49 + src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp | 8423 +------------------- src/3rdparty/angle/src/libGLESv2/libGLESv2.def | 12 +- src/3rdparty/angle/src/libGLESv2/libGLESv2.rc | 103 - .../angle/src/libGLESv2/libGLESv2_mingw32.def | 12 +- src/3rdparty/angle/src/libGLESv2/libGLESv2d.def | 12 +- .../angle/src/libGLESv2/libGLESv2d_mingw32.def | 12 +- src/3rdparty/angle/src/libGLESv2/main.cpp | 186 - src/3rdparty/angle/src/libGLESv2/main.h | 61 - .../angle/src/libGLESv2/queryconversions.cpp | 147 - .../angle/src/libGLESv2/queryconversions.h | 17 - .../angle/src/libGLESv2/renderer/BufferImpl.h | 35 - .../angle/src/libGLESv2/renderer/FenceImpl.h | 52 - .../angle/src/libGLESv2/renderer/Image.cpp | 46 - src/3rdparty/angle/src/libGLESv2/renderer/Image.h | 79 - .../src/libGLESv2/renderer/IndexRangeCache.cpp | 128 - .../angle/src/libGLESv2/renderer/IndexRangeCache.h | 64 - .../angle/src/libGLESv2/renderer/ProgramImpl.cpp | 146 - .../angle/src/libGLESv2/renderer/ProgramImpl.h | 127 - .../angle/src/libGLESv2/renderer/QueryImpl.h | 42 - .../angle/src/libGLESv2/renderer/RenderTarget.cpp | 36 - .../angle/src/libGLESv2/renderer/RenderTarget.h | 53 - .../src/libGLESv2/renderer/RenderbufferImpl.cpp | 21 - .../src/libGLESv2/renderer/RenderbufferImpl.h | 41 - .../angle/src/libGLESv2/renderer/Renderer.cpp | 172 - .../angle/src/libGLESv2/renderer/Renderer.h | 193 - .../src/libGLESv2/renderer/ShaderExecutable.h | 78 - .../angle/src/libGLESv2/renderer/ShaderImpl.h | 55 - .../angle/src/libGLESv2/renderer/SwapChain.h | 56 - .../angle/src/libGLESv2/renderer/TextureImpl.h | 64 - .../src/libGLESv2/renderer/TransformFeedbackImpl.h | 31 - .../angle/src/libGLESv2/renderer/VertexArrayImpl.h | 32 - .../angle/src/libGLESv2/renderer/Workarounds.h | 39 - .../angle/src/libGLESv2/renderer/copyimage.cpp | 22 - .../angle/src/libGLESv2/renderer/copyimage.h | 35 - .../angle/src/libGLESv2/renderer/copyimage.inl | 32 - .../angle/src/libGLESv2/renderer/copyvertex.h | 35 - .../angle/src/libGLESv2/renderer/copyvertex.inl | 288 - .../angle/src/libGLESv2/renderer/d3d/BufferD3D.cpp | 88 - .../angle/src/libGLESv2/renderer/d3d/BufferD3D.h | 59 - .../src/libGLESv2/renderer/d3d/DynamicHLSL.cpp | 1148 --- .../angle/src/libGLESv2/renderer/d3d/DynamicHLSL.h | 101 - .../src/libGLESv2/renderer/d3d/HLSLCompiler.cpp | 333 - .../src/libGLESv2/renderer/d3d/HLSLCompiler.h | 56 - .../angle/src/libGLESv2/renderer/d3d/ImageD3D.cpp | 26 - .../angle/src/libGLESv2/renderer/d3d/ImageD3D.h | 50 - .../src/libGLESv2/renderer/d3d/IndexBuffer.cpp | 199 - .../angle/src/libGLESv2/renderer/d3d/IndexBuffer.h | 112 - .../libGLESv2/renderer/d3d/IndexDataManager.cpp | 271 - .../src/libGLESv2/renderer/d3d/IndexDataManager.h | 71 - .../src/libGLESv2/renderer/d3d/MemoryBuffer.cpp | 74 - .../src/libGLESv2/renderer/d3d/MemoryBuffer.h | 36 - .../src/libGLESv2/renderer/d3d/ProgramD3D.cpp | 1925 ----- .../angle/src/libGLESv2/renderer/d3d/ProgramD3D.h | 219 - .../src/libGLESv2/renderer/d3d/RenderbufferD3D.cpp | 108 - .../src/libGLESv2/renderer/d3d/RenderbufferD3D.h | 51 - .../src/libGLESv2/renderer/d3d/RendererD3D.cpp | 801 -- .../angle/src/libGLESv2/renderer/d3d/RendererD3D.h | 197 - .../angle/src/libGLESv2/renderer/d3d/ShaderD3D.cpp | 481 -- .../angle/src/libGLESv2/renderer/d3d/ShaderD3D.h | 98 - .../src/libGLESv2/renderer/d3d/TextureD3D.cpp | 2813 ------- .../angle/src/libGLESv2/renderer/d3d/TextureD3D.h | 335 - .../src/libGLESv2/renderer/d3d/TextureStorage.cpp | 39 - .../src/libGLESv2/renderer/d3d/TextureStorage.h | 66 - .../renderer/d3d/TransformFeedbackD3D.cpp | 38 - .../libGLESv2/renderer/d3d/TransformFeedbackD3D.h | 32 - .../src/libGLESv2/renderer/d3d/VertexBuffer.cpp | 307 - .../src/libGLESv2/renderer/d3d/VertexBuffer.h | 144 - .../libGLESv2/renderer/d3d/VertexDataManager.cpp | 354 - .../src/libGLESv2/renderer/d3d/VertexDataManager.h | 96 - .../src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp | 1047 --- .../src/libGLESv2/renderer/d3d/d3d11/Blit11.h | 123 - .../src/libGLESv2/renderer/d3d/d3d11/Buffer11.cpp | 983 --- .../src/libGLESv2/renderer/d3d/d3d11/Buffer11.h | 105 - .../src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp | 556 -- .../src/libGLESv2/renderer/d3d/d3d11/Clear11.h | 87 - .../src/libGLESv2/renderer/d3d/d3d11/Fence11.cpp | 232 - .../src/libGLESv2/renderer/d3d/d3d11/Fence11.h | 62 - .../src/libGLESv2/renderer/d3d/d3d11/Image11.cpp | 634 -- .../src/libGLESv2/renderer/d3d/d3d11/Image11.h | 87 - .../libGLESv2/renderer/d3d/d3d11/IndexBuffer11.cpp | 162 - .../libGLESv2/renderer/d3d/d3d11/IndexBuffer11.h | 53 - .../renderer/d3d/d3d11/InputLayoutCache.cpp | 255 - .../renderer/d3d/d3d11/InputLayoutCache.h | 101 - .../renderer/d3d/d3d11/PixelTransfer11.cpp | 304 - .../libGLESv2/renderer/d3d/d3d11/PixelTransfer11.h | 88 - .../src/libGLESv2/renderer/d3d/d3d11/Query11.cpp | 157 - .../src/libGLESv2/renderer/d3d/d3d11/Query11.h | 44 - .../renderer/d3d/d3d11/RenderStateCache.cpp | 439 - .../renderer/d3d/d3d11/RenderStateCache.h | 113 - .../renderer/d3d/d3d11/RenderTarget11.cpp | 404 - .../libGLESv2/renderer/d3d/d3d11/RenderTarget11.h | 110 - .../libGLESv2/renderer/d3d/d3d11/Renderer11.cpp | 3422 -------- .../src/libGLESv2/renderer/d3d/d3d11/Renderer11.h | 362 - .../renderer/d3d/d3d11/ShaderExecutable11.cpp | 110 - .../renderer/d3d/d3d11/ShaderExecutable11.h | 61 - .../libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp | 675 -- .../src/libGLESv2/renderer/d3d/d3d11/SwapChain11.h | 82 - .../renderer/d3d/d3d11/TextureStorage11.cpp | 2112 ----- .../renderer/d3d/d3d11/TextureStorage11.h | 298 - .../libGLESv2/renderer/d3d/d3d11/VertexArray11.h | 42 - .../renderer/d3d/d3d11/VertexBuffer11.cpp | 214 - .../libGLESv2/renderer/d3d/d3d11/VertexBuffer11.h | 52 - .../libGLESv2/renderer/d3d/d3d11/formatutils11.cpp | 1075 --- .../libGLESv2/renderer/d3d/d3d11/formatutils11.h | 84 - .../renderer/d3d/d3d11/renderer11_utils.cpp | 1228 --- .../renderer/d3d/d3d11/renderer11_utils.h | 189 - .../d3d/d3d11/shaders/BufferToTexture11.hlsl | 76 - .../renderer/d3d/d3d11/shaders/Clear11.hlsl | 106 - .../d3d/d3d11/shaders/Passthrough2D11.hlsl | 111 - .../d3d/d3d11/shaders/Passthrough3D11.hlsl | 146 - .../renderer/d3d/d3d11/shaders/Swizzle11.hlsl | 99 - .../src/libGLESv2/renderer/d3d/d3d9/Blit9.cpp | 679 -- .../angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.h | 97 - .../src/libGLESv2/renderer/d3d/d3d9/Buffer9.cpp | 122 - .../src/libGLESv2/renderer/d3d/d3d9/Buffer9.h | 52 - .../src/libGLESv2/renderer/d3d/d3d9/Fence9.cpp | 91 - .../angle/src/libGLESv2/renderer/d3d/d3d9/Fence9.h | 37 - .../src/libGLESv2/renderer/d3d/d3d9/Image9.cpp | 792 -- .../angle/src/libGLESv2/renderer/d3d/d3d9/Image9.h | 77 - .../libGLESv2/renderer/d3d/d3d9/IndexBuffer9.cpp | 173 - .../src/libGLESv2/renderer/d3d/d3d9/IndexBuffer9.h | 53 - .../src/libGLESv2/renderer/d3d/d3d9/Query9.cpp | 144 - .../angle/src/libGLESv2/renderer/d3d/d3d9/Query9.h | 43 - .../libGLESv2/renderer/d3d/d3d9/RenderTarget9.cpp | 148 - .../libGLESv2/renderer/d3d/d3d9/RenderTarget9.h | 89 - .../src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp | 3171 -------- .../src/libGLESv2/renderer/d3d/d3d9/Renderer9.h | 352 - .../src/libGLESv2/renderer/d3d/d3d9/ShaderCache.h | 110 - .../renderer/d3d/d3d9/ShaderExecutable9.cpp | 53 - .../renderer/d3d/d3d9/ShaderExecutable9.h | 39 - .../src/libGLESv2/renderer/d3d/d3d9/SwapChain9.cpp | 422 - .../src/libGLESv2/renderer/d3d/d3d9/SwapChain9.h | 58 - .../renderer/d3d/d3d9/TextureStorage9.cpp | 472 -- .../libGLESv2/renderer/d3d/d3d9/TextureStorage9.h | 114 - .../src/libGLESv2/renderer/d3d/d3d9/VertexArray9.h | 43 - .../libGLESv2/renderer/d3d/d3d9/VertexBuffer9.cpp | 239 - .../libGLESv2/renderer/d3d/d3d9/VertexBuffer9.h | 54 - .../renderer/d3d/d3d9/VertexDeclarationCache.cpp | 237 - .../renderer/d3d/d3d9/VertexDeclarationCache.h | 59 - .../libGLESv2/renderer/d3d/d3d9/formatutils9.cpp | 588 -- .../src/libGLESv2/renderer/d3d/d3d9/formatutils9.h | 74 - .../renderer/d3d/d3d9/renderer9_utils.cpp | 558 -- .../libGLESv2/renderer/d3d/d3d9/renderer9_utils.h | 86 - .../libGLESv2/renderer/d3d/d3d9/shaders/Blit.ps | 33 - .../libGLESv2/renderer/d3d/d3d9/shaders/Blit.vs | 43 - .../angle/src/libGLESv2/renderer/generatemip.h | 28 - .../angle/src/libGLESv2/renderer/generatemip.inl | 266 - .../angle/src/libGLESv2/renderer/imageformats.h | 2029 ----- .../angle/src/libGLESv2/renderer/loadimage.cpp | 661 -- .../angle/src/libGLESv2/renderer/loadimage.h | 193 - .../angle/src/libGLESv2/renderer/loadimage.inl | 156 - .../angle/src/libGLESv2/renderer/loadimageSSE2.cpp | 118 - .../src/libGLESv2/renderer/vertexconversion.h | 197 - src/3rdparty/angle/src/libGLESv2/validationES.cpp | 1954 ----- src/3rdparty/angle/src/libGLESv2/validationES.h | 92 - src/3rdparty/angle/src/libGLESv2/validationES2.cpp | 980 --- src/3rdparty/angle/src/libGLESv2/validationES2.h | 34 - src/3rdparty/angle/src/libGLESv2/validationES3.cpp | 1286 --- src/3rdparty/angle/src/libGLESv2/validationES3.h | 44 - .../src/third_party/compiler/ArrayBoundsClamper.h | 6 +- .../src/third_party/murmurhash/MurmurHash3.cpp | 2 + .../angle/src/third_party/murmurhash/MurmurHash3.h | 2 +- .../angle/src/third_party/systeminfo/SystemInfo.h | 6 +- .../src/third_party/trace_event/trace_event.h | 795 ++ .../patches/0000-General-fixes-for-ANGLE-2.1.patch | 477 -- .../0001-ANGLE-Improve-Windows-Phone-Support.patch | 439 + .../0002-ANGLE-Fix-compilation-with-MinGW.patch | 927 +++ ...03-ANGLE-Fix-compilation-on-MSVC2010-2012.patch | 363 + ...Dynamically-load-D3D-compiler-from-a-list.patch | 61 + ...sible-to-link-ANGLE-statically-for-single.patch | 109 - ...-Add-support-for-querying-platform-device.patch | 84 + ...ically-load-D3D-compiler-from-a-list-or-t.patch | 64 - src/angle/patches/0009-ANGLE-Support-WinRT.patch | 837 -- ...LE-Enable-D3D11-for-feature-level-9-cards.patch | 637 -- .../0012-ANGLE-fix-semantic-index-lookup.patch | 48 - ...-Add-support-for-querying-platform-device.patch | 100 - ...LE-use-multithreaded-devices-if-necessary.patch | 69 - .../0015-ANGLE-Fix-angle-d3d11-on-MSVC2010.patch | 536 -- ...16-ANGLE-Fix-compilation-with-MinGW-D3D11.patch | 169 - .../0017-ANGLE-Fix-compilation-with-D3D9.patch | 62 - ...ix-releasing-textures-after-we-kill-D3D11.patch | 106 - ...andling-of-shader-source-with-fixed-lengt.patch | 37 - .../patches/0020-ANGLE-Do-not-use-std-strlen.patch | 30 - ...GLE-Fix-compilation-with-MSVC2013-Update4.patch | 43 - src/angle/src/common/common.pri | 18 +- .../src/compiler/preprocessor/preprocessor.pro | 2 +- src/angle/src/compiler/translator.pro | 39 +- src/angle/src/config.pri | 5 +- src/angle/src/libEGL/libEGL.pro | 35 +- src/angle/src/libGLESv2/libGLESv2.pro | 760 +- 703 files changed, 92350 insertions(+), 83061 deletions(-) mode change 100644 => 100755 src/3rdparty/angle/include/KHR/khrplatform.h create mode 100644 src/3rdparty/angle/include/export.h create mode 100644 src/3rdparty/angle/include/platform/Platform.h delete mode 100644 src/3rdparty/angle/src/commit.h create mode 100644 src/3rdparty/angle/src/common/MemoryBuffer.cpp create mode 100644 src/3rdparty/angle/src/common/MemoryBuffer.h delete mode 100644 src/3rdparty/angle/src/common/NativeWindow.h create mode 100644 src/3rdparty/angle/src/common/Optional.h delete mode 100644 src/3rdparty/angle/src/common/RefCountObject.cpp delete mode 100644 src/3rdparty/angle/src/common/RefCountObject.h delete mode 100644 src/3rdparty/angle/src/common/blocklayout.cpp delete mode 100644 src/3rdparty/angle/src/common/blocklayout.h create mode 100644 src/3rdparty/angle/src/common/event_tracer.cpp create mode 100644 src/3rdparty/angle/src/common/event_tracer.h delete mode 100644 src/3rdparty/angle/src/common/features.h delete mode 100644 src/3rdparty/angle/src/common/win32/NativeWindow.cpp delete mode 100644 src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.cpp delete mode 100644 src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.h delete mode 100644 src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.cpp delete mode 100644 src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.h delete mode 100644 src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.cpp delete mode 100644 src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.h create mode 100644 src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorGLSL.cpp create mode 100644 src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorGLSL.h create mode 100644 src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorHLSL.cpp create mode 100644 src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorHLSL.h create mode 100644 src/3rdparty/angle/src/compiler/translator/EmulatePrecision.cpp create mode 100644 src/3rdparty/angle/src/compiler/translator/EmulatePrecision.h create mode 100644 src/3rdparty/angle/src/compiler/translator/Intermediate.h create mode 100644 src/3rdparty/angle/src/compiler/translator/Operator.cpp create mode 100644 src/3rdparty/angle/src/compiler/translator/Operator.h create mode 100644 src/3rdparty/angle/src/compiler/translator/RemoveSwitchFallThrough.cpp create mode 100644 src/3rdparty/angle/src/compiler/translator/RemoveSwitchFallThrough.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/RemoveTree.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/RemoveTree.h create mode 100644 src/3rdparty/angle/src/compiler/translator/SimplifyArrayAssignment.cpp create mode 100644 src/3rdparty/angle/src/compiler/translator/SimplifyArrayAssignment.h create mode 100644 src/3rdparty/angle/src/compiler/translator/ValidateSwitch.cpp create mode 100644 src/3rdparty/angle/src/compiler/translator/ValidateSwitch.h create mode 100644 src/3rdparty/angle/src/compiler/translator/blocklayout.cpp create mode 100644 src/3rdparty/angle/src/compiler/translator/blocklayout.h create mode 100644 src/3rdparty/angle/src/compiler/translator/blocklayoutHLSL.cpp create mode 100644 src/3rdparty/angle/src/compiler/translator/blocklayoutHLSL.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/intermediate.h create mode 100644 src/3rdparty/angle/src/id/commit.h create mode 100644 src/3rdparty/angle/src/libANGLE/AttributeMap.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/AttributeMap.h create mode 100644 src/3rdparty/angle/src/libANGLE/BinaryStream.h create mode 100644 src/3rdparty/angle/src/libANGLE/Buffer.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/Buffer.h create mode 100644 src/3rdparty/angle/src/libANGLE/Caps.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/Caps.h create mode 100644 src/3rdparty/angle/src/libANGLE/Compiler.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/Compiler.h create mode 100644 src/3rdparty/angle/src/libANGLE/Config.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/Config.h create mode 100644 src/3rdparty/angle/src/libANGLE/Constants.h create mode 100644 src/3rdparty/angle/src/libANGLE/Context.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/Context.h create mode 100644 src/3rdparty/angle/src/libANGLE/Data.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/Data.h create mode 100644 src/3rdparty/angle/src/libANGLE/Display.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/Display.h create mode 100644 src/3rdparty/angle/src/libANGLE/Error.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/Error.h create mode 100644 src/3rdparty/angle/src/libANGLE/Error.inl create mode 100644 src/3rdparty/angle/src/libANGLE/Fence.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/Fence.h create mode 100644 src/3rdparty/angle/src/libANGLE/Float16ToFloat32.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/Framebuffer.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/Framebuffer.h create mode 100644 src/3rdparty/angle/src/libANGLE/FramebufferAttachment.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/FramebufferAttachment.h create mode 100644 src/3rdparty/angle/src/libANGLE/HandleAllocator.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/HandleAllocator.h create mode 100644 src/3rdparty/angle/src/libANGLE/ImageIndex.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/ImageIndex.h create mode 100644 src/3rdparty/angle/src/libANGLE/Platform.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/Program.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/Program.h create mode 100644 src/3rdparty/angle/src/libANGLE/Query.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/Query.h create mode 100644 src/3rdparty/angle/src/libANGLE/RefCountObject.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/RefCountObject.h create mode 100644 src/3rdparty/angle/src/libANGLE/Renderbuffer.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/Renderbuffer.h create mode 100644 src/3rdparty/angle/src/libANGLE/ResourceManager.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/ResourceManager.h create mode 100644 src/3rdparty/angle/src/libANGLE/Sampler.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/Sampler.h create mode 100644 src/3rdparty/angle/src/libANGLE/Shader.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/Shader.h create mode 100644 src/3rdparty/angle/src/libANGLE/State.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/State.h create mode 100644 src/3rdparty/angle/src/libANGLE/Surface.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/Surface.h create mode 100644 src/3rdparty/angle/src/libANGLE/Texture.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/Texture.h create mode 100644 src/3rdparty/angle/src/libANGLE/TransformFeedback.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/TransformFeedback.h create mode 100644 src/3rdparty/angle/src/libANGLE/Uniform.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/Uniform.h create mode 100644 src/3rdparty/angle/src/libANGLE/VertexArray.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/VertexArray.h create mode 100644 src/3rdparty/angle/src/libANGLE/VertexAttribute.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/VertexAttribute.h create mode 100644 src/3rdparty/angle/src/libANGLE/angletypes.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/angletypes.h create mode 100644 src/3rdparty/angle/src/libANGLE/features.h create mode 100644 src/3rdparty/angle/src/libANGLE/formatutils.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/formatutils.h create mode 100644 src/3rdparty/angle/src/libANGLE/queryconversions.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/queryconversions.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/BufferImpl.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/CompilerImpl.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/DisplayImpl.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/DisplayImpl.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/FenceNVImpl.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/FenceSyncImpl.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/FramebufferImpl.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/Image.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/ImplFactory.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/IndexRangeCache.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/IndexRangeCache.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/ProgramImpl.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/ProgramImpl.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/QueryImpl.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/RenderbufferImpl.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/RenderbufferImpl.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/Renderer.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/Renderer.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/ShaderImpl.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/SurfaceImpl.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/SurfaceImpl.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/TextureImpl.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/TransformFeedbackImpl.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/VertexArrayImpl.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/Workarounds.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/BufferD3D.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/BufferD3D.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/CompilerD3D.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/CompilerD3D.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/DisplayD3D.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/DisplayD3D.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/DynamicHLSL.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/DynamicHLSL.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/FramebufferD3D.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/FramebufferD3D.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/ImageD3D.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/ImageD3D.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexBuffer.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexBuffer.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexDataManager.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexDataManager.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/ProgramD3D.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/ProgramD3D.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderTargetD3D.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderTargetD3D.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderbufferD3D.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderbufferD3D.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/RendererD3D.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/RendererD3D.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderD3D.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderD3D.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderExecutableD3D.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderExecutableD3D.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/SwapChainD3D.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureD3D.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureD3D.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureStorage.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureStorage.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/TransformFeedbackD3D.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/TransformFeedbackD3D.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexBuffer.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexBuffer.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexDataManager.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexDataManager.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/copyimage.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/copyimage.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/copyimage.inl create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Fence11.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Fence11.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Image11.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Image11.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Query11.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Query11.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Trim11.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Trim11.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexArray11.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/copyvertex.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/copyvertex.inl create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/BufferToTexture11.hlsl create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Clear11.hlsl create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Passthrough2D11.hlsl create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Passthrough3D11.hlsl create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Swizzle11.hlsl create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Blit9.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Blit9.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/DebugAnnotator9.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/DebugAnnotator9.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Fence9.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Fence9.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Image9.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Image9.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Query9.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Query9.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/ShaderCache.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexArray9.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/formatutils9.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/formatutils9.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/shaders/Blit.ps create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/shaders/Blit.vs create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/vertexconversion.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/formatutilsD3D.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/formatutilsD3D.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/generatemip.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/generatemip.inl create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/imageformats.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage.inl create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimageSSE2.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/validationEGL.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/validationEGL.h create mode 100644 src/3rdparty/angle/src/libANGLE/validationES.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/validationES.h create mode 100644 src/3rdparty/angle/src/libANGLE/validationES2.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/validationES2.h create mode 100644 src/3rdparty/angle/src/libANGLE/validationES3.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/validationES3.h delete mode 100644 src/3rdparty/angle/src/libEGL/AttributeMap.cpp delete mode 100644 src/3rdparty/angle/src/libEGL/AttributeMap.h delete mode 100644 src/3rdparty/angle/src/libEGL/Config.cpp delete mode 100644 src/3rdparty/angle/src/libEGL/Config.h delete mode 100644 src/3rdparty/angle/src/libEGL/Display.cpp delete mode 100644 src/3rdparty/angle/src/libEGL/Display.h delete mode 100644 src/3rdparty/angle/src/libEGL/Error.cpp delete mode 100644 src/3rdparty/angle/src/libEGL/Error.h delete mode 100644 src/3rdparty/angle/src/libEGL/Surface.cpp delete mode 100644 src/3rdparty/angle/src/libEGL/Surface.h delete mode 100644 src/3rdparty/angle/src/libEGL/libEGL.rc delete mode 100644 src/3rdparty/angle/src/libEGL/main.cpp delete mode 100644 src/3rdparty/angle/src/libEGL/main.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/BinaryStream.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/Buffer.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/Buffer.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/Caps.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/Caps.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/Context.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/Context.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/Data.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/Data.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/Error.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/Error.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/Fence.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/Fence.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/Float16ToFloat32.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/Float16ToFloat32.py delete mode 100644 src/3rdparty/angle/src/libGLESv2/Framebuffer.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/Framebuffer.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/FramebufferAttachment.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/FramebufferAttachment.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/HandleAllocator.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/HandleAllocator.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/ImageIndex.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/ImageIndex.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/Program.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/Program.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/ProgramBinary.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/Query.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/Query.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/Renderbuffer.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/Renderbuffer.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/ResourceManager.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/ResourceManager.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/Sampler.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/Sampler.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/Shader.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/Shader.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/State.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/State.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/Texture.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/Texture.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/TransformFeedback.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/TransformFeedback.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/Uniform.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/Uniform.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/VertexArray.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/VertexArray.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/VertexAttribute.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/VertexAttribute.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/angletypes.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/angletypes.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/constants.h create mode 100644 src/3rdparty/angle/src/libGLESv2/entry_points_egl.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/entry_points_egl.h create mode 100644 src/3rdparty/angle/src/libGLESv2/entry_points_egl_ext.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/entry_points_egl_ext.h create mode 100644 src/3rdparty/angle/src/libGLESv2/entry_points_gles_2_0.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/entry_points_gles_2_0.h create mode 100644 src/3rdparty/angle/src/libGLESv2/entry_points_gles_2_0_ext.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/entry_points_gles_2_0_ext.h create mode 100644 src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_0.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_0.h create mode 100644 src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_0_ext.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_0_ext.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/formatutils.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/formatutils.h create mode 100644 src/3rdparty/angle/src/libGLESv2/global_state.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/global_state.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/libGLESv2.rc delete mode 100644 src/3rdparty/angle/src/libGLESv2/main.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/main.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/queryconversions.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/queryconversions.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/BufferImpl.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/FenceImpl.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/Image.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/Image.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/ProgramImpl.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/ProgramImpl.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/QueryImpl.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/RenderbufferImpl.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/RenderbufferImpl.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/ShaderImpl.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/TextureImpl.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/TransformFeedbackImpl.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/VertexArrayImpl.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/Workarounds.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/copyimage.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/copyimage.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/copyimage.inl delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/copyvertex.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/copyvertex.inl delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/BufferD3D.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/BufferD3D.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/DynamicHLSL.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/DynamicHLSL.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/ImageD3D.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/ImageD3D.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexBuffer.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexBuffer.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexDataManager.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexDataManager.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/MemoryBuffer.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/MemoryBuffer.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/ProgramD3D.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/ProgramD3D.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/RenderbufferD3D.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/RenderbufferD3D.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/RendererD3D.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/RendererD3D.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/ShaderD3D.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/ShaderD3D.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureD3D.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureD3D.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureStorage.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureStorage.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/TransformFeedbackD3D.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/TransformFeedbackD3D.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexBuffer.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexBuffer.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexDataManager.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexDataManager.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Fence11.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Fence11.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Image11.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Image11.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/IndexBuffer11.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/IndexBuffer11.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderStateCache.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderStateCache.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/ShaderExecutable11.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/ShaderExecutable11.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexArray11.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/BufferToTexture11.hlsl delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Clear11.hlsl delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Passthrough2D11.hlsl delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Passthrough3D11.hlsl delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Swizzle11.hlsl delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Buffer9.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Buffer9.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Fence9.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Fence9.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Image9.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Image9.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/IndexBuffer9.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/IndexBuffer9.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Query9.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Query9.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/RenderTarget9.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/RenderTarget9.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderCache.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderExecutable9.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderExecutable9.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexArray9.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexBuffer9.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexBuffer9.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexDeclarationCache.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexDeclarationCache.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/formatutils9.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/formatutils9.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/shaders/Blit.ps delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/shaders/Blit.vs delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/generatemip.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/generatemip.inl delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/imageformats.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/loadimage.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/loadimage.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/loadimage.inl delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/loadimageSSE2.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/vertexconversion.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/validationES.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/validationES.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/validationES2.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/validationES2.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/validationES3.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/validationES3.h create mode 100644 src/3rdparty/angle/src/third_party/trace_event/trace_event.h delete mode 100644 src/angle/patches/0000-General-fixes-for-ANGLE-2.1.patch create mode 100644 src/angle/patches/0001-ANGLE-Improve-Windows-Phone-Support.patch create mode 100644 src/angle/patches/0002-ANGLE-Fix-compilation-with-MinGW.patch create mode 100644 src/angle/patches/0003-ANGLE-Fix-compilation-on-MSVC2010-2012.patch create mode 100644 src/angle/patches/0004-ANGLE-Dynamically-load-D3D-compiler-from-a-list.patch delete mode 100644 src/angle/patches/0004-Make-it-possible-to-link-ANGLE-statically-for-single.patch create mode 100644 src/angle/patches/0005-ANGLE-Add-support-for-querying-platform-device.patch delete mode 100644 src/angle/patches/0008-ANGLE-Dynamically-load-D3D-compiler-from-a-list-or-t.patch delete mode 100644 src/angle/patches/0009-ANGLE-Support-WinRT.patch delete mode 100644 src/angle/patches/0010-ANGLE-Enable-D3D11-for-feature-level-9-cards.patch delete mode 100644 src/angle/patches/0012-ANGLE-fix-semantic-index-lookup.patch delete mode 100644 src/angle/patches/0013-ANGLE-Add-support-for-querying-platform-device.patch delete mode 100644 src/angle/patches/0014-Let-ANGLE-use-multithreaded-devices-if-necessary.patch delete mode 100644 src/angle/patches/0015-ANGLE-Fix-angle-d3d11-on-MSVC2010.patch delete mode 100644 src/angle/patches/0016-ANGLE-Fix-compilation-with-MinGW-D3D11.patch delete mode 100644 src/angle/patches/0017-ANGLE-Fix-compilation-with-D3D9.patch delete mode 100644 src/angle/patches/0018-ANGLE-Fix-releasing-textures-after-we-kill-D3D11.patch delete mode 100644 src/angle/patches/0019-ANGLE-Fix-handling-of-shader-source-with-fixed-lengt.patch delete mode 100644 src/angle/patches/0020-ANGLE-Do-not-use-std-strlen.patch delete mode 100644 src/angle/patches/0020-ANGLE-Fix-compilation-with-MSVC2013-Update4.patch diff --git a/mkspecs/features/win32/opengl.prf b/mkspecs/features/win32/opengl.prf index 46101d6b76..8173348bc4 100644 --- a/mkspecs/features/win32/opengl.prf +++ b/mkspecs/features/win32/opengl.prf @@ -21,7 +21,7 @@ wince* { QMAKE_LIBDIR += $$QMAKE_LIBDIR_OPENGL_ES2_RELEASE } DEFINES += QT_OPENGL_ES_2 QT_OPENGL_ES_2_ANGLE - contains(QT_CONFIG, static): DEFINES += QT_OPENGL_ES_2_ANGLE_STATIC + contains(QT_CONFIG, static): DEFINES += QT_OPENGL_ES_2_ANGLE_STATIC GL_APICALL= EGLAPI= QT_CONFIG -= opengl } else { !contains(QT_CONFIG, dynamicgl) { diff --git a/src/3rdparty/angle/.gitignore b/src/3rdparty/angle/.gitignore index cbb7e6a5af..17958a0fb5 100644 --- a/src/3rdparty/angle/.gitignore +++ b/src/3rdparty/angle/.gitignore @@ -6,19 +6,28 @@ build extensions samples tests -third_party src/ipch +util .svn # Files from ANGLE we don't want/need DEPS +*.chromium +*.isolate +*.md +*.gn *.gyp *.gypi *.sh *.bat *.patch *.py +*.rc +*_unittest.cpp codereview.settings +src/commit.h +src/libANGLE/renderer/gl +src/third_party/khronos/GL # Generated by flex/bison src/compiler/preprocessor/Tokenizer.cpp @@ -28,5 +37,5 @@ src/compiler/translator/glslang_tab.cpp src/compiler/translator/glslang_tab.h # Generated by FXC -src/libGLESv2/renderer/d3d/d3d9/shaders/compiled/*.h -src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/*.h +src/libANGLE/renderer/d3d/d3d9/shaders/compiled/*.h +src/libANGLE/renderer/d3d/d3d11/shaders/compiled/*.h diff --git a/src/3rdparty/angle/AUTHORS b/src/3rdparty/angle/AUTHORS index be114bcf68..836bed8e8a 100644 --- a/src/3rdparty/angle/AUTHORS +++ b/src/3rdparty/angle/AUTHORS @@ -16,17 +16,22 @@ Autodesk, Inc. BlackBerry Limited Cable Television Laboratories, Inc. Cloud Party, Inc. +Imagination Technologies Ltd. Intel Corporation Mozilla Corporation Turbulenz Klarälvdalens Datakonsult AB +Microsoft Corporation Microsoft Open Technologies, Inc. NVIDIA Corporation +Opera Software ASA +The Qt Company Ltd. Jacek Caban Mark Callow Ginn Chen Tibor den Ouden +Régis Fénéon James Hauxwell Sam Hocevar Pierre Leveille @@ -35,3 +40,4 @@ Boying Lu Aitor Moreno Yuri O'Donnell Josh Soref +Maks Naumov diff --git a/src/3rdparty/angle/CONTRIBUTORS b/src/3rdparty/angle/CONTRIBUTORS index 6b27416e38..5252141973 100644 --- a/src/3rdparty/angle/CONTRIBUTORS +++ b/src/3rdparty/angle/CONTRIBUTORS @@ -1,4 +1,4 @@ -# This is the official list of people who can contribute +# This is the official list of people who can contribute # (and who have contributed) code to the ANGLE project # repository. # The AUTHORS file lists the copyright holders; this file @@ -40,6 +40,7 @@ Google Inc. thestig@chromium.org Justin Schuh Scott Graham + Corentin Wallez Adobe Systems Inc. Alexandru Chiculita @@ -55,6 +56,9 @@ Cloud Party, Inc. The Qt Company Ltd. Andrew Knight +Imagination Technologies Ltd. + Gregoire Payen de La Garanderie + Intel Corporation Jin Yang Andy Chen @@ -80,10 +84,21 @@ Mark Banner (standard8mbp) David Kilzer Jacek Caban Tibor den Ouden +Régis Fénéon + +Microsoft Corporation + Cooper Partin + Austin Kinross + Minmin Gong Microsoft Open Technologies, Inc. -Cooper Partin -Austin Kinross + Cooper Partin + Austin Kinross NVIDIA Corporation Olli Etuaho + Arun Patole + Qingqing Deng + +Opera Software ASA + Daniel Bratell diff --git a/src/3rdparty/angle/include/EGL/egl.h b/src/3rdparty/angle/include/EGL/egl.h index 12590a0e20..5a27291213 100644 --- a/src/3rdparty/angle/include/EGL/egl.h +++ b/src/3rdparty/angle/include/EGL/egl.h @@ -33,12 +33,12 @@ extern "C" { ** used to make the header, and the header can be found at ** http://www.opengl.org/registry/ ** -** Khronos $Revision: 27018 $ on $Date: 2014-06-10 08:06:12 -0700 (Tue, 10 Jun 2014) $ +** Khronos $Revision: 29318 $ on $Date: 2015-01-02 03:16:10 -0800 (Fri, 02 Jan 2015) $ */ #include -/* Generated on date 20140610 */ +/* Generated on date 20150102 */ /* Generated C header for: * API: egl @@ -240,6 +240,7 @@ EGLAPI EGLContext EGLAPIENTRY eglGetCurrentContext (void); typedef void *EGLSync; typedef intptr_t EGLAttrib; typedef khronos_utime_nanoseconds_t EGLTime; +typedef void *EGLImage; #define EGL_CONTEXT_MAJOR_VERSION 0x3098 #define EGL_CONTEXT_MINOR_VERSION 0x30FB #define EGL_CONTEXT_OPENGL_PROFILE_MASK 0x30FD @@ -281,10 +282,14 @@ typedef khronos_utime_nanoseconds_t EGLTime; #define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x30B6 #define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x30B7 #define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x30B8 +#define EGL_IMAGE_PRESERVED 0x30D2 +#define EGL_NO_IMAGE ((EGLImage)0) EGLAPI EGLSync EGLAPIENTRY eglCreateSync (EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list); EGLAPI EGLBoolean EGLAPIENTRY eglDestroySync (EGLDisplay dpy, EGLSync sync); EGLAPI EGLint EGLAPIENTRY eglClientWaitSync (EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout); EGLAPI EGLBoolean EGLAPIENTRY eglGetSyncAttrib (EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib *value); +EGLAPI EGLImage EGLAPIENTRY eglCreateImage (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLAttrib *attrib_list); +EGLAPI EGLBoolean EGLAPIENTRY eglDestroyImage (EGLDisplay dpy, EGLImage image); EGLAPI EGLDisplay EGLAPIENTRY eglGetPlatformDisplay (EGLenum platform, void *native_display, const EGLAttrib *attrib_list); EGLAPI EGLSurface EGLAPIENTRY eglCreatePlatformWindowSurface (EGLDisplay dpy, EGLConfig config, void *native_window, const EGLAttrib *attrib_list); EGLAPI EGLSurface EGLAPIENTRY eglCreatePlatformPixmapSurface (EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLAttrib *attrib_list); diff --git a/src/3rdparty/angle/include/EGL/eglext.h b/src/3rdparty/angle/include/EGL/eglext.h index 0cc5eec293..a44afecb3f 100644 --- a/src/3rdparty/angle/include/EGL/eglext.h +++ b/src/3rdparty/angle/include/EGL/eglext.h @@ -440,24 +440,28 @@ EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurfacePointerANGLE (EGLDisplay dpy, EGLSu #ifndef EGL_ANGLE_platform_angle #define EGL_ANGLE_platform_angle 1 -#define EGL_PLATFORM_ANGLE_ANGLE 0x3201 -#define EGL_PLATFORM_ANGLE_TYPE_ANGLE 0x3202 -#define EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE 0x3203 -#define EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE 0x3204 -#define EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE 0x3205 +#define EGL_PLATFORM_ANGLE_ANGLE 0x3202 +#define EGL_PLATFORM_ANGLE_TYPE_ANGLE 0x3203 +#define EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE 0x3204 +#define EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE 0x3205 +#define EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE 0x3206 #endif /* EGL_ANGLE_platform_angle */ #ifndef EGL_ANGLE_platform_angle_d3d #define EGL_ANGLE_platform_angle_d3d 1 -#define EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE 0x3206 -#define EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE 0x3207 -#define EGL_PLATFORM_ANGLE_USE_WARP_ANGLE 0x3208 +#define EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE 0x3207 +#define EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE 0x3208 +#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE 0x3209 +#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE 0x320A +#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE 0x320B +#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_REFERENCE_ANGLE 0x320C +#define EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE 0x320F #endif /* EGL_ANGLE_platform_angle_d3d */ #ifndef EGL_ANGLE_platform_angle_opengl #define EGL_ANGLE_platform_angle_opengl 1 -#define EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE 0x3209 -#define EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE 0x320A +#define EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE 0x320D +#define EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE 0x320E #endif /* EGL_ANGLE_platform_angle_opengl */ #ifndef EGL_ARM_pixmap_multisample_discard diff --git a/src/3rdparty/angle/include/EGL/eglplatform.h b/src/3rdparty/angle/include/EGL/eglplatform.h index 2eb3674a0b..519df3e750 100644 --- a/src/3rdparty/angle/include/EGL/eglplatform.h +++ b/src/3rdparty/angle/include/EGL/eglplatform.h @@ -73,15 +73,14 @@ #endif #include +typedef HDC EGLNativeDisplayType; typedef HBITMAP EGLNativePixmapType; -#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PC_APP || WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) /* Windows Store */ +#if !defined(WINAPI_FAMILY) || (WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP) /* Windows Desktop */ +typedef HWND EGLNativeWindowType; +#else /* Windows Store */ #include -typedef IInspectable* EGLNativeDisplayType; typedef IInspectable* EGLNativeWindowType; -#else -typedef HDC EGLNativeDisplayType; -typedef HWND EGLNativeWindowType; #endif #elif defined(__WINSCW__) || defined(__SYMBIAN32__) /* Symbian */ @@ -110,6 +109,14 @@ typedef Display *EGLNativeDisplayType; typedef Pixmap EGLNativePixmapType; typedef Window EGLNativeWindowType; +#elif defined(__GNUC__) && ( defined(__APPLE_CPP__) || defined(__APPLE_CC__) || defined(__MACOS_CLASSIC__) ) + +// TODO(jmadill): native implementation for OSX + +typedef void *EGLNativeDisplayType; +typedef void *EGLNativePixmapType; +typedef void *EGLNativeWindowType; + #else #error "Platform not recognized" #endif diff --git a/src/3rdparty/angle/include/GLSLANG/ShaderLang.h b/src/3rdparty/angle/include/GLSLANG/ShaderLang.h index 647fed6a02..126205af2c 100644 --- a/src/3rdparty/angle/include/GLSLANG/ShaderLang.h +++ b/src/3rdparty/angle/include/GLSLANG/ShaderLang.h @@ -3,8 +3,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // -#ifndef _COMPILER_INTERFACE_INCLUDED_ -#define _COMPILER_INTERFACE_INCLUDED_ +#ifndef GLSLANG_SHADERLANG_H_ +#define GLSLANG_SHADERLANG_H_ #if defined(COMPONENT_BUILD) && !defined(ANGLE_TRANSLATOR_STATIC) #if defined(_WIN32) || defined(_WIN64) @@ -48,7 +48,7 @@ typedef unsigned int GLenum; // Version number for shader translation API. // It is incremented every time the API changes. -#define ANGLE_SH_VERSION 132 +#define ANGLE_SH_VERSION 134 typedef enum { SH_GLES2_SPEC = 0x8B40, @@ -81,11 +81,16 @@ typedef enum { } ShShaderSpec; typedef enum { - SH_ESSL_OUTPUT = 0x8B45, - SH_GLSL_OUTPUT = 0x8B46, - SH_HLSL_OUTPUT = 0x8B47, - SH_HLSL9_OUTPUT = 0x8B47, - SH_HLSL11_OUTPUT = 0x8B48 + SH_ESSL_OUTPUT = 0x8B45, + // SH_GLSL_OUTPUT is deprecated. This is to not break the build. + SH_GLSL_OUTPUT = 0x8B46, + SH_GLSL_COMPATIBILITY_OUTPUT = 0x8B46, + SH_GLSL_CORE_OUTPUT = 0x8B47, + + // HLSL output only supported in some configurations. + SH_HLSL_OUTPUT = 0x8B48, + SH_HLSL9_OUTPUT = 0x8B48, + SH_HLSL11_OUTPUT = 0x8B49 } ShShaderOutput; // Compile options. @@ -223,6 +228,10 @@ typedef struct int EXT_draw_buffers; int EXT_frag_depth; int EXT_shader_texture_lod; + int WEBGL_debug_shader_precision; + int EXT_shader_framebuffer_fetch; + int NV_shader_framebuffer_fetch; + int ARM_shader_framebuffer_fetch; // Set to 1 to enable replacing GL_EXT_draw_buffers #extension directives // with GL_NV_draw_buffers in ESSL output. This flag can be used to emulate @@ -290,7 +299,8 @@ COMPILER_EXPORT const std::string &ShGetBuiltInResourcesString(const ShHandle ha // 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, -// SH_HLSL9_OUTPUT or SH_HLSL11_OUTPUT. +// SH_HLSL9_OUTPUT or SH_HLSL11_OUTPUT. Note: HLSL output is only +// supported in some configurations. // resources: Specifies the built-in resources. COMPILER_EXPORT ShHandle ShConstructCompiler( sh::GLenum type, @@ -408,4 +418,4 @@ COMPILER_EXPORT bool ShGetUniformRegister(const ShHandle handle, const std::string &uniformName, unsigned int *indexOut); -#endif // _COMPILER_INTERFACE_INCLUDED_ +#endif // GLSLANG_SHADERLANG_H_ diff --git a/src/3rdparty/angle/include/GLSLANG/ShaderVars.h b/src/3rdparty/angle/include/GLSLANG/ShaderVars.h index da21c3e76e..4128c343f8 100644 --- a/src/3rdparty/angle/include/GLSLANG/ShaderVars.h +++ b/src/3rdparty/angle/include/GLSLANG/ShaderVars.h @@ -7,8 +7,8 @@ // Types to represent GL variables (varyings, uniforms, etc) // -#ifndef _COMPILER_INTERFACE_VARIABLES_ -#define _COMPILER_INTERFACE_VARIABLES_ +#ifndef GLSLANG_SHADERVARS_H_ +#define GLSLANG_SHADERVARS_H_ #include #include @@ -28,6 +28,9 @@ enum InterpolationType INTERPOLATION_FLAT }; +// Validate link & SSO consistency of interpolation qualifiers +COMPILER_EXPORT bool InterpolationTypesMatch(InterpolationType a, InterpolationType b); + // Uniform block layout qualifier, see section 4.3.8.3 of the ESSL 3.00.4 spec enum BlockLayoutType { @@ -182,4 +185,4 @@ struct COMPILER_EXPORT InterfaceBlock } -#endif // _COMPILER_INTERFACE_VARIABLES_ +#endif // GLSLANG_SHADERVARS_H_ diff --git a/src/3rdparty/angle/include/KHR/khrplatform.h b/src/3rdparty/angle/include/KHR/khrplatform.h old mode 100644 new mode 100755 index 1ac2d3f324..c9e6f17d34 --- a/src/3rdparty/angle/include/KHR/khrplatform.h +++ b/src/3rdparty/angle/include/KHR/khrplatform.h @@ -97,7 +97,7 @@ *------------------------------------------------------------------------- * This precedes the return type of the function in the function prototype. */ -#if defined(_WIN32) && !defined(__SCITECH_SNAP__) && !defined(QT_OPENGL_ES_2_ANGLE_STATIC) +#if defined(_WIN32) && !defined(__SCITECH_SNAP__) # define KHRONOS_APICALL __declspec(dllimport) #elif defined (__SYMBIAN32__) # define KHRONOS_APICALL IMPORT_C diff --git a/src/3rdparty/angle/include/angle_gl.h b/src/3rdparty/angle/include/angle_gl.h index d093f75ee2..e7ecdbd2f0 100644 --- a/src/3rdparty/angle/include/angle_gl.h +++ b/src/3rdparty/angle/include/angle_gl.h @@ -7,8 +7,8 @@ // Includes all necessary GL headers and definitions for ANGLE. // -#ifndef ANGLE_GL_H_ -#define ANGLE_GL_H_ +#ifndef ANGLEGL_H_ +#define ANGLEGL_H_ #include "GLES2/gl2.h" #include "GLES2/gl2ext.h" @@ -20,4 +20,4 @@ #define GL_SAMPLER_2D_RECT_ARB 0x8B63 #endif -#endif // ANGLE_GL_H_ +#endif // ANGLEGL_H_ diff --git a/src/3rdparty/angle/include/export.h b/src/3rdparty/angle/include/export.h new file mode 100644 index 0000000000..cdf6245d6d --- /dev/null +++ b/src/3rdparty/angle/include/export.h @@ -0,0 +1,28 @@ +// +// Copyright(c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// export.h : Defines ANGLE_EXPORT, a macro for exporting functions from the DLL + +#ifndef LIBGLESV2_EXPORT_H_ +#define LIBGLESV2_EXPORT_H_ + +#if defined(_WIN32) +# if defined(LIBGLESV2_IMPLEMENTATION) || defined(LIBANGLE_IMPLEMENTATION) +# define ANGLE_EXPORT __declspec(dllexport) +# else +# define ANGLE_EXPORT __declspec(dllimport) +# endif +#elif defined(__GNUC__) +# if defined(LIBGLESV2_IMPLEMENTATION) || defined(LIBANGLE_IMPLEMENTATION) +# define ANGLE_EXPORT __attribute__((visibility ("default"))) +# else +# define ANGLE_EXPORT +# endif +#else +# define ANGLE_EXPORT +#endif + +#endif // LIBGLESV2_EXPORT_H_ diff --git a/src/3rdparty/angle/include/platform/Platform.h b/src/3rdparty/angle/include/platform/Platform.h new file mode 100644 index 0000000000..d915d5c0fd --- /dev/null +++ b/src/3rdparty/angle/include/platform/Platform.h @@ -0,0 +1,112 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Platform.h: The public interface ANGLE exposes to the API layer, for +// doing platform-specific tasks like gathering data, or for tracing. + +#ifndef ANGLE_PLATFORM_H +#define ANGLE_PLATFORM_H + +#include + +#include "../export.h" + +namespace angle +{ + +class Platform +{ + public: + + // Tracing -------- + + typedef uint64_t TraceEventHandle; + + // Add a trace event to the platform tracing system. Depending on the actual + // enabled state, this event may be recorded or dropped. + // - phase specifies the type of event: + // - BEGIN ('B'): Marks the beginning of a scoped event. + // - END ('E'): Marks the end of a scoped event. + // - COMPLETE ('X'): Marks the beginning of a scoped event, but doesn't + // need a matching END event. Instead, at the end of the scope, + // updateTraceEventDuration() must be called with the TraceEventHandle + // returned from addTraceEvent(). + // - INSTANT ('I'): Standalone, instantaneous event. + // - START ('S'): Marks the beginning of an asynchronous event (the end + // event can occur in a different scope or thread). The id parameter is + // used to match START/FINISH pairs. + // - FINISH ('F'): Marks the end of an asynchronous event. + // - COUNTER ('C'): Used to trace integer quantities that change over + // time. The argument values are expected to be of type int. + // - METADATA ('M'): Reserved for internal use. + // - categoryEnabled is the pointer returned by getTraceCategoryEnabledFlag. + // - name is the name of the event. Also used to match BEGIN/END and + // START/FINISH pairs. + // - id optionally allows events of the same name to be distinguished from + // each other. For example, to trace the consutruction and destruction of + // objects, specify the pointer as the id parameter. + // - numArgs specifies the number of elements in argNames, argTypes, and + // argValues. + // - argNames is the array of argument names. Use long-lived literal strings + // or specify the COPY flag. + // - argTypes is the array of argument types: + // - BOOL (1): bool + // - UINT (2): unsigned long long + // - INT (3): long long + // - DOUBLE (4): double + // - POINTER (5): void* + // - STRING (6): char* (long-lived null-terminated char* string) + // - COPY_STRING (7): char* (temporary null-terminated char* string) + // - CONVERTABLE (8): WebConvertableToTraceFormat + // - argValues is the array of argument values. Each value is the unsigned + // long long member of a union of all supported types. + // - flags can be 0 or one or more of the following, ORed together: + // - COPY (0x1): treat all strings (name, argNames and argValues of type + // string) as temporary so that they will be copied by addTraceEvent. + // - HAS_ID (0x2): use the id argument to uniquely identify the event for + // matching with other events of the same name. + // - MANGLE_ID (0x4): specify this flag if the id parameter is the value + // of a pointer. + virtual TraceEventHandle addTraceEvent(char phase, + const unsigned char *categoryEnabledFlag, + const char *name, + unsigned long long id, + double timestamp, + int numArgs, + const char **argNames, + const unsigned char *argTypes, + const unsigned long long *argValues, + unsigned char flags) + { + return 0; + } + + // Set the duration field of a COMPLETE trace event. + virtual void updateTraceEventDuration(const unsigned char* categoryEnabledFlag, const char* name, TraceEventHandle) { } + + // Callbacks for reporting histogram data. + // CustomCounts histogram has exponential bucket sizes, so that min=1, max=1000000, bucketCount=50 would do. + virtual void histogramCustomCounts(const char* name, int sample, int min, int max, int bucketCount) { } + // Enumeration histogram buckets are linear, boundaryValue should be larger than any possible sample value. + virtual void histogramEnumeration(const char* name, int sample, int boundaryValue) { } + // Unlike enumeration histograms, sparse histograms only allocate memory for non-empty buckets. + virtual void histogramSparse(const char* name, int sample) { } + + protected: + virtual ~Platform() { } +}; + +} + +typedef void(*ANGLEPlatformInitializeFunc)(angle::Platform*); +ANGLE_EXPORT void ANGLEPlatformInitialize(angle::Platform*); + +typedef void (*ANGLEPlatformShutdownFunc)(); +ANGLE_EXPORT void ANGLEPlatformShutdown(); + +typedef angle::Platform *(*ANGLEPlatformCurrentFunc)(); +ANGLE_EXPORT angle::Platform *ANGLEPlatformCurrent(); + +#endif // ANGLE_PLATFORM_H diff --git a/src/3rdparty/angle/src/commit.h b/src/3rdparty/angle/src/commit.h deleted file mode 100644 index 08fc893c25..0000000000 --- a/src/3rdparty/angle/src/commit.h +++ /dev/null @@ -1,12 +0,0 @@ -// -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// commit.h: -// This is a default commit hash header, when git is not available. -// - -#define ANGLE_COMMIT_HASH "30d6c255d238" -#define ANGLE_COMMIT_HASH_SIZE 12 -#define ANGLE_COMMIT_DATE "2014-11-13 17:37:03 +0000" diff --git a/src/3rdparty/angle/src/common/MemoryBuffer.cpp b/src/3rdparty/angle/src/common/MemoryBuffer.cpp new file mode 100644 index 0000000000..e7a3fb4a2b --- /dev/null +++ b/src/3rdparty/angle/src/common/MemoryBuffer.cpp @@ -0,0 +1,80 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "common/MemoryBuffer.h" + +#include +#include + +#include "common/debug.h" + +namespace rx +{ + +MemoryBuffer::MemoryBuffer() + : mSize(0), + mData(NULL) +{ +} + +MemoryBuffer::~MemoryBuffer() +{ + free(mData); + mData = NULL; +} + +bool MemoryBuffer::resize(size_t size) +{ + if (size == 0) + { + free(mData); + mData = NULL; + mSize = 0; + return true; + } + + if (size == mSize) + { + return true; + } + + // Only reallocate if the size has changed. + uint8_t *newMemory = reinterpret_cast(malloc(sizeof(uint8_t) * size)); + if (newMemory == NULL) + { + return false; + } + + if (mData) + { + // Copy the intersection of the old data and the new data + std::copy(mData, mData + std::min(mSize, size), newMemory); + free(mData); + } + + mData = newMemory; + mSize = size; + + return true; +} + +size_t MemoryBuffer::size() const +{ + return mSize; +} + +const uint8_t *MemoryBuffer::data() const +{ + return mData; +} + +uint8_t *MemoryBuffer::data() +{ + ASSERT(mData); + return mData; +} + +} diff --git a/src/3rdparty/angle/src/common/MemoryBuffer.h b/src/3rdparty/angle/src/common/MemoryBuffer.h new file mode 100644 index 0000000000..ec621cbca7 --- /dev/null +++ b/src/3rdparty/angle/src/common/MemoryBuffer.h @@ -0,0 +1,38 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMMON_MEMORYBUFFER_H_ +#define COMMON_MEMORYBUFFER_H_ + +#include "common/angleutils.h" + +#include +#include + +namespace rx +{ + +class MemoryBuffer : angle::NonCopyable +{ + public: + MemoryBuffer(); + ~MemoryBuffer(); + + bool resize(size_t size); + size_t size() const; + bool empty() const { return mSize == 0; } + + const uint8_t *data() const; + uint8_t *data(); + + private: + size_t mSize; + uint8_t *mData; +}; + +} + +#endif // COMMON_MEMORYBUFFER_H_ diff --git a/src/3rdparty/angle/src/common/NativeWindow.h b/src/3rdparty/angle/src/common/NativeWindow.h deleted file mode 100644 index c4a0e42bcc..0000000000 --- a/src/3rdparty/angle/src/common/NativeWindow.h +++ /dev/null @@ -1,82 +0,0 @@ -// -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// NativeWindow.h: Defines NativeWindow, a class for managing and -// performing operations on an EGLNativeWindowType. -// It is used for HWND (Desktop Windows) and IInspectable objects -//(Windows Store Applications). - -#ifndef COMMON_NATIVEWINDOW_H_ -#define COMMON_NATIVEWINDOW_H_ - -#include -#include "common/debug.h" -#include "common/platform.h" - -// DXGISwapChain and DXGIFactory are typedef'd to specific required -// types. The HWND NativeWindow implementation requires IDXGISwapChain -// and IDXGIFactory and the Windows Store NativeWindow -// implementation requires IDXGISwapChain1 and IDXGIFactory2. -#if defined(ANGLE_ENABLE_WINDOWS_STORE) -typedef IDXGISwapChain1 DXGISwapChain; -typedef IDXGIFactory2 DXGIFactory; - -#include -#include -#include -#include - -namespace rx -{ -class InspectableNativeWindow; -} - -using namespace Microsoft::WRL; -using namespace Microsoft::WRL::Wrappers; - -#else -typedef IDXGISwapChain DXGISwapChain; -typedef IDXGIFactory DXGIFactory; -#endif - -namespace rx -{ - -class NativeWindow -{ -public: - explicit NativeWindow(EGLNativeWindowType window, EGLNativeDisplayType display); - - bool initialize(); - bool getClientRect(LPRECT rect); - bool isIconic(); - -# if defined(ANGLE_ENABLE_D3D11) - typedef ID3D11Device Device; -#else - typedef IDirect3DDevice9 Device; -#endif - HRESULT createSwapChain(Device* device, DXGIFactory* factory, - DXGI_FORMAT format, UINT width, UINT height, - DXGISwapChain** swapChain); - - inline EGLNativeWindowType getNativeWindow() const { return mWindow; } - inline EGLNativeDisplayType getNativeDisplay() const { return mDisplay; } - - private: - EGLNativeWindowType mWindow; - EGLNativeDisplayType mDisplay; - -#if defined(ANGLE_ENABLE_WINDOWS_STORE) - std::shared_ptr mImpl; -#endif - -}; - -bool IsValidEGLNativeWindowType(EGLNativeWindowType window); -} - -#endif // COMMON_NATIVEWINDOW_H_ diff --git a/src/3rdparty/angle/src/common/Optional.h b/src/3rdparty/angle/src/common/Optional.h new file mode 100644 index 0000000000..9665b7ddf6 --- /dev/null +++ b/src/3rdparty/angle/src/common/Optional.h @@ -0,0 +1,61 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// Optional.h: +// Represents a type that may be invalid, similar to std::optional. +// + +#ifndef COMMON_OPTIONAL_H_ +#define COMMON_OPTIONAL_H_ + +template +struct Optional +{ + Optional() + : mValid(false), + mValue(T()) + {} + + explicit Optional(const T &valueIn) + : mValid(true), + mValue(valueIn) + {} + + Optional(const Optional &other) + : mValid(other.mValid), + mValue(other.mValue) + {} + + Optional &operator=(const Optional &other) + { + this->mValid = other.mValid; + this->mValue = other.mValue; + return *this; + } + + static Optional None() + { + return Optional(); + } + + bool valid() const { return mValid; } + const T &value() const { return mValue; } + + bool operator==(const Optional &other) const + { + return ((mValid == other.mValid) && (!mValid || (mValue == other.mValue))); + } + + bool operator!=(const Optional &other) const + { + return !(*this == other); + } + + private: + bool mValid; + T mValue; +}; + +#endif // COMMON_OPTIONAL_H_ diff --git a/src/3rdparty/angle/src/common/RefCountObject.cpp b/src/3rdparty/angle/src/common/RefCountObject.cpp deleted file mode 100644 index c1ef90cdcc..0000000000 --- a/src/3rdparty/angle/src/common/RefCountObject.cpp +++ /dev/null @@ -1,47 +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. -// - -// RefCountObject.cpp: Defines the gl::RefCountObject base class that provides -// lifecycle support for GL objects using the traditional BindObject scheme, but -// that need to be reference counted for correct cross-context deletion. -// (Concretely, textures, buffers and renderbuffers.) - -#include "RefCountObject.h" - -RefCountObject::RefCountObject(GLuint id) -{ - mId = id; - mRefCount = 0; -} - -RefCountObject::~RefCountObject() -{ - ASSERT(mRefCount == 0); -} - -void RefCountObject::addRef() const -{ - mRefCount++; -} - -void RefCountObject::release() const -{ - ASSERT(mRefCount > 0); - - if (--mRefCount == 0) - { - delete this; - } -} - -void RefCountObjectBindingPointer::set(RefCountObject *newObject) -{ - // addRef first in case newObject == mObject and this is the last reference to it. - if (newObject != NULL) newObject->addRef(); - if (mObject != NULL) mObject->release(); - - mObject = newObject; -} diff --git a/src/3rdparty/angle/src/common/RefCountObject.h b/src/3rdparty/angle/src/common/RefCountObject.h deleted file mode 100644 index 6eeaee1928..0000000000 --- a/src/3rdparty/angle/src/common/RefCountObject.h +++ /dev/null @@ -1,95 +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. -// - -// RefCountObject.h: Defines the gl::RefCountObject base class that provides -// lifecycle support for GL objects using the traditional BindObject scheme, but -// that need to be reference counted for correct cross-context deletion. -// (Concretely, textures, buffers and renderbuffers.) - -#ifndef COMMON_REFCOUNTOBJECT_H_ -#define COMMON_REFCOUNTOBJECT_H_ - -#include "common/debug.h" - -#include "angle_gl.h" - -#include - -class RefCountObject -{ - public: - explicit RefCountObject(GLuint id); - virtual ~RefCountObject(); - - virtual void addRef() const; - virtual void release() const; - - GLuint id() const { return mId; } - - private: - GLuint mId; - - mutable std::size_t mRefCount; -}; - -class RefCountObjectBindingPointer -{ - protected: - RefCountObjectBindingPointer() : mObject(NULL) { } - ~RefCountObjectBindingPointer() { ASSERT(mObject == NULL); } // Objects have to be released before the resource manager is destroyed, so they must be explicitly cleaned up. - - void set(RefCountObject *newObject); - RefCountObject *get() const { return mObject; } - - public: - GLuint id() const { return (mObject != NULL) ? mObject->id() : 0; } - bool operator!() const { return (get() == NULL); } - - private: - RefCountObject *mObject; -}; - -template -class BindingPointer : public RefCountObjectBindingPointer -{ - public: - void set(ObjectType *newObject) { RefCountObjectBindingPointer::set(newObject); } - ObjectType *get() const { return static_cast(RefCountObjectBindingPointer::get()); } - ObjectType *operator->() const { return get(); } -}; - -template -class OffsetBindingPointer : public RefCountObjectBindingPointer -{ - public: - OffsetBindingPointer() : mOffset(0), mSize(0) { } - - void set(ObjectType *newObject) - { - RefCountObjectBindingPointer::set(newObject); - mOffset = 0; - mSize = 0; - } - - void set(ObjectType *newObject, GLintptr offset, GLsizeiptr size) - { - RefCountObjectBindingPointer::set(newObject); - mOffset = offset; - mSize = size; - } - - GLintptr getOffset() const { return mOffset; } - GLsizeiptr getSize() const { return mSize; } - - ObjectType *get() const { return static_cast(RefCountObjectBindingPointer::get()); } - ObjectType *operator->() const { return get(); } - - private: - GLintptr mOffset; - GLsizeiptr mSize; -}; - -#endif // COMMON_REFCOUNTOBJECT_H_ diff --git a/src/3rdparty/angle/src/common/angleutils.cpp b/src/3rdparty/angle/src/common/angleutils.cpp index c1367c460a..af5eb6c447 100644 --- a/src/3rdparty/angle/src/common/angleutils.cpp +++ b/src/3rdparty/angle/src/common/angleutils.cpp @@ -5,7 +5,8 @@ // #include "common/angleutils.h" -#include "debug.h" +#include "common/debug.h" + #include #include diff --git a/src/3rdparty/angle/src/common/angleutils.h b/src/3rdparty/angle/src/common/angleutils.h index b343ece5bc..4cf84a3182 100644 --- a/src/3rdparty/angle/src/common/angleutils.h +++ b/src/3rdparty/angle/src/common/angleutils.h @@ -11,19 +11,31 @@ #include "common/platform.h" -#include -#include +#include +#include +#include #include #include #include -#include #include -// A macro to disallow the copy constructor and operator= functions -// This must be used in the private: declarations for a class -#define DISALLOW_COPY_AND_ASSIGN(TypeName) \ - TypeName(const TypeName&); \ - void operator=(const TypeName&) +// A helper class to disallow copy and assignment operators +namespace angle +{ + +class NonCopyable +{ +#if !defined(_MSC_VER) || (_MSC_VER >= 1800) + public: + NonCopyable() = default; + ~NonCopyable() = default; + protected: + NonCopyable(const NonCopyable&) = delete; + void operator=(const NonCopyable&) = delete; +#endif +}; + +} template inline size_t ArraySize(T(&)[N]) @@ -150,13 +162,12 @@ std::string FormatString(const char *fmt, ...); #define snprintf _snprintf #endif -#define VENDOR_ID_AMD 0x1002 -#define VENDOR_ID_INTEL 0x8086 -#define VENDOR_ID_NVIDIA 0x10DE - #define GL_BGRA4_ANGLEX 0x6ABC #define GL_BGR5_A1_ANGLEX 0x6ABD #define GL_INT_64_ANGLEX 0x6ABE #define GL_STRUCT_ANGLEX 0x6ABF +// Hidden enum for the NULL D3D device type. +#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE 0x6AC0 + #endif // COMMON_ANGLEUTILS_H_ diff --git a/src/3rdparty/angle/src/common/blocklayout.cpp b/src/3rdparty/angle/src/common/blocklayout.cpp deleted file mode 100644 index e3b2d43566..0000000000 --- a/src/3rdparty/angle/src/common/blocklayout.cpp +++ /dev/null @@ -1,251 +0,0 @@ -// -// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// blocklayout.cpp: -// Implementation for block layout classes and methods. -// - -#include "common/blocklayout.h" -#include "common/mathutil.h" -#include "common/utilities.h" - -namespace sh -{ - -BlockLayoutEncoder::BlockLayoutEncoder() - : mCurrentOffset(0) -{ -} - -BlockMemberInfo BlockLayoutEncoder::encodeType(GLenum type, unsigned int arraySize, bool isRowMajorMatrix) -{ - int arrayStride; - int matrixStride; - - getBlockLayoutInfo(type, arraySize, isRowMajorMatrix, &arrayStride, &matrixStride); - - const BlockMemberInfo memberInfo(mCurrentOffset * BytesPerComponent, arrayStride * BytesPerComponent, matrixStride * BytesPerComponent, isRowMajorMatrix); - - advanceOffset(type, arraySize, isRowMajorMatrix, arrayStride, matrixStride); - - return memberInfo; -} - -void BlockLayoutEncoder::nextRegister() -{ - mCurrentOffset = rx::roundUp(mCurrentOffset, ComponentsPerRegister); -} - -Std140BlockEncoder::Std140BlockEncoder() -{ -} - -void Std140BlockEncoder::enterAggregateType() -{ - nextRegister(); -} - -void Std140BlockEncoder::exitAggregateType() -{ - nextRegister(); -} - -void Std140BlockEncoder::getBlockLayoutInfo(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut) -{ - // We assume we are only dealing with 4 byte components (no doubles or half-words currently) - ASSERT(gl::VariableComponentSize(gl::VariableComponentType(type)) == BytesPerComponent); - - size_t baseAlignment = 0; - int matrixStride = 0; - int arrayStride = 0; - - if (gl::IsMatrixType(type)) - { - baseAlignment = ComponentsPerRegister; - matrixStride = ComponentsPerRegister; - - if (arraySize > 0) - { - const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix); - arrayStride = ComponentsPerRegister * numRegisters; - } - } - else if (arraySize > 0) - { - baseAlignment = ComponentsPerRegister; - arrayStride = ComponentsPerRegister; - } - else - { - const int numComponents = gl::VariableComponentCount(type); - baseAlignment = (numComponents == 3 ? 4u : static_cast(numComponents)); - } - - mCurrentOffset = rx::roundUp(mCurrentOffset, baseAlignment); - - *matrixStrideOut = matrixStride; - *arrayStrideOut = arrayStride; -} - -void Std140BlockEncoder::advanceOffset(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride) -{ - if (arraySize > 0) - { - mCurrentOffset += arrayStride * arraySize; - } - else if (gl::IsMatrixType(type)) - { - ASSERT(matrixStride == ComponentsPerRegister); - const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix); - mCurrentOffset += ComponentsPerRegister * numRegisters; - } - else - { - mCurrentOffset += gl::VariableComponentCount(type); - } -} - -HLSLBlockEncoder::HLSLBlockEncoder(HLSLBlockEncoderStrategy strategy) - : mEncoderStrategy(strategy) -{ -} - -void HLSLBlockEncoder::enterAggregateType() -{ - nextRegister(); -} - -void HLSLBlockEncoder::exitAggregateType() -{ -} - -void HLSLBlockEncoder::getBlockLayoutInfo(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut) -{ - // We assume we are only dealing with 4 byte components (no doubles or half-words currently) - ASSERT(gl::VariableComponentSize(gl::VariableComponentType(type)) == BytesPerComponent); - - int matrixStride = 0; - int arrayStride = 0; - - // if variables are not to be packed, or we're about to - // pack a matrix or array, skip to the start of the next - // register - if (!isPacked() || - gl::IsMatrixType(type) || - arraySize > 0) - { - nextRegister(); - } - - if (gl::IsMatrixType(type)) - { - matrixStride = ComponentsPerRegister; - - if (arraySize > 0) - { - const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix); - arrayStride = ComponentsPerRegister * numRegisters; - } - } - else if (arraySize > 0) - { - arrayStride = ComponentsPerRegister; - } - else if (isPacked()) - { - int numComponents = gl::VariableComponentCount(type); - if ((numComponents + (mCurrentOffset % ComponentsPerRegister)) > ComponentsPerRegister) - { - nextRegister(); - } - } - - *matrixStrideOut = matrixStride; - *arrayStrideOut = arrayStride; -} - -void HLSLBlockEncoder::advanceOffset(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride) -{ - if (arraySize > 0) - { - mCurrentOffset += arrayStride * (arraySize - 1); - } - - if (gl::IsMatrixType(type)) - { - ASSERT(matrixStride == ComponentsPerRegister); - const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix); - const int numComponents = gl::MatrixComponentCount(type, isRowMajorMatrix); - mCurrentOffset += ComponentsPerRegister * (numRegisters - 1); - mCurrentOffset += numComponents; - } - else if (isPacked()) - { - mCurrentOffset += gl::VariableComponentCount(type); - } - else - { - mCurrentOffset += ComponentsPerRegister; - } -} - -void HLSLBlockEncoder::skipRegisters(unsigned int numRegisters) -{ - mCurrentOffset += (numRegisters * ComponentsPerRegister); -} - -HLSLBlockEncoder::HLSLBlockEncoderStrategy HLSLBlockEncoder::GetStrategyFor(ShShaderOutput outputType) -{ - switch (outputType) - { - case SH_HLSL9_OUTPUT: return ENCODE_LOOSE; - case SH_HLSL11_OUTPUT: return ENCODE_PACKED; - default: UNREACHABLE(); return ENCODE_PACKED; - } -} - -template -void HLSLVariableRegisterCount(const ShaderVarType &variable, HLSLBlockEncoder *encoder) -{ - if (variable.isStruct()) - { - for (size_t arrayElement = 0; arrayElement < variable.elementCount(); arrayElement++) - { - encoder->enterAggregateType(); - - for (size_t fieldIndex = 0; fieldIndex < variable.fields.size(); fieldIndex++) - { - HLSLVariableRegisterCount(variable.fields[fieldIndex], encoder); - } - - encoder->exitAggregateType(); - } - } - else - { - // We operate only on varyings and uniforms, which do not have matrix layout qualifiers - encoder->encodeType(variable.type, variable.arraySize, false); - } -} - -unsigned int HLSLVariableRegisterCount(const Varying &variable) -{ - HLSLBlockEncoder encoder(HLSLBlockEncoder::ENCODE_PACKED); - HLSLVariableRegisterCount(variable, &encoder); - - const size_t registerBytes = (encoder.BytesPerComponent * encoder.ComponentsPerRegister); - return static_cast(rx::roundUp(encoder.getBlockSize(), registerBytes) / registerBytes); -} - -unsigned int HLSLVariableRegisterCount(const Uniform &variable, ShShaderOutput outputType) -{ - HLSLBlockEncoder encoder(HLSLBlockEncoder::GetStrategyFor(outputType)); - HLSLVariableRegisterCount(variable, &encoder); - - const size_t registerBytes = (encoder.BytesPerComponent * encoder.ComponentsPerRegister); - return static_cast(rx::roundUp(encoder.getBlockSize(), registerBytes) / registerBytes); -} - -} diff --git a/src/3rdparty/angle/src/common/blocklayout.h b/src/3rdparty/angle/src/common/blocklayout.h deleted file mode 100644 index d46ac6e547..0000000000 --- a/src/3rdparty/angle/src/common/blocklayout.h +++ /dev/null @@ -1,127 +0,0 @@ -// -// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// blocklayout.h: -// Methods and classes related to uniform layout and packing in GLSL and HLSL. -// - -#ifndef COMMON_BLOCKLAYOUT_H_ -#define COMMON_BLOCKLAYOUT_H_ - -#include -#include - -#include "angle_gl.h" -#include - -namespace sh -{ -struct ShaderVariable; -struct InterfaceBlockField; -struct Uniform; -struct Varying; -struct InterfaceBlock; - -struct BlockMemberInfo -{ - BlockMemberInfo(int offset, int arrayStride, int matrixStride, bool isRowMajorMatrix) - : offset(offset), - arrayStride(arrayStride), - matrixStride(matrixStride), - isRowMajorMatrix(isRowMajorMatrix) - {} - - static BlockMemberInfo getDefaultBlockInfo() - { - return BlockMemberInfo(-1, -1, -1, false); - } - - int offset; - int arrayStride; - int matrixStride; - bool isRowMajorMatrix; -}; - -class BlockLayoutEncoder -{ - public: - BlockLayoutEncoder(); - - BlockMemberInfo encodeType(GLenum type, unsigned int arraySize, bool isRowMajorMatrix); - - size_t getBlockSize() const { return mCurrentOffset * BytesPerComponent; } - size_t getCurrentRegister() const { return mCurrentOffset / ComponentsPerRegister; } - size_t getCurrentElement() const { return mCurrentOffset % ComponentsPerRegister; } - - virtual void enterAggregateType() = 0; - virtual void exitAggregateType() = 0; - - static const size_t BytesPerComponent = 4u; - static const unsigned int ComponentsPerRegister = 4u; - - protected: - size_t mCurrentOffset; - - void nextRegister(); - - virtual void getBlockLayoutInfo(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut) = 0; - virtual void advanceOffset(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride) = 0; -}; - -// Block layout according to the std140 block layout -// See "Standard Uniform Block Layout" in Section 2.11.6 of the OpenGL ES 3.0 specification - -class Std140BlockEncoder : public BlockLayoutEncoder -{ - public: - Std140BlockEncoder(); - - virtual void enterAggregateType(); - virtual void exitAggregateType(); - - protected: - virtual void getBlockLayoutInfo(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut); - virtual void advanceOffset(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride); -}; - -// Block layout packed according to the D3D9 or default D3D10+ register packing rules -// See http://msdn.microsoft.com/en-us/library/windows/desktop/bb509632(v=vs.85).aspx -// The strategy should be ENCODE_LOOSE for D3D9 constant blocks, and ENCODE_PACKED -// for everything else (D3D10+ constant blocks and all attributes/varyings). - -class HLSLBlockEncoder : public BlockLayoutEncoder -{ - public: - enum HLSLBlockEncoderStrategy - { - ENCODE_PACKED, - ENCODE_LOOSE - }; - - HLSLBlockEncoder(HLSLBlockEncoderStrategy strategy); - - virtual void enterAggregateType(); - virtual void exitAggregateType(); - void skipRegisters(unsigned int numRegisters); - - bool isPacked() const { return mEncoderStrategy == ENCODE_PACKED; } - - static HLSLBlockEncoderStrategy GetStrategyFor(ShShaderOutput outputType); - - protected: - virtual void getBlockLayoutInfo(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut); - virtual void advanceOffset(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride); - - HLSLBlockEncoderStrategy mEncoderStrategy; -}; - -// This method returns the number of used registers for a ShaderVariable. It is dependent on the HLSLBlockEncoder -// class to count the number of used registers in a struct (which are individually packed according to the same rules). -unsigned int HLSLVariableRegisterCount(const Varying &variable); -unsigned int HLSLVariableRegisterCount(const Uniform &variable, ShShaderOutput outputType); - -} - -#endif // COMMON_BLOCKLAYOUT_H_ diff --git a/src/3rdparty/angle/src/common/debug.cpp b/src/3rdparty/angle/src/common/debug.cpp index 5f55ff1e39..2fc0a2984a 100644 --- a/src/3rdparty/angle/src/common/debug.cpp +++ b/src/3rdparty/angle/src/common/debug.cpp @@ -17,172 +17,9 @@ namespace gl { -#if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS) -// Wraps the D3D9/D3D11 debug annotation functions. -class DebugAnnotationWrapper -{ - public: - DebugAnnotationWrapper() { }; - virtual ~DebugAnnotationWrapper() { }; - virtual void beginEvent(const std::wstring &eventName) = 0; - virtual void endEvent() = 0; - virtual void setMarker(const std::wstring &markerName) = 0; - virtual bool getStatus() = 0; -}; -#if defined(ANGLE_ENABLE_D3D9) -class D3D9DebugAnnotationWrapper : public DebugAnnotationWrapper +namespace { - public: - void beginEvent(const std::wstring &eventName) - { - D3DPERF_BeginEvent(0, eventName.c_str()); - } - - void endEvent() - { - D3DPERF_EndEvent(); - } - - void setMarker(const std::wstring &markerName) - { - D3DPERF_SetMarker(0, markerName.c_str()); - } - - bool getStatus() - { - return !!D3DPERF_GetStatus(); - } -}; -#endif // ANGLE_ENABLE_D3D9 - -#if defined(ANGLE_ENABLE_D3D11) -class D3D11DebugAnnotationWrapper : public DebugAnnotationWrapper -{ - public: - - D3D11DebugAnnotationWrapper() - : mInitialized(false), - mD3d11Module(NULL), - mUserDefinedAnnotation(NULL) - { - // D3D11 devices can't be created during DllMain. - // We defer device creation until the object is actually used. - } - - ~D3D11DebugAnnotationWrapper() - { - if (mInitialized) - { - SafeRelease(mUserDefinedAnnotation); - FreeLibrary(mD3d11Module); - } - } - - virtual void beginEvent(const std::wstring &eventName) - { - initializeDevice(); - - mUserDefinedAnnotation->BeginEvent(eventName.c_str()); - } - - virtual void endEvent() - { - initializeDevice(); - - mUserDefinedAnnotation->EndEvent(); - } - - virtual void setMarker(const std::wstring &markerName) - { - initializeDevice(); - - mUserDefinedAnnotation->SetMarker(markerName.c_str()); - } - - virtual bool getStatus() - { - // ID3DUserDefinedAnnotation::GetStatus doesn't work with the Graphics Diagnostics tools in Visual Studio 2013. - -#if defined(_DEBUG) && defined(ANGLE_ENABLE_WINDOWS_STORE) - // In the Windows Store, we can use IDXGraphicsAnalysis. The call to GetDebugInterface1 only succeeds if the app is under capture. - // This should only be called in DEBUG mode. - // If an app links against DXGIGetDebugInterface1 in release mode then it will fail Windows Store ingestion checks. - IDXGraphicsAnalysis* graphicsAnalysis; - DXGIGetDebugInterface1(0, IID_PPV_ARGS(&graphicsAnalysis)); - bool underCapture = (graphicsAnalysis != NULL); - SafeRelease(graphicsAnalysis); - return underCapture; -#endif - - // Otherwise, we have to return true here. - return true; - } - - protected: - - void initializeDevice() - { - if (!mInitialized) - { -#if !defined(ANGLE_ENABLE_WINDOWS_STORE) - mD3d11Module = LoadLibrary(TEXT("d3d11.dll")); - ASSERT(mD3d11Module); - - PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE)GetProcAddress(mD3d11Module, "D3D11CreateDevice"); - ASSERT(D3D11CreateDevice != NULL); -#endif // !ANGLE_ENABLE_WINDOWS_STORE - - ID3D11Device* device = NULL; - ID3D11DeviceContext* context = NULL; - - HRESULT hr = E_FAIL; - - // Create a D3D_DRIVER_TYPE_NULL device, which is much cheaper than other types of device. - hr = D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_NULL, NULL, 0, NULL, 0, D3D11_SDK_VERSION, &device, NULL, &context); - ASSERT(SUCCEEDED(hr)); - - hr = context->QueryInterface(__uuidof(mUserDefinedAnnotation), reinterpret_cast(&mUserDefinedAnnotation)); - ASSERT(SUCCEEDED(hr) && mUserDefinedAnnotation != NULL); - - SafeRelease(device); - SafeRelease(context); - - mInitialized = true; - } - } - - bool mInitialized; - HMODULE mD3d11Module; - ID3DUserDefinedAnnotation* mUserDefinedAnnotation; -}; -#endif // ANGLE_ENABLE_D3D11 - -static DebugAnnotationWrapper* g_DebugAnnotationWrapper = NULL; - -void InitializeDebugAnnotations() -{ -#if defined(ANGLE_ENABLE_D3D9) - g_DebugAnnotationWrapper = new D3D9DebugAnnotationWrapper(); -#elif defined(ANGLE_ENABLE_D3D11) - // If the project uses D3D9 then we can use the D3D9 debug annotations, even with the D3D11 renderer. - // However, if D3D9 is unavailable (e.g. in Windows Store), then we use D3D11 debug annotations. - // The D3D11 debug annotations are methods on ID3DUserDefinedAnnotation, which is implemented by the DeviceContext. - // This doesn't have to be the same DeviceContext that the renderer uses, though. - g_DebugAnnotationWrapper = new D3D11DebugAnnotationWrapper(); -#endif -} - -void UninitializeDebugAnnotations() -{ - if (g_DebugAnnotationWrapper != NULL) - { - SafeDelete(g_DebugAnnotationWrapper); - } -} - -#endif // ANGLE_ENABLE_DEBUG_ANNOTATIONS - enum DebugTraceOutputType { DebugTraceOutputTypeNone, @@ -190,29 +27,44 @@ enum DebugTraceOutputType DebugTraceOutputTypeBeginEvent }; -static void output(bool traceInDebugOnly, DebugTraceOutputType outputType, const char *format, va_list vararg) -{ -#if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS) - static std::vector buffer(512); +DebugAnnotator *g_debugAnnotator = nullptr; - if (perfActive()) +void output(bool traceInDebugOnly, MessageType messageType, DebugTraceOutputType outputType, + const char *format, va_list vararg) +{ + if (DebugAnnotationsActive()) { + static std::vector buffer(512); size_t len = FormatStringIntoVector(format, vararg, buffer); std::wstring formattedWideMessage(buffer.begin(), buffer.begin() + len); + ASSERT(g_debugAnnotator != nullptr); switch (outputType) { - case DebugTraceOutputTypeNone: - break; - case DebugTraceOutputTypeBeginEvent: - g_DebugAnnotationWrapper->beginEvent(formattedWideMessage); - break; - case DebugTraceOutputTypeSetMarker: - g_DebugAnnotationWrapper->setMarker(formattedWideMessage); - break; + case DebugTraceOutputTypeNone: + break; + case DebugTraceOutputTypeBeginEvent: + g_debugAnnotator->beginEvent(formattedWideMessage); + break; + case DebugTraceOutputTypeSetMarker: + g_debugAnnotator->setMarker(formattedWideMessage); + break; } } -#endif // ANGLE_ENABLE_DEBUG_ANNOTATIONS + + std::string formattedMessage; + UNUSED_TRACE_VARIABLE(formattedMessage); + +#if !defined(NDEBUG) && defined(_MSC_VER) + if (messageType == MESSAGE_ERR) + { + if (formattedMessage.empty()) + { + formattedMessage = FormatString(format, vararg); + } + OutputDebugStringA(formattedMessage.c_str()); + } +#endif #if defined(ANGLE_ENABLE_DEBUG_TRACE) #if defined(NDEBUG) @@ -221,7 +73,10 @@ static void output(bool traceInDebugOnly, DebugTraceOutputType outputType, const return; } #endif // NDEBUG - std::string formattedMessage = FormatString(format, vararg); + if (formattedMessage.empty()) + { + formattedMessage = FormatString(format, vararg); + } static std::ofstream file(TRACE_OUTPUT_FILE, std::ofstream::app); if (file) @@ -237,53 +92,57 @@ static void output(bool traceInDebugOnly, DebugTraceOutputType outputType, const #endif // ANGLE_ENABLE_DEBUG_TRACE } -void trace(bool traceInDebugOnly, const char *format, ...) +} // namespace + +bool DebugAnnotationsActive() { - va_list vararg; - va_start(vararg, format); #if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS) - output(traceInDebugOnly, DebugTraceOutputTypeSetMarker, format, vararg); + return g_debugAnnotator != nullptr && g_debugAnnotator->getStatus(); #else - output(traceInDebugOnly, DebugTraceOutputTypeNone, format, vararg); + return false; #endif - va_end(vararg); } -bool perfActive() +void InitializeDebugAnnotations(DebugAnnotator *debugAnnotator) { -#if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS) - static bool active = g_DebugAnnotationWrapper->getStatus(); - return active; -#else - return false; -#endif + UninitializeDebugAnnotations(); + g_debugAnnotator = debugAnnotator; +} + +void UninitializeDebugAnnotations() +{ + // Pointer is not managed. + g_debugAnnotator = nullptr; +} + +void trace(bool traceInDebugOnly, MessageType messageType, const char *format, ...) +{ + va_list vararg; + va_start(vararg, format); + output(traceInDebugOnly, messageType, DebugTraceOutputTypeSetMarker, format, vararg); + va_end(vararg); } ScopedPerfEventHelper::ScopedPerfEventHelper(const char* format, ...) { #if !defined(ANGLE_ENABLE_DEBUG_TRACE) - if (!perfActive()) + if (!DebugAnnotationsActive()) { return; } #endif // !ANGLE_ENABLE_DEBUG_TRACE va_list vararg; va_start(vararg, format); -#if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS) - output(true, DebugTraceOutputTypeBeginEvent, format, vararg); -#else - output(true, DebugTraceOutputTypeNone, format, vararg); -#endif // ANGLE_ENABLE_DEBUG_ANNOTATIONS + output(true, MESSAGE_EVENT, DebugTraceOutputTypeBeginEvent, format, vararg); va_end(vararg); } ScopedPerfEventHelper::~ScopedPerfEventHelper() { -#if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS) - if (perfActive()) + if (DebugAnnotationsActive()) { - g_DebugAnnotationWrapper->endEvent(); + g_debugAnnotator->endEvent(); } -#endif } + } diff --git a/src/3rdparty/angle/src/common/debug.h b/src/3rdparty/angle/src/common/debug.h index c177f51314..c4f118ebae 100644 --- a/src/3rdparty/angle/src/common/debug.h +++ b/src/3rdparty/angle/src/common/debug.h @@ -9,8 +9,9 @@ #ifndef COMMON_DEBUG_H_ #define COMMON_DEBUG_H_ -#include #include +#include +#include #include "common/angleutils.h" @@ -20,50 +21,71 @@ namespace gl { - // Outputs text to the debugging log, or the debugging window - void trace(bool traceInDebugOnly, const char *format, ...); - // Returns whether D3DPERF is active. - bool perfActive(); +enum MessageType +{ + MESSAGE_TRACE, + MESSAGE_FIXME, + MESSAGE_ERR, + MESSAGE_EVENT, +}; - // Pairs a D3D begin event with an end event. - class ScopedPerfEventHelper - { - public: - ScopedPerfEventHelper(const char* format, ...); - ~ScopedPerfEventHelper(); +// Outputs text to the debugging log, or the debugging window +void trace(bool traceInDebugOnly, MessageType messageType, const char *format, ...); - private: - DISALLOW_COPY_AND_ASSIGN(ScopedPerfEventHelper); - }; +// Pairs a D3D begin event with an end event. +class ScopedPerfEventHelper : angle::NonCopyable +{ + public: + ScopedPerfEventHelper(const char* format, ...); + ~ScopedPerfEventHelper(); +}; + +// Wraps the D3D9/D3D11 debug annotation functions. +class DebugAnnotator : angle::NonCopyable +{ + public: + DebugAnnotator() { }; + virtual ~DebugAnnotator() { }; + virtual void beginEvent(const std::wstring &eventName) = 0; + virtual void endEvent() = 0; + virtual void setMarker(const std::wstring &markerName) = 0; + virtual bool getStatus() = 0; +}; + +void InitializeDebugAnnotations(DebugAnnotator *debugAnnotator); +void UninitializeDebugAnnotations(); +bool DebugAnnotationsActive(); - void InitializeDebugAnnotations(); - void UninitializeDebugAnnotations(); } -// A macro to output a trace of a function call and its arguments to the debugging log #if defined(ANGLE_ENABLE_DEBUG_TRACE) || defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS) -#define TRACE(message, ...) gl::trace(true, "trace: %s(%d): " message "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__) +#define ANGLE_TRACE_ENABLED +#endif + +// A macro to output a trace of a function call and its arguments to the debugging log +#if defined(ANGLE_TRACE_ENABLED) +#define TRACE(message, ...) gl::trace(true, gl::MESSAGE_TRACE, "trace: %s(%d): " message "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__) #else #define TRACE(message, ...) (void(0)) #endif // A macro to output a function call and its arguments to the debugging log, to denote an item in need of fixing. -#if defined(ANGLE_ENABLE_DEBUG_TRACE) || defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS) -#define FIXME(message, ...) gl::trace(false, "fixme: %s(%d): " message "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__) +#if defined(ANGLE_TRACE_ENABLED) +#define FIXME(message, ...) gl::trace(false, gl::MESSAGE_FIXME, "fixme: %s(%d): " message "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__) #else #define FIXME(message, ...) (void(0)) #endif // A macro to output a function call and its arguments to the debugging log, in case of error. -#if defined(ANGLE_ENABLE_DEBUG_TRACE) || defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS) -#define ERR(message, ...) gl::trace(false, "err: %s(%d): " message "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__) +#if defined(ANGLE_TRACE_ENABLED) +#define ERR(message, ...) gl::trace(false, gl::MESSAGE_ERR, "err: %s(%d): " message "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__) #else #define ERR(message, ...) (void(0)) #endif // A macro to log a performance event around a scope. -#if defined(ANGLE_ENABLE_DEBUG_TRACE) || defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS) +#if defined(ANGLE_TRACE_ENABLED) #if defined(_MSC_VER) #define EVENT(message, ...) gl::ScopedPerfEventHelper scopedPerfEventHelper ## __LINE__("%s" message "\n", __FUNCTION__, __VA_ARGS__); #else @@ -73,6 +95,10 @@ namespace gl #define EVENT(message, ...) (void(0)) #endif +#if defined(ANGLE_TRACE_ENABLED) +#undef ANGLE_TRACE_ENABLED +#endif + // A macro asserting a condition and outputting failures to the debug log #if !defined(NDEBUG) #define ASSERT(expression) do { \ @@ -130,14 +156,4 @@ namespace gl #define HAS_DYNAMIC_TYPE(type, obj) true #endif -// A macro functioning as a compile-time assert to validate constant conditions -#if (defined(_MSC_VER) && _MSC_VER >= 1600) || (defined(__GNUC__) && (__GNUC__ > 4 || __GNUC_MINOR__ >= 3)) -#define META_ASSERT_MSG(condition, msg) static_assert(condition, msg) -#else -#define META_ASSERT_CONCAT(a, b) a ## b -#define META_ASSERT_CONCAT2(a, b) META_ASSERT_CONCAT(a, b) -#define META_ASSERT_MSG(condition, msg) typedef int META_ASSERT_CONCAT2(COMPILE_TIME_ASSERT_, __LINE__)[static_cast(condition)?1:-1] -#endif -#define META_ASSERT(condition) META_ASSERT_MSG(condition, "compile time assertion failed.") - #endif // COMMON_DEBUG_H_ diff --git a/src/3rdparty/angle/src/common/event_tracer.cpp b/src/3rdparty/angle/src/common/event_tracer.cpp new file mode 100644 index 0000000000..eb0c98c9e5 --- /dev/null +++ b/src/3rdparty/angle/src/common/event_tracer.cpp @@ -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. + +#include "common/event_tracer.h" + +namespace gl +{ + +GetCategoryEnabledFlagFunc g_getCategoryEnabledFlag; +AddTraceEventFunc g_addTraceEvent; + +} // namespace gl + +namespace gl +{ + +const unsigned char* TraceGetTraceCategoryEnabledFlag(const char* name) +{ + if (g_getCategoryEnabledFlag) + { + return g_getCategoryEnabledFlag(name); + } + static unsigned char disabled = 0; + return &disabled; +} + +void TraceAddTraceEvent(char phase, const unsigned char* categoryGroupEnabled, const char* name, unsigned long long id, + int numArgs, const char** argNames, const unsigned char* argTypes, + const unsigned long long* argValues, unsigned char flags) +{ + if (g_addTraceEvent) + { + g_addTraceEvent(phase, categoryGroupEnabled, name, id, numArgs, argNames, argTypes, argValues, flags); + } +} + +} // namespace gl diff --git a/src/3rdparty/angle/src/common/event_tracer.h b/src/3rdparty/angle/src/common/event_tracer.h new file mode 100644 index 0000000000..dbe4c1bef9 --- /dev/null +++ b/src/3rdparty/angle/src/common/event_tracer.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 COMMON_EVENT_TRACER_H_ +#define COMMON_EVENT_TRACER_H_ + +#include "common/platform.h" + +extern "C" { + +typedef const unsigned char* (*GetCategoryEnabledFlagFunc)(const char* name); +typedef void (*AddTraceEventFunc)(char phase, const unsigned char* categoryGroupEnabled, const char* name, + unsigned long long id, int numArgs, const char** argNames, + const unsigned char* argTypes, const unsigned long long* argValues, + unsigned char flags); + +} + +namespace gl +{ + +extern GetCategoryEnabledFlagFunc g_getCategoryEnabledFlag; +extern AddTraceEventFunc g_addTraceEvent; + +const unsigned char* TraceGetTraceCategoryEnabledFlag(const char* name); + +void TraceAddTraceEvent(char phase, const unsigned char* categoryGroupEnabled, const char* name, unsigned long long id, + int numArgs, const char** argNames, const unsigned char* argTypes, + const unsigned long long* argValues, unsigned char flags); + +} + +#endif // COMMON_EVENT_TRACER_H_ diff --git a/src/3rdparty/angle/src/common/features.h b/src/3rdparty/angle/src/common/features.h deleted file mode 100644 index b49a0ee852..0000000000 --- a/src/3rdparty/angle/src/common/features.h +++ /dev/null @@ -1,35 +0,0 @@ -// -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#define ANGLE_DISABLED 0 -#define ANGLE_ENABLED 1 - -// Feature defaults - -// Direct3D9EX -// 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_D3D9EX=0" in your project file. -#if !defined(ANGLE_D3D9EX) -#define ANGLE_D3D9EX ANGLE_ENABLED -#endif - -// Vsync -// ENABLED allows Vsync to be configured at runtime -// DISABLED disallows Vsync -#if !defined(ANGLE_VSYNC) -#define ANGLE_VSYNC ANGLE_ENABLED -#endif - -// Program binary loading -#if !defined(ANGLE_PROGRAM_BINARY_LOAD) -#define ANGLE_PROGRAM_BINARY_LOAD ANGLE_ENABLED -#endif - -// Shader debug info -#if !defined(ANGLE_SHADER_DEBUG_INFO) -#define ANGLE_SHADER_DEBUG_INFO ANGLE_DISABLED -#endif diff --git a/src/3rdparty/angle/src/common/mathutil.h b/src/3rdparty/angle/src/common/mathutil.h index a1717892fd..1015bd2312 100644 --- a/src/3rdparty/angle/src/common/mathutil.h +++ b/src/3rdparty/angle/src/common/mathutil.h @@ -6,8 +6,8 @@ // mathutil.h: Math and bit manipulation functions. -#ifndef LIBGLESV2_MATHUTIL_H_ -#define LIBGLESV2_MATHUTIL_H_ +#ifndef COMMON_MATHUTIL_H_ +#define COMMON_MATHUTIL_H_ #include "common/debug.h" #include "common/platform.h" @@ -15,6 +15,7 @@ #include #include #include +#include namespace gl { @@ -118,6 +119,9 @@ inline bool supportsSSE2() return supports; } +#if defined(__GNUC__) + supports = __builtin_cpu_supports("sse2"); +#else int info[4]; __cpuid(info, 0); @@ -127,6 +131,7 @@ inline bool supportsSSE2() supports = (info[3] >> 26) & 1; } +#endif checked = true; @@ -353,7 +358,7 @@ inline float float11ToFloat32(unsigned short fp11) } else // The value is zero { - exponent = -112; + exponent = static_cast(-112); } return bitCast(((exponent + 112) << 23) | (mantissa << 17)); @@ -392,7 +397,7 @@ inline float float10ToFloat32(unsigned short fp11) } else // The value is zero { - exponent = -112; + exponent = static_cast(-112); } return bitCast(((exponent + 112) << 23) | (mantissa << 18)); @@ -402,7 +407,7 @@ inline float float10ToFloat32(unsigned short fp11) template inline float normalizedToFloat(T input) { - META_ASSERT(std::numeric_limits::is_integer); + static_assert(std::numeric_limits::is_integer, "T must be an integer."); const float inverseMax = 1.0f / std::numeric_limits::max(); return input * inverseMax; @@ -411,8 +416,8 @@ inline float normalizedToFloat(T input) template inline float normalizedToFloat(T input) { - META_ASSERT(std::numeric_limits::is_integer); - META_ASSERT(inputBitCount < (sizeof(T) * 8)); + static_assert(std::numeric_limits::is_integer, "T must be an integer."); + static_assert(inputBitCount < (sizeof(T) * 8), "T must have more bits than inputBitCount."); const float inverseMax = 1.0f / ((1 << inputBitCount) - 1); return input * inverseMax; @@ -427,14 +432,15 @@ inline T floatToNormalized(float input) template inline T floatToNormalized(float input) { - META_ASSERT(outputBitCount < (sizeof(T) * 8)); + static_assert(outputBitCount < (sizeof(T) * 8), "T must have more bits than outputBitCount."); return ((1 << outputBitCount) - 1) * input + 0.5f; } template inline T getShiftedData(T input) { - META_ASSERT(inputBitCount + inputBitStart <= (sizeof(T) * 8)); + static_assert(inputBitCount + inputBitStart <= (sizeof(T) * 8), + "T must have at least as many bits as inputBitCount + inputBitStart."); const T mask = (1 << inputBitCount) - 1; return (input >> inputBitStart) & mask; } @@ -442,7 +448,8 @@ inline T getShiftedData(T input) template inline T shiftData(T input) { - META_ASSERT(inputBitCount + inputBitStart <= (sizeof(T) * 8)); + static_assert(inputBitCount + inputBitStart <= (sizeof(T) * 8), + "T must have at least as many bits as inputBitCount + inputBitStart."); const T mask = (1 << inputBitCount) - 1; return (input & mask) << inputBitStart; } @@ -503,6 +510,7 @@ inline unsigned int averageFloat10(unsigned int a, unsigned int b) namespace rx { +// Represents intervals of the type [a, b) template struct Range { @@ -513,6 +521,18 @@ struct Range T end; T length() const { return end - start; } + + bool intersects(Range other) + { + if (start <= other.start) + { + return other.start < end; + } + else + { + return start < other.end; + } + } }; typedef Range RangeI; @@ -533,14 +553,14 @@ inline unsigned int UnsignedCeilDivide(unsigned int value, unsigned int divisor) template inline bool IsUnsignedAdditionSafe(T lhs, T rhs) { - META_ASSERT(!std::numeric_limits::is_signed); + static_assert(!std::numeric_limits::is_signed, "T must be unsigned."); return (rhs <= std::numeric_limits::max() - lhs); } template inline bool IsUnsignedMultiplicationSafe(T lhs, T rhs) { - META_ASSERT(!std::numeric_limits::is_signed); + static_assert(!std::numeric_limits::is_signed, "T must be unsigned."); return (lhs == T(0) || rhs == T(0) || (rhs <= std::numeric_limits::max() / lhs)); } @@ -550,6 +570,21 @@ inline bool IsIntegerCastSafe(BigIntT bigValue) return (static_cast(static_cast(bigValue)) == bigValue); } +#if defined(_MSC_VER) + +#define ANGLE_ROTL(x,y) _rotl(x,y) + +#else + +inline uint32_t RotL(uint32_t x, int8_t r) +{ + return (x << r) | (x >> (32 - r)); +} + +#define ANGLE_ROTL(x,y) RotL(x,y) + +#endif // namespace rx + } -#endif // LIBGLESV2_MATHUTIL_H_ +#endif // COMMON_MATHUTIL_H_ diff --git a/src/3rdparty/angle/src/common/platform.h b/src/3rdparty/angle/src/common/platform.h index 5bf97f9184..3a2aa91bed 100644 --- a/src/3rdparty/angle/src/common/platform.h +++ b/src/3rdparty/angle/src/common/platform.h @@ -14,12 +14,12 @@ #elif defined(__APPLE__) # define ANGLE_PLATFORM_APPLE 1 # define ANGLE_PLATFORM_POSIX 1 -#elif defined(__linux__) -# define ANGLE_PLATFORM_LINUX 1 -# define ANGLE_PLATFORM_POSIX 1 #elif defined(ANDROID) # define ANGLE_PLATFORM_ANDROID 1 # define ANGLE_PLATFORM_POSIX 1 +#elif defined(__linux__) || defined(EMSCRIPTEN) +# define ANGLE_PLATFORM_LINUX 1 +# define ANGLE_PLATFORM_POSIX 1 #elif defined(__FreeBSD__) || \ defined(__OpenBSD__) || \ defined(__NetBSD__) || \ @@ -34,9 +34,6 @@ #endif #ifdef ANGLE_PLATFORM_WINDOWS -# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PC_APP || WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) -# define ANGLE_ENABLE_WINDOWS_STORE 1 -# endif # ifndef STRICT # define STRICT 1 # endif @@ -50,24 +47,32 @@ # include # include +# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY != WINAPI_FAMILY_DESKTOP_APP) +# define ANGLE_ENABLE_WINDOWS_STORE 1 +# endif + # if defined(ANGLE_ENABLE_D3D9) # include -# include -# if !defined(COMPILER_IMPLEMENTATION) +# if !defined(ANGLE_TRANSLATOR_IMPLEMENTATION) # include # endif # endif # if defined(ANGLE_ENABLE_D3D11) # include -# include # include # include -# if defined(_MSC_VER) && (_MSC_VER >= 1700) +# if defined(__MINGW32__) && !defined(__d3d11sdklayers_h__) +# define ANGLE_MINGW32_COMPAT +# endif +# if defined(_MSC_VER) && _MSC_VER >= 1800 +# define ANGLE_ENABLE_D3D11_1 +# endif +# if defined(ANGLE_ENABLE_D3D11_1) # include # include # endif -# if !defined(COMPILER_IMPLEMENTATION) +# if !defined(ANGLE_TRANSLATOR_IMPLEMENTATION) # include # endif # endif @@ -75,88 +80,24 @@ # if defined(ANGLE_ENABLE_WINDOWS_STORE) # include # if defined(_DEBUG) -# if (WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP) +# if WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP # include # endif # include # endif # endif -# if defined(__MINGW32__) // Missing defines on MinGW -typedef enum D3D11_MAP_FLAG -{ - D3D11_MAP_FLAG_DO_NOT_WAIT = 0x100000L -} D3D11_MAP_FLAG; -typedef struct D3D11_QUERY_DATA_SO_STATISTICS -{ - UINT64 NumPrimitivesWritten; - UINT64 PrimitivesStorageNeeded; -} D3D11_QUERY_DATA_SO_STATISTICS; -typedef HRESULT (WINAPI *PFN_D3D11_CREATE_DEVICE)( - IDXGIAdapter *, D3D_DRIVER_TYPE, HMODULE, UINT, CONST D3D_FEATURE_LEVEL *, - UINT FeatureLevels, UINT, ID3D11Device **, D3D_FEATURE_LEVEL *, ID3D11DeviceContext **); -#define D3D11_MESSAGE_CATEGORY UINT -#define D3D11_MESSAGE_SEVERITY UINT -#define D3D11_MESSAGE_ID UINT -struct D3D11_MESSAGE; -typedef struct D3D11_INFO_QUEUE_FILTER_DESC -{ - UINT NumCategories; - D3D11_MESSAGE_CATEGORY *pCategoryList; - UINT NumSeverities; - D3D11_MESSAGE_SEVERITY *pSeverityList; - UINT NumIDs; - D3D11_MESSAGE_ID *pIDList; -} D3D11_INFO_QUEUE_FILTER_DESC; -typedef struct D3D11_INFO_QUEUE_FILTER -{ - D3D11_INFO_QUEUE_FILTER_DESC AllowList; - D3D11_INFO_QUEUE_FILTER_DESC DenyList; -} D3D11_INFO_QUEUE_FILTER; -static const IID IID_ID3D11InfoQueue = { 0x6543dbb6, 0x1b48, 0x42f5, 0xab, 0x82, 0xe9, 0x7e, 0xc7, 0x43, 0x26, 0xf6 }; -MIDL_INTERFACE("6543dbb6-1b48-42f5-ab82-e97ec74326f6") ID3D11InfoQueue : public IUnknown -{ -public: - virtual HRESULT __stdcall SetMessageCountLimit(UINT64) = 0; - virtual void __stdcall ClearStoredMessages() = 0; - virtual HRESULT __stdcall GetMessage(UINT64, D3D11_MESSAGE *, SIZE_T *) = 0; - virtual UINT64 __stdcall GetNumMessagesAllowedByStorageFilter() = 0; - virtual UINT64 __stdcall GetNumMessagesDeniedByStorageFilter() = 0; - virtual UINT64 __stdcall GetNumStoredMessages() = 0; - virtual UINT64 __stdcall GetNumStoredMessagesAllowedByRetrievalFilter() = 0; - virtual UINT64 __stdcall GetNumMessagesDiscardedByMessageCountLimit() = 0; - virtual UINT64 __stdcall GetMessageCountLimit() = 0; - virtual HRESULT __stdcall AddStorageFilterEntries(D3D11_INFO_QUEUE_FILTER *) = 0; - virtual HRESULT __stdcall GetStorageFilter(D3D11_INFO_QUEUE_FILTER *, SIZE_T *) = 0; - virtual void __stdcall ClearStorageFilter() = 0; - virtual HRESULT __stdcall PushEmptyStorageFilter() = 0; - virtual HRESULT __stdcall PushCopyOfStorageFilter() = 0; - virtual HRESULT __stdcall PushStorageFilter(D3D11_INFO_QUEUE_FILTER *) = 0; - virtual void __stdcall PopStorageFilter() = 0; - virtual UINT __stdcall GetStorageFilterStackSize() = 0; - virtual HRESULT __stdcall AddRetrievalFilterEntries(D3D11_INFO_QUEUE_FILTER *) = 0; - virtual HRESULT __stdcall GetRetrievalFilter(D3D11_INFO_QUEUE_FILTER *, SIZE_T *) = 0; - virtual void __stdcall ClearRetrievalFilter() = 0; - virtual HRESULT __stdcall PushEmptyRetrievalFilter() = 0; - virtual HRESULT __stdcall PushCopyOfRetrievalFilter() = 0; - virtual HRESULT __stdcall PushRetrievalFilter(D3D11_INFO_QUEUE_FILTER *) = 0; - virtual void __stdcall PopRetrievalFilter() = 0; - virtual UINT __stdcall GetRetrievalFilterStackSize() = 0; - virtual HRESULT __stdcall AddMessage(D3D11_MESSAGE_CATEGORY, D3D11_MESSAGE_SEVERITY, D3D11_MESSAGE_ID, LPCSTR) = 0; - virtual HRESULT __stdcall AddApplicationMessage(D3D11_MESSAGE_SEVERITY, LPCSTR) = 0; - virtual HRESULT __stdcall SetBreakOnCategory(D3D11_MESSAGE_CATEGORY, BOOL) = 0; - virtual HRESULT __stdcall SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY, BOOL) = 0; - virtual HRESULT __stdcall SetBreakOnID(D3D11_MESSAGE_ID, BOOL) = 0; - virtual BOOL __stdcall GetBreakOnCategory(D3D11_MESSAGE_CATEGORY) = 0; - virtual BOOL __stdcall GetBreakOnSeverity(D3D11_MESSAGE_SEVERITY) = 0; - virtual BOOL __stdcall GetBreakOnID(D3D11_MESSAGE_ID) = 0; - virtual void __stdcall SetMuteDebugOutput(BOOL) = 0; - virtual BOOL __stdcall GetMuteDebugOutput() = 0; -}; -#endif // __MINGW32__ +# if defined(_MSC_VER) && (_MSC_VER <= 1600) +# define final +# define override +# endif # undef near # undef far #endif +#if !defined(_M_ARM) && !defined(ANGLE_PLATFORM_ANDROID) +# define ANGLE_USE_SSE +#endif + #endif // COMMON_PLATFORM_H_ diff --git a/src/3rdparty/angle/src/common/tls.h b/src/3rdparty/angle/src/common/tls.h index 8a06e92d1a..ca9e07ab70 100644 --- a/src/3rdparty/angle/src/common/tls.h +++ b/src/3rdparty/angle/src/common/tls.h @@ -15,7 +15,9 @@ // TLS does not exist for Windows Store and needs to be emulated # ifdef ANGLE_ENABLE_WINDOWS_STORE -# define TLS_OUT_OF_INDEXES -1 +# ifndef TLS_OUT_OF_INDEXES +# define TLS_OUT_OF_INDEXES static_cast(0xFFFFFFFF) +# endif # ifndef CREATE_SUSPENDED # define CREATE_SUSPENDED 0x00000004 # endif diff --git a/src/3rdparty/angle/src/common/utilities.cpp b/src/3rdparty/angle/src/common/utilities.cpp index 0eae42cac2..501e9c2564 100644 --- a/src/3rdparty/angle/src/common/utilities.cpp +++ b/src/3rdparty/angle/src/common/utilities.cpp @@ -254,7 +254,7 @@ int VariableColumnCount(GLenum type) return 0; } -bool IsSampler(GLenum type) +bool IsSamplerType(GLenum type) { switch (type) { @@ -343,9 +343,27 @@ int AllocateFirstFreeBits(unsigned int *bits, unsigned int allocationSize, unsig return -1; } -bool IsCubemapTextureTarget(GLenum target) +static_assert(GL_TEXTURE_CUBE_MAP_NEGATIVE_X - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 1, "Unexpected GL cube map enum value."); +static_assert(GL_TEXTURE_CUBE_MAP_POSITIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 2, "Unexpected GL cube map enum value."); +static_assert(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 3, "Unexpected GL cube map enum value."); +static_assert(GL_TEXTURE_CUBE_MAP_POSITIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 4, "Unexpected GL cube map enum value."); +static_assert(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 5, "Unexpected GL cube map enum value."); + +bool IsCubeMapTextureTarget(GLenum target) +{ + return (target >= FirstCubeMapTextureTarget && target <= LastCubeMapTextureTarget); +} + +size_t CubeMapTextureTargetToLayerIndex(GLenum target) { - return (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z); + ASSERT(IsCubeMapTextureTarget(target)); + return target - static_cast(FirstCubeMapTextureTarget); +} + +GLenum LayerIndexToCubeMapTextureTarget(size_t index) +{ + ASSERT(index <= (LastCubeMapTextureTarget - FirstCubeMapTextureTarget)); + return FirstCubeMapTextureTarget + static_cast(index); } bool IsTriangleMode(GLenum drawMode) @@ -486,10 +504,15 @@ void writeFile(const char* path, const void* content, size_t size) } #endif // !ANGLE_ENABLE_WINDOWS_STORE -#if defined(ANGLE_ENABLE_WINDOWS_STORE) && _MSC_FULL_VER < 180031101 +#if defined (ANGLE_PLATFORM_WINDOWS) -void Sleep(unsigned long dwMilliseconds) +// Causes the thread to relinquish the remainder of its time slice to any +// other thread that is ready to run.If there are no other threads ready +// to run, the function returns immediately, and the thread continues execution. +void ScheduleYield() { +#if defined(ANGLE_ENABLE_WINDOWS_STORE) + // This implementation of Sleep exists because it is not available prior to Update 4. static HANDLE singletonEvent = nullptr; HANDLE sleepEvent = singletonEvent; if (!sleepEvent) @@ -510,7 +533,10 @@ void Sleep(unsigned long dwMilliseconds) } // Emulate sleep by waiting with timeout on an event that is never signalled. - WaitForSingleObjectEx(sleepEvent, dwMilliseconds, false); + WaitForSingleObjectEx(sleepEvent, 0, false); +#else + Sleep(0); +#endif } -#endif // ANGLE_ENABLE_WINDOWS_STORE +#endif diff --git a/src/3rdparty/angle/src/common/utilities.h b/src/3rdparty/angle/src/common/utilities.h index 7583d3e160..9f7f5e03c0 100644 --- a/src/3rdparty/angle/src/common/utilities.h +++ b/src/3rdparty/angle/src/common/utilities.h @@ -6,8 +6,8 @@ // utilities.h: Conversion functions and other utility routines. -#ifndef LIBGLESV2_UTILITIES_H -#define LIBGLESV2_UTILITIES_H +#ifndef COMMON_UTILITIES_H_ +#define COMMON_UTILITIES_H_ #include "angle_gl.h" #include @@ -24,7 +24,7 @@ size_t VariableExternalSize(GLenum type); GLenum VariableBoolVectorType(GLenum type); int VariableRowCount(GLenum type); int VariableColumnCount(GLenum type); -bool IsSampler(GLenum type); +bool IsSamplerType(GLenum type); bool IsMatrixType(GLenum type); GLenum TransposeMatrixType(GLenum type); int VariableRegisterCount(GLenum type); @@ -34,7 +34,11 @@ int VariableSortOrder(GLenum type); int AllocateFirstFreeBits(unsigned int *bits, unsigned int allocationSize, unsigned int bitsSize); -bool IsCubemapTextureTarget(GLenum target); +static const GLenum FirstCubeMapTextureTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X; +static const GLenum LastCubeMapTextureTarget = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z; +bool IsCubeMapTextureTarget(GLenum target); +size_t CubeMapTextureTargetToLayerIndex(GLenum target); +GLenum LayerIndexToCubeMapTextureTarget(size_t index); bool IsTriangleMode(GLenum drawMode); @@ -51,8 +55,8 @@ std::string getTempPath(); void writeFile(const char* path, const void* data, size_t size); #endif -#if defined(ANGLE_ENABLE_WINDOWS_STORE) && _MSC_FULL_VER < 180031101 -void Sleep(_In_ unsigned long dwMilliseconds); +#if defined (ANGLE_PLATFORM_WINDOWS) +void ScheduleYield(); #endif -#endif // LIBGLESV2_UTILITIES_H +#endif // COMMON_UTILITIES_H_ diff --git a/src/3rdparty/angle/src/common/version.h b/src/3rdparty/angle/src/common/version.h index f01e0242cb..758c78d44a 100644 --- a/src/3rdparty/angle/src/common/version.h +++ b/src/3rdparty/angle/src/common/version.h @@ -1,4 +1,13 @@ -#include "../commit.h" +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMMON_VERSION_H_ +#define COMMON_VERSION_H_ + +#include "id/commit.h" #define ANGLE_MAJOR_VERSION 2 #define ANGLE_MINOR_VERSION 1 @@ -10,3 +19,5 @@ ANGLE_MACRO_STRINGIFY(ANGLE_MAJOR_VERSION) "." \ ANGLE_MACRO_STRINGIFY(ANGLE_MINOR_VERSION) "." \ ANGLE_COMMIT_HASH + +#endif // COMMON_VERSION_H_ diff --git a/src/3rdparty/angle/src/common/win32/NativeWindow.cpp b/src/3rdparty/angle/src/common/win32/NativeWindow.cpp deleted file mode 100644 index 46082a2e28..0000000000 --- a/src/3rdparty/angle/src/common/win32/NativeWindow.cpp +++ /dev/null @@ -1,66 +0,0 @@ -// -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// NativeWindow.cpp: Handler for managing HWND native window types. - -#include "common/NativeWindow.h" -#include "common/debug.h" - -namespace rx -{ -bool IsValidEGLNativeWindowType(EGLNativeWindowType window) -{ - return (IsWindow(window) == TRUE); -} - -NativeWindow::NativeWindow(EGLNativeWindowType window, EGLNativeDisplayType display) : mWindow(window), mDisplay(display) -{ -} - -bool NativeWindow::initialize() -{ - return true; -} - -bool NativeWindow::getClientRect(LPRECT rect) -{ - return GetClientRect(mWindow, rect) == TRUE; -} - -bool NativeWindow::isIconic() -{ - return IsIconic(mWindow) == TRUE; -} - -HRESULT NativeWindow::createSwapChain(NativeWindow::Device* device, DXGIFactory* factory, - DXGI_FORMAT format, unsigned int width, unsigned int height, - DXGISwapChain** swapChain) -{ - if (device == NULL || factory == NULL || swapChain == NULL || width == 0 || height == 0) - { - return E_INVALIDARG; - } - - DXGI_SWAP_CHAIN_DESC swapChainDesc = { 0 }; - swapChainDesc.BufferCount = 1; - swapChainDesc.BufferDesc.Format = format; - swapChainDesc.BufferDesc.Width = width; - swapChainDesc.BufferDesc.Height = height; - 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 | DXGI_USAGE_BACK_BUFFER; - swapChainDesc.Flags = 0; - swapChainDesc.OutputWindow = mWindow; - swapChainDesc.SampleDesc.Count = 1; - swapChainDesc.SampleDesc.Quality = 0; - swapChainDesc.Windowed = TRUE; - swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; - - return factory->CreateSwapChain(device, &swapChainDesc, swapChain); -} -} diff --git a/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.cpp b/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.cpp deleted file mode 100644 index 9b65c15625..0000000000 --- a/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.cpp +++ /dev/null @@ -1,200 +0,0 @@ -// -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// CoreWindowNativeWindow.cpp: NativeWindow for managing ICoreWindow native window types. - -#include -#include "common/winrt/CoreWindowNativeWindow.h" -using namespace ABI::Windows::Foundation::Collections; - -namespace rx -{ - -typedef ITypedEventHandler SizeChangedHandler; - -CoreWindowNativeWindow::~CoreWindowNativeWindow() -{ - unregisterForSizeChangeEvents(); -} - -bool CoreWindowNativeWindow::initialize(EGLNativeWindowType window, EGLNativeDisplayType display, IPropertySet *propertySet) -{ - ComPtr props = propertySet; - ComPtr win = window; - ComPtr displayInformation = display; - SIZE swapChainSize = {}; - bool swapChainSizeSpecified = false; - HRESULT result = S_OK; - - // IPropertySet is an optional parameter and can be null. - // If one is specified, cache as an IMap and read the properties - // used for initial host initialization. - if (propertySet) - { - result = props.As(&mPropertyMap); - if (SUCCEEDED(result)) - { - // The EGLRenderSurfaceSizeProperty is optional and may be missing. The IPropertySet - // was prevalidated to contain the EGLNativeWindowType before being passed to - // this host. - result = GetOptionalSizePropertyValue(mPropertyMap, EGLRenderSurfaceSizeProperty, &swapChainSize, &swapChainSizeSpecified); - } - } - - if (SUCCEEDED(result)) - { - result = win.As(&mCoreWindow); - } - - if (SUCCEEDED(result)) - { - result = displayInformation.As(&mDisplayInformation); - } - - if (SUCCEEDED(result)) - { -#if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP - ComPtr displayInformation2; - result = mDisplayInformation.As(&displayInformation2); - ASSERT(SUCCEEDED(result)); - - result = displayInformation2->get_RawPixelsPerViewPixel(&mScaleFactor); - ASSERT(SUCCEEDED(result)); -#else - ABI::Windows::Graphics::Display::ResolutionScale resolutionScale; - result = mDisplayInformation->get_ResolutionScale(&resolutionScale); - ASSERT(SUCCEEDED(result)); - - mScaleFactor = DOUBLE(resolutionScale) / 100.0; -#endif - } - - if (SUCCEEDED(result)) - { - // If a swapchain size is specfied, then the automatic resize - // behaviors implemented by the host should be disabled. The swapchain - // will be still be scaled when being rendered to fit the bounds - // of the host. - // Scaling of the swapchain output occurs automatically because if - // the scaling mode setting DXGI_SCALING_STRETCH on the swapchain. - if (swapChainSizeSpecified) - { - mClientRect = { 0, 0, swapChainSize.cx, swapChainSize.cy }; - mSupportsSwapChainResize = false; - } - else - { - ABI::Windows::Foundation::Rect rect; - HRESULT result = mCoreWindow->get_Bounds(&rect); - if (SUCCEEDED(result)) - { - LONG width = std::floor(rect.Width * mScaleFactor + 0.5); - LONG height = std::floor(rect.Height * mScaleFactor + 0.5); - mClientRect = { 0, 0, width, height }; - } - } - } - - if (SUCCEEDED(result)) - { - mNewClientRect = mClientRect; - mClientRectChanged = false; - return registerForSizeChangeEvents(); - } - - return false; -} - -bool CoreWindowNativeWindow::registerForSizeChangeEvents() -{ - HRESULT result = mCoreWindow->add_SizeChanged(Callback(this, &CoreWindowNativeWindow::onSizeChanged).Get(), - &mSizeChangedEventToken); - - if (SUCCEEDED(result)) - { - return true; - } - - return false; -} - -void CoreWindowNativeWindow::unregisterForSizeChangeEvents() -{ - if (mCoreWindow) - { - (void)mCoreWindow->remove_SizeChanged(mSizeChangedEventToken); - } - mSizeChangedEventToken.value = 0; -} - -HRESULT CoreWindowNativeWindow::createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain) -{ - if (device == NULL || factory == NULL || swapChain == NULL || width == 0 || height == 0) - { - return E_INVALIDARG; - } - - DXGI_SWAP_CHAIN_DESC1 swapChainDesc = { 0 }; - swapChainDesc.Width = width; - swapChainDesc.Height = height; - swapChainDesc.Format = format; - swapChainDesc.Stereo = FALSE; - swapChainDesc.SampleDesc.Count = 1; - swapChainDesc.SampleDesc.Quality = 0; - swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_BACK_BUFFER; - swapChainDesc.BufferCount = 2; - swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; - swapChainDesc.Scaling = DXGI_SCALING_STRETCH; - - *swapChain = nullptr; - - ComPtr newSwapChain; - HRESULT result = factory->CreateSwapChainForCoreWindow(device, mCoreWindow.Get(), &swapChainDesc, nullptr, newSwapChain.ReleaseAndGetAddressOf()); - if (SUCCEEDED(result)) - { - -#if (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) // This block is disabled for Qt applications, as the resize events are expected - // Test if swapchain supports resize. On Windows Phone devices, this will return DXGI_ERROR_UNSUPPORTED. On - // other devices DXGI_ERROR_INVALID_CALL should be returned because the combination of flags passed - // (DXGI_SWAP_CHAIN_FLAG_NONPREROTATED | DXGI_SWAP_CHAIN_FLAG_GDI_COMPATIBLE) are invalid flag combinations. - if (newSwapChain->ResizeBuffers(swapChainDesc.BufferCount, swapChainDesc.Width, swapChainDesc.Height, swapChainDesc.Format, DXGI_SWAP_CHAIN_FLAG_NONPREROTATED | DXGI_SWAP_CHAIN_FLAG_GDI_COMPATIBLE) == DXGI_ERROR_UNSUPPORTED) - { - mSupportsSwapChainResize = false; - } -#endif // (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) - - result = newSwapChain.CopyTo(swapChain); - } - - if (SUCCEEDED(result)) - { - // If automatic swapchain resize behaviors have been disabled, then - // unregister for the resize change events. - if (mSupportsSwapChainResize == false) - { - unregisterForSizeChangeEvents(); - } - } - - return result; -} - -// Basically, this shouldn't be used on Phone -HRESULT CoreWindowNativeWindow::onSizeChanged(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IWindowSizeChangedEventArgs *e) -{ - ABI::Windows::Foundation::Size size; - if (SUCCEEDED(e->get_Size(&size))) - { - SIZE windowSizeInPixels = { - std::floor(size.Width * mScaleFactor + 0.5), - std::floor(size.Height * mScaleFactor + 0.5) - }; - setNewClientSize(windowSizeInPixels); - } - - return S_OK; -} -} diff --git a/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.h b/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.h deleted file mode 100644 index 1c5512417d..0000000000 --- a/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.h +++ /dev/null @@ -1,39 +0,0 @@ -// -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// CoreWindowNativeWindow.h: NativeWindow for managing ICoreWindow native window types. - -#ifndef COMMON_WINRT_COREWINDOWNATIVEWINDOW_H_ -#define COMMON_WINRT_COREWINDOWNATIVEWINDOW_H_ - -#include "common/winrt/InspectableNativeWindow.h" -#include -#include - -namespace rx -{ - -class CoreWindowNativeWindow : public InspectableNativeWindow, public std::enable_shared_from_this -{ - public: - ~CoreWindowNativeWindow(); - - bool initialize(EGLNativeWindowType window, EGLNativeDisplayType display, IPropertySet *propertySet); - bool registerForSizeChangeEvents(); - void unregisterForSizeChangeEvents(); - HRESULT createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain); - - private: - HRESULT onSizeChanged(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IWindowSizeChangedEventArgs *); - - ComPtr mCoreWindow; - ComPtr mDisplayInformation; - ComPtr> mPropertyMap; -}; - -} - -#endif // COMMON_WINRT_COREWINDOWNATIVEWINDOW_H_ diff --git a/src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.cpp b/src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.cpp deleted file mode 100644 index 0589f6dce5..0000000000 --- a/src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.cpp +++ /dev/null @@ -1,274 +0,0 @@ -// -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// InspectableNativeWindow.cpp: NativeWindow base class for managing IInspectable native window types. - -#include "common/winrt/CoreWindowNativeWindow.h" -#include "common/winrt/SwapChainPanelNativeWindow.h" - -namespace rx -{ -NativeWindow::NativeWindow(EGLNativeWindowType window, EGLNativeDisplayType display) - : mWindow(window), mDisplay(display) -{ -} - -bool NativeWindow::initialize() -{ - // If the native window type is a IPropertySet, extract the - // EGLNativeWindowType (IInspectable) and initialize the - // proper host with this IPropertySet. - ComPtr propertySet; - ComPtr eglNativeWindow; - if (IsEGLConfiguredPropertySet(mWindow, &propertySet, &eglNativeWindow)) - { - // A property set was found and the EGLNativeWindowType was - // retrieved. The mWindow member of the host to must be updated - // to use the EGLNativeWindowType specified in the property set. - // mWindow is treated as a raw pointer not an AddRef'd interface, so - // the old mWindow does not need a Release() before this assignment. - mWindow = eglNativeWindow.Get(); - } - - ComPtr coreWindow; - ComPtr swapChainPanel; - if (IsCoreWindow(mWindow, &coreWindow)) - { - mImpl = std::make_shared(); - if (mImpl) - { - return mImpl->initialize(mWindow, mDisplay, propertySet.Get()); - } - } - else if (IsSwapChainPanel(mWindow, &swapChainPanel)) - { - mImpl = std::make_shared(); - if (mImpl) - { - return mImpl->initialize(mWindow, mDisplay, propertySet.Get()); - } - } - else - { - ERR("Invalid IInspectable EGLNativeWindowType detected. Valid IInspectables include ICoreWindow, ISwapChainPanel and IPropertySet"); - } - - return false; -} - -bool NativeWindow::getClientRect(RECT *rect) -{ - if (mImpl) - { - return mImpl->getClientRect(rect); - } - - return false; -} - -bool NativeWindow::isIconic() -{ - return false; -} - -HRESULT NativeWindow::createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain) -{ - if (mImpl) - { - return mImpl->createSwapChain(device, factory, format, width, height, swapChain); - } - - return E_UNEXPECTED; -} - -bool IsCoreWindow(EGLNativeWindowType window, ComPtr *coreWindow) -{ - if (!window) - { - return false; - } - - ComPtr win = window; - ComPtr coreWin; - if (SUCCEEDED(win.As(&coreWin))) - { - if (coreWindow != nullptr) - { - *coreWindow = coreWin.Detach(); - } - return true; - } - - return false; -} - -bool IsSwapChainPanel(EGLNativeWindowType window, ComPtr *swapChainPanel) -{ - if (!window) - { - return false; - } - - ComPtr win = window; - ComPtr panel; - if (SUCCEEDED(win.As(&panel))) - { - if (swapChainPanel != nullptr) - { - *swapChainPanel = panel.Detach(); - } - return true; - } - - return false; -} - -bool IsEGLConfiguredPropertySet(EGLNativeWindowType window, ABI::Windows::Foundation::Collections::IPropertySet **propertySet, IInspectable **eglNativeWindow) -{ - if (!window) - { - return false; - } - - ComPtr props = window; - ComPtr propSet; - ComPtr nativeWindow; - ComPtr> propMap; - boolean hasEglNativeWindowPropertyKey = false; - - HRESULT result = props.As(&propSet); - if (SUCCEEDED(result)) - { - result = propSet.As(&propMap); - } - - // Look for the presence of the EGLNativeWindowType in the property set - if (SUCCEEDED(result)) - { - result = propMap->HasKey(HStringReference(EGLNativeWindowTypeProperty).Get(), &hasEglNativeWindowPropertyKey); - } - - // If the IPropertySet does not contain the required EglNativeWindowType key, the property set is - // considered invalid. - if (SUCCEEDED(result) && !hasEglNativeWindowPropertyKey) - { - ERR("Could not find EGLNativeWindowTypeProperty in IPropertySet. Valid EGLNativeWindowTypeProperty values include ICoreWindow"); - return false; - } - - // The EglNativeWindowType property exists, so retreive the IInspectable that represents the EGLNativeWindowType - if (SUCCEEDED(result) && hasEglNativeWindowPropertyKey) - { - result = propMap->Lookup(HStringReference(EGLNativeWindowTypeProperty).Get(), &nativeWindow); - } - - if (SUCCEEDED(result)) - { - if (propertySet != nullptr) - { - result = propSet.CopyTo(propertySet); - } - } - - if (SUCCEEDED(result)) - { - if (eglNativeWindow != nullptr) - { - result = nativeWindow.CopyTo(eglNativeWindow); - } - } - - if (SUCCEEDED(result)) - { - return true; - } - - return false; -} - -// A Valid EGLNativeWindowType IInspectable can only be: -// -// ICoreWindow -// IPropertySet -// -// Anything else will be rejected as an invalid IInspectable. -bool IsValidEGLNativeWindowType(EGLNativeWindowType window) -{ - return IsCoreWindow(window) || IsSwapChainPanel(window) || IsEGLConfiguredPropertySet(window); -} - -// Attempts to read an optional SIZE property value that is assumed to be in the form of -// an ABI::Windows::Foundation::Size. This function validates the Size value before returning -// it to the caller. -// -// Possible return values are: -// S_OK, valueExists == true - optional SIZE value was successfully retrieved and validated -// S_OK, valueExists == false - optional SIZE value was not found -// E_INVALIDARG, valueExists = false - optional SIZE value was malformed in the property set. -// * Incorrect property type ( must be PropertyType_Size) -// * Invalid property value (width/height must be > 0) -// Additional errors may be returned from IMap or IPropertyValue -// -HRESULT GetOptionalSizePropertyValue(const ComPtr>& propertyMap, const wchar_t *propertyName, SIZE *value, bool *valueExists) -{ - if (!propertyMap || !propertyName || !value || !valueExists) - { - return false; - } - - // Assume that the value does not exist - *valueExists = false; - *value = { 0, 0 }; - - ComPtr propertyValue; - ABI::Windows::Foundation::PropertyType propertyType = ABI::Windows::Foundation::PropertyType::PropertyType_Empty; - Size sizeValue = { 0, 0 }; - boolean hasKey = false; - - HRESULT result = propertyMap->HasKey(HStringReference(propertyName).Get(), &hasKey); - if (SUCCEEDED(result) && !hasKey) - { - // Value does not exist, so return S_OK and set the exists parameter to false to indicate - // that a the optional property does not exist. - *valueExists = false; - return S_OK; - } - - if (SUCCEEDED(result)) - { - result = propertyMap->Lookup(HStringReference(propertyName).Get(), &propertyValue); - } - - if (SUCCEEDED(result)) - { - result = propertyValue->get_Type(&propertyType); - } - - // Check if the expected Size property is of PropertyType_Size type. - if (SUCCEEDED(result) && propertyType == ABI::Windows::Foundation::PropertyType::PropertyType_Size) - { - if (SUCCEEDED(propertyValue->GetSize(&sizeValue)) && (sizeValue.Width > 0 && sizeValue.Height > 0)) - { - // A valid property value exists - *value = { static_cast(sizeValue.Width), static_cast(sizeValue.Height) }; - *valueExists = true; - result = S_OK; - } - else - { - // An invalid Size property was detected. Width/Height values must > 0 - result = E_INVALIDARG; - } - } - else - { - // An invalid property type was detected. Size property must be of PropertyType_Size - result = E_INVALIDARG; - } - - return result; -} -} diff --git a/src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.h b/src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.h deleted file mode 100644 index 402941a788..0000000000 --- a/src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.h +++ /dev/null @@ -1,91 +0,0 @@ -// -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// InspectableNativeWindow.h: Host specific implementation interface for -// managing IInspectable native window types. - -#ifndef COMMON_WINRT_INSPECTABLENATIVEWINDOW_H_ -#define COMMON_WINRT_INSPECTABLENATIVEWINDOW_H_ - -#include "common/platform.h" -#include "common/NativeWindow.h" -#include "angle_windowsstore.h" - -#include -#include - -using namespace Microsoft::WRL; -using namespace Microsoft::WRL::Wrappers; -using namespace ABI::Windows::Foundation; -using namespace ABI::Windows::Foundation::Collections; - -namespace rx -{ -class InspectableNativeWindow -{ - public: - InspectableNativeWindow() : - mSupportsSwapChainResize(true), - mRequiresSwapChainScaling(false), - mClientRectChanged(false), - mClientRect({0,0,0,0}), - mNewClientRect({0,0,0,0}), - mScaleFactor(1.0) - { - mSizeChangedEventToken.value = 0; - } - virtual ~InspectableNativeWindow(){} - - virtual bool initialize(EGLNativeWindowType window, EGLNativeDisplayType display, IPropertySet *propertySet) = 0; - virtual HRESULT createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain) = 0; - virtual bool registerForSizeChangeEvents() = 0; - virtual void unregisterForSizeChangeEvents() = 0; - virtual HRESULT scaleSwapChain(const SIZE& newSize) { return S_OK; } - - bool getClientRect(RECT *rect) - { - if (mClientRectChanged && mSupportsSwapChainResize) - { - mClientRect = mNewClientRect; - mClientRectChanged = false; - } - - *rect = mClientRect; - - return true; - } - - void setNewClientSize(const SIZE &newSize) - { - if (mSupportsSwapChainResize && !mRequiresSwapChainScaling) - { - mNewClientRect = { 0, 0, newSize.cx, newSize.cy }; - mClientRectChanged = true; - } - - if (mRequiresSwapChainScaling) - { - scaleSwapChain(newSize); - } - } - -protected: - bool mSupportsSwapChainResize; - bool mRequiresSwapChainScaling; - RECT mClientRect; - RECT mNewClientRect; - bool mClientRectChanged; - DOUBLE mScaleFactor; - - EventRegistrationToken mSizeChangedEventToken; -}; - -bool IsCoreWindow(EGLNativeWindowType window, ComPtr *coreWindow = nullptr); -bool IsSwapChainPanel(EGLNativeWindowType window, ComPtr *swapChainPanel = nullptr); -bool IsEGLConfiguredPropertySet(EGLNativeWindowType window, ABI::Windows::Foundation::Collections::IPropertySet **propertySet = nullptr, IInspectable **inspectable = nullptr); -HRESULT GetOptionalSizePropertyValue(const ComPtr>& propertyMap, const wchar_t *propertyName, SIZE *value, bool *valueExists); -} -#endif // COMMON_WINRT_INSPECTABLENATIVEWINDOW_H_ diff --git a/src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.cpp b/src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.cpp deleted file mode 100644 index 268dfbd8f0..0000000000 --- a/src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.cpp +++ /dev/null @@ -1,226 +0,0 @@ -// -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// SwapChainPanelNativeWindow.cpp: NativeWindow for managing ISwapChainPanel native window types. - -#include "common/winrt/SwapChainPanelNativeWindow.h" -#include -#include -using namespace ABI::Windows::Foundation::Collections; - -namespace rx -{ -SwapChainPanelNativeWindow::~SwapChainPanelNativeWindow() -{ - unregisterForSizeChangeEvents(); -} - -bool SwapChainPanelNativeWindow::initialize(EGLNativeWindowType window, EGLNativeDisplayType display, IPropertySet *propertySet) -{ - ComPtr props = propertySet; - ComPtr win = window; - SIZE swapChainSize = {}; - bool swapChainSizeSpecified = false; - HRESULT result = S_OK; - - // IPropertySet is an optional parameter and can be null. - // If one is specified, cache as an IMap and read the properties - // used for initial host initialization. - if (propertySet) - { - result = props.As(&mPropertyMap); - if (SUCCEEDED(result)) - { - // The EGLRenderSurfaceSizeProperty is optional and may be missing. The IPropertySet - // was prevalidated to contain the EGLNativeWindowType before being passed to - // this host. - result = GetOptionalSizePropertyValue(mPropertyMap, EGLRenderSurfaceSizeProperty, &swapChainSize, &swapChainSizeSpecified); - } - } - - if (SUCCEEDED(result)) - { - result = win.As(&mSwapChainPanel); - } - - if (SUCCEEDED(result)) - { - // If a swapchain size is specfied, then the automatic resize - // behaviors implemented by the host should be disabled. The swapchain - // will be still be scaled when being rendered to fit the bounds - // of the host. - // Scaling of the swapchain output needs to be handled by the - // host for swapchain panels even though the scaling mode setting - // DXGI_SCALING_STRETCH is configured on the swapchain. - if (swapChainSizeSpecified) - { - mClientRect = { 0, 0, swapChainSize.cx, swapChainSize.cy }; - - // Enable host swapchain scaling - mRequiresSwapChainScaling = true; - } - else - { - result = GetSwapChainPanelSize(mSwapChainPanel, &mClientRect); - } - } - - if (SUCCEEDED(result)) - { - mNewClientRect = mClientRect; - mClientRectChanged = false; - return registerForSizeChangeEvents(); - } - - return false; -} - -bool SwapChainPanelNativeWindow::registerForSizeChangeEvents() -{ - ComPtr sizeChangedHandler; - ComPtr frameworkElement; - HRESULT result = Microsoft::WRL::MakeAndInitialize(sizeChangedHandler.ReleaseAndGetAddressOf(), this->shared_from_this()); - - if (SUCCEEDED(result)) - { - result = mSwapChainPanel.As(&frameworkElement); - } - - if (SUCCEEDED(result)) - { - result = frameworkElement->add_SizeChanged(sizeChangedHandler.Get(), &mSizeChangedEventToken); - } - - if (SUCCEEDED(result)) - { - return true; - } - - return false; -} - -void SwapChainPanelNativeWindow::unregisterForSizeChangeEvents() -{ - ComPtr frameworkElement; - if (SUCCEEDED(mSwapChainPanel.As(&frameworkElement))) - { - (void)frameworkElement->remove_SizeChanged(mSizeChangedEventToken); - } - - mSizeChangedEventToken.value = 0; -} - -HRESULT SwapChainPanelNativeWindow::createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain) -{ - if (device == NULL || factory == NULL || swapChain == NULL || width == 0 || height == 0) - { - return E_INVALIDARG; - } - - DXGI_SWAP_CHAIN_DESC1 swapChainDesc = { 0 }; - swapChainDesc.Width = width; - swapChainDesc.Height = height; - swapChainDesc.Format = format; - swapChainDesc.Stereo = FALSE; - swapChainDesc.SampleDesc.Count = 1; - swapChainDesc.SampleDesc.Quality = 0; - swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_BACK_BUFFER; - swapChainDesc.BufferCount = 2; - swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; - swapChainDesc.Scaling = DXGI_SCALING_STRETCH; - swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE; - - *swapChain = nullptr; - - ComPtr newSwapChain; - ComPtr swapChainPanelNative; - RECT currentPanelSize = {}; - - HRESULT result = factory->CreateSwapChainForComposition(device, &swapChainDesc, nullptr, newSwapChain.ReleaseAndGetAddressOf()); - - if (SUCCEEDED(result)) - { - result = mSwapChainPanel.As(&swapChainPanelNative); - } - - if (SUCCEEDED(result)) - { - result = swapChainPanelNative->SetSwapChain(newSwapChain.Get()); - } - - if (SUCCEEDED(result)) - { - // The swapchain panel host requires an instance of the swapchain set on the SwapChainPanel - // to perform the runtime-scale behavior. This swapchain is cached here because there are - // no methods for retreiving the currently configured on from ISwapChainPanelNative. - mSwapChain = newSwapChain; - result = newSwapChain.CopyTo(swapChain); - } - - // If the host is responsible for scaling the output of the swapchain, then - // scale it now before returning an instance to the caller. This is done by - // first reading the current size of the swapchain panel, then scaling - if (SUCCEEDED(result) && mRequiresSwapChainScaling) - { - result = GetSwapChainPanelSize(mSwapChainPanel, ¤tPanelSize); - } - - // Scale the swapchain to fit inside the contents of the panel. - if (SUCCEEDED(result) && mRequiresSwapChainScaling) - { - SIZE currentSize = { currentPanelSize.right, currentPanelSize.bottom }; - result = scaleSwapChain(currentSize); - } - - if (SUCCEEDED(result)) - { - // If automatic swapchain resize behaviors have been disabled, then - // unregister for the resize change events. - if (mSupportsSwapChainResize == false) - { - unregisterForSizeChangeEvents(); - } - } - - return result; -} - -HRESULT SwapChainPanelNativeWindow::scaleSwapChain(const SIZE &newSize) -{ - ABI::Windows::Foundation::Size renderScale = { (float)newSize.cx/(float)mClientRect.right, (float)newSize.cy/(float)mClientRect.bottom }; - // Setup a scale matrix for the swap chain - DXGI_MATRIX_3X2_F scaleMatrix = {}; - scaleMatrix._11 = renderScale.Width; - scaleMatrix._22 = renderScale.Height; - - ComPtr swapChain2; - HRESULT result = mSwapChain.As(&swapChain2); - if (SUCCEEDED(result)) - { - result = swapChain2->SetMatrixTransform(&scaleMatrix); - } - - return result; -} - -HRESULT GetSwapChainPanelSize(const ComPtr &swapChainPanel, RECT *windowSize) -{ - ComPtr uiElement; - ABI::Windows::Foundation::Size renderSize = { 0, 0 }; - HRESULT result = swapChainPanel.As(&uiElement); - if (SUCCEEDED(result)) - { - result = uiElement->get_RenderSize(&renderSize); - } - - if (SUCCEEDED(result)) - { - *windowSize = { 0, 0, lround(renderSize.Width), lround(renderSize.Height) }; - } - - return result; -} -} diff --git a/src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.h b/src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.h deleted file mode 100644 index 5bbf274e64..0000000000 --- a/src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.h +++ /dev/null @@ -1,79 +0,0 @@ -// -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// SwapChainPanelNativeWindow.h: NativeWindow for managing ISwapChainPanel native window types. - -#ifndef COMMON_WINRT_SWAPCHAINPANELNATIVEWINDOW_H_ -#define COMMON_WINRT_SWAPCHAINPANELNATIVEWINDOW_H_ - -#include "common/winrt/InspectableNativeWindow.h" - -namespace rx -{ -class SwapChainPanelNativeWindow : public InspectableNativeWindow, public std::enable_shared_from_this -{ - public: - ~SwapChainPanelNativeWindow(); - - bool initialize(EGLNativeWindowType window, EGLNativeDisplayType display, IPropertySet *propertySet); - bool registerForSizeChangeEvents(); - void unregisterForSizeChangeEvents(); - HRESULT createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain); - HRESULT scaleSwapChain(const SIZE &newSize); - - private: - ComPtr mSwapChainPanel; - ComPtr> mPropertyMap; - ComPtr mSwapChain; -}; - -[uuid(8ACBD974-8187-4508-AD80-AEC77F93CF36)] -class SwapChainPanelSizeChangedHandler : - public Microsoft::WRL::RuntimeClass, ABI::Windows::UI::Xaml::ISizeChangedEventHandler> -{ - public: - SwapChainPanelSizeChangedHandler() { } - HRESULT RuntimeClassInitialize(std::shared_ptr host) - { - if (!host) - { - return E_INVALIDARG; - } - - mHost = host; - return S_OK; - } - - // ISizeChangedEventHandler - IFACEMETHOD(Invoke)(IInspectable *sender, ABI::Windows::UI::Xaml::ISizeChangedEventArgs *sizeChangedEventArgs) - { - std::shared_ptr host = mHost.lock(); - if (host) - { - // The size of the ISwapChainPanel control is returned in DIPs. - // We are keeping these in dips because the swapchain created for composition - // also uses dip units. This keeps dimensions, viewports, etc in the same unit. - // XAML Clients of the ISwapChainPanel are required to use dips to define their - // layout sizes as well. - ABI::Windows::Foundation::Size newSize; - HRESULT result = sizeChangedEventArgs->get_NewSize(&newSize); - if (SUCCEEDED(result)) - { - SIZE windowSize = { lround(newSize.Width), lround(newSize.Height) }; - host->setNewClientSize(windowSize); - } - } - - return S_OK; - } - - private: - std::weak_ptr mHost; -}; - -HRESULT GetSwapChainPanelSize(const ComPtr &swapChainPanel, RECT *windowSize); -} -#endif // COMMON_WINRT_SWAPCHAINPANELNATIVEWINDOW_H_ diff --git a/src/3rdparty/angle/src/compiler/preprocessor/DiagnosticsBase.h b/src/3rdparty/angle/src/compiler/preprocessor/DiagnosticsBase.h index a7587ed657..5922d03857 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/DiagnosticsBase.h +++ b/src/3rdparty/angle/src/compiler/preprocessor/DiagnosticsBase.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef COMPILER_PREPROCESSOR_DIAGNOSTICS_H_ -#define COMPILER_PREPROCESSOR_DIAGNOSTICS_H_ +#ifndef COMPILER_PREPROCESSOR_DIAGNOSTICSBASE_H_ +#define COMPILER_PREPROCESSOR_DIAGNOSTICSBASE_H_ #include @@ -84,4 +84,5 @@ class Diagnostics }; } // namespace pp -#endif // COMPILER_PREPROCESSOR_DIAGNOSTICS_H_ + +#endif // COMPILER_PREPROCESSOR_DIAGNOSTICSBASE_H_ diff --git a/src/3rdparty/angle/src/compiler/preprocessor/DirectiveHandlerBase.h b/src/3rdparty/angle/src/compiler/preprocessor/DirectiveHandlerBase.h index eec0d5e5f0..cf67895764 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/DirectiveHandlerBase.h +++ b/src/3rdparty/angle/src/compiler/preprocessor/DirectiveHandlerBase.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef COMPILER_PREPROCESSOR_DIRECTIVE_HANDLER_H_ -#define COMPILER_PREPROCESSOR_DIRECTIVE_HANDLER_H_ +#ifndef COMPILER_PREPROCESSOR_DIRECTIVEHANDLERBASE_H_ +#define COMPILER_PREPROCESSOR_DIRECTIVEHANDLERBASE_H_ #include @@ -41,4 +41,5 @@ class DirectiveHandler }; } // namespace pp -#endif // COMPILER_PREPROCESSOR_DIRECTIVE_HANDLER_H_ + +#endif // COMPILER_PREPROCESSOR_DIRECTIVEHANDLERBASE_H_ diff --git a/src/3rdparty/angle/src/compiler/preprocessor/DirectiveParser.h b/src/3rdparty/angle/src/compiler/preprocessor/DirectiveParser.h index 335091781c..e1acdbb8d0 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/DirectiveParser.h +++ b/src/3rdparty/angle/src/compiler/preprocessor/DirectiveParser.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef COMPILER_PREPROCESSOR_DIRECTIVE_PARSER_H_ -#define COMPILER_PREPROCESSOR_DIRECTIVE_PARSER_H_ +#ifndef COMPILER_PREPROCESSOR_DIRECTIVEPARSER_H_ +#define COMPILER_PREPROCESSOR_DIRECTIVEPARSER_H_ #include "Lexer.h" #include "Macro.h" @@ -78,5 +78,5 @@ class DirectiveParser : public Lexer }; } // namespace pp -#endif // COMPILER_PREPROCESSOR_DIRECTIVE_PARSER_H_ +#endif // COMPILER_PREPROCESSOR_DIRECTIVEPARSER_H_ diff --git a/src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.h b/src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.h index f040cb01fa..4b80ba7261 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.h +++ b/src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef COMPILER_PREPROCESSOR_EXPRESSION_PARSER_H_ -#define COMPILER_PREPROCESSOR_EXPRESSION_PARSER_H_ +#ifndef COMPILER_PREPROCESSOR_EXPRESSIONPARSER_H_ +#define COMPILER_PREPROCESSOR_EXPRESSIONPARSER_H_ #include "pp_utils.h" @@ -31,4 +31,5 @@ class ExpressionParser }; } // namespace pp -#endif // COMPILER_PREPROCESSOR_EXPRESSION_PARSER_H_ + +#endif // COMPILER_PREPROCESSOR_EXPRESSIONPARSER_H_ diff --git a/src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.y b/src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.y index 662a31b650..8caf36bfc8 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.y +++ b/src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.y @@ -28,7 +28,7 @@ WHICH GENERATES THE GLSL ES preprocessor expression parser. #pragma GCC diagnostic ignored "-Wuninitialized" #endif #elif defined(_MSC_VER) -#pragma warning(disable: 4065 4701) +#pragma warning(disable: 4065 4701 4702) #endif #include "ExpressionParser.h" @@ -69,7 +69,7 @@ struct Context %} %pure-parser -%name-prefix="pp" +%name-prefix "pp" %parse-param {Context *context} %lex-param {Context *context} diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Input.h b/src/3rdparty/angle/src/compiler/preprocessor/Input.h index 2ac4f0c170..e951cb4d5f 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/Input.h +++ b/src/3rdparty/angle/src/compiler/preprocessor/Input.h @@ -58,5 +58,5 @@ class Input }; } // namespace pp -#endif // COMPILER_PREPROCESSOR_INPUT_H_ +#endif // COMPILER_PREPROCESSOR_INPUT_H_ diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Lexer.h b/src/3rdparty/angle/src/compiler/preprocessor/Lexer.h index d42d3db7e0..990dc5e21d 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/Lexer.h +++ b/src/3rdparty/angle/src/compiler/preprocessor/Lexer.h @@ -21,5 +21,5 @@ class Lexer }; } // namespace pp -#endif // COMPILER_PREPROCESSOR_LEXER_H_ +#endif // COMPILER_PREPROCESSOR_LEXER_H_ diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Macro.h b/src/3rdparty/angle/src/compiler/preprocessor/Macro.h index b77e7bc15c..7662a9c5a2 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/Macro.h +++ b/src/3rdparty/angle/src/compiler/preprocessor/Macro.h @@ -46,4 +46,5 @@ struct Macro typedef std::map MacroSet; } // namespace pp + #endif // COMPILER_PREPROCESSOR_MACRO_H_ diff --git a/src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.h b/src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.h index d4fd091786..5a0c7751a8 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.h +++ b/src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef COMPILER_PREPROCESSOR_MACRO_EXPANDER_H_ -#define COMPILER_PREPROCESSOR_MACRO_EXPANDER_H_ +#ifndef COMPILER_PREPROCESSOR_MACROEXPANDER_H_ +#define COMPILER_PREPROCESSOR_MACROEXPANDER_H_ #include #include @@ -85,5 +85,5 @@ class MacroExpander : public Lexer }; } // namespace pp -#endif // COMPILER_PREPROCESSOR_MACRO_EXPANDER_H_ +#endif // COMPILER_PREPROCESSOR_MACROEXPANDER_H_ diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.h b/src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.h index 0a55f1c9c1..fe25daa123 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.h +++ b/src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.h @@ -50,5 +50,5 @@ class Preprocessor }; } // namespace pp -#endif // COMPILER_PREPROCESSOR_PREPROCESSOR_H_ +#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 index d4c1a5e178..af8a8d5d19 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/SourceLocation.h +++ b/src/3rdparty/angle/src/compiler/preprocessor/SourceLocation.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef COMPILER_PREPROCESSOR_SOURCE_LOCATION_H_ -#define COMPILER_PREPROCESSOR_SOURCE_LOCATION_H_ +#ifndef COMPILER_PREPROCESSOR_SOURCELOCATION_H_ +#define COMPILER_PREPROCESSOR_SOURCELOCATION_H_ namespace pp { @@ -43,4 +43,5 @@ inline bool operator!=(const SourceLocation &lhs, const SourceLocation &rhs) } } // namespace pp -#endif // COMPILER_PREPROCESSOR_SOURCE_LOCATION_H_ + +#endif // COMPILER_PREPROCESSOR_SOURCELOCATION_H_ diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Token.h b/src/3rdparty/angle/src/compiler/preprocessor/Token.h index 8832e279c7..347c47e307 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/Token.h +++ b/src/3rdparty/angle/src/compiler/preprocessor/Token.h @@ -116,4 +116,5 @@ inline bool operator!=(const Token &lhs, const Token &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 index 07ad93da05..78eb86dd3b 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.h +++ b/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.h @@ -55,5 +55,5 @@ class Tokenizer : public Lexer }; } // namespace pp -#endif // COMPILER_PREPROCESSOR_TOKENIZER_H_ +#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 index 2a77b905a4..89cb5c8596 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.l +++ b/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.l @@ -267,7 +267,9 @@ FRACTIONAL_CONSTANT ({DIGIT}*"."{DIGIT}+)|({DIGIT}+".") namespace pp { -Tokenizer::Tokenizer(Diagnostics *diagnostics) : mHandle(0) +Tokenizer::Tokenizer(Diagnostics *diagnostics) + : mHandle(0), + mMaxTokenSize(256) { mContext.diagnostics = diagnostics; } diff --git a/src/3rdparty/angle/src/compiler/preprocessor/numeric_lex.h b/src/3rdparty/angle/src/compiler/preprocessor/numeric_lex.h index 8a24540696..58c51b0961 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/numeric_lex.h +++ b/src/3rdparty/angle/src/compiler/preprocessor/numeric_lex.h @@ -6,8 +6,8 @@ // numeric_lex.h: Functions to extract numeric values from string. -#ifndef COMPILER_PREPROCESSOR_NUMERIC_LEX_H_ -#define COMPILER_PREPROCESSOR_NUMERIC_LEX_H_ +#ifndef COMPILER_PREPROCESSOR_NUMERICLEX_H_ +#define COMPILER_PREPROCESSOR_NUMERICLEX_H_ #include @@ -58,4 +58,5 @@ bool numeric_lex_float(const std::string &str, FloatType *value) } } // namespace pp. -#endif // COMPILER_PREPROCESSOR_NUMERIC_LEX_H_ + +#endif // COMPILER_PREPROCESSOR_NUMERICLEX_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/BaseTypes.h b/src/3rdparty/angle/src/compiler/translator/BaseTypes.h index 324b0669f4..ee1428b2d3 100644 --- a/src/3rdparty/angle/src/compiler/translator/BaseTypes.h +++ b/src/3rdparty/angle/src/compiler/translator/BaseTypes.h @@ -4,10 +4,10 @@ // found in the LICENSE file. // -#ifndef _BASICTYPES_INCLUDED_ -#define _BASICTYPES_INCLUDED_ +#ifndef COMPILER_TRANSLATOR_BASETYPES_H_ +#define COMPILER_TRANSLATOR_BASETYPES_H_ -#include +#include "compiler/translator/compilerdebug.h" // // Precision qualifiers @@ -42,7 +42,15 @@ enum TBasicType EbtInt, EbtUInt, EbtBool, - EbtGVec4, // non type: represents vec4, ivec4 and uvec4 + EbtGVec4, // non type: represents vec4, ivec4, and uvec4 + EbtGenType, // non type: represents float, vec2, vec3, and vec4 + EbtGenIType, // non type: represents int, ivec2, ivec3, and ivec4 + EbtGenUType, // non type: represents uint, uvec2, uvec3, and uvec4 + EbtGenBType, // non type: represents bool, bvec2, bvec3, and bvec4 + EbtVec, // non type: represents vec2, vec3, and vec4 + EbtIVec, // non type: represents ivec2, ivec3, and ivec4 + EbtUVec, // non type: represents uvec2, uvec3, and uvec4 + EbtBVec, // non type: represents bvec2, bvec3, and bvec4 EbtGuardSamplerBegin, // non type: see implementation of IsSampler() EbtSampler2D, EbtSampler3D, @@ -62,10 +70,10 @@ enum TBasicType EbtSamplerCubeShadow, EbtSampler2DArrayShadow, EbtGuardSamplerEnd, // non type: see implementation of IsSampler() - EbtGSampler2D, // non type: represents sampler2D, isampler2D and usampler2D - EbtGSampler3D, // non type: represents sampler3D, isampler3D and usampler3D - EbtGSamplerCube, // non type: represents samplerCube, isamplerCube and usamplerCube - EbtGSampler2DArray, // non type: represents sampler2DArray, isampler2DArray and usampler2DArray + EbtGSampler2D, // non type: represents sampler2D, isampler2D, and usampler2D + EbtGSampler3D, // non type: represents sampler3D, isampler3D, and usampler3D + EbtGSamplerCube, // non type: represents samplerCube, isamplerCube, and usamplerCube + EbtGSampler2DArray, // non type: represents sampler2DArray, isampler2DArray, and usampler2DArray EbtStruct, EbtInterfaceBlock, EbtAddress, // should be deprecated?? @@ -258,6 +266,11 @@ inline bool IsShadowSampler(TBasicType type) return false; } +inline bool IsInteger(TBasicType type) +{ + return type == EbtInt || type == EbtUInt; +} + inline bool SupportsPrecision(TBasicType type) { return type == EbtFloat || type == EbtInt || type == EbtUInt || IsSampler(type); @@ -293,6 +306,9 @@ enum TQualifier EvqInOut, EvqConstReadOnly, + // built-ins read by vertex shader + EvqInstanceID, + // built-ins written by vertex shader EvqPosition, EvqPointSize, @@ -307,6 +323,10 @@ enum TQualifier EvqFragData, EvqFragDepth, + // built-ins written by the shader_framebuffer_fetch extension(s) + EvqLastFragColor, + EvqLastFragData, + // GLSL ES 3.0 vertex output and fragment input EvqSmooth, // Incomplete qualifier, smooth is the default EvqFlat, // Incomplete qualifier @@ -383,6 +403,7 @@ inline const char* getQualifierString(TQualifier q) case EvqIn: return "in"; break; case EvqOut: return "out"; break; case EvqInOut: return "inout"; break; + case EvqInstanceID: return "InstanceID"; break; case EvqPosition: return "Position"; break; case EvqPointSize: return "PointSize"; break; case EvqFragCoord: return "FragCoord"; break; @@ -396,7 +417,9 @@ inline const char* getQualifierString(TQualifier q) case EvqSmoothIn: return "smooth in"; break; case EvqCentroidIn: return "centroid in"; break; case EvqFlatIn: return "flat in"; break; - default: return "unknown qualifier"; + case EvqLastFragColor: return "LastFragColor"; break; + case EvqLastFragData: return "LastFragData"; break; + default: UNREACHABLE(); return "unknown qualifier"; } } @@ -407,7 +430,7 @@ inline const char* getMatrixPackingString(TLayoutMatrixPacking mpq) case EmpUnspecified: return "mp_unspecified"; case EmpRowMajor: return "row_major"; case EmpColumnMajor: return "column_major"; - default: return "unknown matrix packing"; + default: UNREACHABLE(); return "unknown matrix packing"; } } @@ -419,7 +442,7 @@ inline const char* getBlockStorageString(TLayoutBlockStorage bsq) case EbsShared: return "shared"; case EbsPacked: return "packed"; case EbsStd140: return "std140"; - default: return "unknown block storage"; + default: UNREACHABLE(); return "unknown block storage"; } } @@ -433,8 +456,8 @@ inline const char* getInterpolationString(TQualifier q) case EvqSmoothIn: return "smooth"; break; case EvqCentroidIn: return "centroid"; break; case EvqFlatIn: return "flat"; break; - default: return "unknown interpolation"; + default: UNREACHABLE(); return "unknown interpolation"; } } -#endif // _BASICTYPES_INCLUDED_ +#endif // COMPILER_TRANSLATOR_BASETYPES_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.cpp b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.cpp index 0e8239cc1e..51461207c5 100644 --- a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.cpp +++ b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.cpp @@ -8,193 +8,9 @@ #include "compiler/translator/BuiltInFunctionEmulator.h" #include "compiler/translator/SymbolTable.h" -namespace { - -// we use macros here instead of function definitions to work around more GLSL -// compiler bugs, in particular on NVIDIA hardware on Mac OSX. Macros are -// problematic because if the argument has side-effects they will be repeatedly -// evaluated. This is unlikely to show up in real shaders, but is something to -// consider. -const char* kFunctionEmulationVertexSource[] = { - "#error no emulation for cos(float)", - "#error no emulation for cos(vec2)", - "#error no emulation for cos(vec3)", - "#error no emulation for cos(vec4)", - - "#define webgl_distance_emu(x, y) ((x) >= (y) ? (x) - (y) : (y) - (x))", - "#error no emulation for distance(vec2, vec2)", - "#error no emulation for distance(vec3, vec3)", - "#error no emulation for distance(vec4, vec4)", - - "#define webgl_dot_emu(x, y) ((x) * (y))", - "#error no emulation for dot(vec2, vec2)", - "#error no emulation for dot(vec3, vec3)", - "#error no emulation for dot(vec4, vec4)", - - "#define webgl_length_emu(x) ((x) >= 0.0 ? (x) : -(x))", - "#error no emulation for length(vec2)", - "#error no emulation for length(vec3)", - "#error no emulation for length(vec4)", - - "#define webgl_normalize_emu(x) ((x) == 0.0 ? 0.0 : ((x) > 0.0 ? 1.0 : -1.0))", - "#error no emulation for normalize(vec2)", - "#error no emulation for normalize(vec3)", - "#error no emulation for normalize(vec4)", - - "#define webgl_reflect_emu(I, N) ((I) - 2.0 * (N) * (I) * (N))", - "#error no emulation for reflect(vec2, vec2)", - "#error no emulation for reflect(vec3, vec3)", - "#error no emulation for reflect(vec4, vec4)" -}; - -const char* kFunctionEmulationFragmentSource[] = { - "webgl_emu_precision float webgl_cos_emu(webgl_emu_precision float a) { return cos(a); }", - "webgl_emu_precision vec2 webgl_cos_emu(webgl_emu_precision vec2 a) { return cos(a); }", - "webgl_emu_precision vec3 webgl_cos_emu(webgl_emu_precision vec3 a) { return cos(a); }", - "webgl_emu_precision vec4 webgl_cos_emu(webgl_emu_precision vec4 a) { return cos(a); }", - - "#define webgl_distance_emu(x, y) ((x) >= (y) ? (x) - (y) : (y) - (x))", - "#error no emulation for distance(vec2, vec2)", - "#error no emulation for distance(vec3, vec3)", - "#error no emulation for distance(vec4, vec4)", - - "#define webgl_dot_emu(x, y) ((x) * (y))", - "#error no emulation for dot(vec2, vec2)", - "#error no emulation for dot(vec3, vec3)", - "#error no emulation for dot(vec4, vec4)", - - "#define webgl_length_emu(x) ((x) >= 0.0 ? (x) : -(x))", - "#error no emulation for length(vec2)", - "#error no emulation for length(vec3)", - "#error no emulation for length(vec4)", - - "#define webgl_normalize_emu(x) ((x) == 0.0 ? 0.0 : ((x) > 0.0 ? 1.0 : -1.0))", - "#error no emulation for normalize(vec2)", - "#error no emulation for normalize(vec3)", - "#error no emulation for normalize(vec4)", - - "#define webgl_reflect_emu(I, N) ((I) - 2.0 * (N) * (I) * (N))", - "#error no emulation for reflect(vec2, vec2)", - "#error no emulation for reflect(vec3, vec3)", - "#error no emulation for reflect(vec4, vec4)" -}; - -const bool kFunctionEmulationVertexMask[] = { -#if defined(__APPLE__) - // Work around ATI driver bugs in Mac. - false, // TFunctionCos1 - false, // TFunctionCos2 - false, // TFunctionCos3 - false, // TFunctionCos4 - true, // TFunctionDistance1_1 - false, // TFunctionDistance2_2 - false, // TFunctionDistance3_3 - false, // TFunctionDistance4_4 - true, // TFunctionDot1_1 - false, // TFunctionDot2_2 - false, // TFunctionDot3_3 - false, // TFunctionDot4_4 - true, // TFunctionLength1 - false, // TFunctionLength2 - false, // TFunctionLength3 - false, // TFunctionLength4 - true, // TFunctionNormalize1 - false, // TFunctionNormalize2 - false, // TFunctionNormalize3 - false, // TFunctionNormalize4 - true, // TFunctionReflect1_1 - false, // TFunctionReflect2_2 - false, // TFunctionReflect3_3 - false, // TFunctionReflect4_4 -#else - // Work around D3D driver bug in Win. - false, // TFunctionCos1 - false, // TFunctionCos2 - false, // TFunctionCos3 - false, // TFunctionCos4 - false, // TFunctionDistance1_1 - false, // TFunctionDistance2_2 - false, // TFunctionDistance3_3 - false, // TFunctionDistance4_4 - false, // TFunctionDot1_1 - false, // TFunctionDot2_2 - false, // TFunctionDot3_3 - false, // TFunctionDot4_4 - false, // TFunctionLength1 - false, // TFunctionLength2 - false, // TFunctionLength3 - false, // TFunctionLength4 - false, // TFunctionNormalize1 - false, // TFunctionNormalize2 - false, // TFunctionNormalize3 - false, // TFunctionNormalize4 - false, // TFunctionReflect1_1 - false, // TFunctionReflect2_2 - false, // TFunctionReflect3_3 - false, // TFunctionReflect4_4 -#endif - false // TFunctionUnknown -}; - -const bool kFunctionEmulationFragmentMask[] = { -#if defined(__APPLE__) - // Work around ATI driver bugs in Mac. - true, // TFunctionCos1 - true, // TFunctionCos2 - true, // TFunctionCos3 - true, // TFunctionCos4 - true, // TFunctionDistance1_1 - false, // TFunctionDistance2_2 - false, // TFunctionDistance3_3 - false, // TFunctionDistance4_4 - true, // TFunctionDot1_1 - false, // TFunctionDot2_2 - false, // TFunctionDot3_3 - false, // TFunctionDot4_4 - true, // TFunctionLength1 - false, // TFunctionLength2 - false, // TFunctionLength3 - false, // TFunctionLength4 - true, // TFunctionNormalize1 - false, // TFunctionNormalize2 - false, // TFunctionNormalize3 - false, // TFunctionNormalize4 - true, // TFunctionReflect1_1 - false, // TFunctionReflect2_2 - false, // TFunctionReflect3_3 - false, // TFunctionReflect4_4 -#else - // Work around D3D driver bug in Win. - false, // TFunctionCos1 - false, // TFunctionCos2 - false, // TFunctionCos3 - false, // TFunctionCos4 - false, // TFunctionDistance1_1 - false, // TFunctionDistance2_2 - false, // TFunctionDistance3_3 - false, // TFunctionDistance4_4 - false, // TFunctionDot1_1 - false, // TFunctionDot2_2 - false, // TFunctionDot3_3 - false, // TFunctionDot4_4 - false, // TFunctionLength1 - false, // TFunctionLength2 - false, // TFunctionLength3 - false, // TFunctionLength4 - false, // TFunctionNormalize1 - false, // TFunctionNormalize2 - false, // TFunctionNormalize3 - false, // TFunctionNormalize4 - false, // TFunctionReflect1_1 - false, // TFunctionReflect2_2 - false, // TFunctionReflect3_3 - false, // TFunctionReflect4_4 -#endif - false // TFunctionUnknown -}; - -class BuiltInFunctionEmulationMarker : public TIntermTraverser { -public: +class BuiltInFunctionEmulator::BuiltInFunctionEmulationMarker : public TIntermTraverser +{ + public: BuiltInFunctionEmulationMarker(BuiltInFunctionEmulator& emulator) : mEmulator(emulator) { @@ -238,148 +54,119 @@ public: case EOpFaceForward: case EOpReflect: case EOpRefract: + case EOpOuterProduct: case EOpMul: break; default: return true; }; const TIntermSequence& sequence = *(node->getSequence()); - // Right now we only handle built-in functions with two parameters. - if (sequence.size() != 2) - return true; - TIntermTyped* param1 = sequence[0]->getAsTyped(); - TIntermTyped* param2 = sequence[1]->getAsTyped(); - if (!param1 || !param2) + bool needToEmulate = false; + // Right now we only handle built-in functions with two or three parameters. + if (sequence.size() == 2) + { + TIntermTyped* param1 = sequence[0]->getAsTyped(); + TIntermTyped* param2 = sequence[1]->getAsTyped(); + if (!param1 || !param2) + return true; + needToEmulate = mEmulator.SetFunctionCalled( + node->getOp(), param1->getType(), param2->getType()); + } + else if (sequence.size() == 3) + { + TIntermTyped* param1 = sequence[0]->getAsTyped(); + TIntermTyped* param2 = sequence[1]->getAsTyped(); + TIntermTyped* param3 = sequence[2]->getAsTyped(); + if (!param1 || !param2 || !param3) + return true; + needToEmulate = mEmulator.SetFunctionCalled( + node->getOp(), param1->getType(), param2->getType(), param3->getType()); + } + else + { return true; - bool needToEmulate = mEmulator.SetFunctionCalled( - node->getOp(), param1->getType(), param2->getType()); + } + if (needToEmulate) node->setUseEmulatedFunction(); } return true; } -private: + private: BuiltInFunctionEmulator& mEmulator; }; -} // anonymous namepsace +BuiltInFunctionEmulator::BuiltInFunctionEmulator() +{} -BuiltInFunctionEmulator::BuiltInFunctionEmulator(sh::GLenum shaderType) +void BuiltInFunctionEmulator::addEmulatedFunction( + TOperator op, const TType& param, + const char* emulatedFunctionDefinition) { - if (shaderType == GL_FRAGMENT_SHADER) { - mFunctionMask = kFunctionEmulationFragmentMask; - mFunctionSource = kFunctionEmulationFragmentSource; - } else { - mFunctionMask = kFunctionEmulationVertexMask; - mFunctionSource = kFunctionEmulationVertexSource; - } + mEmulatedFunctions[FunctionId(op, param)] = + std::string(emulatedFunctionDefinition); } -bool BuiltInFunctionEmulator::SetFunctionCalled( - TOperator op, const TType& param) +void BuiltInFunctionEmulator::addEmulatedFunction( + TOperator op, const TType& param1, const TType& param2, + const char* emulatedFunctionDefinition) { - TBuiltInFunction function = IdentifyFunction(op, param); - return SetFunctionCalled(function); + mEmulatedFunctions[FunctionId(op, param1, param2)] = + std::string(emulatedFunctionDefinition); } -bool BuiltInFunctionEmulator::SetFunctionCalled( - TOperator op, const TType& param1, const TType& param2) +void BuiltInFunctionEmulator::addEmulatedFunction( + TOperator op, const TType& param1, const TType& param2, const TType& param3, + const char* emulatedFunctionDefinition) { - TBuiltInFunction function = IdentifyFunction(op, param1, param2); - return SetFunctionCalled(function); + mEmulatedFunctions[FunctionId(op, param1, param2, param3)] = + std::string(emulatedFunctionDefinition); } -bool BuiltInFunctionEmulator::SetFunctionCalled( - BuiltInFunctionEmulator::TBuiltInFunction function) { - if (function == TFunctionUnknown || mFunctionMask[function] == false) - return false; - for (size_t i = 0; i < mFunctions.size(); ++i) { - if (mFunctions[i] == function) - return true; - } - mFunctions.push_back(function); - return true; +bool BuiltInFunctionEmulator::IsOutputEmpty() const +{ + return (mFunctions.size() == 0); } -void BuiltInFunctionEmulator::OutputEmulatedFunctionDefinition( - TInfoSinkBase& out, bool withPrecision) const +void BuiltInFunctionEmulator::OutputEmulatedFunctions( + TInfoSinkBase& out) const { - if (mFunctions.size() == 0) - return; - out << "// BEGIN: Generated code for built-in function emulation\n\n"; - if (withPrecision) { - out << "#if defined(GL_FRAGMENT_PRECISION_HIGH)\n" - << "#define webgl_emu_precision highp\n" - << "#else\n" - << "#define webgl_emu_precision mediump\n" - << "#endif\n\n"; - } else { - out << "#define webgl_emu_precision\n\n"; - } for (size_t i = 0; i < mFunctions.size(); ++i) { - out << mFunctionSource[mFunctions[i]] << "\n\n"; + out << mEmulatedFunctions.find(mFunctions[i])->second << "\n\n"; } - out << "// END: Generated code for built-in function emulation\n\n"; } -BuiltInFunctionEmulator::TBuiltInFunction -BuiltInFunctionEmulator::IdentifyFunction( +bool BuiltInFunctionEmulator::SetFunctionCalled( TOperator op, const TType& param) { - if (param.getNominalSize() > 4 || param.getSecondarySize() > 4) - return TFunctionUnknown; - unsigned int function = TFunctionUnknown; - switch (op) { - case EOpCos: - function = TFunctionCos1; - break; - case EOpLength: - function = TFunctionLength1; - break; - case EOpNormalize: - function = TFunctionNormalize1; - break; - default: - break; - } - if (function == TFunctionUnknown) - return TFunctionUnknown; - if (param.isVector()) - function += param.getNominalSize() - 1; - return static_cast(function); + return SetFunctionCalled(FunctionId(op, param)); } -BuiltInFunctionEmulator::TBuiltInFunction -BuiltInFunctionEmulator::IdentifyFunction( +bool BuiltInFunctionEmulator::SetFunctionCalled( TOperator op, const TType& param1, const TType& param2) { - // Right now for all the emulated functions with two parameters, the two - // parameters have the same type. - if (param1.getNominalSize() != param2.getNominalSize() || - param1.getSecondarySize() != param2.getSecondarySize() || - param1.getNominalSize() > 4 || param1.getSecondarySize() > 4) - return TFunctionUnknown; + return SetFunctionCalled(FunctionId(op, param1, param2)); +} + +bool BuiltInFunctionEmulator::SetFunctionCalled( + TOperator op, const TType& param1, const TType& param2, const TType& param3) +{ + return SetFunctionCalled(FunctionId(op, param1, param2, param3)); +} - unsigned int function = TFunctionUnknown; - switch (op) { - case EOpDistance: - function = TFunctionDistance1_1; - break; - case EOpDot: - function = TFunctionDot1_1; - break; - case EOpReflect: - function = TFunctionReflect1_1; - break; - default: - break; +bool BuiltInFunctionEmulator::SetFunctionCalled( + const FunctionId& functionId) { + if (mEmulatedFunctions.find(functionId) != mEmulatedFunctions.end()) + { + for (size_t i = 0; i < mFunctions.size(); ++i) { + if (mFunctions[i] == functionId) + return true; + } + mFunctions.push_back(functionId); + return true; } - if (function == TFunctionUnknown) - return TFunctionUnknown; - if (param1.isVector()) - function += param1.getNominalSize() - 1; - return static_cast(function); + return false; } void BuiltInFunctionEmulator::MarkBuiltInFunctionsForEmulation( @@ -387,6 +174,9 @@ void BuiltInFunctionEmulator::MarkBuiltInFunctionsForEmulation( { ASSERT(root); + if (mEmulatedFunctions.empty()) + return; + BuiltInFunctionEmulationMarker marker(*this); root->traverse(&marker); } @@ -404,3 +194,52 @@ TString BuiltInFunctionEmulator::GetEmulatedFunctionName( return "webgl_" + name.substr(0, name.length() - 1) + "_emu("; } +BuiltInFunctionEmulator::FunctionId::FunctionId + (TOperator op, const TType& param) + : mOp(op), + mParam1(param), + mParam2(EbtVoid), + mParam3(EbtVoid) +{ +} + +BuiltInFunctionEmulator::FunctionId::FunctionId + (TOperator op, const TType& param1, const TType& param2) + : mOp(op), + mParam1(param1), + mParam2(param2), + mParam3(EbtVoid) +{ +} + +BuiltInFunctionEmulator::FunctionId::FunctionId + (TOperator op, const TType& param1, const TType& param2, const TType& param3) + : mOp(op), + mParam1(param1), + mParam2(param2), + mParam3(param3) +{ +} + +bool BuiltInFunctionEmulator::FunctionId::operator== + (const BuiltInFunctionEmulator::FunctionId& other) const +{ + return (mOp == other.mOp && + mParam1 == other.mParam1 && + mParam2 == other.mParam2 && + mParam3 == other.mParam3); +} + +bool BuiltInFunctionEmulator::FunctionId::operator< + (const BuiltInFunctionEmulator::FunctionId& other) const +{ + if (mOp != other.mOp) + return mOp < other.mOp; + if (mParam1 != other.mParam1) + return mParam1 < other.mParam1; + if (mParam2 != other.mParam2) + return mParam2 < other.mParam2; + if (mParam3 != other.mParam3) + return mParam3 < other.mParam3; + return false; // all fields are equal +} diff --git a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.h b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.h index c6bf77c386..df556985e1 100644 --- a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.h +++ b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef COMPILIER_BUILT_IN_FUNCTION_EMULATOR_H_ -#define COMPILIER_BUILT_IN_FUNCTION_EMULATOR_H_ +#ifndef COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATOR_H_ +#define COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATOR_H_ #include "compiler/translator/InfoSink.h" #include "compiler/translator/IntermNode.h" @@ -13,23 +13,13 @@ // // This class decides which built-in functions need to be replaced with the // emulated ones. -// It's only a workaround for OpenGL driver bugs, and isn't needed in general. +// It can be used to work around driver bugs or implement functions that are +// not natively implemented on a specific platform. // -class BuiltInFunctionEmulator { -public: - BuiltInFunctionEmulator(sh::GLenum shaderType); - // Records that a function is called by the shader and might needs to be - // emulated. If the function's group is not in mFunctionGroupFilter, this - // becomes an no-op. - // Returns true if the function call needs to be replaced with an emulated - // one. - bool SetFunctionCalled(TOperator op, const TType& param); - bool SetFunctionCalled( - TOperator op, const TType& param1, const TType& param2); - - // Output function emulation definition. This should be before any other - // shader source. - void OutputEmulatedFunctionDefinition(TInfoSinkBase& out, bool withPrecision) const; +class BuiltInFunctionEmulator +{ + public: + BuiltInFunctionEmulator(); void MarkBuiltInFunctionsForEmulation(TIntermNode* root); @@ -38,54 +28,52 @@ public: // "name(" becomes "webgl_name_emu(". static TString GetEmulatedFunctionName(const TString& name); -private: - // - // Built-in functions. - // - enum TBuiltInFunction { - TFunctionCos1 = 0, // float cos(float); - TFunctionCos2, // vec2 cos(vec2); - TFunctionCos3, // vec3 cos(vec3); - TFunctionCos4, // vec4 cos(vec4); - - TFunctionDistance1_1, // float distance(float, float); - TFunctionDistance2_2, // vec2 distance(vec2, vec2); - TFunctionDistance3_3, // vec3 distance(vec3, vec3); - TFunctionDistance4_4, // vec4 distance(vec4, vec4); - - TFunctionDot1_1, // float dot(float, float); - TFunctionDot2_2, // vec2 dot(vec2, vec2); - TFunctionDot3_3, // vec3 dot(vec3, vec3); - TFunctionDot4_4, // vec4 dot(vec4, vec4); - - TFunctionLength1, // float length(float); - TFunctionLength2, // float length(vec2); - TFunctionLength3, // float length(vec3); - TFunctionLength4, // float length(vec4); - - TFunctionNormalize1, // float normalize(float); - TFunctionNormalize2, // vec2 normalize(vec2); - TFunctionNormalize3, // vec3 normalize(vec3); - TFunctionNormalize4, // vec4 normalize(vec4); - - TFunctionReflect1_1, // float reflect(float, float); - TFunctionReflect2_2, // vec2 reflect(vec2, vec2); - TFunctionReflect3_3, // vec3 reflect(vec3, vec3); - TFunctionReflect4_4, // vec4 reflect(vec4, vec4); - - TFunctionUnknown - }; + bool IsOutputEmpty() const; + + // Output function emulation definition. This should be before any other + // shader source. + void OutputEmulatedFunctions(TInfoSinkBase& out) const; + + // Add functions that need to be emulated. + void addEmulatedFunction(TOperator op, const TType& param, const char* emulatedFunctionDefinition); + void addEmulatedFunction(TOperator op, const TType& param1, const TType& param2, const char* emulatedFunctionDefinition); + void addEmulatedFunction(TOperator op, const TType& param1, const TType& param2, const TType& param3, const char* emulatedFunctionDefinition); - TBuiltInFunction IdentifyFunction(TOperator op, const TType& param); - TBuiltInFunction IdentifyFunction( + private: + class BuiltInFunctionEmulationMarker; + + // Records that a function is called by the shader and might need to be + // emulated. If the function is not in mEmulatedFunctions, this becomes a + // no-op. Returns true if the function call needs to be replaced with an + // emulated one. + bool SetFunctionCalled(TOperator op, const TType& param); + bool SetFunctionCalled( TOperator op, const TType& param1, const TType& param2); + bool SetFunctionCalled( + TOperator op, const TType& param1, const TType& param2, const TType& param3); + + class FunctionId { + public: + FunctionId(TOperator op, const TType& param); + FunctionId(TOperator op, const TType& param1, const TType& param2); + FunctionId(TOperator op, const TType& param1, const TType& param2, const TType& param3); + + bool operator==(const FunctionId& other) const; + bool operator<(const FunctionId& other) const; + private: + TOperator mOp; + TType mParam1; + TType mParam2; + TType mParam3; + }; - bool SetFunctionCalled(TBuiltInFunction function); + bool SetFunctionCalled(const FunctionId& functionId); - std::vector mFunctions; + // Map from function id to emulated function definition + std::map mEmulatedFunctions; - const bool* mFunctionMask; // a boolean flag for each function. - const char** mFunctionSource; + // Called function ids + std::vector mFunctions; }; -#endif // COMPILIER_BUILT_IN_FUNCTION_EMULATOR_H_ +#endif // COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATOR_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorGLSL.cpp b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorGLSL.cpp new file mode 100644 index 0000000000..9de99831ad --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorGLSL.cpp @@ -0,0 +1,37 @@ +// +// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "angle_gl.h" +#include "compiler/translator/BuiltInFunctionEmulator.h" +#include "compiler/translator/BuiltInFunctionEmulatorGLSL.h" +#include "compiler/translator/SymbolTable.h" + +void InitBuiltInFunctionEmulatorForGLSL(BuiltInFunctionEmulator *emu, sh::GLenum shaderType) +{ + // we use macros here instead of function definitions to work around more GLSL + // compiler bugs, in particular on NVIDIA hardware on Mac OSX. Macros are + // problematic because if the argument has side-effects they will be repeatedly + // evaluated. This is unlikely to show up in real shaders, but is something to + // consider. + + TType float1(EbtFloat); + TType float2(EbtFloat, 2); + TType float3(EbtFloat, 3); + TType float4(EbtFloat, 4); + + if (shaderType == GL_FRAGMENT_SHADER) + { + emu->addEmulatedFunction(EOpCos, float1, "webgl_emu_precision float webgl_cos_emu(webgl_emu_precision float a) { return cos(a); }"); + emu->addEmulatedFunction(EOpCos, float2, "webgl_emu_precision vec2 webgl_cos_emu(webgl_emu_precision vec2 a) { return cos(a); }"); + emu->addEmulatedFunction(EOpCos, float3, "webgl_emu_precision vec3 webgl_cos_emu(webgl_emu_precision vec3 a) { return cos(a); }"); + emu->addEmulatedFunction(EOpCos, float4, "webgl_emu_precision vec4 webgl_cos_emu(webgl_emu_precision vec4 a) { return cos(a); }"); + } + emu->addEmulatedFunction(EOpDistance, float1, float1, "#define webgl_distance_emu(x, y) ((x) >= (y) ? (x) - (y) : (y) - (x))"); + emu->addEmulatedFunction(EOpDot, float1, float1, "#define webgl_dot_emu(x, y) ((x) * (y))"); + emu->addEmulatedFunction(EOpLength, float1, "#define webgl_length_emu(x) ((x) >= 0.0 ? (x) : -(x))"); + emu->addEmulatedFunction(EOpNormalize, float1, "#define webgl_normalize_emu(x) ((x) == 0.0 ? 0.0 : ((x) > 0.0 ? 1.0 : -1.0))"); + emu->addEmulatedFunction(EOpReflect, float1, float1, "#define webgl_reflect_emu(I, N) ((I) - 2.0 * (N) * (I) * (N))"); +} diff --git a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorGLSL.h b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorGLSL.h new file mode 100644 index 0000000000..5707a4b35a --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorGLSL.h @@ -0,0 +1,19 @@ +// +// 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_TRANSLATOR_BUILTINFUNCTIONEMULATORGLSL_H_ +#define COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATORGLSL_H_ + +#include "GLSLANG/ShaderLang.h" + +class BuiltInFunctionEmulator; + +// +// This is only a workaround for OpenGL driver bugs, and isn't needed in general. +// +void InitBuiltInFunctionEmulatorForGLSL(BuiltInFunctionEmulator *emu, sh::GLenum shaderType); + +#endif // COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATORGLSL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorHLSL.cpp new file mode 100644 index 0000000000..7123a0d5c0 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorHLSL.cpp @@ -0,0 +1,410 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "angle_gl.h" +#include "compiler/translator/BuiltInFunctionEmulator.h" +#include "compiler/translator/BuiltInFunctionEmulatorHLSL.h" +#include "compiler/translator/SymbolTable.h" + +void InitBuiltInFunctionEmulatorForHLSL(BuiltInFunctionEmulator *emu) +{ + TType float1(EbtFloat); + TType float2(EbtFloat, 2); + TType float3(EbtFloat, 3); + TType float4(EbtFloat, 4); + + emu->addEmulatedFunction(EOpMod, float1, float1, + "float webgl_mod_emu(float x, float y)\n" + "{\n" + " return x - y * floor(x / y);\n" + "}\n" + "\n"); + emu->addEmulatedFunction(EOpMod, float2, float2, + "float2 webgl_mod_emu(float2 x, float2 y)\n" + "{\n" + " return x - y * floor(x / y);\n" + "}\n" + "\n"); + emu->addEmulatedFunction(EOpMod, float2, float1, + "float2 webgl_mod_emu(float2 x, float y)\n" + "{\n" + " return x - y * floor(x / y);\n" + "}\n" + "\n"); + emu->addEmulatedFunction(EOpMod, float3, float3, + "float3 webgl_mod_emu(float3 x, float3 y)\n" + "{\n" + " return x - y * floor(x / y);\n" + "}\n" + "\n"); + emu->addEmulatedFunction(EOpMod, float3, float1, + "float3 webgl_mod_emu(float3 x, float y)\n" + "{\n" + " return x - y * floor(x / y);\n" + "}\n" + "\n"); + emu->addEmulatedFunction(EOpMod, float4, float4, + "float4 webgl_mod_emu(float4 x, float4 y)\n" + "{\n" + " return x - y * floor(x / y);\n" + "}\n" + "\n"); + emu->addEmulatedFunction(EOpMod, float4, float1, + "float4 webgl_mod_emu(float4 x, float y)\n" + "{\n" + " return x - y * floor(x / y);\n" + "}\n" + "\n"); + + emu->addEmulatedFunction(EOpFaceForward, float1, float1, float1, + "float webgl_faceforward_emu(float N, float I, float Nref)\n" + "{\n" + " if(dot(Nref, I) >= 0)\n" + " {\n" + " return -N;\n" + " }\n" + " else\n" + " {\n" + " return N;\n" + " }\n" + "}\n" + "\n"); + emu->addEmulatedFunction(EOpFaceForward, float2, float2, float2, + "float2 webgl_faceforward_emu(float2 N, float2 I, float2 Nref)\n" + "{\n" + " if(dot(Nref, I) >= 0)\n" + " {\n" + " return -N;\n" + " }\n" + " else\n" + " {\n" + " return N;\n" + " }\n" + "}\n" + "\n"); + emu->addEmulatedFunction(EOpFaceForward, float3, float3, float3, + "float3 webgl_faceforward_emu(float3 N, float3 I, float3 Nref)\n" + "{\n" + " if(dot(Nref, I) >= 0)\n" + " {\n" + " return -N;\n" + " }\n" + " else\n" + " {\n" + " return N;\n" + " }\n" + "}\n" + "\n"); + emu->addEmulatedFunction(EOpFaceForward, float4, float4, float4, + "float4 webgl_faceforward_emu(float4 N, float4 I, float4 Nref)\n" + "{\n" + " if(dot(Nref, I) >= 0)\n" + " {\n" + " return -N;\n" + " }\n" + " else\n" + " {\n" + " return N;\n" + " }\n" + "}\n" + "\n"); + + emu->addEmulatedFunction(EOpAtan, float1, float1, + "float webgl_atan_emu(float y, float x)\n" + "{\n" + " if(x == 0 && y == 0) x = 1;\n" // Avoid producing a NaN + " return atan2(y, x);\n" + "}\n"); + emu->addEmulatedFunction(EOpAtan, float2, float2, + "float2 webgl_atan_emu(float2 y, float2 x)\n" + "{\n" + " if(x[0] == 0 && y[0] == 0) x[0] = 1;\n" + " if(x[1] == 0 && y[1] == 0) x[1] = 1;\n" + " return float2(atan2(y[0], x[0]), atan2(y[1], x[1]));\n" + "}\n"); + emu->addEmulatedFunction(EOpAtan, float3, float3, + "float3 webgl_atan_emu(float3 y, float3 x)\n" + "{\n" + " if(x[0] == 0 && y[0] == 0) x[0] = 1;\n" + " if(x[1] == 0 && y[1] == 0) x[1] = 1;\n" + " if(x[2] == 0 && y[2] == 0) x[2] = 1;\n" + " return float3(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], x[2]));\n" + "}\n"); + emu->addEmulatedFunction(EOpAtan, float4, float4, + "float4 webgl_atan_emu(float4 y, float4 x)\n" + "{\n" + " if(x[0] == 0 && y[0] == 0) x[0] = 1;\n" + " if(x[1] == 0 && y[1] == 0) x[1] = 1;\n" + " if(x[2] == 0 && y[2] == 0) x[2] = 1;\n" + " if(x[3] == 0 && y[3] == 0) x[3] = 1;\n" + " return float4(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], x[2]), atan2(y[3], x[3]));\n" + "}\n"); + + emu->addEmulatedFunction(EOpAsinh, float1, + "float webgl_asinh_emu(in float x) {\n" + " return log(x + sqrt(pow(x, 2.0) + 1.0));\n" + "}\n"); + emu->addEmulatedFunction(EOpAsinh, float2, + "float2 webgl_asinh_emu(in float2 x) {\n" + " return log(x + sqrt(pow(x, 2.0) + 1.0));\n" + "}\n"); + emu->addEmulatedFunction(EOpAsinh, float3, + "float3 webgl_asinh_emu(in float3 x) {\n" + " return log(x + sqrt(pow(x, 2.0) + 1.0));\n" + "}\n"); + emu->addEmulatedFunction(EOpAsinh, float4, + "float4 webgl_asinh_emu(in float4 x) {\n" + " return log(x + sqrt(pow(x, 2.0) + 1.0));\n" + "}\n"); + + emu->addEmulatedFunction(EOpAcosh, float1, + "float webgl_acosh_emu(in float x) {\n" + " return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n" + "}\n"); + emu->addEmulatedFunction(EOpAcosh, float2, + "float2 webgl_acosh_emu(in float2 x) {\n" + " return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n" + "}\n"); + emu->addEmulatedFunction(EOpAcosh, float3, + "float3 webgl_acosh_emu(in float3 x) {\n" + " return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n" + "}\n"); + emu->addEmulatedFunction(EOpAcosh, float4, + "float4 webgl_acosh_emu(in float4 x) {\n" + " return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n" + "}\n"); + + emu->addEmulatedFunction(EOpAtanh, float1, + "float webgl_atanh_emu(in float x) {\n" + " return 0.5 * log((1.0 + x) / (1.0 - x));\n" + "}\n"); + emu->addEmulatedFunction(EOpAtanh, float2, + "float2 webgl_atanh_emu(in float2 x) {\n" + " return 0.5 * log((1.0 + x) / (1.0 - x));\n" + "}\n"); + emu->addEmulatedFunction(EOpAtanh, float3, + "float3 webgl_atanh_emu(in float3 x) {\n" + " return 0.5 * log((1.0 + x) / (1.0 - x));\n" + "}\n"); + emu->addEmulatedFunction(EOpAtanh, float4, + "float4 webgl_atanh_emu(in float4 x) {\n" + " return 0.5 * log((1.0 + x) / (1.0 - x));\n" + "}\n"); + + emu->addEmulatedFunction(EOpRoundEven, float1, + "float webgl_roundEven_emu(in float x) {\n" + " return (frac(x) == 0.5 && trunc(x) % 2.0 == 0.0) ? trunc(x) : round(x);\n" + "}\n"); + emu->addEmulatedFunction(EOpRoundEven, float2, + "float2 webgl_roundEven_emu(in float2 x) {\n" + " float2 v;\n" + " v[0] = (frac(x[0]) == 0.5 && trunc(x[0]) % 2.0 == 0.0) ? trunc(x[0]) : round(x[0]);\n" + " v[1] = (frac(x[1]) == 0.5 && trunc(x[1]) % 2.0 == 0.0) ? trunc(x[1]) : round(x[1]);\n" + " return v;\n" + "}\n"); + emu->addEmulatedFunction(EOpRoundEven, float3, + "float3 webgl_roundEven_emu(in float3 x) {\n" + " float3 v;\n" + " v[0] = (frac(x[0]) == 0.5 && trunc(x[0]) % 2.0 == 0.0) ? trunc(x[0]) : round(x[0]);\n" + " v[1] = (frac(x[1]) == 0.5 && trunc(x[1]) % 2.0 == 0.0) ? trunc(x[1]) : round(x[1]);\n" + " v[2] = (frac(x[2]) == 0.5 && trunc(x[2]) % 2.0 == 0.0) ? trunc(x[2]) : round(x[2]);\n" + " return v;\n" + "}\n"); + emu->addEmulatedFunction(EOpRoundEven, float4, + "float4 webgl_roundEven_emu(in float4 x) {\n" + " float4 v;\n" + " v[0] = (frac(x[0]) == 0.5 && trunc(x[0]) % 2.0 == 0.0) ? trunc(x[0]) : round(x[0]);\n" + " v[1] = (frac(x[1]) == 0.5 && trunc(x[1]) % 2.0 == 0.0) ? trunc(x[1]) : round(x[1]);\n" + " v[2] = (frac(x[2]) == 0.5 && trunc(x[2]) % 2.0 == 0.0) ? trunc(x[2]) : round(x[2]);\n" + " v[3] = (frac(x[3]) == 0.5 && trunc(x[3]) % 2.0 == 0.0) ? trunc(x[3]) : round(x[3]);\n" + " return v;\n" + "}\n"); + + emu->addEmulatedFunction(EOpPackSnorm2x16, float2, + "int webgl_toSnorm(in float x) {\n" + " return int(round(clamp(x, -1.0, 1.0) * 32767.0));\n" + "}\n" + "\n" + "uint webgl_packSnorm2x16_emu(in float2 v) {\n" + " int x = webgl_toSnorm(v.x);\n" + " int y = webgl_toSnorm(v.y);\n" + " return (asuint(y) << 16) | (asuint(x) & 0xffffu);\n" + "}\n"); + emu->addEmulatedFunction(EOpPackUnorm2x16, float2, + "uint webgl_toUnorm(in float x) {\n" + " return uint(round(clamp(x, 0.0, 1.0) * 65535.0));\n" + "}\n" + "\n" + "uint webgl_packUnorm2x16_emu(in float2 v) {\n" + " uint x = webgl_toUnorm(v.x);\n" + " uint y = webgl_toUnorm(v.y);\n" + " return (y << 16) | x;\n" + "}\n"); + emu->addEmulatedFunction(EOpPackHalf2x16, float2, + "uint webgl_packHalf2x16_emu(in float2 v) {\n" + " uint x = f32tof16(v.x);\n" + " uint y = f32tof16(v.y);\n" + " return (y << 16) | x;\n" + "}\n"); + + TType uint1(EbtUInt); + + emu->addEmulatedFunction(EOpUnpackSnorm2x16, uint1, + "float webgl_fromSnorm(in uint x) {\n" + " int xi = asint(x & 0x7fffu) - asint(x & 0x8000u);\n" + " return clamp(float(xi) / 32767.0, -1.0, 1.0);\n" + "}\n" + "\n" + "float2 webgl_unpackSnorm2x16_emu(in uint u) {\n" + " uint y = (u >> 16);\n" + " uint x = u;\n" + " return float2(webgl_fromSnorm(x), webgl_fromSnorm(y));\n" + "}\n"); + emu->addEmulatedFunction(EOpUnpackUnorm2x16, uint1, + "float webgl_fromUnorm(in uint x) {\n" + " return float(x) / 65535.0;\n" + "}\n" + "\n" + "float2 webgl_unpackUnorm2x16_emu(in uint u) {\n" + " uint y = (u >> 16);\n" + " uint x = u & 0xffffu;\n" + " return float2(webgl_fromUnorm(x), webgl_fromUnorm(y));\n" + "}\n"); + emu->addEmulatedFunction(EOpUnpackHalf2x16, uint1, + "float2 webgl_unpackHalf2x16_emu(in uint u) {\n" + " uint y = (u >> 16);\n" + " uint x = u & 0xffffu;\n" + " return float2(f16tof32(x), f16tof32(y));\n" + "}\n"); + + // The matrix resulting from outer product needs to be transposed + // (matrices are stored as transposed to simplify element access in HLSL). + // So the function should return transpose(c * r) where c is a column vector + // and r is a row vector. This can be simplified by using the following + // formula: + // transpose(c * r) = transpose(r) * transpose(c) + // transpose(r) and transpose(c) are in a sense free, since to get the + // transpose of r, we simply can build a column matrix out of the original + // vector instead of a row matrix. + emu->addEmulatedFunction(EOpOuterProduct, float2, float2, + "float2x2 webgl_outerProduct_emu(in float2 c, in float2 r) {\n" + " return mul(float2x1(r), float1x2(c));\n" + "}\n"); + emu->addEmulatedFunction(EOpOuterProduct, float3, float3, + "float3x3 webgl_outerProduct_emu(in float3 c, in float3 r) {\n" + " return mul(float3x1(r), float1x3(c));\n" + "}\n"); + emu->addEmulatedFunction(EOpOuterProduct, float4, float4, + "float4x4 webgl_outerProduct_emu(in float4 c, in float4 r) {\n" + " return mul(float4x1(r), float1x4(c));\n" + "}\n"); + + emu->addEmulatedFunction(EOpOuterProduct, float3, float2, + "float2x3 webgl_outerProduct_emu(in float3 c, in float2 r) {\n" + " return mul(float2x1(r), float1x3(c));\n" + "}\n"); + emu->addEmulatedFunction(EOpOuterProduct, float2, float3, + "float3x2 webgl_outerProduct_emu(in float2 c, in float3 r) {\n" + " return mul(float3x1(r), float1x2(c));\n" + "}\n"); + emu->addEmulatedFunction(EOpOuterProduct, float4, float2, + "float2x4 webgl_outerProduct_emu(in float4 c, in float2 r) {\n" + " return mul(float2x1(r), float1x4(c));\n" + "}\n"); + emu->addEmulatedFunction(EOpOuterProduct, float2, float4, + "float4x2 webgl_outerProduct_emu(in float2 c, in float4 r) {\n" + " return mul(float4x1(r), float1x2(c));\n" + "}\n"); + emu->addEmulatedFunction(EOpOuterProduct, float4, float3, + "float3x4 webgl_outerProduct_emu(in float4 c, in float3 r) {\n" + " return mul(float3x1(r), float1x4(c));\n" + "}\n"); + emu->addEmulatedFunction(EOpOuterProduct, float3, float4, + "float4x3 webgl_outerProduct_emu(in float3 c, in float4 r) {\n" + " return mul(float4x1(r), float1x3(c));\n" + "}\n"); + + TType mat2(EbtFloat, 2, 2); + TType mat3(EbtFloat, 3, 3); + TType mat4(EbtFloat, 4, 4); + + // Remember here that the parameter matrix is actually the transpose + // of the matrix that we're trying to invert, and the resulting matrix + // should also be the transpose of the inverse. + + // When accessing the parameter matrix with m[a][b] it can be thought of so + // that a is the column and b is the row of the matrix that we're inverting. + + // We calculate the inverse as the adjugate matrix divided by the + // determinant of the matrix being inverted. However, as the result needs + // to be transposed, we actually use of the transpose of the adjugate matrix + // which happens to be the cofactor matrix. That's stored in "cof". + + // We don't need to care about divide-by-zero since results are undefined + // for singular or poorly-conditioned matrices. + + emu->addEmulatedFunction(EOpInverse, mat2, + "float2x2 webgl_inverse_emu(in float2x2 m) {\n" + " float2x2 cof = { m[1][1], -m[0][1], -m[1][0], m[0][0] };\n" + " return cof / determinant(transpose(m));\n" + "}\n"); + + // cofAB is the cofactor for column A and row B. + + emu->addEmulatedFunction(EOpInverse, mat3, + "float3x3 webgl_inverse_emu(in float3x3 m) {\n" + " float cof00 = m[1][1] * m[2][2] - m[2][1] * m[1][2];\n" + " float cof01 = -(m[1][0] * m[2][2] - m[2][0] * m[1][2]);\n" + " float cof02 = m[1][0] * m[2][1] - m[2][0] * m[1][1];\n" + " float cof10 = -(m[0][1] * m[2][2] - m[2][1] * m[0][2]);\n" + " float cof11 = m[0][0] * m[2][2] - m[2][0] * m[0][2];\n" + " float cof12 = -(m[0][0] * m[2][1] - m[2][0] * m[0][1]);\n" + " float cof20 = m[0][1] * m[1][2] - m[1][1] * m[0][2];\n" + " float cof21 = -(m[0][0] * m[1][2] - m[1][0] * m[0][2]);\n" + " float cof22 = m[0][0] * m[1][1] - m[1][0] * m[0][1];\n" + " float3x3 cof = { cof00, cof10, cof20, cof01, cof11, cof21, cof02, cof12, cof22 };\n" + " return cof / determinant(transpose(m));\n" + "}\n"); + + emu->addEmulatedFunction(EOpInverse, mat4, + "float4x4 webgl_inverse_emu(in float4x4 m) {\n" + " float cof00 = m[1][1] * m[2][2] * m[3][3] + m[2][1] * m[3][2] * m[1][3] + m[3][1] * m[1][2] * m[2][3]" + " - m[1][1] * m[3][2] * m[2][3] - m[2][1] * m[1][2] * m[3][3] - m[3][1] * m[2][2] * m[1][3];\n" + " float cof01 = -(m[1][0] * m[2][2] * m[3][3] + m[2][0] * m[3][2] * m[1][3] + m[3][0] * m[1][2] * m[2][3]" + " - m[1][0] * m[3][2] * m[2][3] - m[2][0] * m[1][2] * m[3][3] - m[3][0] * m[2][2] * m[1][3]);\n" + " float cof02 = m[1][0] * m[2][1] * m[3][3] + m[2][0] * m[3][1] * m[1][3] + m[3][0] * m[1][1] * m[2][3]" + " - m[1][0] * m[3][1] * m[2][3] - m[2][0] * m[1][1] * m[3][3] - m[3][0] * m[2][1] * m[1][3];\n" + " float cof03 = -(m[1][0] * m[2][1] * m[3][2] + m[2][0] * m[3][1] * m[1][2] + m[3][0] * m[1][1] * m[2][2]" + " - m[1][0] * m[3][1] * m[2][2] - m[2][0] * m[1][1] * m[3][2] - m[3][0] * m[2][1] * m[1][2]);\n" + " float cof10 = -(m[0][1] * m[2][2] * m[3][3] + m[2][1] * m[3][2] * m[0][3] + m[3][1] * m[0][2] * m[2][3]" + " - m[0][1] * m[3][2] * m[2][3] - m[2][1] * m[0][2] * m[3][3] - m[3][1] * m[2][2] * m[0][3]);\n" + " float cof11 = m[0][0] * m[2][2] * m[3][3] + m[2][0] * m[3][2] * m[0][3] + m[3][0] * m[0][2] * m[2][3]" + " - m[0][0] * m[3][2] * m[2][3] - m[2][0] * m[0][2] * m[3][3] - m[3][0] * m[2][2] * m[0][3];\n" + " float cof12 = -(m[0][0] * m[2][1] * m[3][3] + m[2][0] * m[3][1] * m[0][3] + m[3][0] * m[0][1] * m[2][3]" + " - m[0][0] * m[3][1] * m[2][3] - m[2][0] * m[0][1] * m[3][3] - m[3][0] * m[2][1] * m[0][3]);\n" + " float cof13 = m[0][0] * m[2][1] * m[3][2] + m[2][0] * m[3][1] * m[0][2] + m[3][0] * m[0][1] * m[2][2]" + " - m[0][0] * m[3][1] * m[2][2] - m[2][0] * m[0][1] * m[3][2] - m[3][0] * m[2][1] * m[0][2];\n" + " float cof20 = m[0][1] * m[1][2] * m[3][3] + m[1][1] * m[3][2] * m[0][3] + m[3][1] * m[0][2] * m[1][3]" + " - m[0][1] * m[3][2] * m[1][3] - m[1][1] * m[0][2] * m[3][3] - m[3][1] * m[1][2] * m[0][3];\n" + " float cof21 = -(m[0][0] * m[1][2] * m[3][3] + m[1][0] * m[3][2] * m[0][3] + m[3][0] * m[0][2] * m[1][3]" + " - m[0][0] * m[3][2] * m[1][3] - m[1][0] * m[0][2] * m[3][3] - m[3][0] * m[1][2] * m[0][3]);\n" + " float cof22 = m[0][0] * m[1][1] * m[3][3] + m[1][0] * m[3][1] * m[0][3] + m[3][0] * m[0][1] * m[1][3]" + " - m[0][0] * m[3][1] * m[1][3] - m[1][0] * m[0][1] * m[3][3] - m[3][0] * m[1][1] * m[0][3];\n" + " float cof23 = -(m[0][0] * m[1][1] * m[3][2] + m[1][0] * m[3][1] * m[0][2] + m[3][0] * m[0][1] * m[1][2]" + " - m[0][0] * m[3][1] * m[1][2] - m[1][0] * m[0][1] * m[3][2] - m[3][0] * m[1][1] * m[0][2]);\n" + " float cof30 = -(m[0][1] * m[1][2] * m[2][3] + m[1][1] * m[2][2] * m[0][3] + m[2][1] * m[0][2] * m[1][3]" + " - m[0][1] * m[2][2] * m[1][3] - m[1][1] * m[0][2] * m[2][3] - m[2][1] * m[1][2] * m[0][3]);\n" + " float cof31 = m[0][0] * m[1][2] * m[2][3] + m[1][0] * m[2][2] * m[0][3] + m[2][0] * m[0][2] * m[1][3]" + " - m[0][0] * m[2][2] * m[1][3] - m[1][0] * m[0][2] * m[2][3] - m[2][0] * m[1][2] * m[0][3];\n" + " float cof32 = -(m[0][0] * m[1][1] * m[2][3] + m[1][0] * m[2][1] * m[0][3] + m[2][0] * m[0][1] * m[1][3]" + " - m[0][0] * m[2][1] * m[1][3] - m[1][0] * m[0][1] * m[2][3] - m[2][0] * m[1][1] * m[0][3]);\n" + " float cof33 = m[0][0] * m[1][1] * m[2][2] + m[1][0] * m[2][1] * m[0][2] + m[2][0] * m[0][1] * m[1][2]" + " - m[0][0] * m[2][1] * m[1][2] - m[1][0] * m[0][1] * m[2][2] - m[2][0] * m[1][1] * m[0][2];\n" + " float4x4 cof = { cof00, cof10, cof20, cof30, cof01, cof11, cof21, cof31," + " cof02, cof12, cof22, cof32, cof03, cof13, cof23, cof33 };\n" + " return cof / determinant(transpose(m));\n" + "}\n"); +} diff --git a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorHLSL.h b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorHLSL.h new file mode 100644 index 0000000000..4c45a93dc4 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorHLSL.h @@ -0,0 +1,16 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATORHLSL_H_ +#define COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATORHLSL_H_ + +#include "GLSLANG/ShaderLang.h" + +class BuiltInFunctionEmulator; + +void InitBuiltInFunctionEmulatorForHLSL(BuiltInFunctionEmulator *emu); + +#endif // COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATORHLSL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/CodeGen.cpp b/src/3rdparty/angle/src/compiler/translator/CodeGen.cpp index 71056f4297..5e3eb1cc05 100644 --- a/src/3rdparty/angle/src/compiler/translator/CodeGen.cpp +++ b/src/3rdparty/angle/src/compiler/translator/CodeGen.cpp @@ -6,7 +6,9 @@ #include "compiler/translator/TranslatorESSL.h" #include "compiler/translator/TranslatorGLSL.h" +#ifdef ANGLE_ENABLE_HLSL #include "compiler/translator/TranslatorHLSL.h" +#endif // ANGLE_ENABLE_HLSL // // This function must be provided to create the actual @@ -17,14 +19,22 @@ TCompiler* ConstructCompiler( sh::GLenum type, ShShaderSpec spec, ShShaderOutput output) { switch (output) { - case SH_ESSL_OUTPUT: + case SH_ESSL_OUTPUT: return new TranslatorESSL(type, spec); - case SH_GLSL_OUTPUT: - return new TranslatorGLSL(type, spec); - case SH_HLSL9_OUTPUT: - case SH_HLSL11_OUTPUT: + case SH_GLSL_CORE_OUTPUT: + case SH_GLSL_COMPATIBILITY_OUTPUT: + return new TranslatorGLSL(type, spec, output); + case SH_HLSL9_OUTPUT: + case SH_HLSL11_OUTPUT: +#ifdef ANGLE_ENABLE_HLSL return new TranslatorHLSL(type, spec, output); - default: +#else + // This compiler is not supported in this + // configuration. Return NULL per the ShConstructCompiler API. + return NULL; +#endif // ANGLE_ENABLE_HLSL + default: + // Unknown format. Return NULL per the ShConstructCompiler API. return NULL; } } diff --git a/src/3rdparty/angle/src/compiler/translator/Common.h b/src/3rdparty/angle/src/compiler/translator/Common.h index 1e4503e340..ac1aef0f4c 100644 --- a/src/3rdparty/angle/src/compiler/translator/Common.h +++ b/src/3rdparty/angle/src/compiler/translator/Common.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef _COMMON_INCLUDED_ -#define _COMMON_INCLUDED_ +#ifndef COMPILER_TRANSLATOR_COMMON_H_ +#define COMPILER_TRANSLATOR_COMMON_H_ #include #include @@ -89,4 +89,4 @@ inline TString str(T i) return buffer; } -#endif // _COMMON_INCLUDED_ +#endif // COMPILER_TRANSLATOR_COMMON_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/Compiler.cpp b/src/3rdparty/angle/src/compiler/translator/Compiler.cpp index 5c62a64d10..534861ca70 100644 --- a/src/3rdparty/angle/src/compiler/translator/Compiler.cpp +++ b/src/3rdparty/angle/src/compiler/translator/Compiler.cpp @@ -4,7 +4,6 @@ // found in the LICENSE file. // -#include "compiler/translator/BuiltInFunctionEmulator.h" #include "compiler/translator/Compiler.h" #include "compiler/translator/DetectCallDepth.h" #include "compiler/translator/ForLoopUnroll.h" @@ -126,7 +125,8 @@ TCompiler::TCompiler(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output) maxCallStackDepth(0), fragmentPrecisionHigh(false), clampingStrategy(SH_CLAMP_WITH_CLAMP_INTRINSIC), - builtInFunctionEmulator(type) + builtInFunctionEmulator(), + mSourcePath(NULL) { } @@ -159,33 +159,41 @@ bool TCompiler::Init(const ShBuiltInResources& resources) return true; } -bool TCompiler::compile(const char* const shaderStrings[], - size_t numStrings, - int compileOptions) +TIntermNode *TCompiler::compileTreeForTesting(const char* const shaderStrings[], + size_t numStrings, int compileOptions) +{ + return compileTreeImpl(shaderStrings, numStrings, compileOptions); +} + +TIntermNode *TCompiler::compileTreeImpl(const char* const shaderStrings[], + size_t numStrings, int compileOptions) { - TScopedPoolAllocator scopedAlloc(&allocator); clearResults(); - if (numStrings == 0) - return true; + ASSERT(numStrings > 0); + ASSERT(GetGlobalPoolAllocator()); + + // Reset the extension behavior for each compilation unit. + ResetExtensionBehavior(extensionBehavior); // If compiling for WebGL, validate loop and indexing as well. if (IsWebGLBasedSpec(shaderSpec)) compileOptions |= SH_VALIDATE_LOOP_INDEXING; // First string is path of source file if flag is set. The actual source follows. - const char* sourcePath = NULL; size_t firstSource = 0; if (compileOptions & SH_SOURCE_PATH) { - sourcePath = shaderStrings[0]; + mSourcePath = shaderStrings[0]; ++firstSource; } + bool debugShaderPrecision = getResources().WEBGL_debug_shader_precision == 1; TIntermediate intermediate(infoSink); TParseContext parseContext(symbolTable, extensionBehavior, intermediate, shaderType, shaderSpec, compileOptions, true, - sourcePath, infoSink); + infoSink, debugShaderPrecision); + parseContext.fragmentPrecisionHigh = fragmentPrecisionHigh; SetGlobalParseContext(&parseContext); @@ -206,6 +214,8 @@ bool TCompiler::compile(const char* const shaderStrings[], success = false; } + TIntermNode *root = NULL; + if (success) { mPragma = parseContext.pragma(); @@ -214,7 +224,7 @@ bool TCompiler::compile(const char* const shaderStrings[], symbolTable.setGlobalInvariant(); } - TIntermNode* root = parseContext.treeRoot; + root = parseContext.treeRoot; success = intermediate.postProcess(root); // Disallow expressions deemed too complex. @@ -255,8 +265,11 @@ bool TCompiler::compile(const char* const shaderStrings[], } // Built-in function emulation needs to happen after validateLimitations pass. - if (success && (compileOptions & SH_EMULATE_BUILT_IN_FUNCTIONS)) + if (success) + { + initBuiltInFunctionEmulator(&builtInFunctionEmulator, compileOptions); builtInFunctionEmulator.MarkBuiltInFunctionsForEmulation(root); + } // Clamping uniform array bounds needs to happen after validateLimitations pass. if (success && (compileOptions & SH_CLAMP_INDIRECT_ARRAY_BOUNDS)) @@ -301,18 +314,37 @@ bool TCompiler::compile(const char* const shaderStrings[], RegenerateStructNames gen(symbolTable, shaderVersion); root->traverse(&gen); } - - if (success && (compileOptions & SH_INTERMEDIATE_TREE)) - intermediate.outputTree(root); - - if (success && (compileOptions & SH_OBJECT_CODE)) - translate(root); } - // Cleanup memory. - intermediate.remove(parseContext.treeRoot); SetGlobalParseContext(NULL); - return success; + if (success) + return root; + + return NULL; +} + +bool TCompiler::compile(const char* const shaderStrings[], + size_t numStrings, int compileOptions) +{ + if (numStrings == 0) + return true; + + TScopedPoolAllocator scopedAlloc(&allocator); + TIntermNode *root = compileTreeImpl(shaderStrings, numStrings, compileOptions); + + if (root) + { + if (compileOptions & SH_INTERMEDIATE_TREE) + TIntermediate::outputTree(root, infoSink.info); + + if (compileOptions & SH_OBJECT_CODE) + translate(root, compileOptions); + + // The IntermNode tree doesn't need to be deleted here, since the + // memory will be freed in a big chunk by the PoolAllocator. + return true; + } + return false; } bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources &resources) @@ -390,11 +422,15 @@ void TCompiler::setResourceString() << ":MaxCallStackDepth:" << compileResources.MaxCallStackDepth << ":EXT_frag_depth:" << compileResources.EXT_frag_depth << ":EXT_shader_texture_lod:" << compileResources.EXT_shader_texture_lod + << ":EXT_shader_framebuffer_fetch:" << compileResources.EXT_shader_framebuffer_fetch + << ":NV_shader_framebuffer_fetch:" << compileResources.NV_shader_framebuffer_fetch + << ":ARM_shader_framebuffer_fetch:" << compileResources.ARM_shader_framebuffer_fetch << ":MaxVertexOutputVectors:" << compileResources.MaxVertexOutputVectors << ":MaxFragmentInputVectors:" << compileResources.MaxFragmentInputVectors << ":MinProgramTexelOffset:" << compileResources.MinProgramTexelOffset << ":MaxProgramTexelOffset:" << compileResources.MaxProgramTexelOffset - << ":NV_draw_buffers:" << compileResources.NV_draw_buffers; + << ":NV_draw_buffers:" << compileResources.NV_draw_buffers + << ":WEBGL_debug_shader_precision:" << compileResources.WEBGL_debug_shader_precision; builtInResourcesString = strstream.str(); } @@ -416,27 +452,29 @@ void TCompiler::clearResults() builtInFunctionEmulator.Cleanup(); nameMap.clear(); + + mSourcePath = NULL; } -bool TCompiler::detectCallDepth(TIntermNode* root, TInfoSink& infoSink, bool limitCallStackDepth) +bool TCompiler::detectCallDepth(TIntermNode* inputRoot, TInfoSink& inputInfoSink, bool limitCallStackDepth) { - DetectCallDepth detect(infoSink, limitCallStackDepth, maxCallStackDepth); - root->traverse(&detect); + DetectCallDepth detect(inputInfoSink, limitCallStackDepth, maxCallStackDepth); + inputRoot->traverse(&detect); switch (detect.detectCallDepth()) { case DetectCallDepth::kErrorNone: return true; case DetectCallDepth::kErrorMissingMain: - infoSink.info.prefix(EPrefixError); - infoSink.info << "Missing main()"; + inputInfoSink.info.prefix(EPrefixError); + inputInfoSink.info << "Missing main()"; return false; case DetectCallDepth::kErrorRecursion: - infoSink.info.prefix(EPrefixError); - infoSink.info << "Function recursion detected"; + inputInfoSink.info.prefix(EPrefixError); + inputInfoSink.info << "Function recursion detected"; return false; case DetectCallDepth::kErrorMaxDepthExceeded: - infoSink.info.prefix(EPrefixError); - infoSink.info << "Function call stack too deep"; + inputInfoSink.info.prefix(EPrefixError); + inputInfoSink.info << "Function call stack too deep"; return false; default: UNREACHABLE(); @@ -594,6 +632,11 @@ const TExtensionBehavior& TCompiler::getExtensionBehavior() const return extensionBehavior; } +const char *TCompiler::getSourcePath() const +{ + return mSourcePath; +} + const ShBuiltInResources& TCompiler::getResources() const { return compileResources; diff --git a/src/3rdparty/angle/src/compiler/translator/Compiler.h b/src/3rdparty/angle/src/compiler/translator/Compiler.h index b6c9d13ed0..bcdb0d4c9d 100644 --- a/src/3rdparty/angle/src/compiler/translator/Compiler.h +++ b/src/3rdparty/angle/src/compiler/translator/Compiler.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef _SHHANDLE_INCLUDED_ -#define _SHHANDLE_INCLUDED_ +#ifndef COMPILER_TRANSLATOR_COMPILER_H_ +#define COMPILER_TRANSLATOR_COMPILER_H_ // // Machine independent part of the compiler private objects @@ -25,7 +25,9 @@ class TCompiler; class TDependencyGraph; +#ifdef ANGLE_ENABLE_HLSL class TranslatorHLSL; +#endif // ANGLE_ENABLE_HLSL // // Helper function to identify specs that are based on the WebGL spec, @@ -41,7 +43,9 @@ public: TShHandleBase(); virtual ~TShHandleBase(); virtual TCompiler* getAsCompiler() { return 0; } +#ifdef ANGLE_ENABLE_HLSL virtual TranslatorHLSL* getAsTranslatorHLSL() { return 0; } +#endif // ANGLE_ENABLE_HLSL protected: // Memory allocator. Allocates and tracks memory required by the compiler. @@ -61,9 +65,15 @@ class TCompiler : public TShHandleBase virtual TCompiler* getAsCompiler() { return this; } bool Init(const ShBuiltInResources& resources); + + // compileTreeForTesting should be used only when tests require access to + // the AST. Users of this function need to manually manage the global pool + // allocator. Returns NULL whenever there are compilation errors. + TIntermNode *compileTreeForTesting(const char* const shaderStrings[], + size_t numStrings, int compileOptions); + bool compile(const char* const shaderStrings[], - size_t numStrings, - int compileOptions); + size_t numStrings, int compileOptions); // Get results of the last compilation. int getShaderVersion() const { return shaderVersion; } @@ -104,8 +114,10 @@ class TCompiler : public TShHandleBase bool validateLimitations(TIntermNode* root); // Collect info for all attribs, uniforms, varyings. void collectVariables(TIntermNode* root); + // Add emulated functions to the built-in function emulator. + virtual void initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu, int compileOptions) {}; // Translate to object code. - virtual void translate(TIntermNode* root) = 0; + virtual void translate(TIntermNode *root, int compileOptions) = 0; // Returns true if, after applying the packing rules in the GLSL 1.017 spec // Appendix A, section 7, the shader does not use too many uniforms. bool enforcePackingRestrictions(); @@ -130,6 +142,7 @@ class TCompiler : public TShHandleBase bool limitExpressionComplexity(TIntermNode* root); // Get built-in extensions with default behavior. const TExtensionBehavior& getExtensionBehavior() const; + const char *getSourcePath() const; const TPragma& getPragma() const { return mPragma; } void writePragma(); @@ -145,6 +158,9 @@ class TCompiler : public TShHandleBase std::vector interfaceBlocks; private: + TIntermNode *compileTreeImpl(const char* const shaderStrings[], + size_t numStrings, int compileOptions); + sh::GLenum shaderType; ShShaderSpec shaderSpec; ShShaderOutput outputType; @@ -170,6 +186,7 @@ class TCompiler : public TShHandleBase // Results of compilation. int shaderVersion; TInfoSink infoSink; // Output sink. + const char *mSourcePath; // Path of source file or NULL // name hashing. ShHashFunction64 hashFunction; @@ -191,4 +208,4 @@ TCompiler* ConstructCompiler( sh::GLenum type, ShShaderSpec spec, ShShaderOutput output); void DeleteCompiler(TCompiler*); -#endif // _SHHANDLE_INCLUDED_ +#endif // COMPILER_TRANSLATOR_COMPILER_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/ConstantUnion.h b/src/3rdparty/angle/src/compiler/translator/ConstantUnion.h index 5e86c64805..31ff2ccfa7 100644 --- a/src/3rdparty/angle/src/compiler/translator/ConstantUnion.h +++ b/src/3rdparty/angle/src/compiler/translator/ConstantUnion.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef _CONSTANT_UNION_INCLUDED_ -#define _CONSTANT_UNION_INCLUDED_ +#ifndef COMPILER_TRANSLATOR_CONSTANTUNION_H_ +#define COMPILER_TRANSLATOR_CONSTANTUNION_H_ #include @@ -254,7 +254,10 @@ public: ConstantUnion operator<<(const ConstantUnion& constant) const { ConstantUnion returnValue; - assert(type == constant.type); + // The signedness of the second parameter might be different, but we + // don't care, since the result is undefined if the second parameter is + // negative, and aliasing should not be a problem with unions. + assert(constant.type == EbtInt || constant.type == EbtUInt); switch (type) { case EbtInt: returnValue.setIConst(iConst << constant.iConst); break; case EbtUInt: returnValue.setUConst(uConst << constant.uConst); break; @@ -267,7 +270,7 @@ public: ConstantUnion operator&(const ConstantUnion& constant) const { ConstantUnion returnValue; - assert(type == constant.type); + assert(constant.type == EbtInt || constant.type == EbtUInt); switch (type) { case EbtInt: returnValue.setIConst(iConst & constant.iConst); break; case EbtUInt: returnValue.setUConst(uConst & constant.uConst); break; @@ -340,4 +343,4 @@ private: TBasicType type; }; -#endif // _CONSTANT_UNION_INCLUDED_ +#endif // COMPILER_TRANSLATOR_CONSTANTUNION_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/DetectCallDepth.cpp b/src/3rdparty/angle/src/compiler/translator/DetectCallDepth.cpp index bfc1d5852f..0dc5d22709 100644 --- a/src/3rdparty/angle/src/compiler/translator/DetectCallDepth.cpp +++ b/src/3rdparty/angle/src/compiler/translator/DetectCallDepth.cpp @@ -33,7 +33,7 @@ int DetectCallDepth::FunctionNode::detectCallDepth(DetectCallDepth* detectCallDe ASSERT(visit == PreVisit); ASSERT(detectCallDepth); - int maxDepth = depth; + int retMaxDepth = depth; visit = InVisit; for (size_t i = 0; i < callees.size(); ++i) { switch (callees[i]->visit) { @@ -52,7 +52,7 @@ int DetectCallDepth::FunctionNode::detectCallDepth(DetectCallDepth* detectCallDe detectCallDepth->getInfoSink().info << "<-" << callees[i]->getName(); return callDepth; } - maxDepth = std::max(callDepth, maxDepth); + retMaxDepth = std::max(callDepth, retMaxDepth); break; } default: @@ -61,7 +61,7 @@ int DetectCallDepth::FunctionNode::detectCallDepth(DetectCallDepth* detectCallDe } } visit = PostVisit; - return maxDepth; + return retMaxDepth; } void DetectCallDepth::FunctionNode::reset() diff --git a/src/3rdparty/angle/src/compiler/translator/DetectCallDepth.h b/src/3rdparty/angle/src/compiler/translator/DetectCallDepth.h index 86810650dc..8dd1391e67 100644 --- a/src/3rdparty/angle/src/compiler/translator/DetectCallDepth.h +++ b/src/3rdparty/angle/src/compiler/translator/DetectCallDepth.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef COMPILER_DETECT_RECURSION_H_ -#define COMPILER_DETECT_RECURSION_H_ +#ifndef COMPILER_TRANSLATOR_DETECTCALLDEPTH_H_ +#define COMPILER_TRANSLATOR_DETECTCALLDEPTH_H_ #include #include "compiler/translator/IntermNode.h" @@ -75,4 +75,4 @@ private: void operator=(const DetectCallDepth&); }; -#endif // COMPILER_DETECT_RECURSION_H_ +#endif // COMPILER_TRANSLATOR_DETECTCALLDEPTH_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/DetectDiscontinuity.h b/src/3rdparty/angle/src/compiler/translator/DetectDiscontinuity.h index 67e37be398..623be13533 100644 --- a/src/3rdparty/angle/src/compiler/translator/DetectDiscontinuity.h +++ b/src/3rdparty/angle/src/compiler/translator/DetectDiscontinuity.h @@ -8,8 +8,8 @@ // gradients of functions with discontinuities. // -#ifndef COMPILER_DETECTDISCONTINUITY_H_ -#define COMPILER_DETECTDISCONTINUITY_H_ +#ifndef COMPILER_TRANSLATOR_DETECTDISCONTINUITY_H_ +#define COMPILER_TRANSLATOR_DETECTDISCONTINUITY_H_ #include "compiler/translator/IntermNode.h" @@ -68,4 +68,4 @@ bool containsGradientOperation(TIntermNode *node); } -#endif // COMPILER_DETECTDISCONTINUITY_H_ +#endif // COMPILER_TRANSLATOR_DETECTDISCONTINUITY_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/Diagnostics.h b/src/3rdparty/angle/src/compiler/translator/Diagnostics.h index 664da7803b..078bc97772 100644 --- a/src/3rdparty/angle/src/compiler/translator/Diagnostics.h +++ b/src/3rdparty/angle/src/compiler/translator/Diagnostics.h @@ -4,14 +4,15 @@ // found in the LICENSE file. // -#ifndef COMPILER_DIAGNOSTICS_H_ -#define COMPILER_DIAGNOSTICS_H_ +#ifndef COMPILER_TRANSLATOR_DIAGNOSTICS_H_ +#define COMPILER_TRANSLATOR_DIAGNOSTICS_H_ +#include "common/angleutils.h" #include "compiler/preprocessor/DiagnosticsBase.h" class TInfoSink; -class TDiagnostics : public pp::Diagnostics +class TDiagnostics : public pp::Diagnostics, angle::NonCopyable { public: TDiagnostics(TInfoSink& infoSink); @@ -41,4 +42,4 @@ class TDiagnostics : public pp::Diagnostics int mNumWarnings; }; -#endif // COMPILER_DIAGNOSTICS_H_ +#endif // COMPILER_TRANSLATOR_DIAGNOSTICS_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.cpp b/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.cpp index f67a03aa93..936c00a56c 100644 --- a/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.cpp +++ b/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.cpp @@ -27,10 +27,12 @@ static TBehavior getBehavior(const std::string& str) TDirectiveHandler::TDirectiveHandler(TExtensionBehavior& extBehavior, TDiagnostics& diagnostics, - int& shaderVersion) + int& shaderVersion, + bool debugShaderPrecisionSupported) : mExtensionBehavior(extBehavior), mDiagnostics(diagnostics), - mShaderVersion(shaderVersion) + mShaderVersion(shaderVersion), + mDebugShaderPrecisionSupported(debugShaderPrecisionSupported) { } @@ -65,6 +67,7 @@ void TDirectiveHandler::handlePragma(const pp::SourceLocation& loc, { const char kOptimize[] = "optimize"; const char kDebug[] = "debug"; + const char kDebugShaderPrecision[] = "webgl_debug_shader_precision"; const char kOn[] = "on"; const char kOff[] = "off"; @@ -81,6 +84,12 @@ void TDirectiveHandler::handlePragma(const pp::SourceLocation& loc, else if (value == kOff) mPragma.debug = false; else invalidValue = true; } + else if (name == kDebugShaderPrecision && mDebugShaderPrecisionSupported) + { + if (value == kOn) mPragma.debugShaderPrecision = true; + else if (value == kOff) mPragma.debugShaderPrecision = false; + else invalidValue = true; + } else { mDiagnostics.report(pp::Diagnostics::PP_UNRECOGNIZED_PRAGMA, loc, name); diff --git a/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.h b/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.h index 0433c3bf89..2a81ee5707 100644 --- a/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.h +++ b/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.h @@ -4,21 +4,23 @@ // found in the LICENSE file. // -#ifndef COMPILER_DIRECTIVE_HANDLER_H_ -#define COMPILER_DIRECTIVE_HANDLER_H_ +#ifndef COMPILER_TRANSLATOR_DIRECTIVEHANDLER_H_ +#define COMPILER_TRANSLATOR_DIRECTIVEHANDLER_H_ +#include "common/angleutils.h" #include "compiler/translator/ExtensionBehavior.h" #include "compiler/translator/Pragma.h" #include "compiler/preprocessor/DirectiveHandlerBase.h" class TDiagnostics; -class TDirectiveHandler : public pp::DirectiveHandler +class TDirectiveHandler : public pp::DirectiveHandler, angle::NonCopyable { public: TDirectiveHandler(TExtensionBehavior& extBehavior, TDiagnostics& diagnostics, - int& shaderVersion); + int& shaderVersion, + bool debugShaderPrecisionSupported); virtual ~TDirectiveHandler(); const TPragma& pragma() const { return mPragma; } @@ -44,6 +46,7 @@ class TDirectiveHandler : public pp::DirectiveHandler TExtensionBehavior& mExtensionBehavior; TDiagnostics& mDiagnostics; int& mShaderVersion; + bool mDebugShaderPrecisionSupported; }; -#endif // COMPILER_DIRECTIVE_HANDLER_H_ +#endif // COMPILER_TRANSLATOR_DIRECTIVEHANDLER_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/EmulatePrecision.cpp b/src/3rdparty/angle/src/compiler/translator/EmulatePrecision.cpp new file mode 100644 index 0000000000..697e042954 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/EmulatePrecision.cpp @@ -0,0 +1,528 @@ +// +// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/EmulatePrecision.h" + +namespace +{ + +static void writeVectorPrecisionEmulationHelpers( + TInfoSinkBase& sink, ShShaderOutput outputLanguage, unsigned int size) +{ + std::stringstream vecTypeStrStr; + if (outputLanguage == SH_ESSL_OUTPUT) + vecTypeStrStr << "highp "; + vecTypeStrStr << "vec" << size; + std::string vecType = vecTypeStrStr.str(); + + sink << + vecType << " angle_frm(in " << vecType << " v) {\n" + " v = clamp(v, -65504.0, 65504.0);\n" + " " << vecType << " exponent = floor(log2(abs(v) + 1e-30)) - 10.0;\n" + " bvec" << size << " isNonZero = greaterThanEqual(exponent, vec" << size << "(-25.0));\n" + " v = v * exp2(-exponent);\n" + " v = sign(v) * floor(abs(v));\n" + " return v * exp2(exponent) * vec" << size << "(isNonZero);\n" + "}\n"; + + sink << + vecType << " angle_frl(in " << vecType << " v) {\n" + " v = clamp(v, -2.0, 2.0);\n" + " v = v * 256.0;\n" + " v = sign(v) * floor(abs(v));\n" + " return v * 0.00390625;\n" + "}\n"; +} + +static void writeMatrixPrecisionEmulationHelper( + TInfoSinkBase& sink, ShShaderOutput outputLanguage, unsigned int size, const char *functionName) +{ + std::stringstream matTypeStrStr; + if (outputLanguage == SH_ESSL_OUTPUT) + matTypeStrStr << "highp "; + matTypeStrStr << "mat" << size; + std::string matType = matTypeStrStr.str(); + + sink << matType << " " << functionName << "(in " << matType << " m) {\n" + " " << matType << " rounded;\n"; + + for (unsigned int i = 0; i < size; ++i) + { + sink << " rounded[" << i << "] = " << functionName << "(m[" << i << "]);\n"; + } + + sink << " return rounded;\n" + "}\n"; +} + +static void writeCommonPrecisionEmulationHelpers(TInfoSinkBase& sink, ShShaderOutput outputLanguage) +{ + // Write the angle_frm functions that round floating point numbers to + // half precision, and angle_frl functions that round them to minimum lowp + // precision. + + // Unoptimized version of angle_frm for single floats: + // + // int webgl_maxNormalExponent(in int exponentBits) { + // int possibleExponents = int(exp2(float(exponentBits))); + // int exponentBias = possibleExponents / 2 - 1; + // int allExponentBitsOne = possibleExponents - 1; + // return (allExponentBitsOne - 1) - exponentBias; + // } + // + // float angle_frm(in float x) { + // int mantissaBits = 10; + // int exponentBits = 5; + // float possibleMantissas = exp2(float(mantissaBits)); + // float mantissaMax = 2.0 - 1.0 / possibleMantissas; + // int maxNE = webgl_maxNormalExponent(exponentBits); + // float max = exp2(float(maxNE)) * mantissaMax; + // if (x > max) { + // return max; + // } + // if (x < -max) { + // return -max; + // } + // float exponent = floor(log2(abs(x))); + // if (abs(x) == 0.0 || exponent < -float(maxNE)) { + // return 0.0 * sign(x) + // } + // x = x * exp2(-(exponent - float(mantissaBits))); + // x = sign(x) * floor(abs(x)); + // return x * exp2(exponent - float(mantissaBits)); + // } + + // All numbers with a magnitude less than 2^-15 are subnormal, and are + // flushed to zero. + + // Note the constant numbers below: + // a) 65504 is the maximum possible mantissa (1.1111111111 in binary) times + // 2^15, the maximum normal exponent. + // b) 10.0 is the number of mantissa bits. + // c) -25.0 is the minimum normal half-float exponent -15.0 minus the number + // of mantissa bits. + // d) + 1e-30 is to make sure the argument of log2() won't be zero. It can + // only affect the result of log2 on x where abs(x) < 1e-22. Since these + // numbers will be flushed to zero either way (2^-15 is the smallest + // normal positive number), this does not introduce any error. + + std::string floatType = "float"; + if (outputLanguage == SH_ESSL_OUTPUT) + floatType = "highp float"; + + sink << + floatType << " angle_frm(in " << floatType << " x) {\n" + " x = clamp(x, -65504.0, 65504.0);\n" + " " << floatType << " exponent = floor(log2(abs(x) + 1e-30)) - 10.0;\n" + " bool isNonZero = (exponent >= -25.0);\n" + " x = x * exp2(-exponent);\n" + " x = sign(x) * floor(abs(x));\n" + " return x * exp2(exponent) * float(isNonZero);\n" + "}\n"; + + sink << + floatType << " angle_frl(in " << floatType << " x) {\n" + " x = clamp(x, -2.0, 2.0);\n" + " x = x * 256.0;\n" + " x = sign(x) * floor(abs(x));\n" + " return x * 0.00390625;\n" + "}\n"; + + writeVectorPrecisionEmulationHelpers(sink, outputLanguage, 2); + writeVectorPrecisionEmulationHelpers(sink, outputLanguage, 3); + writeVectorPrecisionEmulationHelpers(sink, outputLanguage, 4); + for (unsigned int size = 2; size <= 4; ++size) + { + writeMatrixPrecisionEmulationHelper(sink, outputLanguage, size, "angle_frm"); + writeMatrixPrecisionEmulationHelper(sink, outputLanguage, size, "angle_frl"); + } +} + +static void writeCompoundAssignmentPrecisionEmulation( + TInfoSinkBase& sink, ShShaderOutput outputLanguage, + const char *lType, const char *rType, const char *opStr, const char *opNameStr) +{ + std::string lTypeStr = lType; + std::string rTypeStr = rType; + if (outputLanguage == SH_ESSL_OUTPUT) + { + std::stringstream lTypeStrStr; + lTypeStrStr << "highp " << lType; + lTypeStr = lTypeStrStr.str(); + std::stringstream rTypeStrStr; + rTypeStrStr << "highp " << rType; + rTypeStr = rTypeStrStr.str(); + } + + // Note that y should be passed through angle_frm at the function call site, + // but x can't be passed through angle_frm there since it is an inout parameter. + // So only pass x and the result through angle_frm here. + sink << + lTypeStr << " angle_compound_" << opNameStr << "_frm(inout " << lTypeStr << " x, in " << rTypeStr << " y) {\n" + " x = angle_frm(angle_frm(x) " << opStr << " y);\n" + " return x;\n" + "}\n"; + sink << + lTypeStr << " angle_compound_" << opNameStr << "_frl(inout " << lTypeStr << " x, in " << rTypeStr << " y) {\n" + " x = angle_frl(angle_frm(x) " << opStr << " y);\n" + " return x;\n" + "}\n"; +} + +const char *getFloatTypeStr(const TType& type) +{ + switch (type.getNominalSize()) + { + case 1: + return "float"; + case 2: + return type.getSecondarySize() > 1 ? "mat2" : "vec2"; + case 3: + return type.getSecondarySize() > 1 ? "mat3" : "vec3"; + case 4: + return type.getSecondarySize() > 1 ? "mat4" : "vec4"; + default: + UNREACHABLE(); + return NULL; + } +} + +bool canRoundFloat(const TType &type) +{ + return type.getBasicType() == EbtFloat && !type.isNonSquareMatrix() && !type.isArray() && + (type.getPrecision() == EbpLow || type.getPrecision() == EbpMedium); +} + +TIntermAggregate *createInternalFunctionCallNode(TString name, TIntermNode *child) +{ + TIntermAggregate *callNode = new TIntermAggregate(); + callNode->setOp(EOpInternalFunctionCall); + callNode->setName(name); + callNode->getSequence()->push_back(child); + return callNode; +} + +TIntermAggregate *createRoundingFunctionCallNode(TIntermTyped *roundedChild) +{ + TString roundFunctionName; + if (roundedChild->getPrecision() == EbpMedium) + roundFunctionName = "angle_frm"; + else + roundFunctionName = "angle_frl"; + return createInternalFunctionCallNode(roundFunctionName, roundedChild); +} + +TIntermAggregate *createCompoundAssignmentFunctionCallNode(TIntermTyped *left, TIntermTyped *right, const char *opNameStr) +{ + std::stringstream strstr; + if (left->getPrecision() == EbpMedium) + strstr << "angle_compound_" << opNameStr << "_frm"; + else + strstr << "angle_compound_" << opNameStr << "_frl"; + TString functionName = strstr.str().c_str(); + TIntermAggregate *callNode = createInternalFunctionCallNode(functionName, left); + callNode->getSequence()->push_back(right); + return callNode; +} + +bool parentUsesResult(TIntermNode* parent, TIntermNode* node) +{ + if (!parent) + { + return false; + } + + TIntermAggregate *aggParent = parent->getAsAggregate(); + // If the parent's op is EOpSequence, the result is not assigned anywhere, + // so rounding it is not needed. In particular, this can avoid a lot of + // unnecessary rounding of unused return values of assignment. + if (aggParent && aggParent->getOp() == EOpSequence) + { + return false; + } + if (aggParent && aggParent->getOp() == EOpComma && (aggParent->getSequence()->back() != node)) + { + return false; + } + return true; +} + +} // namespace anonymous + +EmulatePrecision::EmulatePrecision() + : TIntermTraverser(true, true, true), + mDeclaringVariables(false), + mInLValue(false), + mInFunctionCallOutParameter(false) +{} + +void EmulatePrecision::visitSymbol(TIntermSymbol *node) +{ + if (canRoundFloat(node->getType()) && + !mDeclaringVariables && !mInLValue && !mInFunctionCallOutParameter) + { + TIntermNode *parent = getParentNode(); + TIntermNode *replacement = createRoundingFunctionCallNode(node); + mReplacements.push_back(NodeUpdateEntry(parent, node, replacement, true)); + } +} + + +bool EmulatePrecision::visitBinary(Visit visit, TIntermBinary *node) +{ + bool visitChildren = true; + + if (node->isAssignment()) + { + if (visit == PreVisit) + mInLValue = true; + else if (visit == InVisit) + mInLValue = false; + } + + TOperator op = node->getOp(); + + // RHS of initialize is not being declared. + if (op == EOpInitialize && visit == InVisit) + mDeclaringVariables = false; + + if ((op == EOpIndexDirectStruct || op == EOpVectorSwizzle) && visit == InVisit) + visitChildren = false; + + if (visit != PreVisit) + return visitChildren; + + const TType& type = node->getType(); + bool roundFloat = canRoundFloat(type); + + if (roundFloat) { + switch (op) { + // Math operators that can result in a float may need to apply rounding to the return + // value. Note that in the case of assignment, the rounding is applied to its return + // value here, not the value being assigned. + case EOpAssign: + case EOpAdd: + case EOpSub: + case EOpMul: + case EOpDiv: + case EOpVectorTimesScalar: + case EOpVectorTimesMatrix: + case EOpMatrixTimesVector: + case EOpMatrixTimesScalar: + case EOpMatrixTimesMatrix: + { + TIntermNode *parent = getParentNode(); + if (!parentUsesResult(parent, node)) + { + break; + } + TIntermNode *replacement = createRoundingFunctionCallNode(node); + mReplacements.push_back(NodeUpdateEntry(parent, node, replacement, true)); + break; + } + + // Compound assignment cases need to replace the operator with a function call. + case EOpAddAssign: + { + mEmulateCompoundAdd.insert(TypePair(getFloatTypeStr(type), getFloatTypeStr(node->getRight()->getType()))); + TIntermNode *parent = getParentNode(); + TIntermNode *replacement = createCompoundAssignmentFunctionCallNode(node->getLeft(), node->getRight(), "add"); + mReplacements.push_back(NodeUpdateEntry(parent, node, replacement, false)); + break; + } + case EOpSubAssign: + { + mEmulateCompoundSub.insert(TypePair(getFloatTypeStr(type), getFloatTypeStr(node->getRight()->getType()))); + TIntermNode *parent = getParentNode(); + TIntermNode *replacement = createCompoundAssignmentFunctionCallNode(node->getLeft(), node->getRight(), "sub"); + mReplacements.push_back(NodeUpdateEntry(parent, node, replacement, false)); + break; + } + case EOpMulAssign: + case EOpVectorTimesMatrixAssign: + case EOpVectorTimesScalarAssign: + case EOpMatrixTimesScalarAssign: + case EOpMatrixTimesMatrixAssign: + { + mEmulateCompoundMul.insert(TypePair(getFloatTypeStr(type), getFloatTypeStr(node->getRight()->getType()))); + TIntermNode *parent = getParentNode(); + TIntermNode *replacement = createCompoundAssignmentFunctionCallNode(node->getLeft(), node->getRight(), "mul"); + mReplacements.push_back(NodeUpdateEntry(parent, node, replacement, false)); + break; + } + case EOpDivAssign: + { + mEmulateCompoundDiv.insert(TypePair(getFloatTypeStr(type), getFloatTypeStr(node->getRight()->getType()))); + TIntermNode *parent = getParentNode(); + TIntermNode *replacement = createCompoundAssignmentFunctionCallNode(node->getLeft(), node->getRight(), "div"); + mReplacements.push_back(NodeUpdateEntry(parent, node, replacement, false)); + break; + } + default: + // The rest of the binary operations should not need precision emulation. + break; + } + } + return visitChildren; +} + +bool EmulatePrecision::visitAggregate(Visit visit, TIntermAggregate *node) +{ + bool visitChildren = true; + switch (node->getOp()) + { + case EOpSequence: + case EOpConstructStruct: + // No special handling + break; + case EOpFunction: + if (visit == PreVisit) + { + const TIntermSequence &sequence = *(node->getSequence()); + TIntermSequence::const_iterator seqIter = sequence.begin(); + TIntermAggregate *params = (*seqIter)->getAsAggregate(); + ASSERT(params != NULL); + ASSERT(params->getOp() == EOpParameters); + mFunctionMap[node->getName()] = params->getSequence(); + } + break; + case EOpPrototype: + if (visit == PreVisit) + mFunctionMap[node->getName()] = node->getSequence(); + visitChildren = false; + break; + case EOpParameters: + visitChildren = false; + break; + case EOpInvariantDeclaration: + visitChildren = false; + break; + case EOpDeclaration: + // Variable declaration. + if (visit == PreVisit) + { + mDeclaringVariables = true; + } + else if (visit == InVisit) + { + mDeclaringVariables = true; + } + else + { + mDeclaringVariables = false; + } + break; + case EOpFunctionCall: + { + // Function call. + bool inFunctionMap = (mFunctionMap.find(node->getName()) != mFunctionMap.end()); + if (visit == PreVisit) + { + // User-defined function return values are not rounded, this relies on that + // calculations producing the value were rounded. + TIntermNode *parent = getParentNode(); + if (canRoundFloat(node->getType()) && !inFunctionMap && parentUsesResult(parent, node)) + { + TIntermNode *replacement = createRoundingFunctionCallNode(node); + mReplacements.push_back(NodeUpdateEntry(parent, node, replacement, true)); + } + + if (inFunctionMap) + { + mSeqIterStack.push_back(mFunctionMap[node->getName()]->begin()); + if (mSeqIterStack.back() != mFunctionMap[node->getName()]->end()) + { + TQualifier qualifier = (*mSeqIterStack.back())->getAsTyped()->getQualifier(); + mInFunctionCallOutParameter = (qualifier == EvqOut || qualifier == EvqInOut); + } + } + else + { + // The function is not user-defined - it is likely built-in texture function. + // Assume that those do not have out parameters. + mInFunctionCallOutParameter = false; + } + } + else if (visit == InVisit) + { + if (inFunctionMap) + { + ++mSeqIterStack.back(); + TQualifier qualifier = (*mSeqIterStack.back())->getAsTyped()->getQualifier(); + mInFunctionCallOutParameter = (qualifier == EvqOut || qualifier == EvqInOut); + } + } + else + { + if (inFunctionMap) + { + mSeqIterStack.pop_back(); + mInFunctionCallOutParameter = false; + } + } + break; + } + default: + TIntermNode *parent = getParentNode(); + if (canRoundFloat(node->getType()) && visit == PreVisit && parentUsesResult(parent, node)) + { + TIntermNode *replacement = createRoundingFunctionCallNode(node); + mReplacements.push_back(NodeUpdateEntry(parent, node, replacement, true)); + } + break; + } + return visitChildren; +} + +bool EmulatePrecision::visitUnary(Visit visit, TIntermUnary *node) +{ + switch (node->getOp()) + { + case EOpNegative: + case EOpVectorLogicalNot: + case EOpLogicalNot: + break; + case EOpPostIncrement: + case EOpPostDecrement: + case EOpPreIncrement: + case EOpPreDecrement: + if (visit == PreVisit) + mInLValue = true; + else if (visit == PostVisit) + mInLValue = false; + break; + default: + if (canRoundFloat(node->getType()) && visit == PreVisit) + { + TIntermNode *parent = getParentNode(); + TIntermNode *replacement = createRoundingFunctionCallNode(node); + mReplacements.push_back(NodeUpdateEntry(parent, node, replacement, true)); + } + break; + } + + return true; +} + +void EmulatePrecision::writeEmulationHelpers(TInfoSinkBase& sink, ShShaderOutput outputLanguage) +{ + // Other languages not yet supported + ASSERT(outputLanguage == SH_GLSL_COMPATIBILITY_OUTPUT || + outputLanguage == SH_GLSL_CORE_OUTPUT || + outputLanguage == SH_ESSL_OUTPUT); + writeCommonPrecisionEmulationHelpers(sink, outputLanguage); + + EmulationSet::const_iterator it; + for (it = mEmulateCompoundAdd.begin(); it != mEmulateCompoundAdd.end(); it++) + writeCompoundAssignmentPrecisionEmulation(sink, outputLanguage, it->lType, it->rType, "+", "add"); + for (it = mEmulateCompoundSub.begin(); it != mEmulateCompoundSub.end(); it++) + writeCompoundAssignmentPrecisionEmulation(sink, outputLanguage, it->lType, it->rType, "-", "sub"); + for (it = mEmulateCompoundDiv.begin(); it != mEmulateCompoundDiv.end(); it++) + writeCompoundAssignmentPrecisionEmulation(sink, outputLanguage, it->lType, it->rType, "/", "div"); + for (it = mEmulateCompoundMul.begin(); it != mEmulateCompoundMul.end(); it++) + writeCompoundAssignmentPrecisionEmulation(sink, outputLanguage, it->lType, it->rType, "*", "mul"); +} + diff --git a/src/3rdparty/angle/src/compiler/translator/EmulatePrecision.h b/src/3rdparty/angle/src/compiler/translator/EmulatePrecision.h new file mode 100644 index 0000000000..f1f560aa85 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/EmulatePrecision.h @@ -0,0 +1,74 @@ +// +// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_TRANSLATOR_EMULATE_PRECISION_H_ +#define COMPILER_TRANSLATOR_EMULATE_PRECISION_H_ + +#include "common/angleutils.h" +#include "compiler/translator/InfoSink.h" +#include "compiler/translator/IntermNode.h" +#include "GLSLANG/ShaderLang.h" + +// This class gathers all compound assignments from the AST and can then write +// the functions required for their precision emulation. This way there is no +// need to write a huge number of variations of the emulated compound assignment +// to every translated shader with emulation enabled. + +class EmulatePrecision : public TIntermTraverser +{ + public: + EmulatePrecision(); + + virtual void visitSymbol(TIntermSymbol *node); + virtual bool visitBinary(Visit visit, TIntermBinary *node); + virtual bool visitUnary(Visit visit, TIntermUnary *node); + virtual bool visitAggregate(Visit visit, TIntermAggregate *node); + + void writeEmulationHelpers(TInfoSinkBase& sink, ShShaderOutput outputLanguage); + + private: + struct TypePair + { + TypePair(const char *l, const char *r) + : lType(l), rType(r) { } + + const char *lType; + const char *rType; + }; + + struct TypePairComparator + { + bool operator() (const TypePair& l, const TypePair& r) const + { + if (l.lType == r.lType) + return l.rType < r.rType; + return l.lType < r.lType; + } + }; + + typedef std::set EmulationSet; + EmulationSet mEmulateCompoundAdd; + EmulationSet mEmulateCompoundSub; + EmulationSet mEmulateCompoundMul; + EmulationSet mEmulateCompoundDiv; + + // Stack of function call parameter iterators + std::vector mSeqIterStack; + + bool mDeclaringVariables; + bool mInLValue; + bool mInFunctionCallOutParameter; + + struct TStringComparator + { + bool operator() (const TString& a, const TString& b) const { return a.compare(b) < 0; } + }; + + // Map from function names to their parameter sequences + std::map mFunctionMap; +}; + +#endif // COMPILER_TRANSLATOR_EMULATE_PRECISION_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/ExtensionBehavior.h b/src/3rdparty/angle/src/compiler/translator/ExtensionBehavior.h index 5c1595fb21..cf4d7fba31 100644 --- a/src/3rdparty/angle/src/compiler/translator/ExtensionBehavior.h +++ b/src/3rdparty/angle/src/compiler/translator/ExtensionBehavior.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef _EXTENSION_BEHAVIOR_INCLUDED_ -#define _EXTENSION_BEHAVIOR_INCLUDED_ +#ifndef COMPILER_TRANSLATOR_EXTENSIONBEHAVIOR_H_ +#define COMPILER_TRANSLATOR_EXTENSIONBEHAVIOR_H_ #include #include @@ -34,4 +34,4 @@ inline const char* getBehaviorString(TBehavior b) // Mapping between extension name and behavior. typedef std::map TExtensionBehavior; -#endif // _EXTENSION_TABLE_INCLUDED_ +#endif // COMPILER_TRANSLATOR_EXTENSIONBEHAVIOR_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/FlagStd140Structs.h b/src/3rdparty/angle/src/compiler/translator/FlagStd140Structs.h index c93a6f808e..07b9a72c5c 100644 --- a/src/3rdparty/angle/src/compiler/translator/FlagStd140Structs.h +++ b/src/3rdparty/angle/src/compiler/translator/FlagStd140Structs.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef COMPILER_FLAGSTD140STRUCTS_H_ -#define COMPILER_FLAGSTD140STRUCTS_H_ +#ifndef COMPILER_TRANSLATOR_FLAGSTD140STRUCTS_H_ +#define COMPILER_TRANSLATOR_FLAGSTD140STRUCTS_H_ #include "compiler/translator/IntermNode.h" @@ -34,4 +34,4 @@ std::vector FlagStd140ValueStructs(TIntermNode *node); } -#endif // COMPILER_FLAGSTD140STRUCTS_H_ +#endif // COMPILER_TRANSLATOR_FLAGSTD140STRUCTS_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/ForLoopUnroll.h b/src/3rdparty/angle/src/compiler/translator/ForLoopUnroll.h index a820d2a20d..c8787d55a0 100644 --- a/src/3rdparty/angle/src/compiler/translator/ForLoopUnroll.h +++ b/src/3rdparty/angle/src/compiler/translator/ForLoopUnroll.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef COMPILER_FORLOOPUNROLL_H_ -#define COMPILER_FORLOOPUNROLL_H_ +#ifndef COMPILER_TRANSLATOR_FORLOOPUNROLL_H_ +#define COMPILER_TRANSLATOR_FORLOOPUNROLL_H_ #include "compiler/translator/LoopInfo.h" @@ -47,4 +47,4 @@ class ForLoopUnrollMarker : public TIntermTraverser bool mVisitSamplerArrayIndexNodeInsideLoop; }; -#endif +#endif // COMPILER_TRANSLATOR_FORLOOPUNROLL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/HashNames.h b/src/3rdparty/angle/src/compiler/translator/HashNames.h index 26546a3e7b..09c959f9da 100644 --- a/src/3rdparty/angle/src/compiler/translator/HashNames.h +++ b/src/3rdparty/angle/src/compiler/translator/HashNames.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef COMPILER_HASH_NAMES_H_ -#define COMPILER_HASH_NAMES_H_ +#ifndef COMPILER_TRANSLATOR_HASHNAMES_H_ +#define COMPILER_TRANSLATOR_HASHNAMES_H_ #include @@ -15,4 +15,4 @@ typedef std::map NameMap; -#endif // COMPILER_HASH_NAMES_H_ +#endif // COMPILER_TRANSLATOR_HASHNAMES_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/InfoSink.h b/src/3rdparty/angle/src/compiler/translator/InfoSink.h index 698a8b454b..f47fafa8ee 100644 --- a/src/3rdparty/angle/src/compiler/translator/InfoSink.h +++ b/src/3rdparty/angle/src/compiler/translator/InfoSink.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef _INFOSINK_INCLUDED_ -#define _INFOSINK_INCLUDED_ +#ifndef COMPILER_TRANSLATOR_INFOSINK_H_ +#define COMPILER_TRANSLATOR_INFOSINK_H_ #include #include @@ -113,4 +113,4 @@ public: TInfoSinkBase obj; }; -#endif // _INFOSINK_INCLUDED_ +#endif // COMPILER_TRANSLATOR_INFOSINK_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/Initialize.cpp b/src/3rdparty/angle/src/compiler/translator/Initialize.cpp index 10b21e6d28..9e11405758 100644 --- a/src/3rdparty/angle/src/compiler/translator/Initialize.cpp +++ b/src/3rdparty/angle/src/compiler/translator/Initialize.cpp @@ -21,307 +21,208 @@ void InsertBuiltInFunctions(sh::GLenum type, ShShaderSpec spec, const ShBuiltInR TType *float2 = new TType(EbtFloat, 2); TType *float3 = new TType(EbtFloat, 3); TType *float4 = new TType(EbtFloat, 4); - TType *int1 = new TType(EbtInt); TType *int2 = new TType(EbtInt, 2); TType *int3 = new TType(EbtInt, 3); - TType *int4 = new TType(EbtInt, 4); + TType *uint1 = new TType(EbtUInt); + TType *bool1 = new TType(EbtBool); + TType *genType = new TType(EbtGenType); + TType *genIType = new TType(EbtGenIType); + TType *genUType = new TType(EbtGenUType); + TType *genBType = new TType(EbtGenBType); // // Angle and Trigonometric Functions. // - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "radians", float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "radians", float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "radians", float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "radians", float4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "degrees", float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "degrees", float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "degrees", float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "degrees", float4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "sin", float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "sin", float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "sin", float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "sin", float4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "cos", float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "cos", float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "cos", float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "cos", float4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "tan", float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "tan", float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "tan", float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "tan", float4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "asin", float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "asin", float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "asin", float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "asin", float4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "acos", float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "acos", float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "acos", float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "acos", float4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "atan", float1, float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "atan", float2, float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "atan", float3, float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "atan", float4, float4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "atan", float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "atan", float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "atan", float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "atan", float4); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpRadians, genType, "radians", genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpDegrees, genType, "degrees", genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpSin, genType, "sin", genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpCos, genType, "cos", genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpTan, genType, "tan", genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpAsin, genType, "asin", genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpAcos, genType, "acos", genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpAtan, genType, "atan", genType, genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpAtan, genType, "atan", genType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpSinh, genType, "sinh", genType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpCosh, genType, "cosh", genType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTanh, genType, "tanh", genType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpAsinh, genType, "asinh", genType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpAcosh, genType, "acosh", genType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpAtanh, genType, "atanh", genType); // // Exponential Functions. // - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "pow", float1, float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "pow", float2, float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "pow", float3, float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "pow", float4, float4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "exp", float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "exp", float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "exp", float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "exp", float4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "log", float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "log", float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "log", float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "log", float4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "exp2", float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "exp2", float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "exp2", float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "exp2", float4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "log2", float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "log2", float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "log2", float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "log2", float4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "sqrt", float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "sqrt", float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "sqrt", float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "sqrt", float4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "inversesqrt", float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "inversesqrt", float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "inversesqrt", float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "inversesqrt", float4); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpPow, genType, "pow", genType, genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpExp, genType, "exp", genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpLog, genType, "log", genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpExp2, genType, "exp2", genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpLog2, genType, "log2", genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpSqrt, genType, "sqrt", genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpInverseSqrt, genType, "inversesqrt", genType); // // Common Functions. // - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "abs", float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "abs", float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "abs", float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "abs", float4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "sign", float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "sign", float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "sign", float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "sign", float4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "floor", float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "floor", float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "floor", float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "floor", float4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "ceil", float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "ceil", float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "ceil", float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "ceil", float4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "fract", float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "fract", float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "fract", float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "fract", float4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "mod", float1, float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "mod", float2, float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "mod", float3, float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "mod", float4, float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "mod", float2, float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "mod", float3, float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "mod", float4, float4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "min", float1, float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "min", float2, float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "min", float3, float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "min", float4, float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "min", float2, float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "min", float3, float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "min", float4, float4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "max", float1, float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "max", float2, float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "max", float3, float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "max", float4, float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "max", float2, float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "max", float3, float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "max", float4, float4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "clamp", float1, float1, float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "clamp", float2, float1, float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "clamp", float3, float1, float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "clamp", float4, float1, float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "clamp", float2, float2, float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "clamp", float3, float3, float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "clamp", float4, float4, float4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "mix", float1, float1, float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "mix", float2, float2, float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "mix", float3, float3, float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "mix", float4, float4, float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "mix", float2, float2, float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "mix", float3, float3, float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "mix", float4, float4, float4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "step", float1, float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "step", float2, float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "step", float3, float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "step", float4, float4); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "step", float1, float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "step", float1, float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "step", float1, float4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "smoothstep", float1, float1, float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "smoothstep", float2, float2, float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "smoothstep", float3, float3, float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "smoothstep", float4, float4, float4); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "smoothstep", float1, float1, float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "smoothstep", float1, float1, float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "smoothstep", float1, float1, float4); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpAbs, genType, "abs", genType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpAbs, genIType, "abs", genIType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpSign, genType, "sign", genType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpSign, genIType, "sign", genIType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpFloor, genType, "floor", genType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTrunc, genType, "trunc", genType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpRound, genType, "round", genType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpRoundEven, genType, "roundEven", genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpCeil, genType, "ceil", genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpFract, genType, "fract", genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMod, genType, "mod", genType, float1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMod, genType, "mod", genType, genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMin, genType, "min", genType, float1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMin, genType, "min", genType, genType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMin, genIType, "min", genIType, genIType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMin, genIType, "min", genIType, int1); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMin, genUType, "min", genUType, genUType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMin, genUType, "min", genUType, uint1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMax, genType, "max", genType, float1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMax, genType, "max", genType, genType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMax, genIType, "max", genIType, genIType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMax, genIType, "max", genIType, int1); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMax, genUType, "max", genUType, genUType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMax, genUType, "max", genUType, uint1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpClamp, genType, "clamp", genType, float1, float1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpClamp, genType, "clamp", genType, genType, genType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpClamp, genIType, "clamp", genIType, int1, int1); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpClamp, genIType, "clamp", genIType, genIType, genIType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpClamp, genUType, "clamp", genUType, uint1, uint1); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpClamp, genUType, "clamp", genUType, genUType, genUType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMix, genType, "mix", genType, genType, float1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMix, genType, "mix", genType, genType, genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpStep, genType, "step", genType, genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpStep, genType, "step", float1, genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpSmoothStep, genType, "smoothstep", genType, genType, genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpSmoothStep, genType, "smoothstep", float1, float1, genType); + + TType *outFloat1 = new TType(EbtFloat); + TType *outFloat2 = new TType(EbtFloat, 2); + TType *outFloat3 = new TType(EbtFloat, 3); + TType *outFloat4 = new TType(EbtFloat, 4); + outFloat1->setQualifier(EvqOut); + outFloat2->setQualifier(EvqOut); + outFloat3->setQualifier(EvqOut); + outFloat4->setQualifier(EvqOut); + + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpModf, float1, "modf", float1, outFloat1); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpModf, float2, "modf", float2, outFloat2); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpModf, float3, "modf", float3, outFloat3); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpModf, float4, "modf", float4, outFloat4); + + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpIsNan, genBType, "isnan", genType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpIsInf, genBType, "isinf", genType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpFloatBitsToInt, genIType, "floatBitsToInt", genType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpFloatBitsToUint, genUType, "floatBitsToUint", genType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpIntBitsToFloat, genType, "intBitsToFloat", genIType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpUintBitsToFloat, genType, "uintBitsToFloat", genUType); + + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpPackSnorm2x16, uint1, "packSnorm2x16", float2); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpPackUnorm2x16, uint1, "packUnorm2x16", float2); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpPackHalf2x16, uint1, "packHalf2x16", float2); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpUnpackSnorm2x16, float2, "unpackSnorm2x16", uint1); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpUnpackUnorm2x16, float2, "unpackUnorm2x16", uint1); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpUnpackHalf2x16, float2, "unpackHalf2x16", uint1); // // Geometric Functions. // - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "length", float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "length", float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "length", float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "length", float4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "distance", float1, float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "distance", float2, float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "distance", float3, float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "distance", float4, float4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "dot", float1, float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "dot", float2, float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "dot", float3, float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "dot", float4, float4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "cross", float3, float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "normalize", float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "normalize", float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "normalize", float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "normalize", float4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "faceforward", float1, float1, float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "faceforward", float2, float2, float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "faceforward", float3, float3, float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "faceforward", float4, float4, float4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "reflect", float1, float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "reflect", float2, float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "reflect", float3, float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "reflect", float4, float4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "refract", float1, float1, float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "refract", float2, float2, float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "refract", float3, float3, float1); - symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "refract", float4, float4, float1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpLength, float1, "length", genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpDistance, float1, "distance", genType, genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpDot, float1, "dot", genType, genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpCross, float3, "cross", float3, float3); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpNormalize, genType, "normalize", genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpFaceForward, genType, "faceforward", genType, genType, genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpReflect, genType, "reflect", genType, genType); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpRefract, genType, "refract", genType, genType, float1); TType *mat2 = new TType(EbtFloat, 2, 2); TType *mat3 = new TType(EbtFloat, 3, 3); TType *mat4 = new TType(EbtFloat, 4, 4); + TType *mat2x3 = new TType(EbtFloat, 2, 3); + TType *mat3x2 = new TType(EbtFloat, 3, 2); + TType *mat2x4 = new TType(EbtFloat, 2, 4); + TType *mat4x2 = new TType(EbtFloat, 4, 2); + TType *mat3x4 = new TType(EbtFloat, 3, 4); + TType *mat4x3 = new TType(EbtFloat, 4, 3); // // Matrix Functions. // - symbolTable.insertBuiltIn(COMMON_BUILTINS, mat2, "matrixCompMult", mat2, mat2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, mat3, "matrixCompMult", mat3, mat3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, mat4, "matrixCompMult", mat4, mat4); - - TType *bool1 = new TType(EbtBool); - TType *bool2 = new TType(EbtBool, 2); - TType *bool3 = new TType(EbtBool, 3); - TType *bool4 = new TType(EbtBool, 4); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMul, mat2, "matrixCompMult", mat2, mat2); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMul, mat3, "matrixCompMult", mat3, mat3); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMul, mat4, "matrixCompMult", mat4, mat4); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMul, mat2x3, "matrixCompMult", mat2x3, mat2x3); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMul, mat3x2, "matrixCompMult", mat3x2, mat3x2); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMul, mat2x4, "matrixCompMult", mat2x4, mat2x4); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMul, mat4x2, "matrixCompMult", mat4x2, mat4x2); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMul, mat3x4, "matrixCompMult", mat3x4, mat3x4); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMul, mat4x3, "matrixCompMult", mat4x3, mat4x3); + + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpOuterProduct, mat2, "outerProduct", float2, float2); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpOuterProduct, mat3, "outerProduct", float3, float3); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpOuterProduct, mat4, "outerProduct", float4, float4); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpOuterProduct, mat2x3, "outerProduct", float3, float2); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpOuterProduct, mat3x2, "outerProduct", float2, float3); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpOuterProduct, mat2x4, "outerProduct", float4, float2); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpOuterProduct, mat4x2, "outerProduct", float2, float4); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpOuterProduct, mat3x4, "outerProduct", float4, float3); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpOuterProduct, mat4x3, "outerProduct", float3, float4); + + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTranspose, mat2, "transpose", mat2); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTranspose, mat3, "transpose", mat3); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTranspose, mat4, "transpose", mat4); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTranspose, mat2x3, "transpose", mat3x2); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTranspose, mat3x2, "transpose", mat2x3); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTranspose, mat2x4, "transpose", mat4x2); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTranspose, mat4x2, "transpose", mat2x4); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTranspose, mat3x4, "transpose", mat4x3); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTranspose, mat4x3, "transpose", mat3x4); + + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpDeterminant, float1, "determinant", mat2); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpDeterminant, float1, "determinant", mat3); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpDeterminant, float1, "determinant", mat4); + + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpInverse, mat2, "inverse", mat2); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpInverse, mat3, "inverse", mat3); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpInverse, mat4, "inverse", mat4); + + TType *vec = new TType(EbtVec); + TType *ivec = new TType(EbtIVec); + TType *uvec = new TType(EbtUVec); + TType *bvec = new TType(EbtBVec); // // Vector relational functions. // - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "lessThan", float2, float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "lessThan", float3, float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "lessThan", float4, float4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "lessThan", int2, int2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "lessThan", int3, int3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "lessThan", int4, int4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "lessThanEqual", float2, float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "lessThanEqual", float3, float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "lessThanEqual", float4, float4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "lessThanEqual", int2, int2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "lessThanEqual", int3, int3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "lessThanEqual", int4, int4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "greaterThan", float2, float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "greaterThan", float3, float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "greaterThan", float4, float4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "greaterThan", int2, int2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "greaterThan", int3, int3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "greaterThan", int4, int4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "greaterThanEqual", float2, float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "greaterThanEqual", float3, float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "greaterThanEqual", float4, float4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "greaterThanEqual", int2, int2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "greaterThanEqual", int3, int3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "greaterThanEqual", int4, int4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "equal", float2, float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "equal", float3, float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "equal", float4, float4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "equal", int2, int2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "equal", int3, int3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "equal", int4, int4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "equal", bool2, bool2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "equal", bool3, bool3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "equal", bool4, bool4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "notEqual", float2, float2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "notEqual", float3, float3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "notEqual", float4, float4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "notEqual", int2, int2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "notEqual", int3, int3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "notEqual", int4, int4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "notEqual", bool2, bool2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "notEqual", bool3, bool3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "notEqual", bool4, bool4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool1, "any", bool2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool1, "any", bool3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool1, "any", bool4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool1, "all", bool2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool1, "all", bool3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool1, "all", bool4); - - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "not", bool2); - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "not", bool3); - symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "not", bool4); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpLessThan, bvec, "lessThan", vec, vec); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpLessThan, bvec, "lessThan", ivec, ivec); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpLessThan, bvec, "lessThan", uvec, uvec); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpLessThanEqual, bvec, "lessThanEqual", vec, vec); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpLessThanEqual, bvec, "lessThanEqual", ivec, ivec); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpLessThanEqual, bvec, "lessThanEqual", uvec, uvec); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpGreaterThan, bvec, "greaterThan", vec, vec); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpGreaterThan, bvec, "greaterThan", ivec, ivec); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpGreaterThan, bvec, "greaterThan", uvec, uvec); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpGreaterThanEqual, bvec, "greaterThanEqual", vec, vec); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpGreaterThanEqual, bvec, "greaterThanEqual", ivec, ivec); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpGreaterThanEqual, bvec, "greaterThanEqual", uvec, uvec); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpVectorEqual, bvec, "equal", vec, vec); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpVectorEqual, bvec, "equal", ivec, ivec); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpVectorEqual, bvec, "equal", uvec, uvec); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpVectorEqual, bvec, "equal", bvec, bvec); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpVectorNotEqual, bvec, "notEqual", vec, vec); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpVectorNotEqual, bvec, "notEqual", ivec, ivec); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpVectorNotEqual, bvec, "notEqual", uvec, uvec); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpVectorNotEqual, bvec, "notEqual", bvec, bvec); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpAny, bool1, "any", bvec); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpAll, bool1, "all", bvec); + symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpVectorLogicalNot, bvec, "not", bvec); TType *sampler2D = new TType(EbtSampler2D); TType *samplerCube = new TType(EbtSamplerCube); @@ -357,10 +258,10 @@ void InsertBuiltInFunctions(sh::GLenum type, ShShaderSpec spec, const ShBuiltInR /* The *Grad* variants are new to both vertex and fragment shaders; the fragment * shader specific pieces are added separately below. */ - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DGradEXT", sampler2D, float2, float2, float2); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProjGradEXT", sampler2D, float3, float2, float2); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProjGradEXT", sampler2D, float4, float2, float2); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "textureCubeGradEXT", samplerCube, float3, float3, float3); + symbolTable.insertBuiltIn(ESSL1_BUILTINS, "GL_EXT_shader_texture_lod", float4, "texture2DGradEXT", sampler2D, float2, float2, float2); + symbolTable.insertBuiltIn(ESSL1_BUILTINS, "GL_EXT_shader_texture_lod", float4, "texture2DProjGradEXT", sampler2D, float3, float2, float2); + symbolTable.insertBuiltIn(ESSL1_BUILTINS, "GL_EXT_shader_texture_lod", float4, "texture2DProjGradEXT", sampler2D, float4, float2, float2); + symbolTable.insertBuiltIn(ESSL1_BUILTINS, "GL_EXT_shader_texture_lod", float4, "textureCubeGradEXT", samplerCube, float3, float3, float3); } if (type == GL_FRAGMENT_SHADER) @@ -372,32 +273,21 @@ void InsertBuiltInFunctions(sh::GLenum type, ShShaderSpec spec, const ShBuiltInR if (resources.OES_standard_derivatives) { - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float1, "dFdx", float1); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float2, "dFdx", float2); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float3, "dFdx", float3); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "dFdx", float4); - - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float1, "dFdy", float1); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float2, "dFdy", float2); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float3, "dFdy", float3); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "dFdy", float4); - - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float1, "fwidth", float1); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float2, "fwidth", float2); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float3, "fwidth", float3); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "fwidth", float4); + symbolTable.insertBuiltIn(ESSL1_BUILTINS, EOpDFdx, "GL_OES_standard_derivatives", genType, "dFdx", genType); + symbolTable.insertBuiltIn(ESSL1_BUILTINS, EOpDFdy, "GL_OES_standard_derivatives", genType, "dFdy", genType); + symbolTable.insertBuiltIn(ESSL1_BUILTINS, EOpFwidth, "GL_OES_standard_derivatives", genType, "fwidth", genType); } if (resources.EXT_shader_texture_lod) { - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DLodEXT", sampler2D, float2, float1); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProjLodEXT", sampler2D, float3, float1); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProjLodEXT", sampler2D, float4, float1); - symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "textureCubeLodEXT", samplerCube, float3, float1); + symbolTable.insertBuiltIn(ESSL1_BUILTINS, "GL_EXT_shader_texture_lod", float4, "texture2DLodEXT", sampler2D, float2, float1); + symbolTable.insertBuiltIn(ESSL1_BUILTINS, "GL_EXT_shader_texture_lod", float4, "texture2DProjLodEXT", sampler2D, float3, float1); + symbolTable.insertBuiltIn(ESSL1_BUILTINS, "GL_EXT_shader_texture_lod", float4, "texture2DProjLodEXT", sampler2D, float4, float1); + symbolTable.insertBuiltIn(ESSL1_BUILTINS, "GL_EXT_shader_texture_lod", float4, "textureCubeLodEXT", samplerCube, float3, float1); } } - if(type == GL_VERTEX_SHADER) + if (type == GL_VERTEX_SHADER) { symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DLod", sampler2D, float2, float1); symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProjLod", sampler2D, float3, float1); @@ -463,22 +353,11 @@ void InsertBuiltInFunctions(sh::GLenum type, ShShaderSpec spec, const ShBuiltInR symbolTable.insertBuiltIn(ESSL3_BUILTINS, int2, "textureSize", samplerCubeShadow, int1); symbolTable.insertBuiltIn(ESSL3_BUILTINS, int3, "textureSize", sampler2DArrayShadow, int1); - if(type == GL_FRAGMENT_SHADER) + if (type == GL_FRAGMENT_SHADER) { - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "dFdx", float1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float2, "dFdx", float2); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float3, "dFdx", float3); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float4, "dFdx", float4); - - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "dFdy", float1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float2, "dFdy", float2); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float3, "dFdy", float3); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float4, "dFdy", float4); - - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "fwidth", float1); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float2, "fwidth", float2); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float3, "fwidth", float3); - symbolTable.insertBuiltIn(ESSL3_BUILTINS, float4, "fwidth", float4); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpDFdx, genType, "dFdx", genType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpDFdy, genType, "dFdy", genType); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpFwidth, genType, "fwidth", genType); } symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureOffset", gsampler2D, float2, int2); @@ -486,7 +365,7 @@ void InsertBuiltInFunctions(sh::GLenum type, ShShaderSpec spec, const ShBuiltInR symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureOffset", sampler2DShadow, float3, int2); symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureOffset", gsampler2DArray, float3, int2); - if(type == GL_FRAGMENT_SHADER) + if (type == GL_FRAGMENT_SHADER) { symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureOffset", gsampler2D, float2, int2, float1); symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureOffset", gsampler3D, float3, int3, float1); @@ -499,7 +378,7 @@ void InsertBuiltInFunctions(sh::GLenum type, ShShaderSpec spec, const ShBuiltInR symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjOffset", gsampler3D, float4, int3); symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureProjOffset", sampler2DShadow, float4, int2); - if(type == GL_FRAGMENT_SHADER) + if (type == GL_FRAGMENT_SHADER) { symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjOffset", gsampler2D, float3, int2, float1); symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjOffset", gsampler2D, float4, int2, float1); @@ -600,146 +479,84 @@ void IdentifyBuiltIns(sh::GLenum type, ShShaderSpec spec, TSymbolTable &symbolTable) { // - // First, insert some special built-in variables that are not in + // Insert some special built-in variables that are not in // the built-in header files. // - switch(type) { - case GL_FRAGMENT_SHADER: - symbolTable.insert(COMMON_BUILTINS, new TVariable(NewPoolTString("gl_FragCoord"), TType(EbtFloat, EbpMedium, EvqFragCoord, 4))); - symbolTable.insert(COMMON_BUILTINS, new TVariable(NewPoolTString("gl_FrontFacing"), TType(EbtBool, EbpUndefined, EvqFrontFacing, 1))); - symbolTable.insert(COMMON_BUILTINS, new TVariable(NewPoolTString("gl_PointCoord"), TType(EbtFloat, EbpMedium, EvqPointCoord, 2))); + switch (type) + { + case GL_FRAGMENT_SHADER: + symbolTable.insert(COMMON_BUILTINS, new TVariable(NewPoolTString("gl_FragCoord"), + TType(EbtFloat, EbpMedium, EvqFragCoord, 4))); + symbolTable.insert(COMMON_BUILTINS, new TVariable(NewPoolTString("gl_FrontFacing"), + TType(EbtBool, EbpUndefined, EvqFrontFacing, 1))); + symbolTable.insert(COMMON_BUILTINS, new TVariable(NewPoolTString("gl_PointCoord"), + TType(EbtFloat, EbpMedium, EvqPointCoord, 2))); // // In CSS Shaders, gl_FragColor, gl_FragData, and gl_MaxDrawBuffers are not available. // Instead, css_MixColor and css_ColorMatrix are available. // - if (spec != SH_CSS_SHADERS_SPEC) { - symbolTable.insert(ESSL1_BUILTINS, new TVariable(NewPoolTString("gl_FragColor"), TType(EbtFloat, EbpMedium, EvqFragColor, 4))); - symbolTable.insert(ESSL1_BUILTINS, new TVariable(NewPoolTString("gl_FragData[gl_MaxDrawBuffers]"), TType(EbtFloat, EbpMedium, EvqFragData, 4))); - if (resources.EXT_frag_depth) { - symbolTable.insert(ESSL1_BUILTINS, new TVariable(NewPoolTString("gl_FragDepthEXT"), TType(EbtFloat, resources.FragmentPrecisionHigh ? EbpHigh : EbpMedium, EvqFragDepth, 1))); - symbolTable.relateToExtension(ESSL1_BUILTINS, "gl_FragDepthEXT", "GL_EXT_frag_depth"); - } - } else { - symbolTable.insert(ESSL1_BUILTINS, new TVariable(NewPoolTString("css_MixColor"), TType(EbtFloat, EbpMedium, EvqGlobal, 4))); - symbolTable.insert(ESSL1_BUILTINS, new TVariable(NewPoolTString("css_ColorMatrix"), TType(EbtFloat, EbpMedium, EvqGlobal, 4, 4))); - } - - break; - - case GL_VERTEX_SHADER: - symbolTable.insert(COMMON_BUILTINS, new TVariable(NewPoolTString("gl_Position"), TType(EbtFloat, EbpHigh, EvqPosition, 4))); - symbolTable.insert(COMMON_BUILTINS, new TVariable(NewPoolTString("gl_PointSize"), TType(EbtFloat, EbpMedium, EvqPointSize, 1))); - break; - - default: assert(false && "Language not supported"); - } - - // - // Next, identify which built-ins from the already loaded headers have - // a mapping to an operator. Those that are not identified as such are - // expected to be resolved through a library of functions, versus as - // operations. - // - symbolTable.relateToOperator(COMMON_BUILTINS, "matrixCompMult", EOpMul); - - symbolTable.relateToOperator(COMMON_BUILTINS, "equal", EOpVectorEqual); - symbolTable.relateToOperator(COMMON_BUILTINS, "notEqual", EOpVectorNotEqual); - symbolTable.relateToOperator(COMMON_BUILTINS, "lessThan", EOpLessThan); - symbolTable.relateToOperator(COMMON_BUILTINS, "greaterThan", EOpGreaterThan); - symbolTable.relateToOperator(COMMON_BUILTINS, "lessThanEqual", EOpLessThanEqual); - symbolTable.relateToOperator(COMMON_BUILTINS, "greaterThanEqual", EOpGreaterThanEqual); - - symbolTable.relateToOperator(COMMON_BUILTINS, "radians", EOpRadians); - symbolTable.relateToOperator(COMMON_BUILTINS, "degrees", EOpDegrees); - symbolTable.relateToOperator(COMMON_BUILTINS, "sin", EOpSin); - symbolTable.relateToOperator(COMMON_BUILTINS, "cos", EOpCos); - symbolTable.relateToOperator(COMMON_BUILTINS, "tan", EOpTan); - symbolTable.relateToOperator(COMMON_BUILTINS, "asin", EOpAsin); - symbolTable.relateToOperator(COMMON_BUILTINS, "acos", EOpAcos); - symbolTable.relateToOperator(COMMON_BUILTINS, "atan", EOpAtan); - - symbolTable.relateToOperator(COMMON_BUILTINS, "pow", EOpPow); - symbolTable.relateToOperator(COMMON_BUILTINS, "exp2", EOpExp2); - symbolTable.relateToOperator(COMMON_BUILTINS, "log", EOpLog); - symbolTable.relateToOperator(COMMON_BUILTINS, "exp", EOpExp); - symbolTable.relateToOperator(COMMON_BUILTINS, "log2", EOpLog2); - symbolTable.relateToOperator(COMMON_BUILTINS, "sqrt", EOpSqrt); - symbolTable.relateToOperator(COMMON_BUILTINS, "inversesqrt", EOpInverseSqrt); - - symbolTable.relateToOperator(COMMON_BUILTINS, "abs", EOpAbs); - symbolTable.relateToOperator(COMMON_BUILTINS, "sign", EOpSign); - symbolTable.relateToOperator(COMMON_BUILTINS, "floor", EOpFloor); - symbolTable.relateToOperator(COMMON_BUILTINS, "ceil", EOpCeil); - symbolTable.relateToOperator(COMMON_BUILTINS, "fract", EOpFract); - symbolTable.relateToOperator(COMMON_BUILTINS, "mod", EOpMod); - symbolTable.relateToOperator(COMMON_BUILTINS, "min", EOpMin); - symbolTable.relateToOperator(COMMON_BUILTINS, "max", EOpMax); - symbolTable.relateToOperator(COMMON_BUILTINS, "clamp", EOpClamp); - symbolTable.relateToOperator(COMMON_BUILTINS, "mix", EOpMix); - symbolTable.relateToOperator(COMMON_BUILTINS, "step", EOpStep); - symbolTable.relateToOperator(COMMON_BUILTINS, "smoothstep", EOpSmoothStep); - - symbolTable.relateToOperator(COMMON_BUILTINS, "length", EOpLength); - symbolTable.relateToOperator(COMMON_BUILTINS, "distance", EOpDistance); - symbolTable.relateToOperator(COMMON_BUILTINS, "dot", EOpDot); - symbolTable.relateToOperator(COMMON_BUILTINS, "cross", EOpCross); - symbolTable.relateToOperator(COMMON_BUILTINS, "normalize", EOpNormalize); - symbolTable.relateToOperator(COMMON_BUILTINS, "faceforward", EOpFaceForward); - symbolTable.relateToOperator(COMMON_BUILTINS, "reflect", EOpReflect); - symbolTable.relateToOperator(COMMON_BUILTINS, "refract", EOpRefract); - - symbolTable.relateToOperator(COMMON_BUILTINS, "any", EOpAny); - symbolTable.relateToOperator(COMMON_BUILTINS, "all", EOpAll); - symbolTable.relateToOperator(COMMON_BUILTINS, "not", EOpVectorLogicalNot); - - // Map language-specific operators. - switch(type) { - case GL_VERTEX_SHADER: - break; - case GL_FRAGMENT_SHADER: - if (resources.OES_standard_derivatives) + if (spec != SH_CSS_SHADERS_SPEC) { - symbolTable.relateToOperator(ESSL1_BUILTINS, "dFdx", EOpDFdx); - symbolTable.relateToOperator(ESSL1_BUILTINS, "dFdy", EOpDFdy); - symbolTable.relateToOperator(ESSL1_BUILTINS, "fwidth", EOpFwidth); + symbolTable.insert(ESSL1_BUILTINS, new TVariable(NewPoolTString("gl_FragColor"), + TType(EbtFloat, EbpMedium, EvqFragColor, 4))); + TType fragData(EbtFloat, EbpMedium, EvqFragData, 4, 1, true); + fragData.setArraySize(resources.MaxDrawBuffers); + symbolTable.insert(ESSL1_BUILTINS, new TVariable(NewPoolTString("gl_FragData"), fragData)); + + if (resources.EXT_frag_depth) + { + symbolTable.insert(ESSL1_BUILTINS, "GL_EXT_frag_depth", new TVariable(NewPoolTString("gl_FragDepthEXT"), + TType(EbtFloat, resources.FragmentPrecisionHigh ? EbpHigh : EbpMedium, EvqFragDepth, 1))); + } - symbolTable.relateToExtension(ESSL1_BUILTINS, "dFdx", "GL_OES_standard_derivatives"); - symbolTable.relateToExtension(ESSL1_BUILTINS, "dFdy", "GL_OES_standard_derivatives"); - symbolTable.relateToExtension(ESSL1_BUILTINS, "fwidth", "GL_OES_standard_derivatives"); + if (resources.EXT_shader_framebuffer_fetch || resources.NV_shader_framebuffer_fetch) + { + TType lastFragData(EbtFloat, EbpMedium, EvqLastFragData, 4, 1, true); + lastFragData.setArraySize(resources.MaxDrawBuffers); + + if (resources.EXT_shader_framebuffer_fetch) + { + symbolTable.insert(ESSL1_BUILTINS, "GL_EXT_shader_framebuffer_fetch", + new TVariable(NewPoolTString("gl_LastFragData"), lastFragData)); + } + else if (resources.NV_shader_framebuffer_fetch) + { + symbolTable.insert(ESSL1_BUILTINS, "GL_NV_shader_framebuffer_fetch", + new TVariable(NewPoolTString("gl_LastFragColor"), + TType(EbtFloat, EbpMedium, EvqLastFragColor, 4))); + symbolTable.insert(ESSL1_BUILTINS, "GL_NV_shader_framebuffer_fetch", + new TVariable(NewPoolTString("gl_LastFragData"), lastFragData)); + } + } + else if (resources.ARM_shader_framebuffer_fetch) + { + symbolTable.insert(ESSL1_BUILTINS, "GL_ARM_shader_framebuffer_fetch", + new TVariable(NewPoolTString("gl_LastFragColorARM"), + TType(EbtFloat, EbpMedium, EvqLastFragColor, 4))); + } } - if (resources.EXT_shader_texture_lod) + else { - symbolTable.relateToExtension(ESSL1_BUILTINS, "texture2DLodEXT", "GL_EXT_shader_texture_lod"); - symbolTable.relateToExtension(ESSL1_BUILTINS, "texture2DProjLodEXT", "GL_EXT_shader_texture_lod"); - symbolTable.relateToExtension(ESSL1_BUILTINS, "textureCubeLodEXT", "GL_EXT_shader_texture_lod"); + symbolTable.insert(ESSL1_BUILTINS, new TVariable(NewPoolTString("css_MixColor"), + TType(EbtFloat, EbpMedium, EvqGlobal, 4))); + symbolTable.insert(ESSL1_BUILTINS, new TVariable(NewPoolTString("css_ColorMatrix"), + TType(EbtFloat, EbpMedium, EvqGlobal, 4, 4))); } - break; - default: break; - } - symbolTable.relateToOperator(ESSL3_BUILTINS, "dFdx", EOpDFdx); - symbolTable.relateToOperator(ESSL3_BUILTINS, "dFdy", EOpDFdy); - symbolTable.relateToOperator(ESSL3_BUILTINS, "fwidth", EOpFwidth); - - if (resources.EXT_shader_texture_lod) - { - symbolTable.relateToExtension(ESSL1_BUILTINS, "texture2DGradEXT", "GL_EXT_shader_texture_lod"); - symbolTable.relateToExtension(ESSL1_BUILTINS, "texture2DProjGradEXT", "GL_EXT_shader_texture_lod"); - symbolTable.relateToExtension(ESSL1_BUILTINS, "textureCubeGradEXT", "GL_EXT_shader_texture_lod"); - } + break; - // Finally add resource-specific variables. - switch(type) { - case GL_FRAGMENT_SHADER: - if (spec != SH_CSS_SHADERS_SPEC) { - // Set up gl_FragData. The array size. - TType fragData(EbtFloat, EbpMedium, EvqFragData, 4, 1, true); - fragData.setArraySize(resources.MaxDrawBuffers); - symbolTable.insert(ESSL1_BUILTINS, new TVariable(NewPoolTString("gl_FragData"), fragData)); - } + case GL_VERTEX_SHADER: + symbolTable.insert(COMMON_BUILTINS, new TVariable(NewPoolTString("gl_Position"), + TType(EbtFloat, EbpHigh, EvqPosition, 4))); + symbolTable.insert(COMMON_BUILTINS, new TVariable(NewPoolTString("gl_PointSize"), + TType(EbtFloat, EbpMedium, EvqPointSize, 1))); + symbolTable.insert(ESSL3_BUILTINS, new TVariable(NewPoolTString("gl_InstanceID"), + TType(EbtInt, EbpHigh, EvqInstanceID, 1))); break; - default: break; + + default: + assert(false && "Language not supported"); } } @@ -758,4 +575,20 @@ void InitExtensionBehavior(const ShBuiltInResources& resources, extBehavior["GL_EXT_frag_depth"] = EBhUndefined; if (resources.EXT_shader_texture_lod) extBehavior["GL_EXT_shader_texture_lod"] = EBhUndefined; + if (resources.EXT_shader_framebuffer_fetch) + extBehavior["GL_EXT_shader_framebuffer_fetch"] = EBhUndefined; + if (resources.NV_shader_framebuffer_fetch) + extBehavior["GL_NV_shader_framebuffer_fetch"] = EBhUndefined; + if (resources.ARM_shader_framebuffer_fetch) + extBehavior["GL_ARM_shader_framebuffer_fetch"] = EBhUndefined; +} + +void ResetExtensionBehavior(TExtensionBehavior &extBehavior) +{ + for (auto ext_iter = extBehavior.begin(); + ext_iter != extBehavior.end(); + ++ext_iter) + { + ext_iter->second = EBhUndefined; + } } diff --git a/src/3rdparty/angle/src/compiler/translator/Initialize.h b/src/3rdparty/angle/src/compiler/translator/Initialize.h index cc1862c90e..c43ce3417a 100644 --- a/src/3rdparty/angle/src/compiler/translator/Initialize.h +++ b/src/3rdparty/angle/src/compiler/translator/Initialize.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef _INITIALIZE_INCLUDED_ -#define _INITIALIZE_INCLUDED_ +#ifndef COMPILER_TRANSLATOR_INITIALIZE_H_ +#define COMPILER_TRANSLATOR_INITIALIZE_H_ #include "compiler/translator/Common.h" #include "compiler/translator/Compiler.h" @@ -20,4 +20,10 @@ void IdentifyBuiltIns(sh::GLenum type, ShShaderSpec spec, void InitExtensionBehavior(const ShBuiltInResources& resources, TExtensionBehavior& extensionBehavior); -#endif // _INITIALIZE_INCLUDED_ +// Resets the behavior of the extensions listed in |extensionBehavior| to the +// undefined state. These extensions will only be those initially supported in +// the ShBuiltInResources object for this compiler instance. All other +// extensions will remain unsupported. +void ResetExtensionBehavior(TExtensionBehavior &extensionBehavior); + +#endif // COMPILER_TRANSLATOR_INITIALIZE_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/InitializeDll.h b/src/3rdparty/angle/src/compiler/translator/InitializeDll.h index 43070cc3ff..4c400760f6 100644 --- a/src/3rdparty/angle/src/compiler/translator/InitializeDll.h +++ b/src/3rdparty/angle/src/compiler/translator/InitializeDll.h @@ -3,11 +3,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // -#ifndef __INITIALIZEDLL_H -#define __INITIALIZEDLL_H +#ifndef COMPILER_TRANSLATOR_INITIALIZEDLL_H_ +#define COMPILER_TRANSLATOR_INITIALIZEDLL_H_ bool InitProcess(); void DetachProcess(); -#endif // __INITIALIZEDLL_H +#endif // COMPILER_TRANSLATOR_INITIALIZEDLL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/InitializeGlobals.h b/src/3rdparty/angle/src/compiler/translator/InitializeGlobals.h index 0715941424..8c65cb28da 100644 --- a/src/3rdparty/angle/src/compiler/translator/InitializeGlobals.h +++ b/src/3rdparty/angle/src/compiler/translator/InitializeGlobals.h @@ -4,10 +4,10 @@ // found in the LICENSE file. // -#ifndef __INITIALIZE_GLOBALS_INCLUDED_ -#define __INITIALIZE_GLOBALS_INCLUDED_ +#ifndef COMPILER_TRANSLATOR_INITIALIZEGLOBALS_H_ +#define COMPILER_TRANSLATOR_INITIALIZEGLOBALS_H_ bool InitializePoolIndex(); void FreePoolIndex(); -#endif // __INITIALIZE_GLOBALS_INCLUDED_ +#endif // COMPILER_TRANSLATOR_INITIALIZEGLOBALS_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/InitializeParseContext.h b/src/3rdparty/angle/src/compiler/translator/InitializeParseContext.h index bffbab87d0..fa9b885e80 100644 --- a/src/3rdparty/angle/src/compiler/translator/InitializeParseContext.h +++ b/src/3rdparty/angle/src/compiler/translator/InitializeParseContext.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef __INITIALIZE_PARSE_CONTEXT_INCLUDED_ -#define __INITIALIZE_PARSE_CONTEXT_INCLUDED_ +#ifndef COMPILER_TRANSLATOR_INITIALIZEPARSECONTEXT_H_ +#define COMPILER_TRANSLATOR_INITIALIZEPARSECONTEXT_H_ bool InitializeParseContextIndex(); void FreeParseContextIndex(); @@ -14,4 +14,4 @@ struct TParseContext; extern void SetGlobalParseContext(TParseContext* context); extern TParseContext* GetGlobalParseContext(); -#endif // __INITIALIZE_PARSE_CONTEXT_INCLUDED_ +#endif // COMPILER_TRANSLATOR_INITIALIZEPARSECONTEXT_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/InitializeVariables.h b/src/3rdparty/angle/src/compiler/translator/InitializeVariables.h index 59c3ea0a39..4a81266498 100644 --- a/src/3rdparty/angle/src/compiler/translator/InitializeVariables.h +++ b/src/3rdparty/angle/src/compiler/translator/InitializeVariables.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef COMPILER_INITIALIZE_VARIABLES_H_ -#define COMPILER_INITIALIZE_VARIABLES_H_ +#ifndef COMPILER_TRANSLATOR_INITIALIZEVARIABLES_H_ +#define COMPILER_TRANSLATOR_INITIALIZEVARIABLES_H_ #include "compiler/translator/IntermNode.h" @@ -47,4 +47,4 @@ class InitializeVariables : public TIntermTraverser bool mCodeInserted; }; -#endif // COMPILER_INITIALIZE_VARIABLES_H_ +#endif // COMPILER_TRANSLATOR_INITIALIZEVARIABLES_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/IntermNode.cpp b/src/3rdparty/angle/src/compiler/translator/IntermNode.cpp index aa0f31d170..266e3c8e3d 100644 --- a/src/3rdparty/angle/src/compiler/translator/IntermNode.cpp +++ b/src/3rdparty/angle/src/compiler/translator/IntermNode.cpp @@ -157,26 +157,6 @@ bool TIntermLoop::replaceChildNode( return false; } -void TIntermLoop::enqueueChildren(std::queue *nodeQueue) const -{ - if (mInit) - { - nodeQueue->push(mInit); - } - if (mCond) - { - nodeQueue->push(mCond); - } - if (mExpr) - { - nodeQueue->push(mExpr); - } - if (mBody) - { - nodeQueue->push(mBody); - } -} - bool TIntermBranch::replaceChildNode( TIntermNode *original, TIntermNode *replacement) { @@ -184,14 +164,6 @@ bool TIntermBranch::replaceChildNode( return false; } -void TIntermBranch::enqueueChildren(std::queue *nodeQueue) const -{ - if (mExpression) - { - nodeQueue->push(mExpression); - } -} - bool TIntermBinary::replaceChildNode( TIntermNode *original, TIntermNode *replacement) { @@ -200,18 +172,6 @@ bool TIntermBinary::replaceChildNode( return false; } -void TIntermBinary::enqueueChildren(std::queue *nodeQueue) const -{ - if (mLeft) - { - nodeQueue->push(mLeft); - } - if (mRight) - { - nodeQueue->push(mRight); - } -} - bool TIntermUnary::replaceChildNode( TIntermNode *original, TIntermNode *replacement) { @@ -219,14 +179,6 @@ bool TIntermUnary::replaceChildNode( return false; } -void TIntermUnary::enqueueChildren(std::queue *nodeQueue) const -{ - if (mOperand) - { - nodeQueue->push(mOperand); - } -} - bool TIntermAggregate::replaceChildNode( TIntermNode *original, TIntermNode *replacement) { @@ -237,14 +189,6 @@ bool TIntermAggregate::replaceChildNode( return false; } -void TIntermAggregate::enqueueChildren(std::queue *nodeQueue) const -{ - for (size_t childIndex = 0; childIndex < mSequence.size(); childIndex++) - { - nodeQueue->push(mSequence[childIndex]); - } -} - void TIntermAggregate::setPrecisionFromChildren() { if (getBasicType() == EbtBool) @@ -300,20 +244,19 @@ bool TIntermSelection::replaceChildNode( return false; } -void TIntermSelection::enqueueChildren(std::queue *nodeQueue) const +bool TIntermSwitch::replaceChildNode( + TIntermNode *original, TIntermNode *replacement) { - if (mCondition) - { - nodeQueue->push(mCondition); - } - if (mTrueBlock) - { - nodeQueue->push(mTrueBlock); - } - if (mFalseBlock) - { - nodeQueue->push(mFalseBlock); - } + REPLACE_IF_IS(mInit, TIntermTyped, original, replacement); + REPLACE_IF_IS(mStatementList, TIntermAggregate, original, replacement); + return false; +} + +bool TIntermCase::replaceChildNode( + TIntermNode *original, TIntermNode *replacement) +{ + REPLACE_IF_IS(mCondition, TIntermTyped, original, replacement); + return false; } // @@ -336,6 +279,12 @@ bool TIntermOperator::isAssignment() const case EOpMatrixTimesScalarAssign: case EOpMatrixTimesMatrixAssign: case EOpDivAssign: + case EOpIModAssign: + case EOpBitShiftLeftAssign: + case EOpBitShiftRightAssign: + case EOpBitwiseAndAssign: + case EOpBitwiseXorAssign: + case EOpBitwiseOrAssign: return true; default: return false; @@ -379,65 +328,55 @@ bool TIntermOperator::isConstructor() const // Make sure the type of a unary operator is appropriate for its // combination of operation and operand type. // -// Returns false in nothing makes sense. -// -bool TIntermUnary::promote(TInfoSink &) +void TIntermUnary::promote(const TType *funcReturnType) { switch (mOp) { - case EOpLogicalNot: - if (mOperand->getBasicType() != EbtBool) - return false; + case EOpFloatBitsToInt: + case EOpFloatBitsToUint: + case EOpIntBitsToFloat: + case EOpUintBitsToFloat: + case EOpPackSnorm2x16: + case EOpPackUnorm2x16: + case EOpPackHalf2x16: + case EOpUnpackSnorm2x16: + case EOpUnpackUnorm2x16: + mType.setPrecision(EbpHigh); break; - case EOpNegative: - case EOpPositive: - case EOpPostIncrement: - case EOpPostDecrement: - case EOpPreIncrement: - case EOpPreDecrement: - if (mOperand->getBasicType() == EbtBool) - return false; + case EOpUnpackHalf2x16: + mType.setPrecision(EbpMedium); break; - - // operators for built-ins are already type checked against their prototype - case EOpAny: - case EOpAll: - case EOpVectorLogicalNot: - return true; - default: - if (mOperand->getBasicType() != EbtFloat) - return false; + setType(mOperand->getType()); } - setType(mOperand->getType()); - mType.setQualifier(EvqTemporary); + if (funcReturnType != nullptr) + { + if (funcReturnType->getBasicType() == EbtBool) + { + // Bool types should not have precision. + setType(*funcReturnType); + } + else + { + // Precision of the node has been set based on the operand. + setTypePreservePrecision(*funcReturnType); + } + } - return true; + mType.setQualifier(EvqTemporary); } // // Establishes the type of the resultant operation, as well as // makes the operator the correct one for the operands. // -// Returns false if operator can't work on operands. +// For lots of operations it should already be established that the operand +// combination is valid, but returns false if operator can't work on operands. // bool TIntermBinary::promote(TInfoSink &infoSink) { - // This function only handles scalars, vectors, and matrices. - if (mLeft->isArray() || mRight->isArray()) - { - infoSink.info.message(EPrefixInternalError, getLine(), - "Invalid operation for arrays"); - return false; - } - - // GLSL ES 2.0 does not support implicit type casting. - // So the basic type should always match. - if (mLeft->getBasicType() != mRight->getBasicType()) - { - return false; - } + ASSERT(mLeft->isArray() == mRight->isArray()); // // Base assumption: just make the type the same as the left @@ -483,12 +422,9 @@ bool TIntermBinary::promote(TInfoSink &infoSink) // And and Or operate on conditionals // case EOpLogicalAnd: + case EOpLogicalXor: case EOpLogicalOr: - // Both operands must be of type bool. - if (mLeft->getBasicType() != EbtBool || mRight->getBasicType() != EbtBool) - { - return false; - } + ASSERT(mLeft->getBasicType() == EbtBool && mRight->getBasicType() == EbtBool); setType(TType(EbtBool, EbpUndefined)); break; @@ -625,12 +561,28 @@ bool TIntermBinary::promote(TInfoSink &infoSink) case EOpAssign: case EOpInitialize: + // No more additional checks are needed. + ASSERT((mLeft->getNominalSize() == mRight->getNominalSize()) && + (mLeft->getSecondarySize() == mRight->getSecondarySize())); + break; case EOpAdd: case EOpSub: case EOpDiv: + case EOpIMod: + case EOpBitShiftLeft: + case EOpBitShiftRight: + case EOpBitwiseAnd: + case EOpBitwiseXor: + case EOpBitwiseOr: case EOpAddAssign: case EOpSubAssign: case EOpDivAssign: + case EOpIModAssign: + case EOpBitShiftLeftAssign: + case EOpBitShiftRightAssign: + case EOpBitwiseAndAssign: + case EOpBitwiseXorAssign: + case EOpBitwiseOrAssign: if ((mLeft->isMatrix() && mRight->isVector()) || (mLeft->isVector() && mRight->isMatrix())) { @@ -641,13 +593,19 @@ bool TIntermBinary::promote(TInfoSink &infoSink) if (mLeft->getNominalSize() != mRight->getNominalSize() || mLeft->getSecondarySize() != mRight->getSecondarySize()) { - // If the nominal size of operands do not match: - // One of them must be scalar. + // If the nominal sizes of operands do not match: + // One of them must be a scalar. if (!mLeft->isScalar() && !mRight->isScalar()) return false; - // Operator cannot be of type pure assignment. - if (mOp == EOpAssign || mOp == EOpInitialize) + // In the case of compound assignment other than multiply-assign, + // the right side needs to be a scalar. Otherwise a vector/matrix + // would be assigned to a scalar. A scalar can't be shifted by a + // vector either. + if (!mRight->isScalar() && + (isAssignment() || + mOp == EOpBitShiftLeft || + mOp == EOpBitShiftRight)) return false; } @@ -656,6 +614,11 @@ bool TIntermBinary::promote(TInfoSink &infoSink) mLeft->getSecondarySize(), mRight->getSecondarySize()); setType(TType(basicType, higherPrecision, EvqTemporary, nominalSize, secondarySize)); + if (mLeft->isArray()) + { + ASSERT(mLeft->getArraySize() == mRight->getArraySize()); + mType.setArraySize(mLeft->getArraySize()); + } } break; @@ -665,11 +628,8 @@ bool TIntermBinary::promote(TInfoSink &infoSink) case EOpGreaterThan: case EOpLessThanEqual: case EOpGreaterThanEqual: - if ((mLeft->getNominalSize() != mRight->getNominalSize()) || - (mLeft->getSecondarySize() != mRight->getSecondarySize())) - { - return false; - } + ASSERT((mLeft->getNominalSize() == mRight->getNominalSize()) && + (mLeft->getSecondarySize() == mRight->getSecondarySize())); setType(TType(EbtBool, EbpUndefined)); break; @@ -793,6 +753,7 @@ TIntermTyped *TIntermConstantUnion::fold( break; case EOpDiv: + case EOpIMod: { tempConstArray = new ConstantUnion[objectSize]; for (size_t i = 0; i < objectSize; i++) @@ -810,6 +771,7 @@ TIntermTyped *TIntermConstantUnion::fold( } else { + ASSERT(op == EOpDiv); tempConstArray[i].setFConst( unionArray[i].getFConst() / rightUnionArray[i].getFConst()); @@ -826,9 +788,19 @@ TIntermTyped *TIntermConstantUnion::fold( } else { - tempConstArray[i].setIConst( - unionArray[i].getIConst() / - rightUnionArray[i].getIConst()); + if (op == EOpDiv) + { + tempConstArray[i].setIConst( + unionArray[i].getIConst() / + rightUnionArray[i].getIConst()); + } + else + { + ASSERT(op == EOpIMod); + tempConstArray[i].setIConst( + unionArray[i].getIConst() % + rightUnionArray[i].getIConst()); + } } break; @@ -842,9 +814,19 @@ TIntermTyped *TIntermConstantUnion::fold( } else { - tempConstArray[i].setUConst( - unionArray[i].getUConst() / - rightUnionArray[i].getUConst()); + if (op == EOpDiv) + { + tempConstArray[i].setUConst( + unionArray[i].getUConst() / + rightUnionArray[i].getUConst()); + } + else + { + ASSERT(op == EOpIMod); + tempConstArray[i].setUConst( + unionArray[i].getUConst() % + rightUnionArray[i].getUConst()); + } } break; @@ -968,6 +950,32 @@ TIntermTyped *TIntermConstantUnion::fold( } break; + case EOpBitwiseAnd: + tempConstArray = new ConstantUnion[objectSize]; + for (size_t i = 0; i < objectSize; i++) + tempConstArray[i] = unionArray[i] & rightUnionArray[i]; + break; + case EOpBitwiseXor: + tempConstArray = new ConstantUnion[objectSize]; + for (size_t i = 0; i < objectSize; i++) + tempConstArray[i] = unionArray[i] ^ rightUnionArray[i]; + break; + case EOpBitwiseOr: + tempConstArray = new ConstantUnion[objectSize]; + for (size_t i = 0; i < objectSize; i++) + tempConstArray[i] = unionArray[i] | rightUnionArray[i]; + break; + case EOpBitShiftLeft: + tempConstArray = new ConstantUnion[objectSize]; + for (size_t i = 0; i < objectSize; i++) + tempConstArray[i] = unionArray[i] << rightUnionArray[i]; + break; + case EOpBitShiftRight: + tempConstArray = new ConstantUnion[objectSize]; + for (size_t i = 0; i < objectSize; i++) + tempConstArray[i] = unionArray[i] >> rightUnionArray[i]; + break; + case EOpLessThan: ASSERT(objectSize == 1); tempConstArray = new ConstantUnion[1]; @@ -1160,6 +1168,23 @@ TIntermTyped *TIntermConstantUnion::fold( } break; + case EOpBitwiseNot: + switch (getType().getBasicType()) + { + case EbtInt: + tempConstArray[i].setIConst(~unionArray[i].getIConst()); + break; + case EbtUInt: + tempConstArray[i].setUConst(~unionArray[i].getUConst()); + break; + default: + infoSink.info.message( + EPrefixInternalError, getLine(), + "Unary operation not folded into constant"); + return NULL; + } + break; + default: return NULL; } @@ -1181,3 +1206,29 @@ TString TIntermTraverser::hash(const TString &name, ShHashFunction64 hashFunctio TString hashedName = stream.str(); return hashedName; } + +void TIntermTraverser::updateTree() +{ + for (size_t ii = 0; ii < mReplacements.size(); ++ii) + { + const NodeUpdateEntry& entry = mReplacements[ii]; + ASSERT(entry.parent); + bool replaced = entry.parent->replaceChildNode( + entry.original, entry.replacement); + ASSERT(replaced); + + if (!entry.originalBecomesChildOfReplacement) + { + // In AST traversing, a parent is visited before its children. + // After we replace a node, if an immediate child is to + // be replaced, we need to make sure we don't update the replaced + // node; instead, we update the replacement node. + for (size_t jj = ii + 1; jj < mReplacements.size(); ++jj) + { + NodeUpdateEntry& entry2 = mReplacements[jj]; + if (entry2.parent == entry.original) + entry2.parent = entry.replacement; + } + } + } +} diff --git a/src/3rdparty/angle/src/compiler/translator/IntermNode.h b/src/3rdparty/angle/src/compiler/translator/IntermNode.h index 32c70f4671..9f732cbb00 100644 --- a/src/3rdparty/angle/src/compiler/translator/IntermNode.h +++ b/src/3rdparty/angle/src/compiler/translator/IntermNode.h @@ -13,182 +13,19 @@ // each node can have it's own type of list of children. // -#ifndef COMPILER_TRANSLATOR_INTERMEDIATE_H_ -#define COMPILER_TRANSLATOR_INTERMEDIATE_H_ +#ifndef COMPILER_TRANSLATOR_INTERMNODE_H_ +#define COMPILER_TRANSLATOR_INTERMNODE_H_ #include "GLSLANG/ShaderLang.h" #include #include +#include "common/angleutils.h" #include "compiler/translator/Common.h" #include "compiler/translator/Types.h" #include "compiler/translator/ConstantUnion.h" - -// -// Operators used by the high-level (parse tree) representation. -// -enum TOperator -{ - EOpNull, // if in a node, should only mean a node is still being built - EOpSequence, // denotes a list of statements, or parameters, etc. - EOpFunctionCall, - EOpFunction, // For function definition - EOpParameters, // an aggregate listing the parameters to a function - - EOpDeclaration, - EOpInvariantDeclaration, // Specialized declarations for attributing invariance - EOpPrototype, - - // - // Unary operators - // - - EOpNegative, - EOpPositive, - EOpLogicalNot, - EOpVectorLogicalNot, - - EOpPostIncrement, - EOpPostDecrement, - EOpPreIncrement, - EOpPreDecrement, - - // - // binary operations - // - - EOpAdd, - EOpSub, - EOpMul, - EOpDiv, - EOpEqual, - EOpNotEqual, - EOpVectorEqual, - EOpVectorNotEqual, - EOpLessThan, - EOpGreaterThan, - EOpLessThanEqual, - EOpGreaterThanEqual, - EOpComma, - - EOpVectorTimesScalar, - EOpVectorTimesMatrix, - EOpMatrixTimesVector, - EOpMatrixTimesScalar, - - EOpLogicalOr, - EOpLogicalXor, - EOpLogicalAnd, - - EOpIndexDirect, - EOpIndexIndirect, - EOpIndexDirectStruct, - EOpIndexDirectInterfaceBlock, - - EOpVectorSwizzle, - - // - // Built-in functions potentially mapped to operators - // - - EOpRadians, - EOpDegrees, - EOpSin, - EOpCos, - EOpTan, - EOpAsin, - EOpAcos, - EOpAtan, - - EOpPow, - EOpExp, - EOpLog, - EOpExp2, - EOpLog2, - EOpSqrt, - EOpInverseSqrt, - - EOpAbs, - EOpSign, - EOpFloor, - EOpCeil, - EOpFract, - EOpMod, - EOpMin, - EOpMax, - EOpClamp, - EOpMix, - EOpStep, - EOpSmoothStep, - - EOpLength, - EOpDistance, - EOpDot, - EOpCross, - EOpNormalize, - EOpFaceForward, - EOpReflect, - EOpRefract, - - EOpDFdx, // Fragment only, OES_standard_derivatives extension - EOpDFdy, // Fragment only, OES_standard_derivatives extension - EOpFwidth, // Fragment only, OES_standard_derivatives extension - - EOpMatrixTimesMatrix, - - EOpAny, - EOpAll, - - // - // Branch - // - - EOpKill, // Fragment only - EOpReturn, - EOpBreak, - EOpContinue, - - // - // Constructors - // - - EOpConstructInt, - EOpConstructUInt, - EOpConstructBool, - EOpConstructFloat, - EOpConstructVec2, - EOpConstructVec3, - EOpConstructVec4, - EOpConstructBVec2, - EOpConstructBVec3, - EOpConstructBVec4, - EOpConstructIVec2, - EOpConstructIVec3, - EOpConstructIVec4, - EOpConstructUVec2, - EOpConstructUVec3, - EOpConstructUVec4, - EOpConstructMat2, - EOpConstructMat3, - EOpConstructMat4, - EOpConstructStruct, - - // - // moves - // - - EOpAssign, - EOpInitialize, - EOpAddAssign, - EOpSubAssign, - EOpMulAssign, - EOpVectorTimesMatrixAssign, - EOpVectorTimesScalarAssign, - EOpMatrixTimesScalarAssign, - EOpMatrixTimesMatrixAssign, - EOpDivAssign -}; +#include "compiler/translator/Operator.h" class TIntermTraverser; class TIntermAggregate; @@ -196,10 +33,13 @@ class TIntermBinary; class TIntermUnary; class TIntermConstantUnion; class TIntermSelection; +class TIntermSwitch; +class TIntermCase; class TIntermTyped; class TIntermSymbol; class TIntermLoop; class TInfoSink; +class TInfoSinkBase; class TIntermRaw; // @@ -228,6 +68,8 @@ class TIntermNode virtual TIntermBinary *getAsBinaryNode() { return 0; } virtual TIntermUnary *getAsUnaryNode() { return 0; } virtual TIntermSelection *getAsSelectionNode() { return 0; } + virtual TIntermSwitch *getAsSwitchNode() { return 0; } + virtual TIntermCase *getAsCaseNode() { return 0; } virtual TIntermSymbol *getAsSymbolNode() { return 0; } virtual TIntermLoop *getAsLoopNode() { return 0; } virtual TIntermRaw *getAsRawNode() { return 0; } @@ -237,10 +79,6 @@ class TIntermNode virtual bool replaceChildNode( TIntermNode *original, TIntermNode *replacement) = 0; - // For traversing a tree in no particular order, but using - // heap memory. - virtual void enqueueChildren(std::queue *nodeQueue) const = 0; - protected: TSourceLoc mLine; }; @@ -331,8 +169,6 @@ class TIntermLoop : public TIntermNode void setUnrollFlag(bool flag) { mUnrollFlag = flag; } bool getUnrollFlag() const { return mUnrollFlag; } - virtual void enqueueChildren(std::queue *nodeQueue) const; - protected: TLoopType mType; TIntermNode *mInit; // for-loop initialization @@ -360,8 +196,6 @@ class TIntermBranch : public TIntermNode TOperator getFlowOp() { return mFlowOp; } TIntermTyped* getExpression() { return mExpression; } - virtual void enqueueChildren(std::queue *nodeQueue) const; - protected: TOperator mFlowOp; TIntermTyped *mExpression; // non-zero except for "return exp;" statements @@ -394,8 +228,6 @@ class TIntermSymbol : public TIntermTyped virtual TIntermSymbol *getAsSymbolNode() { return this; } virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; } - virtual void enqueueChildren(std::queue *nodeQueue) const {} - protected: int mId; TString mSymbol; @@ -419,7 +251,6 @@ class TIntermRaw : public TIntermTyped virtual TIntermRaw *getAsRawNode() { return this; } virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; } - virtual void enqueueChildren(std::queue *nodeQueue) const {} protected: TString mRawText; @@ -459,8 +290,6 @@ class TIntermConstantUnion : public TIntermTyped TIntermTyped *fold(TOperator, TIntermTyped *, TInfoSink &); - virtual void enqueueChildren(std::queue *nodeQueue) const {} - protected: ConstantUnion *mUnionArrayPointer; }; @@ -519,8 +348,6 @@ class TIntermBinary : public TIntermOperator void setAddIndexClamp() { mAddIndexClamp = true; } bool getAddIndexClamp() { return mAddIndexClamp; } - virtual void enqueueChildren(std::queue *nodeQueue) const; - protected: TIntermTyped* mLeft; TIntermTyped* mRight; @@ -556,13 +383,11 @@ class TIntermUnary : public TIntermOperator void setOperand(TIntermTyped *operand) { mOperand = operand; } TIntermTyped *getOperand() { return mOperand; } - bool promote(TInfoSink &); + void promote(const TType *funcReturnType); void setUseEmulatedFunction() { mUseEmulatedFunction = true; } bool getUseEmulatedFunction() { return mUseEmulatedFunction; } - virtual void enqueueChildren(std::queue *nodeQueue) const; - protected: TIntermTyped *mOperand; @@ -613,8 +438,6 @@ class TIntermAggregate : public TIntermOperator void setUseEmulatedFunction() { mUseEmulatedFunction = true; } bool getUseEmulatedFunction() { return mUseEmulatedFunction; } - virtual void enqueueChildren(std::queue *nodeQueue) const; - void setPrecisionFromChildren(); void setBuiltInFunctionPrecision(); @@ -634,7 +457,7 @@ class TIntermAggregate : public TIntermOperator }; // -// For if tests. Simplified since there is no switch statement. +// For if tests. // class TIntermSelection : public TIntermTyped { @@ -664,14 +487,64 @@ class TIntermSelection : public TIntermTyped TIntermNode *getFalseBlock() const { return mFalseBlock; } TIntermSelection *getAsSelectionNode() { return this; } - virtual void enqueueChildren(std::queue *nodeQueue) const; - protected: TIntermTyped *mCondition; TIntermNode *mTrueBlock; TIntermNode *mFalseBlock; }; +// +// Switch statement. +// +class TIntermSwitch : public TIntermNode +{ + public: + TIntermSwitch(TIntermTyped *init, TIntermAggregate *statementList) + : TIntermNode(), + mInit(init), + mStatementList(statementList) + { + } + + void traverse(TIntermTraverser *it) override; + bool replaceChildNode( + TIntermNode *original, TIntermNode *replacement) override; + + TIntermSwitch *getAsSwitchNode() override { return this; } + + TIntermAggregate *getStatementList() { return mStatementList; } + void setStatementList(TIntermAggregate *statementList) { mStatementList = statementList; } + + protected: + TIntermTyped *mInit; + TIntermAggregate *mStatementList; +}; + +// +// Case label. +// +class TIntermCase : public TIntermNode +{ + public: + TIntermCase(TIntermTyped *condition) + : TIntermNode(), + mCondition(condition) + { + } + + void traverse(TIntermTraverser *it) override; + bool replaceChildNode( + TIntermNode *original, TIntermNode *replacement) override; + + TIntermCase *getAsCaseNode() override { return this; } + + bool hasCondition() const { return mCondition != nullptr; } + TIntermTyped *getCondition() const { return mCondition; } + + protected: + TIntermTyped *mCondition; +}; + enum Visit { PreVisit, @@ -687,7 +560,7 @@ enum Visit // When using this, just fill in the methods for nodes you want visited. // Return false from a pre-visit to skip visiting that node's subtree. // -class TIntermTraverser +class TIntermTraverser : angle::NonCopyable { public: POOL_ALLOCATOR_NEW_DELETE(); @@ -708,6 +581,8 @@ class TIntermTraverser virtual bool visitBinary(Visit, TIntermBinary *) { return true; } virtual bool visitUnary(Visit, TIntermUnary *) { return true; } virtual bool visitSelection(Visit, TIntermSelection *) { return true; } + virtual bool visitSwitch(Visit, TIntermSwitch *) { return true; } + virtual bool visitCase(Visit, TIntermCase *) { return true; } virtual bool visitAggregate(Visit, TIntermAggregate *) { return true; } virtual bool visitLoop(Visit, TIntermLoop *) { return true; } virtual bool visitBranch(Visit, TIntermBranch *) { return true; } @@ -741,12 +616,38 @@ class TIntermTraverser const bool postVisit; const bool rightToLeft; + // If traversers need to replace nodes, they can add the replacements in + // mReplacements during traversal and the user of the traverser should call + // this function after traversal to perform them. + void updateTree(); + protected: int mDepth; int mMaxDepth; // All the nodes from root to the current node's parent during traversing. TVector mPath; + + struct NodeUpdateEntry + { + NodeUpdateEntry(TIntermNode *_parent, + TIntermNode *_original, + TIntermNode *_replacement, + bool _originalBecomesChildOfReplacement) + : parent(_parent), + original(_original), + replacement(_replacement), + originalBecomesChildOfReplacement(_originalBecomesChildOfReplacement) {} + + TIntermNode *parent; + TIntermNode *original; + TIntermNode *replacement; + bool originalBecomesChildOfReplacement; + }; + + // During traversing, save all the changes that need to happen into + // mReplacements, then do them by calling updateTree(). + std::vector mReplacements; }; // @@ -768,10 +669,10 @@ class TMaxDepthTraverser : public TIntermTraverser virtual bool visitLoop(Visit, TIntermLoop *) { return depthCheck(); } virtual bool visitBranch(Visit, TIntermBranch *) { return depthCheck(); } -protected: + protected: bool depthCheck() const { return mMaxDepth < mDepthLimit; } int mDepthLimit; }; -#endif // COMPILER_TRANSLATOR_INTERMEDIATE_H_ +#endif // COMPILER_TRANSLATOR_INTERMNODE_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/IntermTraverse.cpp b/src/3rdparty/angle/src/compiler/translator/IntermTraverse.cpp index 72b2033fb3..7a7efb71f5 100644 --- a/src/3rdparty/angle/src/compiler/translator/IntermTraverse.cpp +++ b/src/3rdparty/angle/src/compiler/translator/IntermTraverse.cpp @@ -193,6 +193,60 @@ void TIntermSelection::traverse(TIntermTraverser *it) it->visitSelection(PostVisit, this); } +// +// Traverse a switch node. Same comments in binary node apply here. +// +void TIntermSwitch::traverse(TIntermTraverser *it) +{ + bool visit = true; + + if (it->preVisit) + visit = it->visitSwitch(PreVisit, this); + + if (visit) + { + it->incrementDepth(this); + if (it->rightToLeft) + { + if (mStatementList) + mStatementList->traverse(it); + if (it->inVisit) + visit = it->visitSwitch(InVisit, this); + if (visit) + mInit->traverse(it); + } + else + { + mInit->traverse(it); + if (it->inVisit) + visit = it->visitSwitch(InVisit, this); + if (visit && mStatementList) + mStatementList->traverse(it); + } + it->decrementDepth(); + } + + if (visit && it->postVisit) + it->visitSwitch(PostVisit, this); +} + +// +// Traverse a switch node. Same comments in binary node apply here. +// +void TIntermCase::traverse(TIntermTraverser *it) +{ + bool visit = true; + + if (it->preVisit) + visit = it->visitCase(PreVisit, this); + + if (visit && mCondition) + mCondition->traverse(it); + + if (visit && it->postVisit) + it->visitCase(PostVisit, this); +} + // // Traverse a loop node. Same comments in binary node apply here. // diff --git a/src/3rdparty/angle/src/compiler/translator/Intermediate.cpp b/src/3rdparty/angle/src/compiler/translator/Intermediate.cpp index e558683c55..320056f8ce 100644 --- a/src/3rdparty/angle/src/compiler/translator/Intermediate.cpp +++ b/src/3rdparty/angle/src/compiler/translator/Intermediate.cpp @@ -13,7 +13,6 @@ #include #include "compiler/translator/Intermediate.h" -#include "compiler/translator/RemoveTree.h" #include "compiler/translator/SymbolTable.h" //////////////////////////////////////////////////////////////////////////// @@ -46,47 +45,6 @@ TIntermSymbol *TIntermediate::addSymbol( TIntermTyped *TIntermediate::addBinaryMath( TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &line) { - switch (op) - { - case EOpEqual: - case EOpNotEqual: - if (left->isArray()) - return NULL; - break; - case EOpLessThan: - case EOpGreaterThan: - case EOpLessThanEqual: - case EOpGreaterThanEqual: - if (left->isMatrix() || left->isArray() || left->isVector() || - left->getBasicType() == EbtStruct) - { - return NULL; - } - break; - case EOpLogicalOr: - case EOpLogicalXor: - case EOpLogicalAnd: - if (left->getBasicType() != EbtBool || - left->isMatrix() || left->isArray() || left->isVector()) - { - return NULL; - } - break; - case EOpAdd: - case EOpSub: - case EOpDiv: - case EOpMul: - if (left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool) - return NULL; - default: - break; - } - - if (left->getBasicType() != right->getBasicType()) - { - return NULL; - } - // // Need a new node holding things together then. Make // one and promote it to the right type. @@ -169,45 +127,8 @@ TIntermTyped *TIntermediate::addIndex( // Returns the added node. // TIntermTyped *TIntermediate::addUnaryMath( - TOperator op, TIntermNode *childNode, const TSourceLoc &line) + TOperator op, TIntermTyped *child, const TSourceLoc &line, const TType *funcReturnType) { - TIntermUnary *node; - TIntermTyped *child = childNode->getAsTyped(); - - if (child == NULL) - { - mInfoSink.info.message(EPrefixInternalError, line, - "Bad type in AddUnaryMath"); - return NULL; - } - - switch (op) - { - case EOpLogicalNot: - if (child->getType().getBasicType() != EbtBool || - child->getType().isMatrix() || - child->getType().isArray() || - child->getType().isVector()) - { - return NULL; - } - break; - - case EOpPostIncrement: - case EOpPreIncrement: - case EOpPostDecrement: - case EOpPreDecrement: - case EOpNegative: - case EOpPositive: - if (child->getType().getBasicType() == EbtStruct || - child->getType().isArray()) - { - return NULL; - } - default: - break; - } - TIntermConstantUnion *childTempConstant = 0; if (child->getAsConstantUnion()) childTempConstant = child->getAsConstantUnion(); @@ -215,12 +136,10 @@ TIntermTyped *TIntermediate::addUnaryMath( // // Make a new node for the operator. // - node = new TIntermUnary(op); + TIntermUnary *node = new TIntermUnary(op); node->setLine(line); node->setOperand(child); - - if (!node->promote(mInfoSink)) - return 0; + node->promote(funcReturnType); if (childTempConstant) { @@ -423,6 +342,24 @@ TIntermTyped *TIntermediate::addSelection( return node; } +TIntermSwitch *TIntermediate::addSwitch( + TIntermTyped *init, TIntermAggregate *statementList, const TSourceLoc &line) +{ + TIntermSwitch *node = new TIntermSwitch(init, statementList); + node->setLine(line); + + return node; +} + +TIntermCase *TIntermediate::addCase( + TIntermTyped *condition, const TSourceLoc &line) +{ + TIntermCase *node = new TIntermCase(condition); + node->setLine(line); + + return node; +} + // // Constant terminal nodes. Has a union that contains bool, float or int constants // @@ -510,12 +447,3 @@ bool TIntermediate::postProcess(TIntermNode *root) return true; } - -// -// This deletes the tree. -// -void TIntermediate::remove(TIntermNode *root) -{ - if (root) - RemoveAllTreeNodes(root); -} diff --git a/src/3rdparty/angle/src/compiler/translator/Intermediate.h b/src/3rdparty/angle/src/compiler/translator/Intermediate.h new file mode 100644 index 0000000000..ec73e22834 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/Intermediate.h @@ -0,0 +1,71 @@ +// +// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_TRANSLATOR_INTERMEDIATE_H_ +#define COMPILER_TRANSLATOR_INTERMEDIATE_H_ + +#include "compiler/translator/IntermNode.h" + +struct TVectorFields +{ + int offsets[4]; + int num; +}; + +// +// Set of helper functions to help parse and build the tree. +// +class TInfoSink; +class TIntermediate +{ + public: + POOL_ALLOCATOR_NEW_DELETE(); + TIntermediate(TInfoSink &i) + : mInfoSink(i) { } + + TIntermSymbol *addSymbol( + int id, const TString &, const TType &, const TSourceLoc &); + TIntermTyped *addBinaryMath( + TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &); + TIntermTyped *addAssign( + TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &); + TIntermTyped *addIndex( + TOperator op, TIntermTyped *base, TIntermTyped *index, const TSourceLoc &); + TIntermTyped *addUnaryMath( + TOperator op, TIntermTyped *child, const TSourceLoc &line, const TType *funcReturnType); + TIntermAggregate *growAggregate( + TIntermNode *left, TIntermNode *right, const TSourceLoc &); + TIntermAggregate *makeAggregate(TIntermNode *node, const TSourceLoc &); + TIntermAggregate *setAggregateOperator(TIntermNode *, TOperator, const TSourceLoc &); + TIntermNode *addSelection(TIntermTyped *cond, TIntermNodePair code, const TSourceLoc &); + TIntermTyped *addSelection( + TIntermTyped *cond, TIntermTyped *trueBlock, TIntermTyped *falseBlock, const TSourceLoc &); + TIntermSwitch *addSwitch( + TIntermTyped *init, TIntermAggregate *statementList, const TSourceLoc &line); + TIntermCase *addCase( + TIntermTyped *condition, const TSourceLoc &line); + TIntermTyped *addComma( + TIntermTyped *left, TIntermTyped *right, const TSourceLoc &); + TIntermConstantUnion *addConstantUnion(ConstantUnion *, const TType &, const TSourceLoc &); + // TODO(zmo): Get rid of default value. + bool parseConstTree(const TSourceLoc &, TIntermNode *, ConstantUnion *, + TOperator, TType, bool singleConstantParam = false); + TIntermNode *addLoop(TLoopType, TIntermNode *, TIntermTyped *, TIntermTyped *, + TIntermNode *, const TSourceLoc &); + TIntermBranch *addBranch(TOperator, const TSourceLoc &); + TIntermBranch *addBranch(TOperator, TIntermTyped *, const TSourceLoc &); + TIntermTyped *addSwizzle(TVectorFields &, const TSourceLoc &); + bool postProcess(TIntermNode *); + + static void outputTree(TIntermNode *, TInfoSinkBase &); + + private: + void operator=(TIntermediate &); // prevent assignments + + TInfoSink & mInfoSink; +}; + +#endif // COMPILER_TRANSLATOR_INTERMEDIATE_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/LoopInfo.h b/src/3rdparty/angle/src/compiler/translator/LoopInfo.h index 5f72a6e944..ec73fd0fa5 100644 --- a/src/3rdparty/angle/src/compiler/translator/LoopInfo.h +++ b/src/3rdparty/angle/src/compiler/translator/LoopInfo.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef COMPILER_TRANSLATOR_LOOP_INFO_H_ -#define COMPILER_TRANSLATOR_LOOP_INFO_H_ +#ifndef COMPILER_TRANSLATOR_LOOPINFO_H_ +#define COMPILER_TRANSLATOR_LOOPINFO_H_ #include "compiler/translator/IntermNode.h" @@ -76,5 +76,5 @@ class TLoopStack : public TVector void pop(); }; -#endif // COMPILER_TRANSLATOR_LOOP_INDEX_H_ +#endif // COMPILER_TRANSLATOR_LOOPINFO_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/MMap.h b/src/3rdparty/angle/src/compiler/translator/MMap.h index a308671514..fca843992b 100644 --- a/src/3rdparty/angle/src/compiler/translator/MMap.h +++ b/src/3rdparty/angle/src/compiler/translator/MMap.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef _MMAP_INCLUDED_ -#define _MMAP_INCLUDED_ +#ifndef COMPILER_TRANSLATOR_MMAP_H_ +#define COMPILER_TRANSLATOR_MMAP_H_ // // Encapsulate memory mapped files @@ -53,4 +53,4 @@ private: char* fBuff; // the actual data; }; -#endif // _MMAP_INCLUDED_ +#endif // COMPILER_TRANSLATOR_MMAP_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/NodeSearch.h b/src/3rdparty/angle/src/compiler/translator/NodeSearch.h index 60070c9d33..8ffed614c3 100644 --- a/src/3rdparty/angle/src/compiler/translator/NodeSearch.h +++ b/src/3rdparty/angle/src/compiler/translator/NodeSearch.h @@ -6,8 +6,8 @@ // NodeSearch.h: Utilities for searching translator node graphs // -#ifndef TRANSLATOR_NODESEARCH_H_ -#define TRANSLATOR_NODESEARCH_H_ +#ifndef COMPILER_TRANSLATOR_NODESEARCH_H_ +#define COMPILER_TRANSLATOR_NODESEARCH_H_ #include "compiler/translator/IntermNode.h" @@ -77,4 +77,4 @@ class FindSideEffectRewriting : public NodeSearchTraverser"; + case EOpLessThanEqual: return "<="; + case EOpGreaterThanEqual: return ">="; + case EOpComma: return ","; + + // Fall-through. + case EOpVectorTimesScalar: + case EOpVectorTimesMatrix: + case EOpMatrixTimesVector: + case EOpMatrixTimesScalar: return "*"; + + case EOpLogicalOr: return "||"; + case EOpLogicalXor: return "^^"; + case EOpLogicalAnd: return "&&"; + + case EOpBitShiftLeft: return "<<"; + case EOpBitShiftRight: return ">>"; + + case EOpBitwiseAnd: return "&"; + case EOpBitwiseXor: return "^"; + case EOpBitwiseOr: return "|"; + + // Fall-through. + case EOpIndexDirect: + case EOpIndexIndirect: return "[]"; + + case EOpIndexDirectStruct: + case EOpIndexDirectInterfaceBlock: return "."; + + case EOpVectorSwizzle: return "."; + + case EOpRadians: return "radians"; + case EOpDegrees: return "degrees"; + case EOpSin: return "sin"; + case EOpCos: return "cos"; + case EOpTan: return "tan"; + case EOpAsin: return "asin"; + case EOpAcos: return "acos"; + case EOpAtan: return "atan"; + + case EOpSinh: return "sinh"; + case EOpCosh: return "cosh"; + case EOpTanh: return "tanh"; + case EOpAsinh: return "asinh"; + case EOpAcosh: return "acosh"; + case EOpAtanh: return "atanh"; + + case EOpPow: return "pow"; + case EOpExp: return "exp"; + case EOpLog: return "log"; + case EOpExp2: return "exp2"; + case EOpLog2: return "log2"; + case EOpSqrt: return "sqrt"; + case EOpInverseSqrt: return "inversesqrt"; + + case EOpAbs: return "abs"; + case EOpSign: return "sign"; + case EOpFloor: return "floor"; + case EOpTrunc: return "trunc"; + case EOpRound: return "round"; + case EOpRoundEven: return "roundEven"; + case EOpCeil: return "ceil"; + case EOpFract: return "fract"; + case EOpMod: return "mod"; + case EOpModf: return "modf"; + case EOpMin: return "min"; + case EOpMax: return "max"; + case EOpClamp: return "clamp"; + case EOpMix: return "mix"; + case EOpStep: return "step"; + case EOpSmoothStep: return "smoothstep"; + case EOpIsNan: return "isnan"; + case EOpIsInf: return "isinf"; + + case EOpFloatBitsToInt: return "floatBitsToInt"; + case EOpFloatBitsToUint: return "floatBitsToUint"; + case EOpIntBitsToFloat: return "intBitsToFloat"; + case EOpUintBitsToFloat: return "uintBitsToFloat"; + + case EOpPackSnorm2x16: return "packSnorm2x16"; + case EOpPackUnorm2x16: return "packUnorm2x16"; + case EOpPackHalf2x16: return "packHalf2x16"; + case EOpUnpackSnorm2x16: return "unpackSnorm2x16"; + case EOpUnpackUnorm2x16: return "unpackUnorm2x16"; + case EOpUnpackHalf2x16: return "unpackHalf2x16"; + + case EOpLength: return "length"; + case EOpDistance: return "distance"; + case EOpDot: return "dot"; + case EOpCross: return "cross"; + case EOpNormalize: return "normalize"; + case EOpFaceForward: return "faceforward"; + case EOpReflect: return "reflect"; + case EOpRefract: return "refract"; + + case EOpDFdx: return "dFdx"; + case EOpDFdy: return "dFdy"; + case EOpFwidth: return "fwidth"; + + case EOpMatrixTimesMatrix: return "*"; + + case EOpOuterProduct: return "outerProduct"; + case EOpTranspose: return "transpose"; + case EOpDeterminant: return "determinant"; + case EOpInverse: return "inverse"; + + case EOpAny: return "any"; + case EOpAll: return "all"; + + case EOpKill: return "kill"; + case EOpReturn: return "return"; + case EOpBreak: return "break"; + case EOpContinue: return "continue"; + + case EOpConstructInt: return "int"; + case EOpConstructUInt: return "uint"; + case EOpConstructBool: return "bool"; + case EOpConstructFloat: return "float"; + case EOpConstructVec2: return "vec2"; + case EOpConstructVec3: return "vec3"; + case EOpConstructVec4: return "vec4"; + case EOpConstructBVec2: return "bvec2"; + case EOpConstructBVec3: return "bvec3"; + case EOpConstructBVec4: return "bvec4"; + case EOpConstructIVec2: return "ivec2"; + case EOpConstructIVec3: return "ivec3"; + case EOpConstructIVec4: return "ivec4"; + case EOpConstructUVec2: return "uvec2"; + case EOpConstructUVec3: return "uvec3"; + case EOpConstructUVec4: return "uvec4"; + case EOpConstructMat2: return "mat2"; + case EOpConstructMat3: return "mat3"; + case EOpConstructMat4: return "mat4"; + // Note: EOpConstructStruct can't be handled here + + case EOpAssign: return "="; + case EOpInitialize: return "="; + case EOpAddAssign: return "+="; + case EOpSubAssign: return "-="; + + // Fall-through. + case EOpMulAssign: + case EOpVectorTimesMatrixAssign: + case EOpVectorTimesScalarAssign: + case EOpMatrixTimesScalarAssign: + case EOpMatrixTimesMatrixAssign: return "*="; + + case EOpDivAssign: return "/="; + case EOpIModAssign: return "%="; + case EOpBitShiftLeftAssign: return "<<="; + case EOpBitShiftRightAssign: return ">>="; + case EOpBitwiseAndAssign: return "&="; + case EOpBitwiseXorAssign: return "^="; + case EOpBitwiseOrAssign: return "|="; + + default: break; + } + return ""; +} + diff --git a/src/3rdparty/angle/src/compiler/translator/Operator.h b/src/3rdparty/angle/src/compiler/translator/Operator.h new file mode 100644 index 0000000000..8290f952fc --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/Operator.h @@ -0,0 +1,226 @@ +// +// Copyright (c) 2002-2015 The ANGLE Project 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_TRANSLATOR_OPERATOR_H_ +#define COMPILER_TRANSLATOR_OPERATOR_H_ + +// +// Operators used by the high-level (parse tree) representation. +// +enum TOperator +{ + EOpNull, // if in a node, should only mean a node is still being built + EOpSequence, // denotes a list of statements, or parameters, etc. + EOpFunctionCall, + EOpInternalFunctionCall, // Call to an internal helper function + EOpFunction, // For function definition + EOpParameters, // an aggregate listing the parameters to a function + + EOpDeclaration, + EOpInvariantDeclaration, // Specialized declarations for attributing invariance + EOpPrototype, + + // + // Unary operators + // + + EOpNegative, + EOpPositive, + EOpLogicalNot, + EOpVectorLogicalNot, + EOpBitwiseNot, + + EOpPostIncrement, + EOpPostDecrement, + EOpPreIncrement, + EOpPreDecrement, + + // + // binary operations + // + + EOpAdd, + EOpSub, + EOpMul, + EOpDiv, + EOpIMod, + EOpEqual, + EOpNotEqual, + EOpVectorEqual, + EOpVectorNotEqual, + EOpLessThan, + EOpGreaterThan, + EOpLessThanEqual, + EOpGreaterThanEqual, + EOpComma, + + EOpVectorTimesScalar, + EOpVectorTimesMatrix, + EOpMatrixTimesVector, + EOpMatrixTimesScalar, + + EOpLogicalOr, + EOpLogicalXor, + EOpLogicalAnd, + + EOpBitShiftLeft, + EOpBitShiftRight, + + EOpBitwiseAnd, + EOpBitwiseXor, + EOpBitwiseOr, + + EOpIndexDirect, + EOpIndexIndirect, + EOpIndexDirectStruct, + EOpIndexDirectInterfaceBlock, + + EOpVectorSwizzle, + + // + // Built-in functions potentially mapped to operators + // + + EOpRadians, + EOpDegrees, + EOpSin, + EOpCos, + EOpTan, + EOpAsin, + EOpAcos, + EOpAtan, + + EOpSinh, + EOpCosh, + EOpTanh, + EOpAsinh, + EOpAcosh, + EOpAtanh, + + EOpPow, + EOpExp, + EOpLog, + EOpExp2, + EOpLog2, + EOpSqrt, + EOpInverseSqrt, + + EOpAbs, + EOpSign, + EOpFloor, + EOpTrunc, + EOpRound, + EOpRoundEven, + EOpCeil, + EOpFract, + EOpMod, + EOpModf, + EOpMin, + EOpMax, + EOpClamp, + EOpMix, + EOpStep, + EOpSmoothStep, + EOpIsNan, + EOpIsInf, + + EOpFloatBitsToInt, + EOpFloatBitsToUint, + EOpIntBitsToFloat, + EOpUintBitsToFloat, + + EOpPackSnorm2x16, + EOpPackUnorm2x16, + EOpPackHalf2x16, + EOpUnpackSnorm2x16, + EOpUnpackUnorm2x16, + EOpUnpackHalf2x16, + + EOpLength, + EOpDistance, + EOpDot, + EOpCross, + EOpNormalize, + EOpFaceForward, + EOpReflect, + EOpRefract, + + EOpDFdx, // Fragment only, OES_standard_derivatives extension + EOpDFdy, // Fragment only, OES_standard_derivatives extension + EOpFwidth, // Fragment only, OES_standard_derivatives extension + + EOpMatrixTimesMatrix, + + EOpOuterProduct, + EOpTranspose, + EOpDeterminant, + EOpInverse, + + EOpAny, + EOpAll, + + // + // Branch + // + + EOpKill, // Fragment only + EOpReturn, + EOpBreak, + EOpContinue, + + // + // Constructors + // + + EOpConstructInt, + EOpConstructUInt, + EOpConstructBool, + EOpConstructFloat, + EOpConstructVec2, + EOpConstructVec3, + EOpConstructVec4, + EOpConstructBVec2, + EOpConstructBVec3, + EOpConstructBVec4, + EOpConstructIVec2, + EOpConstructIVec3, + EOpConstructIVec4, + EOpConstructUVec2, + EOpConstructUVec3, + EOpConstructUVec4, + EOpConstructMat2, + EOpConstructMat3, + EOpConstructMat4, + EOpConstructStruct, + + // + // moves + // + + EOpAssign, + EOpInitialize, + EOpAddAssign, + EOpSubAssign, + + EOpMulAssign, + EOpVectorTimesMatrixAssign, + EOpVectorTimesScalarAssign, + EOpMatrixTimesScalarAssign, + EOpMatrixTimesMatrixAssign, + + EOpDivAssign, + EOpIModAssign, + EOpBitShiftLeftAssign, + EOpBitShiftRightAssign, + EOpBitwiseAndAssign, + EOpBitwiseXorAssign, + EOpBitwiseOrAssign +}; + +// Returns the string corresponding to the operator in GLSL +const char* GetOperatorString(TOperator op); + +#endif // COMPILER_TRANSLATOR_OPERATOR_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/OutputESSL.cpp b/src/3rdparty/angle/src/compiler/translator/OutputESSL.cpp index 65635af1ff..77e0a8fb37 100644 --- a/src/3rdparty/angle/src/compiler/translator/OutputESSL.cpp +++ b/src/3rdparty/angle/src/compiler/translator/OutputESSL.cpp @@ -6,13 +6,21 @@ #include "compiler/translator/OutputESSL.h" -TOutputESSL::TOutputESSL(TInfoSinkBase& objSink, +TOutputESSL::TOutputESSL(TInfoSinkBase &objSink, ShArrayIndexClampingStrategy clampingStrategy, ShHashFunction64 hashFunction, - NameMap& nameMap, - TSymbolTable& symbolTable, - int shaderVersion) - : TOutputGLSLBase(objSink, clampingStrategy, hashFunction, nameMap, symbolTable, shaderVersion) + NameMap &nameMap, + TSymbolTable &symbolTable, + int shaderVersion, + bool forceHighp) + : TOutputGLSLBase(objSink, + clampingStrategy, + hashFunction, + nameMap, + symbolTable, + shaderVersion, + SH_ESSL_OUTPUT), + mForceHighp(forceHighp) { } @@ -22,6 +30,9 @@ bool TOutputESSL::writeVariablePrecision(TPrecision precision) return false; TInfoSinkBase& out = objSink(); - out << getPrecisionString(precision); + if (mForceHighp) + out << getPrecisionString(EbpHigh); + else + out << getPrecisionString(precision); return true; } diff --git a/src/3rdparty/angle/src/compiler/translator/OutputESSL.h b/src/3rdparty/angle/src/compiler/translator/OutputESSL.h index 8a567fb8aa..813f1e944b 100644 --- a/src/3rdparty/angle/src/compiler/translator/OutputESSL.h +++ b/src/3rdparty/angle/src/compiler/translator/OutputESSL.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef CROSSCOMPILERGLSL_OUTPUTESSL_H_ -#define CROSSCOMPILERGLSL_OUTPUTESSL_H_ +#ifndef COMPILER_TRANSLATOR_OUTPUTESSL_H_ +#define COMPILER_TRANSLATOR_OUTPUTESSL_H_ #include "compiler/translator/OutputGLSLBase.h" @@ -17,10 +17,13 @@ public: ShHashFunction64 hashFunction, NameMap& nameMap, TSymbolTable& symbolTable, - int shaderVersion); + int shaderVersion, + bool forceHighp); protected: virtual bool writeVariablePrecision(TPrecision precision); +private: + bool mForceHighp; }; -#endif // CROSSCOMPILERGLSL_OUTPUTESSL_H_ +#endif // COMPILER_TRANSLATOR_OUTPUTESSL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/OutputGLSL.cpp b/src/3rdparty/angle/src/compiler/translator/OutputGLSL.cpp index eb7cbb4ae8..9badf0e2fc 100644 --- a/src/3rdparty/angle/src/compiler/translator/OutputGLSL.cpp +++ b/src/3rdparty/angle/src/compiler/translator/OutputGLSL.cpp @@ -11,8 +11,15 @@ TOutputGLSL::TOutputGLSL(TInfoSinkBase& objSink, ShHashFunction64 hashFunction, NameMap& nameMap, TSymbolTable& symbolTable, - int shaderVersion) - : TOutputGLSLBase(objSink, clampingStrategy, hashFunction, nameMap, symbolTable, shaderVersion) + int shaderVersion, + ShShaderOutput output) + : TOutputGLSLBase(objSink, + clampingStrategy, + hashFunction, + nameMap, + symbolTable, + shaderVersion, + output) { } @@ -21,21 +28,30 @@ bool TOutputGLSL::writeVariablePrecision(TPrecision) return false; } -void TOutputGLSL::visitSymbol(TIntermSymbol* node) +void TOutputGLSL::visitSymbol(TIntermSymbol *node) { TInfoSinkBase& out = objSink(); - if (node->getSymbol() == "gl_FragDepthEXT") + const TString &symbol = node->getSymbol(); + if (symbol == "gl_FragDepthEXT") { out << "gl_FragDepth"; } + else if (symbol == "gl_FragColor" && getShaderOutput() == SH_GLSL_CORE_OUTPUT) + { + out << "webgl_FragColor"; + } + else if (symbol == "gl_FragData" && getShaderOutput() == SH_GLSL_CORE_OUTPUT) + { + out << "webgl_FragData"; + } else { TOutputGLSLBase::visitSymbol(node); } } -TString TOutputGLSL::translateTextureFunction(TString& name) +TString TOutputGLSL::translateTextureFunction(TString &name) { static const char *simpleRename[] = { "texture2DLodEXT", "texture2DLod", @@ -46,10 +62,30 @@ TString TOutputGLSL::translateTextureFunction(TString& name) "textureCubeGradEXT", "textureCubeGradARB", NULL, NULL }; + static const char *legacyToCoreRename[] = { + "texture2D", "texture", + "texture2DProj", "textureProj", + "texture2DLod", "textureLod", + "texture2DProjLod", "textureProjLod", + "textureCube", "texture", + "textureCubeLod", "textureLod", + // Extensions + "texture2DLodEXT", "textureLod", + "texture2DProjLodEXT", "textureProjLod", + "textureCubeLodEXT", "textureLod", + "texture2DGradEXT", "textureGrad", + "texture2DProjGradEXT", "textureProjGrad", + "textureCubeGradEXT", "textureGrad", + NULL, NULL + }; + const char **mapping = (getShaderOutput() == SH_GLSL_CORE_OUTPUT) ? + legacyToCoreRename : simpleRename; - for (int i = 0; simpleRename[i] != NULL; i += 2) { - if (name == simpleRename[i]) { - return simpleRename[i+1]; + for (int i = 0; mapping[i] != NULL; i += 2) + { + if (name == mapping[i]) + { + return mapping[i+1]; } } diff --git a/src/3rdparty/angle/src/compiler/translator/OutputGLSL.h b/src/3rdparty/angle/src/compiler/translator/OutputGLSL.h index bceebe397d..21b2d079d3 100644 --- a/src/3rdparty/angle/src/compiler/translator/OutputGLSL.h +++ b/src/3rdparty/angle/src/compiler/translator/OutputGLSL.h @@ -4,25 +4,26 @@ // found in the LICENSE file. // -#ifndef CROSSCOMPILERGLSL_OUTPUTGLSL_H_ -#define CROSSCOMPILERGLSL_OUTPUTGLSL_H_ +#ifndef COMPILER_TRANSLATOR_OUTPUTGLSL_H_ +#define COMPILER_TRANSLATOR_OUTPUTGLSL_H_ #include "compiler/translator/OutputGLSLBase.h" class TOutputGLSL : public TOutputGLSLBase { -public: + public: TOutputGLSL(TInfoSinkBase& objSink, ShArrayIndexClampingStrategy clampingStrategy, ShHashFunction64 hashFunction, NameMap& nameMap, TSymbolTable& symbolTable, - int shaderVersion); + int shaderVersion, + ShShaderOutput output); -protected: + protected: virtual bool writeVariablePrecision(TPrecision); virtual void visitSymbol(TIntermSymbol* node); virtual TString translateTextureFunction(TString& name); }; -#endif // CROSSCOMPILERGLSL_OUTPUTGLSL_H_ +#endif // COMPILER_TRANSLATOR_OUTPUTGLSL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp b/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp index ed590967b1..4bb6305d05 100644 --- a/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp +++ b/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp @@ -36,8 +36,17 @@ bool isSingleStatement(TIntermNode *node) { return false; } + else if (node->getAsSwitchNode()) + { + return false; + } + else if (node->getAsCaseNode()) + { + return false; + } return true; } + } // namespace TOutputGLSLBase::TOutputGLSLBase(TInfoSinkBase &objSink, @@ -45,7 +54,8 @@ TOutputGLSLBase::TOutputGLSLBase(TInfoSinkBase &objSink, ShHashFunction64 hashFunction, NameMap &nameMap, TSymbolTable &symbolTable, - int shaderVersion) + int shaderVersion, + ShShaderOutput output) : TIntermTraverser(true, true, true), mObjSink(objSink), mDeclaringVariables(false), @@ -53,7 +63,8 @@ TOutputGLSLBase::TOutputGLSLBase(TInfoSinkBase &objSink, mHashFunction(hashFunction), mNameMap(nameMap), mSymbolTable(symbolTable), - mShaderVersion(shaderVersion) + mShaderVersion(shaderVersion), + mOutput(output) { } @@ -83,7 +94,34 @@ void TOutputGLSLBase::writeVariableType(const TType &type) TQualifier qualifier = type.getQualifier(); if (qualifier != EvqTemporary && qualifier != EvqGlobal) { - out << type.getQualifierString() << " "; + if (mOutput == SH_GLSL_CORE_OUTPUT) + { + switch (qualifier) + { + case EvqAttribute: + out << "in" << " "; + break; + case EvqVaryingIn: + out << "in" << " "; + break; + case EvqVaryingOut: + out << "out" << " "; + break; + case EvqInvariantVaryingIn: + out << "invariant in" << " "; + break; + case EvqInvariantVaryingOut: + out << "invariant out" << " "; + break; + default: + out << type.getQualifierString() << " "; + break; + } + } + else + { + out << type.getQualifierString() << " "; + } } // Declare the struct if we have not done so already. if (type.getBasicType() == EbtStruct && !structDeclared(type.getStruct())) @@ -166,6 +204,9 @@ const ConstantUnion *TOutputGLSLBase::writeConstantUnion( case EbtInt: out << pConstUnion->getIConst(); break; + case EbtUInt: + out << pConstUnion->getUConst() << "u"; + break; case EbtBool: out << pConstUnion->getBConst(); break; @@ -223,6 +264,9 @@ bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary *node) case EOpDivAssign: writeTriplet(visit, "(", " /= ", ")"); break; + case EOpIModAssign: + writeTriplet(visit, "(", " %= ", ")"); + break; // Notice the fall-through. case EOpMulAssign: case EOpVectorTimesMatrixAssign: @@ -231,6 +275,21 @@ bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary *node) case EOpMatrixTimesMatrixAssign: writeTriplet(visit, "(", " *= ", ")"); break; + case EOpBitShiftLeftAssign: + writeTriplet(visit, "(", " <<= ", ")"); + break; + case EOpBitShiftRightAssign: + writeTriplet(visit, "(", " >>= ", ")"); + break; + case EOpBitwiseAndAssign: + writeTriplet(visit, "(", " &= ", ")"); + break; + case EOpBitwiseXorAssign: + writeTriplet(visit, "(", " ^= ", ")"); + break; + case EOpBitwiseOrAssign: + writeTriplet(visit, "(", " |= ", ")"); + break; case EOpIndexDirect: writeTriplet(visit, NULL, "[", "]"); @@ -340,9 +399,25 @@ bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary *node) case EOpDiv: writeTriplet(visit, "(", " / ", ")"); break; - case EOpMod: - UNIMPLEMENTED(); + case EOpIMod: + writeTriplet(visit, "(", " % ", ")"); + break; + case EOpBitShiftLeft: + writeTriplet(visit, "(", " << ", ")"); break; + case EOpBitShiftRight: + writeTriplet(visit, "(", " >> ", ")"); + break; + case EOpBitwiseAnd: + writeTriplet(visit, "(", " & ", ")"); + break; + case EOpBitwiseXor: + writeTriplet(visit, "(", " ^ ", ")"); + break; + case EOpBitwiseOr: + writeTriplet(visit, "(", " | ", ")"); + break; + case EOpEqual: writeTriplet(visit, "(", " == ", ")"); break; @@ -398,6 +473,7 @@ bool TOutputGLSLBase::visitUnary(Visit visit, TIntermUnary *node) case EOpPositive: preString = "(+"; break; case EOpVectorLogicalNot: preString = "not("; break; case EOpLogicalNot: preString = "(!"; break; + case EOpBitwiseNot: preString = "(~"; break; case EOpPostIncrement: preString = "("; postString = "++)"; break; case EOpPostDecrement: preString = "("; postString = "--)"; break; @@ -429,6 +505,25 @@ bool TOutputGLSLBase::visitUnary(Visit visit, TIntermUnary *node) preString = "atan("; break; + case EOpSinh: + preString = "sinh("; + break; + case EOpCosh: + preString = "cosh("; + break; + case EOpTanh: + preString = "tanh("; + break; + case EOpAsinh: + preString = "asinh("; + break; + case EOpAcosh: + preString = "acosh("; + break; + case EOpAtanh: + preString = "atanh("; + break; + case EOpExp: preString = "exp("; break; @@ -457,12 +552,59 @@ bool TOutputGLSLBase::visitUnary(Visit visit, TIntermUnary *node) case EOpFloor: preString = "floor("; break; + case EOpTrunc: + preString = "trunc("; + break; + case EOpRound: + preString = "round("; + break; + case EOpRoundEven: + preString = "roundEven("; + break; case EOpCeil: preString = "ceil("; break; case EOpFract: preString = "fract("; break; + case EOpIsNan: + preString = "isnan("; + break; + case EOpIsInf: + preString = "isinf("; + break; + + case EOpFloatBitsToInt: + preString = "floatBitsToInt("; + break; + case EOpFloatBitsToUint: + preString = "floatBitsToUint("; + break; + case EOpIntBitsToFloat: + preString = "intBitsToFloat("; + break; + case EOpUintBitsToFloat: + preString = "uintBitsToFloat("; + break; + + case EOpPackSnorm2x16: + preString = "packSnorm2x16("; + break; + case EOpPackUnorm2x16: + preString = "packUnorm2x16("; + break; + case EOpPackHalf2x16: + preString = "packHalf2x16("; + break; + case EOpUnpackSnorm2x16: + preString = "unpackSnorm2x16("; + break; + case EOpUnpackUnorm2x16: + preString = "unpackUnorm2x16("; + break; + case EOpUnpackHalf2x16: + preString = "unpackHalf2x16("; + break; case EOpLength: preString = "length("; @@ -481,6 +623,16 @@ bool TOutputGLSLBase::visitUnary(Visit visit, TIntermUnary *node) preString = "fwidth("; break; + case EOpTranspose: + preString = "transpose("; + break; + case EOpDeterminant: + preString = "determinant("; + break; + case EOpInverse: + preString = "inverse("; + break; + case EOpAny: preString = "any("; break; @@ -536,6 +688,36 @@ bool TOutputGLSLBase::visitSelection(Visit visit, TIntermSelection *node) return false; } +bool TOutputGLSLBase::visitSwitch(Visit visit, TIntermSwitch *node) +{ + if (node->getStatementList()) + { + writeTriplet(visit, "switch (", ") ", nullptr); + // The curly braces get written when visiting the statementList aggregate + } + else + { + // No statementList, so it won't output curly braces + writeTriplet(visit, "switch (", ") {", "}\n"); + } + return true; +} + +bool TOutputGLSLBase::visitCase(Visit visit, TIntermCase *node) +{ + if (node->hasCondition()) + { + writeTriplet(visit, "case (", nullptr, "):\n"); + return true; + } + else + { + TInfoSinkBase &out = objSink(); + out << "default:\n"; + return false; + } +} + bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node) { bool visitChildren = true; @@ -555,11 +737,11 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node) for (TIntermSequence::const_iterator iter = node->getSequence()->begin(); iter != node->getSequence()->end(); ++iter) { - TIntermNode *node = *iter; - ASSERT(node != NULL); - node->traverse(this); + TIntermNode *curNode = *iter; + ASSERT(curNode != NULL); + curNode->traverse(this); - if (isSingleStatement(node)) + if (isSingleStatement(curNode)) out << ";\n"; } decrementDepth(); @@ -622,6 +804,15 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node) else out << ")"; break; + case EOpInternalFunctionCall: + // Function call to an internal helper function. + if (visit == PreVisit) + out << node->getName() << "("; + else if (visit == InVisit) + out << ", "; + else + out << ")"; + break; case EOpParameters: // Function parameters. ASSERT(visit == PreVisit); @@ -724,6 +915,10 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node) } break; + case EOpOuterProduct: + writeBuiltInFunctionTriplet(visit, "outerProduct(", useEmulatedFunction); + break; + case EOpLessThan: writeBuiltInFunctionTriplet(visit, "lessThan(", useEmulatedFunction); break; @@ -749,6 +944,9 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node) case EOpMod: writeBuiltInFunctionTriplet(visit, "mod(", useEmulatedFunction); break; + case EOpModf: + writeBuiltInFunctionTriplet(visit, "modf(", useEmulatedFunction); + break; case EOpPow: writeBuiltInFunctionTriplet(visit, "pow(", useEmulatedFunction); break; diff --git a/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.h b/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.h index e5174f5660..4e66059c21 100644 --- a/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.h +++ b/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef CROSSCOMPILERGLSL_OUTPUTGLSLBASE_H_ -#define CROSSCOMPILERGLSL_OUTPUTGLSLBASE_H_ +#ifndef COMPILER_TRANSLATOR_OUTPUTGLSLBASE_H_ +#define COMPILER_TRANSLATOR_OUTPUTGLSLBASE_H_ #include @@ -21,7 +21,13 @@ class TOutputGLSLBase : public TIntermTraverser ShHashFunction64 hashFunction, NameMap &nameMap, TSymbolTable& symbolTable, - int shaderVersion); + int shaderVersion, + ShShaderOutput output); + + ShShaderOutput getShaderOutput() const + { + return mOutput; + } protected: TInfoSinkBase &objSink() { return mObjSink; } @@ -37,6 +43,8 @@ class TOutputGLSLBase : public TIntermTraverser virtual bool visitBinary(Visit visit, TIntermBinary *node); virtual bool visitUnary(Visit visit, TIntermUnary *node); virtual bool visitSelection(Visit visit, TIntermSelection *node); + virtual bool visitSwitch(Visit visit, TIntermSwitch *node); + virtual bool visitCase(Visit visit, TIntermCase *node); virtual bool visitAggregate(Visit visit, TIntermAggregate *node); virtual bool visitLoop(Visit visit, TIntermLoop *node); virtual bool visitBranch(Visit visit, TIntermBranch *node); @@ -78,6 +86,8 @@ class TOutputGLSLBase : public TIntermTraverser TSymbolTable &mSymbolTable; const int mShaderVersion; + + ShShaderOutput mOutput; }; -#endif // CROSSCOMPILERGLSL_OUTPUTGLSLBASE_H_ +#endif // COMPILER_TRANSLATOR_OUTPUTGLSLBASE_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/OutputHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/OutputHLSL.cpp index 30bbbff0f5..94225b81c4 100644 --- a/src/3rdparty/angle/src/compiler/translator/OutputHLSL.cpp +++ b/src/3rdparty/angle/src/compiler/translator/OutputHLSL.cpp @@ -6,26 +6,29 @@ #include "compiler/translator/OutputHLSL.h" +#include +#include +#include + #include "common/angleutils.h" #include "common/utilities.h" -#include "common/blocklayout.h" -#include "compiler/translator/compilerdebug.h" -#include "compiler/translator/InfoSink.h" +#include "compiler/translator/BuiltInFunctionEmulator.h" +#include "compiler/translator/BuiltInFunctionEmulatorHLSL.h" #include "compiler/translator/DetectDiscontinuity.h" -#include "compiler/translator/SearchSymbol.h" -#include "compiler/translator/UnfoldShortCircuit.h" #include "compiler/translator/FlagStd140Structs.h" +#include "compiler/translator/InfoSink.h" #include "compiler/translator/NodeSearch.h" +#include "compiler/translator/RemoveSwitchFallThrough.h" #include "compiler/translator/RewriteElseBlocks.h" -#include "compiler/translator/UtilsHLSL.h" -#include "compiler/translator/util.h" -#include "compiler/translator/UniformHLSL.h" +#include "compiler/translator/SearchSymbol.h" #include "compiler/translator/StructureHLSL.h" #include "compiler/translator/TranslatorHLSL.h" - -#include -#include -#include +#include "compiler/translator/UnfoldShortCircuit.h" +#include "compiler/translator/UniformHLSL.h" +#include "compiler/translator/UtilsHLSL.h" +#include "compiler/translator/blocklayout.h" +#include "compiler/translator/compilerdebug.h" +#include "compiler/translator/util.h" namespace sh { @@ -94,12 +97,21 @@ bool OutputHLSL::TextureFunction::operator<(const TextureFunction &rhs) const return false; } -OutputHLSL::OutputHLSL(TParseContext &context, TranslatorHLSL *parentTranslator) +OutputHLSL::OutputHLSL(sh::GLenum shaderType, int shaderVersion, + const TExtensionBehavior &extensionBehavior, + const char *sourcePath, ShShaderOutput outputType, + int numRenderTargets, const std::vector &uniforms, + int compileOptions) : TIntermTraverser(true, true, true), - mContext(context), - mOutputType(parentTranslator->getOutputType()) + mShaderType(shaderType), + mShaderVersion(shaderVersion), + mExtensionBehavior(extensionBehavior), + mSourcePath(sourcePath), + mOutputType(outputType), + mNumRenderTargets(numRenderTargets), + mCompileOptions(compileOptions) { - mUnfoldShortCircuit = new UnfoldShortCircuit(context, this); + mUnfoldShortCircuit = new UnfoldShortCircuit(this); mInsideFunction = false; mUsesFragColor = false; @@ -109,28 +121,12 @@ OutputHLSL::OutputHLSL(TParseContext &context, TranslatorHLSL *parentTranslator) mUsesPointCoord = false; mUsesFrontFacing = false; mUsesPointSize = false; + mUsesInstanceID = false; mUsesFragDepth = false; mUsesXor = false; - mUsesMod1 = false; - mUsesMod2v = false; - mUsesMod2f = false; - mUsesMod3v = false; - mUsesMod3f = false; - mUsesMod4v = false; - mUsesMod4f = false; - mUsesFaceforward1 = false; - mUsesFaceforward2 = false; - mUsesFaceforward3 = false; - mUsesFaceforward4 = false; - mUsesAtan2_1 = false; - mUsesAtan2_2 = false; - mUsesAtan2_3 = false; - mUsesAtan2_4 = false; mUsesDiscardRewriting = false; mUsesNestedBreak = false; - - const ShBuiltInResources &resources = parentTranslator->getResources(); - mNumRenderTargets = resources.EXT_draw_buffers ? resources.MaxDrawBuffers : 1; + mRequiresIEEEStrictCompiling = false; mUniqueIndex = 0; @@ -143,20 +139,14 @@ OutputHLSL::OutputHLSL(TParseContext &context, TranslatorHLSL *parentTranslator) mExcessiveLoopIndex = NULL; mStructureHLSL = new StructureHLSL; - mUniformHLSL = new UniformHLSL(mStructureHLSL, parentTranslator); + mUniformHLSL = new UniformHLSL(mStructureHLSL, outputType, uniforms); if (mOutputType == SH_HLSL9_OUTPUT) { - if (mContext.shaderType == GL_FRAGMENT_SHADER) - { - // Reserve registers for dx_DepthRange, dx_ViewCoords and dx_DepthFront - mUniformHLSL->reserveUniformRegisters(3); - } - else - { - // Reserve registers for dx_DepthRange and dx_ViewAdjust - mUniformHLSL->reserveUniformRegisters(2); - } + // Fragment shaders need dx_DepthRange, dx_ViewCoords and dx_DepthFront. + // Vertex shaders need a slightly different set: dx_DepthRange, dx_ViewCoords and dx_ViewAdjust. + // In both cases total 3 uniform registers need to be reserved. + mUniformHLSL->reserveUniformRegisters(3); } // Reserve registers for the default uniform block and driver constants @@ -168,27 +158,55 @@ OutputHLSL::~OutputHLSL() SafeDelete(mUnfoldShortCircuit); SafeDelete(mStructureHLSL); SafeDelete(mUniformHLSL); + for (auto it = mStructEqualityFunctions.begin(); it != mStructEqualityFunctions.end(); ++it) + { + SafeDelete(*it); + } + for (auto it = mArrayEqualityFunctions.begin(); it != mArrayEqualityFunctions.end(); ++it) + { + SafeDelete(*it); + } } -void OutputHLSL::output() +void OutputHLSL::output(TIntermNode *treeRoot, TInfoSinkBase &objSink) { - mContainsLoopDiscontinuity = mContext.shaderType == GL_FRAGMENT_SHADER && containsLoopDiscontinuity(mContext.treeRoot); - mContainsAnyLoop = containsAnyLoop(mContext.treeRoot); - const std::vector &flaggedStructs = FlagStd140ValueStructs(mContext.treeRoot); + mContainsLoopDiscontinuity = mShaderType == GL_FRAGMENT_SHADER && containsLoopDiscontinuity(treeRoot); + mContainsAnyLoop = containsAnyLoop(treeRoot); + const std::vector &flaggedStructs = FlagStd140ValueStructs(treeRoot); makeFlaggedStructMaps(flaggedStructs); // Work around D3D9 bug that would manifest in vertex shaders with selection blocks which // use a vertex attribute as a condition, and some related computation in the else block. - if (mOutputType == SH_HLSL9_OUTPUT && mContext.shaderType == GL_VERTEX_SHADER) + if (mOutputType == SH_HLSL9_OUTPUT && mShaderType == GL_VERTEX_SHADER) + { + RewriteElseBlocks(treeRoot); + } + + BuiltInFunctionEmulator builtInFunctionEmulator; + InitBuiltInFunctionEmulatorForHLSL(&builtInFunctionEmulator); + builtInFunctionEmulator.MarkBuiltInFunctionsForEmulation(treeRoot); + + // Output the body and footer first to determine what has to go in the header + mInfoSinkStack.push(&mBody); + treeRoot->traverse(this); + mInfoSinkStack.pop(); + + mInfoSinkStack.push(&mFooter); + if (!mDeferredGlobalInitializers.empty()) { - RewriteElseBlocks(mContext.treeRoot); + writeDeferredGlobalInitializers(mFooter); } + mInfoSinkStack.pop(); + + mInfoSinkStack.push(&mHeader); + header(&builtInFunctionEmulator); + mInfoSinkStack.pop(); - mContext.treeRoot->traverse(this); // Output the body first to determine what has to go in the header - header(); + objSink << mHeader.c_str(); + objSink << mBody.c_str(); + objSink << mFooter.c_str(); - mContext.infoSink().obj << mHeader.c_str(); - mContext.infoSink().obj << mBody.c_str(); + builtInFunctionEmulator.Cleanup(); } void OutputHLSL::makeFlaggedStructMaps(const std::vector &flaggedStructs) @@ -197,10 +215,14 @@ void OutputHLSL::makeFlaggedStructMaps(const std::vector &flagge { TIntermTyped *flaggedNode = flaggedStructs[structIndex]; + TInfoSinkBase structInfoSink; + mInfoSinkStack.push(&structInfoSink); + // This will mark the necessary block elements as referenced flaggedNode->traverse(this); - TString structName(mBody.c_str()); - mBody.erase(); + + TString structName(structInfoSink.c_str()); + mInfoSinkStack.pop(); mFlaggedStructOriginalNames[flaggedNode] = structName; @@ -213,11 +235,6 @@ void OutputHLSL::makeFlaggedStructMaps(const std::vector &flagge } } -TInfoSinkBase &OutputHLSL::getBodyStream() -{ - return mBody; -} - const std::map &OutputHLSL::getInterfaceBlockRegisterMap() const { return mUniformHLSL->getInterfaceBlockRegisterMap(); @@ -277,9 +294,9 @@ TString OutputHLSL::structInitializerString(int indent, const TStructure &struct return init; } -void OutputHLSL::header() +void OutputHLSL::header(const BuiltInFunctionEmulator *builtInFunctionEmulator) { - TInfoSinkBase &out = mHeader; + TInfoSinkBase &out = getInfoSink(); TString varyings; TString attributes; @@ -320,6 +337,23 @@ void OutputHLSL::header() out << mUniformHLSL->uniformsHeader(mOutputType, mReferencedUniforms); out << mUniformHLSL->interfaceBlocksHeader(mReferencedInterfaceBlocks); + if (!mEqualityFunctions.empty()) + { + out << "\n// Equality functions\n\n"; + for (auto it = mEqualityFunctions.cbegin(); it != mEqualityFunctions.cend(); ++it) + { + out << (*it)->functionDefinition << "\n"; + } + } + if (!mArrayAssignmentFunctions.empty()) + { + out << "\n// Assignment functions\n\n"; + for (auto it = mArrayAssignmentFunctions.cbegin(); it != mArrayAssignmentFunctions.cend(); ++it) + { + out << it->functionDefinition << "\n"; + } + } + if (mUsesDiscardRewriting) { out << "#define ANGLE_USES_DISCARD_REWRITING\n"; @@ -330,6 +364,11 @@ void OutputHLSL::header() out << "#define ANGLE_USES_NESTED_BREAK\n"; } + if (mRequiresIEEEStrictCompiling) + { + out << "#define ANGLE_REQUIRES_IEEE_STRICT_COMPILING\n"; + } + out << "#ifdef ANGLE_ENABLE_LOOP_FLATTEN\n" "#define LOOP [loop]\n" "#define FLATTEN [flatten]\n" @@ -338,16 +377,16 @@ void OutputHLSL::header() "#define FLATTEN\n" "#endif\n"; - if (mContext.shaderType == GL_FRAGMENT_SHADER) + if (mShaderType == GL_FRAGMENT_SHADER) { - TExtensionBehavior::const_iterator iter = mContext.extensionBehavior().find("GL_EXT_draw_buffers"); - const bool usingMRTExtension = (iter != mContext.extensionBehavior().end() && (iter->second == EBhEnable || iter->second == EBhRequire)); + TExtensionBehavior::const_iterator iter = mExtensionBehavior.find("GL_EXT_draw_buffers"); + const bool usingMRTExtension = (iter != mExtensionBehavior.end() && (iter->second == EBhEnable || iter->second == EBhRequire)); out << "// Varyings\n"; out << varyings; out << "\n"; - if (mContext.getShaderVersion() >= 300) + if (mShaderVersion >= 300) { for (ReferencedSymbols::const_iterator outputVariableIt = mReferencedOutputVariables.begin(); outputVariableIt != mReferencedOutputVariables.end(); outputVariableIt++) { @@ -493,6 +532,11 @@ void OutputHLSL::header() out << "static float gl_PointSize = float(1);\n"; } + if (mUsesInstanceID) + { + out << "static int gl_InstanceID;"; + } + out << "\n" "// Varyings\n"; out << varyings; @@ -511,14 +555,22 @@ void OutputHLSL::header() if (mOutputType == SH_HLSL11_OUTPUT) { + out << "cbuffer DriverConstants : register(b1)\n" + "{\n"; + if (mUsesDepthRange) { - out << "cbuffer DriverConstants : register(b1)\n" - "{\n" - " float3 dx_DepthRange : packoffset(c0);\n" - "};\n" - "\n"; + out << " float3 dx_DepthRange : packoffset(c0);\n"; } + + // dx_ViewAdjust and dx_ViewCoords will only be used in Feature Level 9 shaders. + // However, we declare it for all shaders (including Feature Level 10+). + // The bytecode is the same whether we declare it or not, since D3DCompiler removes it if it's unused. + out << " float4 dx_ViewAdjust : packoffset(c1);\n"; + out << " float2 dx_ViewCoords : packoffset(c2);\n"; + + out << "};\n" + "\n"; } else { @@ -527,7 +579,8 @@ void OutputHLSL::header() out << "uniform float3 dx_DepthRange : register(c0);\n"; } - out << "uniform float4 dx_ViewAdjust : register(c1);\n" + out << "uniform float4 dx_ViewAdjust : register(c1);\n"; + out << "uniform float2 dx_ViewCoords : register(c2);\n" "\n"; } @@ -980,7 +1033,15 @@ void OutputHLSL::header() } else if (IsShadowSampler(textureFunction->sampler)) { - out << "x.SampleCmp(s, "; + switch(textureFunction->method) + { + case TextureFunction::IMPLICIT: out << "x.SampleCmp(s, "; break; + case TextureFunction::BIAS: out << "x.SampleCmp(s, "; break; + case TextureFunction::LOD: out << "x.SampleCmp(s, "; break; + case TextureFunction::LOD0: out << "x.SampleCmpLevelZero(s, "; break; + case TextureFunction::LOD0BIAS: out << "x.SampleCmpLevelZero(s, "; break; + default: UNREACHABLE(); + } } else { @@ -1111,11 +1172,20 @@ void OutputHLSL::header() else if (IsShadowSampler(textureFunction->sampler)) { // Compare value - switch(textureFunction->coords) + if (textureFunction->proj) { - case 3: out << "), t.z"; break; - case 4: out << "), t.w"; break; - default: UNREACHABLE(); + // According to ESSL 3.00.4 sec 8.8 p95 on textureProj: + // The resulting third component of P' in the shadow forms is used as Dref + out << "), t.z" << proj; + } + else + { + switch(textureFunction->coords) + { + case 3: out << "), t.z"; break; + case 4: out << "), t.w"; break; + default: UNREACHABLE(); + } } } else @@ -1131,11 +1201,20 @@ void OutputHLSL::header() else if (IsShadowSampler(textureFunction->sampler)) { // Compare value - switch(textureFunction->coords) + if (textureFunction->proj) { - case 3: out << "), t.z"; break; - case 4: out << "), t.w"; break; - default: UNREACHABLE(); + // According to ESSL 3.00.4 sec 8.8 p95 on textureProj: + // The resulting third component of P' in the shadow forms is used as Dref + out << "), t.z" << proj; + } + else + { + switch(textureFunction->coords) + { + case 3: out << "), t.z"; break; + case 4: out << "), t.w"; break; + default: UNREACHABLE(); + } } } else @@ -1205,179 +1284,12 @@ void OutputHLSL::header() "\n"; } - if (mUsesMod1) - { - out << "float mod(float x, float y)\n" - "{\n" - " return x - y * floor(x / y);\n" - "}\n" - "\n"; - } - - if (mUsesMod2v) - { - out << "float2 mod(float2 x, float2 y)\n" - "{\n" - " return x - y * floor(x / y);\n" - "}\n" - "\n"; - } - - if (mUsesMod2f) - { - out << "float2 mod(float2 x, float y)\n" - "{\n" - " return x - y * floor(x / y);\n" - "}\n" - "\n"; - } - - if (mUsesMod3v) - { - out << "float3 mod(float3 x, float3 y)\n" - "{\n" - " return x - y * floor(x / y);\n" - "}\n" - "\n"; - } - - if (mUsesMod3f) - { - out << "float3 mod(float3 x, float y)\n" - "{\n" - " return x - y * floor(x / y);\n" - "}\n" - "\n"; - } - - if (mUsesMod4v) - { - out << "float4 mod(float4 x, float4 y)\n" - "{\n" - " return x - y * floor(x / y);\n" - "}\n" - "\n"; - } - - if (mUsesMod4f) - { - out << "float4 mod(float4 x, float y)\n" - "{\n" - " return x - y * floor(x / y);\n" - "}\n" - "\n"; - } - - if (mUsesFaceforward1) - { - out << "float faceforward(float N, float I, float Nref)\n" - "{\n" - " if(dot(Nref, I) >= 0)\n" - " {\n" - " return -N;\n" - " }\n" - " else\n" - " {\n" - " return N;\n" - " }\n" - "}\n" - "\n"; - } - - if (mUsesFaceforward2) - { - out << "float2 faceforward(float2 N, float2 I, float2 Nref)\n" - "{\n" - " if(dot(Nref, I) >= 0)\n" - " {\n" - " return -N;\n" - " }\n" - " else\n" - " {\n" - " return N;\n" - " }\n" - "}\n" - "\n"; - } - - if (mUsesFaceforward3) - { - out << "float3 faceforward(float3 N, float3 I, float3 Nref)\n" - "{\n" - " if(dot(Nref, I) >= 0)\n" - " {\n" - " return -N;\n" - " }\n" - " else\n" - " {\n" - " return N;\n" - " }\n" - "}\n" - "\n"; - } - - if (mUsesFaceforward4) - { - out << "float4 faceforward(float4 N, float4 I, float4 Nref)\n" - "{\n" - " if(dot(Nref, I) >= 0)\n" - " {\n" - " return -N;\n" - " }\n" - " else\n" - " {\n" - " return N;\n" - " }\n" - "}\n" - "\n"; - } - - if (mUsesAtan2_1) - { - out << "float atanyx(float y, float x)\n" - "{\n" - " if(x == 0 && y == 0) x = 1;\n" // Avoid producing a NaN - " return atan2(y, x);\n" - "}\n"; - } - - if (mUsesAtan2_2) - { - out << "float2 atanyx(float2 y, float2 x)\n" - "{\n" - " if(x[0] == 0 && y[0] == 0) x[0] = 1;\n" - " if(x[1] == 0 && y[1] == 0) x[1] = 1;\n" - " return float2(atan2(y[0], x[0]), atan2(y[1], x[1]));\n" - "}\n"; - } - - if (mUsesAtan2_3) - { - out << "float3 atanyx(float3 y, float3 x)\n" - "{\n" - " if(x[0] == 0 && y[0] == 0) x[0] = 1;\n" - " if(x[1] == 0 && y[1] == 0) x[1] = 1;\n" - " if(x[2] == 0 && y[2] == 0) x[2] = 1;\n" - " return float3(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], x[2]));\n" - "}\n"; - } - - if (mUsesAtan2_4) - { - out << "float4 atanyx(float4 y, float4 x)\n" - "{\n" - " if(x[0] == 0 && y[0] == 0) x[0] = 1;\n" - " if(x[1] == 0 && y[1] == 0) x[1] = 1;\n" - " if(x[2] == 0 && y[2] == 0) x[2] = 1;\n" - " if(x[3] == 0 && y[3] == 0) x[3] = 1;\n" - " return float4(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], x[2]), atan2(y[3], x[3]));\n" - "}\n"; - } + builtInFunctionEmulator->OutputEmulatedFunctions(out); } void OutputHLSL::visitSymbol(TIntermSymbol *node) { - TInfoSinkBase &out = mBody; + TInfoSinkBase &out = getInfoSink(); // Handle accessing std140 structs by value if (mFlaggedStructMappedNames.count(node) > 0) @@ -1458,6 +1370,11 @@ void OutputHLSL::visitSymbol(TIntermSymbol *node) mUsesPointSize = true; out << name; } + else if (qualifier == EvqInstanceID) + { + mUsesInstanceID = true; + out << name; + } else if (name == "gl_FragDepthEXT") { mUsesFragDepth = true; @@ -1476,12 +1393,51 @@ void OutputHLSL::visitSymbol(TIntermSymbol *node) void OutputHLSL::visitRaw(TIntermRaw *node) { - mBody << node->getRawText(); + getInfoSink() << node->getRawText(); +} + +void OutputHLSL::outputEqual(Visit visit, const TType &type, TOperator op, TInfoSinkBase &out) +{ + if (type.isScalar() && !type.isArray()) + { + if (op == EOpEqual) + { + outputTriplet(visit, "(", " == ", ")", out); + } + else + { + outputTriplet(visit, "(", " != ", ")", out); + } + } + else + { + if (visit == PreVisit && op == EOpNotEqual) + { + out << "!"; + } + + if (type.isArray()) + { + const TString &functionName = addArrayEqualityFunction(type); + outputTriplet(visit, (functionName + "(").c_str(), ", ", ")", out); + } + else if (type.getBasicType() == EbtStruct) + { + const TStructure &structure = *type.getStruct(); + const TString &functionName = addStructEqualityFunction(structure); + outputTriplet(visit, (functionName + "(").c_str(), ", ", ")", out); + } + else + { + ASSERT(type.isMatrix() || type.isVector()); + outputTriplet(visit, "all(", " == ", ")", out); + } + } } bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node) { - TInfoSinkBase &out = mBody; + TInfoSinkBase &out = getInfoSink(); // Handle accessing std140 structs by value if (mFlaggedStructMappedNames.count(node) > 0) @@ -1492,7 +1448,17 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node) switch (node->getOp()) { - case EOpAssign: outputTriplet(visit, "(", " = ", ")"); break; + case EOpAssign: + if (node->getLeft()->isArray()) + { + const TString &functionName = addArrayAssignmentFunction(node->getType()); + outputTriplet(visit, (functionName + "(").c_str(), ", ", ")"); + } + else + { + outputTriplet(visit, "(", " = ", ")"); + } + break; case EOpInitialize: if (visit == PreVisit) { @@ -1502,22 +1468,21 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node) // this to "float t = x, x = t;". TIntermSymbol *symbolNode = node->getLeft()->getAsSymbolNode(); + ASSERT(symbolNode); TIntermTyped *expression = node->getRight(); - sh::SearchSymbol searchSymbol(symbolNode->getSymbol()); - expression->traverse(&searchSymbol); - bool sameSymbol = searchSymbol.foundMatch(); - - if (sameSymbol) + // TODO (jmadill): do a 'deep' scan to know if an expression is statically const + if (symbolNode->getQualifier() == EvqGlobal && expression->getQualifier() != EvqConst) { - // Type already printed - out << "t" + str(mUniqueIndex) + " = "; - expression->traverse(this); - out << ", "; - symbolNode->traverse(this); - out << " = t" + str(mUniqueIndex); - - mUniqueIndex++; + // For variables which are not constant, defer their real initialization until + // after we initialize other globals: uniforms, attributes and varyings. + mDeferredGlobalInitializers.push_back(std::make_pair(symbolNode, expression)); + const TString &initString = initializer(node->getType()); + node->setRight(new TIntermRaw(node->getType(), initString)); + } + else if (writeSameSymbolInitializer(out, symbolNode, expression)) + { + // Skip initializing the rest of the expression return false; } } @@ -1554,16 +1519,22 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node) } else if (visit == InVisit) { - out << " = mul("; + out << " = transpose(mul(transpose("; node->getLeft()->traverse(this); - out << ", "; + out << "), transpose("; } else { - out << "))"; + out << "))))"; } break; case EOpDivAssign: outputTriplet(visit, "(", " /= ", ")"); break; + case EOpIModAssign: outputTriplet(visit, "(", " %= ", ")"); break; + case EOpBitShiftLeftAssign: outputTriplet(visit, "(", " <<= ", ")"); break; + case EOpBitShiftRightAssign: outputTriplet(visit, "(", " >>= ", ")"); break; + case EOpBitwiseAndAssign: outputTriplet(visit, "(", " &= ", ")"); break; + case EOpBitwiseXorAssign: outputTriplet(visit, "(", " ^= ", ")"); break; + case EOpBitwiseOrAssign: outputTriplet(visit, "(", " |= ", ")"); break; case EOpIndexDirect: { const TType& leftType = node->getLeft()->getType(); @@ -1651,65 +1622,15 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node) case EOpSub: outputTriplet(visit, "(", " - ", ")"); break; case EOpMul: outputTriplet(visit, "(", " * ", ")"); break; case EOpDiv: outputTriplet(visit, "(", " / ", ")"); break; + case EOpIMod: outputTriplet(visit, "(", " % ", ")"); break; + case EOpBitShiftLeft: outputTriplet(visit, "(", " << ", ")"); break; + case EOpBitShiftRight: outputTriplet(visit, "(", " >> ", ")"); break; + case EOpBitwiseAnd: outputTriplet(visit, "(", " & ", ")"); break; + case EOpBitwiseXor: outputTriplet(visit, "(", " ^ ", ")"); break; + case EOpBitwiseOr: outputTriplet(visit, "(", " | ", ")"); break; case EOpEqual: case EOpNotEqual: - if (node->getLeft()->isScalar()) - { - if (node->getOp() == EOpEqual) - { - outputTriplet(visit, "(", " == ", ")"); - } - else - { - outputTriplet(visit, "(", " != ", ")"); - } - } - else if (node->getLeft()->getBasicType() == EbtStruct) - { - if (node->getOp() == EOpEqual) - { - out << "("; - } - else - { - out << "!("; - } - - const TStructure &structure = *node->getLeft()->getType().getStruct(); - const TFieldList &fields = structure.fields(); - - for (size_t i = 0; i < fields.size(); i++) - { - const TField *field = fields[i]; - - node->getLeft()->traverse(this); - out << "." + DecorateField(field->name(), structure) + " == "; - node->getRight()->traverse(this); - out << "." + DecorateField(field->name(), structure); - - if (i < fields.size() - 1) - { - out << " && "; - } - } - - out << ")"; - - return false; - } - else - { - ASSERT(node->getLeft()->isMatrix() || node->getLeft()->isVector()); - - if (node->getOp() == EOpEqual) - { - outputTriplet(visit, "all(", " == ", ")"); - } - else - { - outputTriplet(visit, "!all(", " == ", ")"); - } - } + outputEqual(visit, node->getLeft()->getType(), node->getOp(), out); break; case EOpLessThan: outputTriplet(visit, "(", " < ", ")"); break; case EOpGreaterThan: outputTriplet(visit, "(", " > ", ")"); break; @@ -1760,6 +1681,7 @@ bool OutputHLSL::visitUnary(Visit visit, TIntermUnary *node) case EOpPositive: outputTriplet(visit, "(+", "", ")"); break; case EOpVectorLogicalNot: outputTriplet(visit, "(!", "", ")"); break; case EOpLogicalNot: outputTriplet(visit, "(!", "", ")"); break; + case EOpBitwiseNot: outputTriplet(visit, "(~", "", ")"); break; case EOpPostIncrement: outputTriplet(visit, "(", "", "++)"); break; case EOpPostDecrement: outputTriplet(visit, "(", "", "--)"); break; case EOpPreIncrement: outputTriplet(visit, "(++", "", ")"); break; @@ -1772,6 +1694,21 @@ bool OutputHLSL::visitUnary(Visit visit, TIntermUnary *node) case EOpAsin: outputTriplet(visit, "asin(", "", ")"); break; case EOpAcos: outputTriplet(visit, "acos(", "", ")"); break; case EOpAtan: outputTriplet(visit, "atan(", "", ")"); break; + case EOpSinh: outputTriplet(visit, "sinh(", "", ")"); break; + case EOpCosh: outputTriplet(visit, "cosh(", "", ")"); break; + case EOpTanh: outputTriplet(visit, "tanh(", "", ")"); break; + case EOpAsinh: + ASSERT(node->getUseEmulatedFunction()); + writeEmulatedFunctionTriplet(visit, "asinh("); + break; + case EOpAcosh: + ASSERT(node->getUseEmulatedFunction()); + writeEmulatedFunctionTriplet(visit, "acosh("); + break; + case EOpAtanh: + ASSERT(node->getUseEmulatedFunction()); + writeEmulatedFunctionTriplet(visit, "atanh("); + break; case EOpExp: outputTriplet(visit, "exp(", "", ")"); break; case EOpLog: outputTriplet(visit, "log(", "", ")"); break; case EOpExp2: outputTriplet(visit, "exp2(", "", ")"); break; @@ -1781,8 +1718,47 @@ bool OutputHLSL::visitUnary(Visit visit, TIntermUnary *node) case EOpAbs: outputTriplet(visit, "abs(", "", ")"); break; case EOpSign: outputTriplet(visit, "sign(", "", ")"); break; case EOpFloor: outputTriplet(visit, "floor(", "", ")"); break; + case EOpTrunc: outputTriplet(visit, "trunc(", "", ")"); break; + case EOpRound: outputTriplet(visit, "round(", "", ")"); break; + case EOpRoundEven: + ASSERT(node->getUseEmulatedFunction()); + writeEmulatedFunctionTriplet(visit, "roundEven("); + break; case EOpCeil: outputTriplet(visit, "ceil(", "", ")"); break; case EOpFract: outputTriplet(visit, "frac(", "", ")"); break; + case EOpIsNan: + outputTriplet(visit, "isnan(", "", ")"); + mRequiresIEEEStrictCompiling = true; + break; + case EOpIsInf: outputTriplet(visit, "isinf(", "", ")"); break; + case EOpFloatBitsToInt: outputTriplet(visit, "asint(", "", ")"); break; + case EOpFloatBitsToUint: outputTriplet(visit, "asuint(", "", ")"); break; + case EOpIntBitsToFloat: outputTriplet(visit, "asfloat(", "", ")"); break; + case EOpUintBitsToFloat: outputTriplet(visit, "asfloat(", "", ")"); break; + case EOpPackSnorm2x16: + ASSERT(node->getUseEmulatedFunction()); + writeEmulatedFunctionTriplet(visit, "packSnorm2x16("); + break; + case EOpPackUnorm2x16: + ASSERT(node->getUseEmulatedFunction()); + writeEmulatedFunctionTriplet(visit, "packUnorm2x16("); + break; + case EOpPackHalf2x16: + ASSERT(node->getUseEmulatedFunction()); + writeEmulatedFunctionTriplet(visit, "packHalf2x16("); + break; + case EOpUnpackSnorm2x16: + ASSERT(node->getUseEmulatedFunction()); + writeEmulatedFunctionTriplet(visit, "unpackSnorm2x16("); + break; + case EOpUnpackUnorm2x16: + ASSERT(node->getUseEmulatedFunction()); + writeEmulatedFunctionTriplet(visit, "unpackUnorm2x16("); + break; + case EOpUnpackHalf2x16: + ASSERT(node->getUseEmulatedFunction()); + writeEmulatedFunctionTriplet(visit, "unpackHalf2x16("); + break; case EOpLength: outputTriplet(visit, "length(", "", ")"); break; case EOpNormalize: outputTriplet(visit, "normalize(", "", ")"); break; case EOpDFdx: @@ -1815,6 +1791,13 @@ bool OutputHLSL::visitUnary(Visit visit, TIntermUnary *node) outputTriplet(visit, "fwidth(", "", ")"); } break; + case EOpTranspose: outputTriplet(visit, "transpose(", "", ")"); break; + case EOpDeterminant: outputTriplet(visit, "determinant(transpose(", "", "))"); break; + case EOpInverse: + ASSERT(node->getUseEmulatedFunction()); + writeEmulatedFunctionTriplet(visit, "inverse("); + break; + case EOpAny: outputTriplet(visit, "any(", "", ")"); break; case EOpAll: outputTriplet(visit, "all(", "", ")"); break; default: UNREACHABLE(); @@ -1825,7 +1808,7 @@ bool OutputHLSL::visitUnary(Visit visit, TIntermUnary *node) bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) { - TInfoSinkBase &out = mBody; + TInfoSinkBase &out = getInfoSink(); switch (node->getOp()) { @@ -1843,7 +1826,11 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) traverseStatements(*sit); - out << ";\n"; + // Don't output ; after case labels, they're terminated by : + // This is needed especially since outputting a ; after a case statement would turn empty + // case statements into non-empty case statements, disallowing fall-through from them. + if ((*sit)->getAsCaseNode() == nullptr) + out << ";\n"; } if (mInsideFunction) @@ -1871,11 +1858,12 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) if (!variable->getAsSymbolNode() || variable->getAsSymbolNode()->getSymbol() != "") // Variable declaration { - for (TIntermSequence::iterator sit = sequence->begin(); sit != sequence->end(); sit++) + for (auto it = sequence->cbegin(); it != sequence->cend(); ++it) { - if (isSingleStatement(*sit)) + const auto &seqElement = *it; + if (isSingleStatement(seqElement)) { - mUnfoldShortCircuit->traverse(*sit); + mUnfoldShortCircuit->traverse(seqElement); } if (!mInsideFunction) @@ -1885,7 +1873,7 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) out << TypeString(variable->getType()) + " "; - TIntermSymbol *symbol = (*sit)->getAsSymbolNode(); + TIntermSymbol *symbol = seqElement->getAsSymbolNode(); if (symbol) { @@ -1895,10 +1883,10 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) } else { - (*sit)->traverse(this); + seqElement->traverse(this); } - if (*sit != sequence->back()) + if (seqElement != sequence->back()) { out << ";\n"; } @@ -2149,7 +2137,7 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) bool bias = (arguments->size() > mandatoryArgumentCount); // Bias argument is optional - if (lod0 || mContext.shaderType == GL_VERTEX_SHADER) + if (lod0 || mShaderType == GL_VERTEX_SHADER) { if (bias) { @@ -2217,7 +2205,7 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) { const TString &structName = StructNameString(*node->getType().getStruct()); mStructureHLSL->addConstructor(node->getType(), structName, node->getSequence()); - outputTriplet(visit, structName + "_ctor(", ", ", ")"); + outputTriplet(visit, (structName + "_ctor(").c_str(), ", ", ")"); } break; case EOpLessThan: outputTriplet(visit, "(", " < ", ")"); break; @@ -2227,37 +2215,15 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) case EOpVectorEqual: outputTriplet(visit, "(", " == ", ")"); break; case EOpVectorNotEqual: outputTriplet(visit, "(", " != ", ")"); break; case EOpMod: - { - // We need to look at the number of components in both arguments - const int modValue = (*node->getSequence())[0]->getAsTyped()->getNominalSize() * 10 + - (*node->getSequence())[1]->getAsTyped()->getNominalSize(); - switch (modValue) - { - case 11: mUsesMod1 = true; break; - case 22: mUsesMod2v = true; break; - case 21: mUsesMod2f = true; break; - case 33: mUsesMod3v = true; break; - case 31: mUsesMod3f = true; break; - case 44: mUsesMod4v = true; break; - case 41: mUsesMod4f = true; break; - default: UNREACHABLE(); - } - - outputTriplet(visit, "mod(", ", ", ")"); - } + ASSERT(node->getUseEmulatedFunction()); + writeEmulatedFunctionTriplet(visit, "mod("); break; + case EOpModf: outputTriplet(visit, "modf(", ", ", ")"); break; case EOpPow: outputTriplet(visit, "pow(", ", ", ")"); break; case EOpAtan: ASSERT(node->getSequence()->size() == 2); // atan(x) is a unary operator - switch ((*node->getSequence())[0]->getAsTyped()->getNominalSize()) - { - case 1: mUsesAtan2_1 = true; break; - case 2: mUsesAtan2_2 = true; break; - case 3: mUsesAtan2_3 = true; break; - case 4: mUsesAtan2_4 = true; break; - default: UNREACHABLE(); - } - outputTriplet(visit, "atanyx(", ", ", ")"); + ASSERT(node->getUseEmulatedFunction()); + writeEmulatedFunctionTriplet(visit, "atan("); break; case EOpMin: outputTriplet(visit, "min(", ", ", ")"); break; case EOpMax: outputTriplet(visit, "max(", ", ", ")"); break; @@ -2269,21 +2235,15 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) case EOpDot: outputTriplet(visit, "dot(", ", ", ")"); break; case EOpCross: outputTriplet(visit, "cross(", ", ", ")"); break; case EOpFaceForward: - { - switch ((*node->getSequence())[0]->getAsTyped()->getNominalSize()) // Number of components in the first argument - { - case 1: mUsesFaceforward1 = true; break; - case 2: mUsesFaceforward2 = true; break; - case 3: mUsesFaceforward3 = true; break; - case 4: mUsesFaceforward4 = true; break; - default: UNREACHABLE(); - } - - outputTriplet(visit, "faceforward(", ", ", ")"); - } + ASSERT(node->getUseEmulatedFunction()); + writeEmulatedFunctionTriplet(visit, "faceforward("); break; case EOpReflect: outputTriplet(visit, "reflect(", ", ", ")"); break; case EOpRefract: outputTriplet(visit, "refract(", ", ", ")"); break; + case EOpOuterProduct: + ASSERT(node->getUseEmulatedFunction()); + writeEmulatedFunctionTriplet(visit, "outerProduct("); + break; case EOpMul: outputTriplet(visit, "(", " * ", ")"); break; default: UNREACHABLE(); } @@ -2293,7 +2253,7 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) bool OutputHLSL::visitSelection(Visit visit, TIntermSelection *node) { - TInfoSinkBase &out = mBody; + TInfoSinkBase &out = getInfoSink(); if (node->usesTernaryOperator()) { @@ -2307,7 +2267,7 @@ bool OutputHLSL::visitSelection(Visit visit, TIntermSelection *node) // however flattening all the ifs in branch heavy shaders made D3D error too. // As a temporary workaround we flatten the ifs only if there is at least a loop // present somewhere in the shader. - if (mContext.shaderType == GL_FRAGMENT_SHADER && mContainsAnyLoop) + if (mShaderType == GL_FRAGMENT_SHADER && mContainsAnyLoop) { out << "FLATTEN "; } @@ -2361,6 +2321,37 @@ bool OutputHLSL::visitSelection(Visit visit, TIntermSelection *node) return false; } +bool OutputHLSL::visitSwitch(Visit visit, TIntermSwitch *node) +{ + if (node->getStatementList()) + { + node->setStatementList(RemoveSwitchFallThrough::removeFallThrough(node->getStatementList())); + outputTriplet(visit, "switch (", ") ", ""); + // The curly braces get written when visiting the statementList aggregate + } + else + { + // No statementList, so it won't output curly braces + outputTriplet(visit, "switch (", ") {", "}\n"); + } + return true; +} + +bool OutputHLSL::visitCase(Visit visit, TIntermCase *node) +{ + if (node->hasCondition()) + { + outputTriplet(visit, "case (", "", "):\n"); + return true; + } + else + { + TInfoSinkBase &out = getInfoSink(); + out << "default:\n"; + return false; + } +} + void OutputHLSL::visitConstantUnion(TIntermConstantUnion *node) { writeConstantUnion(node->getType(), node->getUnionArrayPointer()); @@ -2388,7 +2379,7 @@ bool OutputHLSL::visitLoop(Visit visit, TIntermLoop *node) } } - TInfoSinkBase &out = mBody; + TInfoSinkBase &out = getInfoSink(); if (node->getType() == ELoopDoWhile) { @@ -2454,7 +2445,7 @@ bool OutputHLSL::visitLoop(Visit visit, TIntermLoop *node) bool OutputHLSL::visitBranch(Visit visit, TIntermBranch *node) { - TInfoSinkBase &out = mBody; + TInfoSinkBase &out = getInfoSink(); switch (node->getFlowOp()) { @@ -2556,7 +2547,7 @@ bool OutputHLSL::isSingleStatement(TIntermNode *node) bool OutputHLSL::handleExcessiveLoop(TIntermLoop *node) { const int MAX_LOOP_ITERATIONS = 254; - TInfoSinkBase &out = mBody; + TInfoSinkBase &out = getInfoSink(); // Parse loops of the form: // for(int index = initial; index [comparator] limit; index += increment) @@ -2756,10 +2747,8 @@ bool OutputHLSL::handleExcessiveLoop(TIntermLoop *node) return false; // Not handled as an excessive loop } -void OutputHLSL::outputTriplet(Visit visit, const TString &preString, const TString &inString, const TString &postString) +void OutputHLSL::outputTriplet(Visit visit, const char *preString, const char *inString, const char *postString, TInfoSinkBase &out) { - TInfoSinkBase &out = mBody; - if (visit == PreVisit) { out << preString; @@ -2774,19 +2763,26 @@ void OutputHLSL::outputTriplet(Visit visit, const TString &preString, const TStr } } +void OutputHLSL::outputTriplet(Visit visit, const char *preString, const char *inString, const char *postString) +{ + outputTriplet(visit, preString, inString, postString, getInfoSink()); +} + void OutputHLSL::outputLineDirective(int line) { - if ((mContext.compileOptions & SH_LINE_DIRECTIVES) && (line > 0)) + if ((mCompileOptions & SH_LINE_DIRECTIVES) && (line > 0)) { - mBody << "\n"; - mBody << "#line " << line; + TInfoSinkBase &out = getInfoSink(); + + out << "\n"; + out << "#line " << line; - if (mContext.sourcePath) + if (mSourcePath) { - mBody << " \"" << mContext.sourcePath << "\""; + out << " \"" << mSourcePath << "\""; } - mBody << "\n"; + out << "\n"; } } @@ -2832,15 +2828,15 @@ TString OutputHLSL::initializer(const TType &type) return "{" + string + "}"; } -void OutputHLSL::outputConstructor(Visit visit, const TType &type, const TString &name, const TIntermSequence *parameters) +void OutputHLSL::outputConstructor(Visit visit, const TType &type, const char *name, const TIntermSequence *parameters) { - TInfoSinkBase &out = mBody; + TInfoSinkBase &out = getInfoSink(); if (visit == PreVisit) { mStructureHLSL->addConstructor(type, name, parameters); - out << name + "("; + out << name << "("; } else if (visit == InVisit) { @@ -2854,7 +2850,7 @@ void OutputHLSL::outputConstructor(Visit visit, const TType &type, const TString const ConstantUnion *OutputHLSL::writeConstantUnion(const TType &type, const ConstantUnion *constUnion) { - TInfoSinkBase &out = mBody; + TInfoSinkBase &out = getInfoSink(); const TStructure* structure = type.getStruct(); if (structure) @@ -2912,4 +2908,209 @@ const ConstantUnion *OutputHLSL::writeConstantUnion(const TType &type, const Con return constUnion; } +void OutputHLSL::writeEmulatedFunctionTriplet(Visit visit, const char *preStr) +{ + TString preString = BuiltInFunctionEmulator::GetEmulatedFunctionName(preStr); + outputTriplet(visit, preString.c_str(), ", ", ")"); +} + +bool OutputHLSL::writeSameSymbolInitializer(TInfoSinkBase &out, TIntermSymbol *symbolNode, TIntermTyped *expression) +{ + sh::SearchSymbol searchSymbol(symbolNode->getSymbol()); + expression->traverse(&searchSymbol); + + if (searchSymbol.foundMatch()) + { + // Type already printed + out << "t" + str(mUniqueIndex) + " = "; + expression->traverse(this); + out << ", "; + symbolNode->traverse(this); + out << " = t" + str(mUniqueIndex); + + mUniqueIndex++; + return true; + } + + return false; +} + +void OutputHLSL::writeDeferredGlobalInitializers(TInfoSinkBase &out) +{ + out << "#define ANGLE_USES_DEFERRED_INIT\n" + << "\n" + << "void initializeDeferredGlobals()\n" + << "{\n"; + + for (auto it = mDeferredGlobalInitializers.cbegin(); it != mDeferredGlobalInitializers.cend(); ++it) + { + const auto &deferredGlobal = *it; + TIntermSymbol *symbol = deferredGlobal.first; + TIntermTyped *expression = deferredGlobal.second; + ASSERT(symbol); + ASSERT(symbol->getQualifier() == EvqGlobal && expression->getQualifier() != EvqConst); + + out << " " << Decorate(symbol->getSymbol()) << " = "; + + if (!writeSameSymbolInitializer(out, symbol, expression)) + { + ASSERT(mInfoSinkStack.top() == &out); + expression->traverse(this); + } + + out << ";\n"; + } + + out << "}\n" + << "\n"; +} + +TString OutputHLSL::addStructEqualityFunction(const TStructure &structure) +{ + const TFieldList &fields = structure.fields(); + + for (auto it = mStructEqualityFunctions.cbegin(); it != mStructEqualityFunctions.cend(); ++it) + { + auto *eqFunction = *it; + if (eqFunction->structure == &structure) + { + return eqFunction->functionName; + } + } + + const TString &structNameString = StructNameString(structure); + + StructEqualityFunction *function = new StructEqualityFunction(); + function->structure = &structure; + function->functionName = "angle_eq_" + structNameString; + + TInfoSinkBase fnOut; + + fnOut << "bool " << function->functionName << "(" << structNameString << " a, " << structNameString + " b)\n" + << "{\n" + " return "; + + for (size_t i = 0; i < fields.size(); i++) + { + const TField *field = fields[i]; + const TType *fieldType = field->type(); + + const TString &fieldNameA = "a." + Decorate(field->name()); + const TString &fieldNameB = "b." + Decorate(field->name()); + + if (i > 0) + { + fnOut << " && "; + } + + fnOut << "("; + outputEqual(PreVisit, *fieldType, EOpEqual, fnOut); + fnOut << fieldNameA; + outputEqual(InVisit, *fieldType, EOpEqual, fnOut); + fnOut << fieldNameB; + outputEqual(PostVisit, *fieldType, EOpEqual, fnOut); + fnOut << ")"; + } + + fnOut << ";\n" << "}\n"; + + function->functionDefinition = fnOut.c_str(); + + mStructEqualityFunctions.push_back(function); + mEqualityFunctions.push_back(function); + + return function->functionName; +} + +TString OutputHLSL::addArrayEqualityFunction(const TType& type) +{ + for (auto it = mArrayEqualityFunctions.cbegin(); it != mArrayEqualityFunctions.cend(); ++it) + { + const auto &eqFunction = *it; + if (eqFunction->type == type) + { + return eqFunction->functionName; + } + } + + const TString &typeName = TypeString(type); + + ArrayHelperFunction *function = new ArrayHelperFunction(); + function->type = type; + + TInfoSinkBase fnNameOut; + fnNameOut << "angle_eq_" << type.getArraySize() << "_" << typeName; + function->functionName = fnNameOut.c_str(); + + TType nonArrayType = type; + nonArrayType.clearArrayness(); + + TInfoSinkBase fnOut; + + fnOut << "bool " << function->functionName << "(" + << typeName << " a[" << type.getArraySize() << "], " + << typeName << " b[" << type.getArraySize() << "])\n" + << "{\n" + " for (int i = 0; i < " << type.getArraySize() << "; ++i)\n" + " {\n" + " if ("; + + outputEqual(PreVisit, nonArrayType, EOpNotEqual, fnOut); + fnOut << "a[i]"; + outputEqual(InVisit, nonArrayType, EOpNotEqual, fnOut); + fnOut << "b[i]"; + outputEqual(PostVisit, nonArrayType, EOpNotEqual, fnOut); + + fnOut << ") { return false; }\n" + " }\n" + " return true;\n" + "}\n"; + + function->functionDefinition = fnOut.c_str(); + + mArrayEqualityFunctions.push_back(function); + mEqualityFunctions.push_back(function); + + return function->functionName; +} + +TString OutputHLSL::addArrayAssignmentFunction(const TType& type) +{ + for (auto it = mArrayAssignmentFunctions.cbegin(); it != mArrayAssignmentFunctions.cend(); ++it) + { + const auto &assignFunction = *it; + if (assignFunction.type == type) + { + return assignFunction.functionName; + } + } + + const TString &typeName = TypeString(type); + + ArrayHelperFunction function; + function.type = type; + + TInfoSinkBase fnNameOut; + fnNameOut << "angle_assign_" << type.getArraySize() << "_" << typeName; + function.functionName = fnNameOut.c_str(); + + TInfoSinkBase fnOut; + + fnOut << "void " << function.functionName << "(out " + << typeName << " a[" << type.getArraySize() << "], " + << typeName << " b[" << type.getArraySize() << "])\n" + << "{\n" + " for (int i = 0; i < " << type.getArraySize() << "; ++i)\n" + " {\n" + " a[i] = b[i];\n" + " }\n" + "}\n"; + + function.functionDefinition = fnOut.c_str(); + + mArrayAssignmentFunctions.push_back(function); + + return function.functionName; +} + } diff --git a/src/3rdparty/angle/src/compiler/translator/OutputHLSL.h b/src/3rdparty/angle/src/compiler/translator/OutputHLSL.h index 5525e6eaa6..51da877c72 100644 --- a/src/3rdparty/angle/src/compiler/translator/OutputHLSL.h +++ b/src/3rdparty/angle/src/compiler/translator/OutputHLSL.h @@ -4,18 +4,20 @@ // found in the LICENSE file. // -#ifndef COMPILER_OUTPUTHLSL_H_ -#define COMPILER_OUTPUTHLSL_H_ +#ifndef COMPILER_TRANSLATOR_OUTPUTHLSL_H_ +#define COMPILER_TRANSLATOR_OUTPUTHLSL_H_ #include #include #include +#include #include "angle_gl.h" - #include "compiler/translator/IntermNode.h" #include "compiler/translator/ParseContext.h" +class BuiltInFunctionEmulator; + namespace sh { class UnfoldShortCircuit; @@ -27,20 +29,25 @@ typedef std::map ReferencedSymbols; class OutputHLSL : public TIntermTraverser { public: - OutputHLSL(TParseContext &context, TranslatorHLSL *parentTranslator); - ~OutputHLSL(); + OutputHLSL(sh::GLenum shaderType, int shaderVersion, + const TExtensionBehavior &extensionBehavior, + const char *sourcePath, ShShaderOutput outputType, + int numRenderTargets, const std::vector &uniforms, + int compileOptions); - void output(); + ~OutputHLSL(); - TInfoSinkBase &getBodyStream(); + void output(TIntermNode *treeRoot, TInfoSinkBase &objSink); const std::map &getInterfaceBlockRegisterMap() const; const std::map &getUniformRegisterMap() const; static TString initializer(const TType &type); + TInfoSinkBase &getInfoSink() { ASSERT(!mInfoSinkStack.empty()); return *mInfoSinkStack.top(); } + protected: - void header(); + void header(const BuiltInFunctionEmulator *builtInFunctionEmulator); // Visit AST nodes and output their code to the body stream void visitSymbol(TIntermSymbol*); @@ -49,6 +56,8 @@ class OutputHLSL : public TIntermTraverser bool visitBinary(Visit visit, TIntermBinary*); bool visitUnary(Visit visit, TIntermUnary*); bool visitSelection(Visit visit, TIntermSelection*); + bool visitSwitch(Visit visit, TIntermSwitch *); + bool visitCase(Visit visit, TIntermCase *); bool visitAggregate(Visit visit, TIntermAggregate*); bool visitLoop(Visit visit, TIntermLoop*); bool visitBranch(Visit visit, TIntermBranch*); @@ -56,16 +65,39 @@ class OutputHLSL : public TIntermTraverser void traverseStatements(TIntermNode *node); bool isSingleStatement(TIntermNode *node); bool handleExcessiveLoop(TIntermLoop *node); - void outputTriplet(Visit visit, const TString &preString, const TString &inString, const TString &postString); + + // Emit one of three strings depending on traverse phase. Called with literal strings so using const char* instead of TString. + void outputTriplet(Visit visit, const char *preString, const char *inString, const char *postString, TInfoSinkBase &out); + void outputTriplet(Visit visit, const char *preString, const char *inString, const char *postString); void outputLineDirective(int line); TString argumentString(const TIntermSymbol *symbol); int vectorSize(const TType &type) const; - void outputConstructor(Visit visit, const TType &type, const TString &name, const TIntermSequence *parameters); + // Emit constructor. Called with literal names so using const char* instead of TString. + void outputConstructor(Visit visit, const TType &type, const char *name, const TIntermSequence *parameters); const ConstantUnion *writeConstantUnion(const TType &type, const ConstantUnion *constUnion); - TParseContext &mContext; + void outputEqual(Visit visit, const TType &type, TOperator op, TInfoSinkBase &out); + + void writeEmulatedFunctionTriplet(Visit visit, const char *preStr); + void makeFlaggedStructMaps(const std::vector &flaggedStructs); + + // Returns true if it found a 'same symbol' initializer (initializer that references the variable it's initting) + bool writeSameSymbolInitializer(TInfoSinkBase &out, TIntermSymbol *symbolNode, TIntermTyped *expression); + void writeDeferredGlobalInitializers(TInfoSinkBase &out); + + // Returns the function name + TString addStructEqualityFunction(const TStructure &structure); + TString addArrayEqualityFunction(const TType &type); + TString addArrayAssignmentFunction(const TType &type); + + sh::GLenum mShaderType; + int mShaderVersion; + const TExtensionBehavior &mExtensionBehavior; + const char *mSourcePath; const ShShaderOutput mOutputType; + int mCompileOptions; + UnfoldShortCircuit *mUnfoldShortCircuit; bool mInsideFunction; @@ -74,6 +106,11 @@ class OutputHLSL : public TIntermTraverser TInfoSinkBase mBody; TInfoSinkBase mFooter; + // A stack is useful when we want to traverse in the header, or in helper functions, but not always + // write to the body. Instead use an InfoSink stack to keep our current state intact. + // TODO (jmadill): Just passing an InfoSink in function parameters would be simpler. + std::stack mInfoSinkStack; + ReferencedSymbols mReferencedUniforms; ReferencedSymbols mReferencedInterfaceBlocks; ReferencedSymbols mReferencedAttributes; @@ -119,25 +156,13 @@ class OutputHLSL : public TIntermTraverser bool mUsesPointCoord; bool mUsesFrontFacing; bool mUsesPointSize; + bool mUsesInstanceID; bool mUsesFragDepth; bool mUsesXor; - bool mUsesMod1; - bool mUsesMod2v; - bool mUsesMod2f; - bool mUsesMod3v; - bool mUsesMod3f; - bool mUsesMod4v; - bool mUsesMod4f; - bool mUsesFaceforward1; - bool mUsesFaceforward2; - bool mUsesFaceforward3; - bool mUsesFaceforward4; - bool mUsesAtan2_1; - bool mUsesAtan2_2; - bool mUsesAtan2_3; - bool mUsesAtan2_4; bool mUsesDiscardRewriting; bool mUsesNestedBreak; + bool mRequiresIEEEStrictCompiling; + int mNumRenderTargets; @@ -156,9 +181,41 @@ class OutputHLSL : public TIntermTraverser std::map mFlaggedStructMappedNames; std::map mFlaggedStructOriginalNames; - void makeFlaggedStructMaps(const std::vector &flaggedStructs); + // Some initializers use varyings, uniforms or attributes, thus we can't evaluate some variables + // at global static scope in HLSL. These variables depend on values which we retrieve from the + // shader input structure, which we set in the D3D main function. Instead, we can initialize + // these static globals after we initialize our other globals. + std::vector> mDeferredGlobalInitializers; + + struct HelperFunction + { + TString functionName; + TString functionDefinition; + + virtual ~HelperFunction() {} + }; + + // A list of all equality comparison functions. It's important to preserve the order at + // which we add the functions, since nested structures call each other recursively, and + // structure equality functions may need to call array equality functions and vice versa. + // The ownership of the pointers is maintained by the type-specific arrays. + std::vector mEqualityFunctions; + + struct StructEqualityFunction : public HelperFunction + { + const TStructure *structure; + }; + std::vector mStructEqualityFunctions; + + struct ArrayHelperFunction : public HelperFunction + { + TType type; + }; + std::vector mArrayEqualityFunctions; + + std::vector mArrayAssignmentFunctions; }; } -#endif // COMPILER_OUTPUTHLSL_H_ +#endif // COMPILER_TRANSLATOR_OUTPUTHLSL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/ParseContext.cpp b/src/3rdparty/angle/src/compiler/translator/ParseContext.cpp index 37969b5468..7ad3f817ad 100644 --- a/src/3rdparty/angle/src/compiler/translator/ParseContext.cpp +++ b/src/3rdparty/angle/src/compiler/translator/ParseContext.cpp @@ -9,8 +9,9 @@ #include #include -#include "compiler/translator/glslang.h" #include "compiler/preprocessor/SourceLocation.h" +#include "compiler/translator/glslang.h" +#include "compiler/translator/ValidateSwitch.h" /////////////////////////////////////////////////////////////////////// // @@ -796,9 +797,24 @@ bool TParseContext::arrayErrorCheck(const TSourceLoc& line, const TString& ident bool sameScope = false; TSymbol* symbol = symbolTable.find(identifier, 0, &builtIn, &sameScope); if (symbol == 0 || !sameScope) { - if (reservedErrorCheck(line, identifier)) - return true; - + bool needsReservedErrorCheck = true; + + // gl_LastFragData may be redeclared with a new precision qualifier + if (identifier.compare(0, 15, "gl_LastFragData") == 0) { + if (type.arraySize == static_cast(symbolTable.findBuiltIn("gl_MaxDrawBuffers", shaderVersion))->getConstPointer()->getIConst()) { + if (TSymbol* builtInSymbol = symbolTable.findBuiltIn(identifier, shaderVersion)) { + needsReservedErrorCheck = extensionErrorCheck(line, builtInSymbol->getExtension()); + } + } else { + error(line, "redeclaration of array with size != gl_MaxDrawBuffers", identifier.c_str()); + return true; + } + } + + if (needsReservedErrorCheck) + if (reservedErrorCheck(line, identifier)) + return true; + variable = new TVariable(&identifier, TType(type)); if (type.arraySize) @@ -976,6 +992,26 @@ bool TParseContext::layoutLocationErrorCheck(const TSourceLoc& location, const T return false; } +bool TParseContext::functionCallLValueErrorCheck(const TFunction *fnCandidate, TIntermAggregate *aggregate) +{ + for (size_t i = 0; i < fnCandidate->getParamCount(); ++i) + { + TQualifier qual = fnCandidate->getParam(i).type->getQualifier(); + if (qual == EvqOut || qual == EvqInOut) + { + TIntermTyped *node = (*(aggregate->getSequence()))[i]->getAsTyped(); + if (lValueErrorCheck(node->getLine(), "assign", node)) + { + error(node->getLine(), + "Constant value cannot be passed for 'out' or 'inout' parameters.", "Error"); + recover(); + return true; + } + } + } + return false; +} + bool TParseContext::supportsExtension(const char* extension) { const TExtensionBehavior& extbehavior = extensionBehavior(); @@ -1062,14 +1098,14 @@ const TVariable *TParseContext::getNamedVariable(const TSourceLoc &location, // // Return the function symbol if found, otherwise 0. // -const TFunction* TParseContext::findFunction(const TSourceLoc& line, TFunction* call, int shaderVersion, bool *builtIn) +const TFunction* TParseContext::findFunction(const TSourceLoc& line, TFunction* call, int inputShaderVersion, bool *builtIn) { // First find by unmangled name to check whether the function name has been // hidden by a variable name or struct typename. // If a function is found, check for one with a matching argument list. - const TSymbol* symbol = symbolTable.find(call->getName(), shaderVersion, builtIn); + const TSymbol* symbol = symbolTable.find(call->getName(), inputShaderVersion, builtIn); if (symbol == 0 || symbol->isFunction()) { - symbol = symbolTable.find(call->getMangledName(), shaderVersion, builtIn); + symbol = symbolTable.find(call->getMangledName(), inputShaderVersion, builtIn); } if (symbol == 0) { @@ -1162,7 +1198,7 @@ bool TParseContext::executeInitializer(const TSourceLoc& line, const TString& id if (qualifier != EvqConst) { TIntermSymbol* intermSymbol = intermediate.addSymbol(variable->getUniqueId(), variable->getName(), variable->getType(), line); - intermNode = intermediate.addAssign(EOpInitialize, intermSymbol, initializer, line); + intermNode = createAssign(EOpInitialize, intermSymbol, initializer, line); if (intermNode == 0) { assignError(line, "=", intermSymbol->getCompleteString(), initializer->getCompleteString()); return true; @@ -1375,7 +1411,7 @@ TIntermAggregate* TParseContext::parseInvariantDeclaration(const TSourceLoc &inv recover(); return NULL; } - symbolTable.addInvariantVarying(*identifier); + symbolTable.addInvariantVarying(std::string(identifier->c_str())); const TVariable *variable = getNamedVariable(identifierLoc, identifier, symbol); ASSERT(variable); const TType &type = variable->getType(); @@ -1605,7 +1641,7 @@ TFunction *TParseContext::addConstructorFunc(TPublicType publicType) // // Returns 0 for an error or the constructed node (aggregate or typed) for no error. // -TIntermTyped *TParseContext::addConstructor(TIntermNode *arguments, const TType *type, TOperator op, TFunction *fnCall, const TSourceLoc &line) +TIntermTyped *TParseContext::addConstructor(TIntermNode *arguments, TType *type, TOperator op, TFunction *fnCall, const TSourceLoc &line) { TIntermAggregate *aggregateArguments = arguments->getAsAggregate(); @@ -1633,13 +1669,21 @@ TIntermTyped *TParseContext::addConstructor(TIntermNode *arguments, const TType } // Turn the argument list itself into a constructor - TIntermTyped *constructor = intermediate.setAggregateOperator(aggregateArguments, op, line); - TIntermTyped *constConstructor = foldConstConstructor(constructor->getAsAggregate(), *type); + TIntermAggregate *constructor = intermediate.setAggregateOperator(aggregateArguments, op, line); + TIntermTyped *constConstructor = foldConstConstructor(constructor, *type); if (constConstructor) { return constConstructor; } + // Structs should not be precision qualified, the individual members may be. + // Built-in types on the other hand should be precision qualified. + if (op != EOpConstructStruct) + { + constructor->setPrecisionFromChildren(); + type->setPrecision(constructor->getPrecision()); + } + return constructor; } @@ -2028,9 +2072,11 @@ TIntermTyped* TParseContext::addIndexExpression(TIntermTyped *baseExpression, co recover(); } - if (indexExpression->getQualifier() == EvqConst) + TIntermConstantUnion *indexConstantUnion = indexExpression->getAsConstantUnion(); + + if (indexExpression->getQualifier() == EvqConst && indexConstantUnion) { - int index = indexExpression->getAsConstantUnion()->getIConst(0); + int index = indexConstantUnion->getIConst(0); if (index < 0) { std::stringstream infoStream; @@ -2091,7 +2137,7 @@ TIntermTyped* TParseContext::addIndexExpression(TIntermTyped *baseExpression, co index = baseExpression->getType().getNominalSize() - 1; } - indexExpression->getAsConstantUnion()->getUnionArrayPointer()->setIConst(index); + indexConstantUnion->getUnionArrayPointer()->setIConst(index); indexedExpression = intermediate.addIndex(EOpIndexDirect, baseExpression, indexExpression, location); } } @@ -2520,7 +2566,10 @@ TPublicType TParseContext::addStructure(const TSourceLoc& structLine, const TSou TStructure* structure = new TStructure(structName, fieldList); TType* structureType = new TType(structure); + // Store a bool in the struct if we're at global scope, to allow us to + // skip the local struct scoping workaround in HLSL. structure->setUniqueId(TSymbolTable::nextUniqueId()); + structure->setAtGlobalScope(symbolTable.atGlobalLevel()); if (!structName->empty()) { @@ -2560,6 +2609,553 @@ TPublicType TParseContext::addStructure(const TSourceLoc& structLine, const TSou return publicType; } +TIntermSwitch *TParseContext::addSwitch(TIntermTyped *init, TIntermAggregate *statementList, const TSourceLoc &loc) +{ + TBasicType switchType = init->getBasicType(); + if ((switchType != EbtInt && switchType != EbtUInt) || + init->isMatrix() || + init->isArray() || + init->isVector()) + { + error(init->getLine(), "init-expression in a switch statement must be a scalar integer", "switch"); + recover(); + return nullptr; + } + + if (statementList) + { + if (!ValidateSwitch::validate(switchType, this, statementList, loc)) + { + recover(); + return nullptr; + } + } + + TIntermSwitch *node = intermediate.addSwitch(init, statementList, loc); + if (node == nullptr) + { + error(loc, "erroneous switch statement", "switch"); + recover(); + return nullptr; + } + return node; +} + +TIntermCase *TParseContext::addCase(TIntermTyped *condition, const TSourceLoc &loc) +{ + if (mSwitchNestingLevel == 0) + { + error(loc, "case labels need to be inside switch statements", "case"); + recover(); + return nullptr; + } + if (condition == nullptr) + { + error(loc, "case label must have a condition", "case"); + recover(); + return nullptr; + } + if ((condition->getBasicType() != EbtInt && condition->getBasicType() != EbtUInt) || + condition->isMatrix() || + condition->isArray() || + condition->isVector()) + { + error(condition->getLine(), "case label must be a scalar integer", "case"); + recover(); + } + TIntermConstantUnion *conditionConst = condition->getAsConstantUnion(); + if (conditionConst == nullptr) + { + error(condition->getLine(), "case label must be constant", "case"); + recover(); + } + TIntermCase *node = intermediate.addCase(condition, loc); + if (node == nullptr) + { + error(loc, "erroneous case statement", "case"); + recover(); + return nullptr; + } + return node; +} + +TIntermCase *TParseContext::addDefault(const TSourceLoc &loc) +{ + if (mSwitchNestingLevel == 0) + { + error(loc, "default labels need to be inside switch statements", "default"); + recover(); + return nullptr; + } + TIntermCase *node = intermediate.addCase(nullptr, loc); + if (node == nullptr) + { + error(loc, "erroneous default statement", "default"); + recover(); + return nullptr; + } + return node; +} + +TIntermTyped *TParseContext::createUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc, + const TType *funcReturnType) +{ + if (child == nullptr) + { + return nullptr; + } + + switch (op) + { + case EOpLogicalNot: + if (child->getBasicType() != EbtBool || + child->isMatrix() || + child->isArray() || + child->isVector()) + { + return nullptr; + } + break; + case EOpBitwiseNot: + if ((child->getBasicType() != EbtInt && child->getBasicType() != EbtUInt) || + child->isMatrix() || + child->isArray()) + { + return nullptr; + } + break; + case EOpPostIncrement: + case EOpPreIncrement: + case EOpPostDecrement: + case EOpPreDecrement: + case EOpNegative: + case EOpPositive: + if (child->getBasicType() == EbtStruct || + child->getBasicType() == EbtBool || + child->isArray()) + { + return nullptr; + } + // Operators for built-ins are already type checked against their prototype. + default: + break; + } + + return intermediate.addUnaryMath(op, child, loc, funcReturnType); +} + +TIntermTyped *TParseContext::addUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc) +{ + TIntermTyped *node = createUnaryMath(op, child, loc, nullptr); + if (node == nullptr) + { + unaryOpError(loc, GetOperatorString(op), child->getCompleteString()); + recover(); + return child; + } + return node; +} + +TIntermTyped *TParseContext::addUnaryMathLValue(TOperator op, TIntermTyped *child, const TSourceLoc &loc) +{ + if (lValueErrorCheck(loc, GetOperatorString(op), child)) + recover(); + return addUnaryMath(op, child, loc); +} + +bool TParseContext::binaryOpCommonCheck(TOperator op, TIntermTyped *left, TIntermTyped *right, + const TSourceLoc &loc) +{ + if (left->isArray() || right->isArray()) + { + if (shaderVersion < 300) + { + error(loc, "Invalid operation for arrays", GetOperatorString(op)); + return false; + } + + if (left->isArray() != right->isArray()) + { + error(loc, "array / non-array mismatch", GetOperatorString(op)); + return false; + } + + switch (op) + { + case EOpEqual: + case EOpNotEqual: + case EOpAssign: + case EOpInitialize: + break; + default: + error(loc, "Invalid operation for arrays", GetOperatorString(op)); + return false; + } + if (left->getArraySize() != right->getArraySize()) + { + error(loc, "array size mismatch", GetOperatorString(op)); + return false; + } + } + + // Check ops which require integer / ivec parameters + bool isBitShift = false; + switch (op) + { + case EOpBitShiftLeft: + case EOpBitShiftRight: + case EOpBitShiftLeftAssign: + case EOpBitShiftRightAssign: + // Unsigned can be bit-shifted by signed and vice versa, but we need to + // check that the basic type is an integer type. + isBitShift = true; + if (!IsInteger(left->getBasicType()) || !IsInteger(right->getBasicType())) + { + return false; + } + break; + case EOpBitwiseAnd: + case EOpBitwiseXor: + case EOpBitwiseOr: + case EOpBitwiseAndAssign: + case EOpBitwiseXorAssign: + case EOpBitwiseOrAssign: + // It is enough to check the type of only one operand, since later it + // is checked that the operand types match. + if (!IsInteger(left->getBasicType())) + { + return false; + } + break; + default: + break; + } + + // GLSL ES 1.00 and 3.00 do not support implicit type casting. + // So the basic type should usually match. + if (!isBitShift && left->getBasicType() != right->getBasicType()) + { + return false; + } + + // Check that type sizes match exactly on ops that require that. + // Also check restrictions for structs that contain arrays or samplers. + switch(op) + { + case EOpAssign: + case EOpInitialize: + case EOpEqual: + case EOpNotEqual: + // ESSL 1.00 sections 5.7, 5.8, 5.9 + if (shaderVersion < 300 && left->getType().isStructureContainingArrays()) + { + error(loc, "undefined operation for structs containing arrays", GetOperatorString(op)); + return false; + } + // Samplers as l-values are disallowed also in ESSL 3.00, see section 4.1.7, + // we interpret the spec so that this extends to structs containing samplers, + // similarly to ESSL 1.00 spec. + if ((shaderVersion < 300 || op == EOpAssign || op == EOpInitialize) && + left->getType().isStructureContainingSamplers()) + { + error(loc, "undefined operation for structs containing samplers", GetOperatorString(op)); + return false; + } + case EOpLessThan: + case EOpGreaterThan: + case EOpLessThanEqual: + case EOpGreaterThanEqual: + if ((left->getNominalSize() != right->getNominalSize()) || + (left->getSecondarySize() != right->getSecondarySize())) + { + return false; + } + default: + break; + } + + return true; +} + +TIntermTyped *TParseContext::addBinaryMathInternal(TOperator op, TIntermTyped *left, TIntermTyped *right, + const TSourceLoc &loc) +{ + if (!binaryOpCommonCheck(op, left, right, loc)) + return nullptr; + + switch (op) + { + case EOpEqual: + case EOpNotEqual: + break; + case EOpLessThan: + case EOpGreaterThan: + case EOpLessThanEqual: + case EOpGreaterThanEqual: + ASSERT(!left->isArray() && !right->isArray()); + if (left->isMatrix() || left->isVector() || + left->getBasicType() == EbtStruct) + { + return nullptr; + } + break; + case EOpLogicalOr: + case EOpLogicalXor: + case EOpLogicalAnd: + ASSERT(!left->isArray() && !right->isArray()); + if (left->getBasicType() != EbtBool || + left->isMatrix() || left->isVector()) + { + return nullptr; + } + break; + case EOpAdd: + case EOpSub: + case EOpDiv: + case EOpMul: + ASSERT(!left->isArray() && !right->isArray()); + if (left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool) + { + return nullptr; + } + break; + case EOpIMod: + ASSERT(!left->isArray() && !right->isArray()); + // Note that this is only for the % operator, not for mod() + if (left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool || left->getBasicType() == EbtFloat) + { + return nullptr; + } + break; + // Note that for bitwise ops, type checking is done in promote() to + // share code between ops and compound assignment + default: + break; + } + + return intermediate.addBinaryMath(op, left, right, loc); +} + +TIntermTyped *TParseContext::addBinaryMath(TOperator op, TIntermTyped *left, TIntermTyped *right, + const TSourceLoc &loc) +{ + TIntermTyped *node = addBinaryMathInternal(op, left, right, loc); + if (node == 0) + { + binaryOpError(loc, GetOperatorString(op), left->getCompleteString(), right->getCompleteString()); + recover(); + return left; + } + return node; +} + +TIntermTyped *TParseContext::addBinaryMathBooleanResult(TOperator op, TIntermTyped *left, TIntermTyped *right, + const TSourceLoc &loc) +{ + TIntermTyped *node = addBinaryMathInternal(op, left, right, loc); + if (node == 0) + { + binaryOpError(loc, GetOperatorString(op), left->getCompleteString(), right->getCompleteString()); + recover(); + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setBConst(false); + return intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), loc); + } + return node; +} + +TIntermTyped *TParseContext::createAssign(TOperator op, TIntermTyped *left, TIntermTyped *right, + const TSourceLoc &loc) +{ + if (binaryOpCommonCheck(op, left, right, loc)) + { + return intermediate.addAssign(op, left, right, loc); + } + return nullptr; +} + +TIntermTyped *TParseContext::addAssign(TOperator op, TIntermTyped *left, TIntermTyped *right, + const TSourceLoc &loc) +{ + TIntermTyped *node = createAssign(op, left, right, loc); + if (node == nullptr) + { + assignError(loc, "assign", left->getCompleteString(), right->getCompleteString()); + recover(); + return left; + } + return node; +} + +TIntermBranch *TParseContext::addBranch(TOperator op, const TSourceLoc &loc) +{ + switch (op) + { + case EOpContinue: + if (mLoopNestingLevel <= 0) + { + error(loc, "continue statement only allowed in loops", ""); + recover(); + } + break; + case EOpBreak: + if (mLoopNestingLevel <= 0 && mSwitchNestingLevel <= 0) + { + error(loc, "break statement only allowed in loops and switch statements", ""); + recover(); + } + break; + case EOpReturn: + if (currentFunctionType->getBasicType() != EbtVoid) + { + error(loc, "non-void function must return a value", "return"); + recover(); + } + break; + default: + // No checks for discard + break; + } + return intermediate.addBranch(op, loc); +} + +TIntermBranch *TParseContext::addBranch(TOperator op, TIntermTyped *returnValue, const TSourceLoc &loc) +{ + ASSERT(op == EOpReturn); + mFunctionReturnsValue = true; + if (currentFunctionType->getBasicType() == EbtVoid) + { + error(loc, "void function cannot return a value", "return"); + recover(); + } + else if (*currentFunctionType != returnValue->getType()) + { + error(loc, "function return is not matching type:", "return"); + recover(); + } + return intermediate.addBranch(op, returnValue, loc); +} + +TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunction *fnCall, TIntermNode *node, + const TSourceLoc &loc, bool *fatalError) +{ + *fatalError = false; + TOperator op = fnCall->getBuiltInOp(); + TIntermTyped *callNode = nullptr; + + if (op != EOpNull) + { + // + // Then this should be a constructor. + // Don't go through the symbol table for constructors. + // Their parameters will be verified algorithmically. + // + TType type(EbtVoid, EbpUndefined); // use this to get the type back + if (!constructorErrorCheck(loc, node, *fnCall, op, &type)) + { + // + // It's a constructor, of type 'type'. + // + callNode = addConstructor(node, &type, op, fnCall, loc); + } + + if (callNode == nullptr) + { + recover(); + callNode = intermediate.setAggregateOperator(nullptr, op, loc); + } + callNode->setType(type); + } + else + { + // + // Not a constructor. Find it in the symbol table. + // + const TFunction* fnCandidate; + bool builtIn; + fnCandidate = findFunction(loc, fnCall, shaderVersion, &builtIn); + if (fnCandidate) + { + // + // A declared function. + // + if (builtIn && !fnCandidate->getExtension().empty() && + extensionErrorCheck(loc, fnCandidate->getExtension())) + { + recover(); + } + op = fnCandidate->getBuiltInOp(); + if (builtIn && op != EOpNull) + { + // + // A function call mapped to a built-in operation. + // + if (fnCandidate->getParamCount() == 1) + { + // + // Treat it like a built-in unary operator. + // + callNode = createUnaryMath(op, node->getAsTyped(), loc, &fnCandidate->getReturnType()); + if (callNode == nullptr) + { + std::stringstream extraInfoStream; + extraInfoStream << "built in unary operator function. Type: " + << static_cast(node)->getCompleteString(); + std::string extraInfo = extraInfoStream.str(); + error(node->getLine(), " wrong operand type", "Internal Error", extraInfo.c_str()); + *fatalError = true; + return nullptr; + } + } + else + { + TIntermAggregate *aggregate = intermediate.setAggregateOperator(node, op, loc); + aggregate->setType(fnCandidate->getReturnType()); + aggregate->setPrecisionFromChildren(); + callNode = aggregate; + + // Some built-in functions have out parameters too. + functionCallLValueErrorCheck(fnCandidate, aggregate); + } + } + else + { + // This is a real function call + + TIntermAggregate *aggregate = intermediate.setAggregateOperator(node, EOpFunctionCall, loc); + aggregate->setType(fnCandidate->getReturnType()); + + // this is how we know whether the given function is a builtIn function or a user defined function + // if builtIn == false, it's a userDefined -> could be an overloaded builtIn function also + // if builtIn == true, it's definitely a builtIn function with EOpNull + if (!builtIn) + aggregate->setUserDefined(); + aggregate->setName(fnCandidate->getMangledName()); + + // This needs to happen after the name is set + if (builtIn) + aggregate->setBuiltInFunctionPrecision(); + + callNode = aggregate; + + functionCallLValueErrorCheck(fnCandidate, aggregate); + } + } + else + { + // error message was put out by findFunction() + // Put on a dummy node for error recovery + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setFConst(0.0f); + callNode = intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), loc); + recover(); + } + } + delete fnCall; + return callNode; +} + + // // Parse an array of strings using yyparse. // diff --git a/src/3rdparty/angle/src/compiler/translator/ParseContext.h b/src/3rdparty/angle/src/compiler/translator/ParseContext.h index 414c475cbb..b6a0f4a637 100644 --- a/src/3rdparty/angle/src/compiler/translator/ParseContext.h +++ b/src/3rdparty/angle/src/compiler/translator/ParseContext.h @@ -3,8 +3,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // -#ifndef _PARSER_HELPER_INCLUDED_ -#define _PARSER_HELPER_INCLUDED_ +#ifndef COMPILER_TRANSLATOR_PARSECONTEXT_H_ +#define COMPILER_TRANSLATOR_PARSECONTEXT_H_ #include "compiler/translator/Compiler.h" #include "compiler/translator/Diagnostics.h" @@ -25,24 +25,25 @@ struct TMatrixFields { // they can be passed to the parser without needing a global. // struct TParseContext { - TParseContext(TSymbolTable& symt, TExtensionBehavior& ext, TIntermediate& interm, sh::GLenum type, ShShaderSpec spec, int options, bool checksPrecErrors, const char* sourcePath, TInfoSink& is) : + TParseContext(TSymbolTable& symt, TExtensionBehavior& ext, TIntermediate& interm, sh::GLenum type, ShShaderSpec spec, int options, bool checksPrecErrors, TInfoSink& is, bool debugShaderPrecisionSupported) : intermediate(interm), symbolTable(symt), shaderType(type), shaderSpec(spec), compileOptions(options), - sourcePath(sourcePath), treeRoot(0), - loopNestingLevel(0), + mLoopNestingLevel(0), structNestingLevel(0), + mSwitchNestingLevel(0), currentFunctionType(NULL), - functionReturnsValue(false), + mFunctionReturnsValue(false), checksPrecisionErrors(checksPrecErrors), + fragmentPrecisionHigh(false), defaultMatrixPacking(EmpColumnMajor), defaultBlockStorage(EbsShared), diagnostics(is), shaderVersion(100), - directiveHandler(ext, diagnostics, shaderVersion), + directiveHandler(ext, diagnostics, shaderVersion, debugShaderPrecisionSupported), preprocessor(&diagnostics, &directiveHandler), scanner(NULL) { } TIntermediate& intermediate; // to hold and build a parse tree @@ -51,12 +52,12 @@ struct TParseContext { ShShaderSpec shaderSpec; // The language specification compiler conforms to - GLES2 or WebGL. int shaderVersion; int compileOptions; - const char* sourcePath; // Path of source file or NULL. TIntermNode* treeRoot; // root of parse tree being created - int loopNestingLevel; // 0 if outside all loops + int mLoopNestingLevel; // 0 if outside all loops int structNestingLevel; // incremented while parsing a struct declaration + int mSwitchNestingLevel; // 0 if outside all switch statements 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 mFunctionReturnsValue; // 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. TLayoutMatrixPacking defaultMatrixPacking; @@ -110,6 +111,7 @@ struct TParseContext { bool extensionErrorCheck(const TSourceLoc& line, const TString&); bool singleDeclarationErrorCheck(TPublicType &publicType, const TSourceLoc& identifierLocation, const TString &identifier); bool layoutLocationErrorCheck(const TSourceLoc& location, const TLayoutQualifier &layoutQualifier); + bool functionCallLValueErrorCheck(const TFunction *fnCandidate, TIntermAggregate *); const TPragma& pragma() const { return directiveHandler.pragma(); } const TExtensionBehavior& extensionBehavior() const { return directiveHandler.extensionBehavior(); } @@ -120,7 +122,7 @@ struct TParseContext { bool containsSampler(TType& type); bool areAllChildConst(TIntermAggregate* aggrNode); - const TFunction* findFunction(const TSourceLoc& line, TFunction* pfnCall, int shaderVersion, bool *builtIn = 0); + const TFunction* findFunction(const TSourceLoc& line, TFunction* pfnCall, int inputShaderVersion, bool *builtIn = 0); bool executeInitializer(const TSourceLoc& line, const TString& identifier, TPublicType& pType, TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable = 0); @@ -136,7 +138,7 @@ struct TParseContext { TIntermAggregate* parseInitDeclarator(TPublicType &publicType, TIntermAggregate *declaratorList, const TSourceLoc& identifierLocation, const TString &identifier, const TSourceLoc& initLocation, TIntermTyped *initializer); void parseGlobalLayoutQualifier(const TPublicType &typeQualifier); TFunction *addConstructorFunc(TPublicType publicType); - TIntermTyped* addConstructor(TIntermNode*, const TType*, TOperator, TFunction*, const TSourceLoc&); + TIntermTyped* addConstructor(TIntermNode*, TType*, TOperator, TFunction*, const TSourceLoc&); TIntermTyped* foldConstConstructor(TIntermAggregate* aggrNode, const TType& type); TIntermTyped* addConstVectorNode(TVectorFields&, TIntermTyped*, const TSourceLoc&); TIntermTyped* addConstMatrixNode(int , TIntermTyped*, const TSourceLoc&); @@ -164,9 +166,42 @@ struct TParseContext { void exitStructDeclaration(); bool structNestingErrorCheck(const TSourceLoc& line, const TField& field); + + TIntermSwitch *addSwitch(TIntermTyped *init, TIntermAggregate *statementList, const TSourceLoc &loc); + TIntermCase *addCase(TIntermTyped *condition, const TSourceLoc &loc); + TIntermCase *addDefault(const TSourceLoc &loc); + + TIntermTyped *addUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &); + TIntermTyped *addUnaryMathLValue(TOperator op, TIntermTyped *child, const TSourceLoc &); + TIntermTyped *addBinaryMath(TOperator op, TIntermTyped *left, TIntermTyped *right, + const TSourceLoc &); + TIntermTyped *addBinaryMathBooleanResult(TOperator op, TIntermTyped *left, TIntermTyped *right, + const TSourceLoc &); + TIntermTyped *addAssign(TOperator op, TIntermTyped *left, TIntermTyped *right, + const TSourceLoc &loc); + + TIntermBranch *addBranch(TOperator op, const TSourceLoc &loc); + TIntermBranch *addBranch(TOperator op, TIntermTyped *returnValue, const TSourceLoc &loc); + + TIntermTyped *addFunctionCallOrMethod(TFunction *fnCall, TIntermNode *node, + const TSourceLoc &loc, bool *fatalError); + + private: + TIntermTyped *addBinaryMathInternal(TOperator op, TIntermTyped *left, TIntermTyped *right, + const TSourceLoc &loc); + TIntermTyped *createAssign(TOperator op, TIntermTyped *left, TIntermTyped *right, + const TSourceLoc &loc); + // The funcReturnType parameter is expected to be non-null when the operation is a built-in function. + // It is expected to be null for other unary operators. + TIntermTyped *createUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc, + const TType *funcReturnType); + + // Return true if the checks pass + bool binaryOpCommonCheck(TOperator op, TIntermTyped *left, TIntermTyped *right, + const TSourceLoc &loc); }; int PaParseStrings(size_t count, const char* const string[], const int length[], TParseContext* context); -#endif // _PARSER_HELPER_INCLUDED_ +#endif // COMPILER_TRANSLATOR_PARSECONTEXT_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/PoolAlloc.h b/src/3rdparty/angle/src/compiler/translator/PoolAlloc.h index edd249c4d3..6cd8d30114 100644 --- a/src/3rdparty/angle/src/compiler/translator/PoolAlloc.h +++ b/src/3rdparty/angle/src/compiler/translator/PoolAlloc.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef _POOLALLOC_INCLUDED_ -#define _POOLALLOC_INCLUDED_ +#ifndef COMPILER_TRANSLATOR_POOLALLOC_H_ +#define COMPILER_TRANSLATOR_POOLALLOC_H_ #ifdef _DEBUG #define GUARD_BLOCKS // define to enable guard block sanity checking @@ -297,4 +297,4 @@ protected: TPoolAllocator* allocator; }; -#endif // _POOLALLOC_INCLUDED_ +#endif // COMPILER_TRANSLATOR_POOLALLOC_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/Pragma.h b/src/3rdparty/angle/src/compiler/translator/Pragma.h index 4a930a2962..57b1134970 100644 --- a/src/3rdparty/angle/src/compiler/translator/Pragma.h +++ b/src/3rdparty/angle/src/compiler/translator/Pragma.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef COMPILER_PRAGMA_H_ -#define COMPILER_PRAGMA_H_ +#ifndef COMPILER_TRANSLATOR_PRAGMA_H_ +#define COMPILER_TRANSLATOR_PRAGMA_H_ struct TPragma { @@ -18,12 +18,15 @@ struct TPragma // By default optimization is turned on and debug is turned off. - TPragma() : optimize(true), debug(false) { } - TPragma(bool o, bool d) : optimize(o), debug(d) { } + // Precision emulation is turned on by default, but has no effect unless + // the extension is enabled. + TPragma() : optimize(true), debug(false), debugShaderPrecision(true) { } + TPragma(bool o, bool d) : optimize(o), debug(d), debugShaderPrecision(true) { } bool optimize; bool debug; + bool debugShaderPrecision; STDGL stdgl; }; -#endif // COMPILER_PRAGMA_H_ +#endif // COMPILER_TRANSLATOR_PRAGMA_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/QualifierAlive.cpp b/src/3rdparty/angle/src/compiler/translator/QualifierAlive.cpp index 1f6fb75821..3d950aab5a 100644 --- a/src/3rdparty/angle/src/compiler/translator/QualifierAlive.cpp +++ b/src/3rdparty/angle/src/compiler/translator/QualifierAlive.cpp @@ -49,7 +49,7 @@ void TAliveTraverser::visitSymbol(TIntermSymbol* node) found = true; } -bool TAliveTraverser::visitSelection(Visit preVisit, TIntermSelection* node) +bool TAliveTraverser::visitSelection(Visit, TIntermSelection*) { if (wasFound()) return false; diff --git a/src/3rdparty/angle/src/compiler/translator/QualifierAlive.h b/src/3rdparty/angle/src/compiler/translator/QualifierAlive.h index 872a06f721..3e4f18012a 100644 --- a/src/3rdparty/angle/src/compiler/translator/QualifierAlive.h +++ b/src/3rdparty/angle/src/compiler/translator/QualifierAlive.h @@ -4,4 +4,9 @@ // found in the LICENSE file. // +#ifndef COMPILER_TRANSLATOR_QUALIFIERALIVE_H_ +#define COMPILER_TRANSLATOR_QUALIFIERALIVE_H_ + bool QualifierWritten(TIntermNode* root, TQualifier); + +#endif // COMPILER_TRANSLATOR_QUALIFIERALIVE_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/RegenerateStructNames.h b/src/3rdparty/angle/src/compiler/translator/RegenerateStructNames.h index ac87600347..2acd68be34 100644 --- a/src/3rdparty/angle/src/compiler/translator/RegenerateStructNames.h +++ b/src/3rdparty/angle/src/compiler/translator/RegenerateStructNames.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef COMPILER_TRANSLATOR_REGENERATE_STRUCT_NAMES_H_ -#define COMPILER_TRANSLATOR_REGENERATE_STRUCT_NAMES_H_ +#ifndef COMPILER_TRANSLATOR_REGENERATESTRUCTNAMES_H_ +#define COMPILER_TRANSLATOR_REGENERATESTRUCTNAMES_H_ #include "compiler/translator/Intermediate.h" #include "compiler/translator/SymbolTable.h" @@ -37,4 +37,4 @@ class RegenerateStructNames : public TIntermTraverser std::set mDeclaredGlobalStructs; }; -#endif // COMPILER_TRANSLATOR_REGENERATE_STRUCT_NAMES_H_ +#endif // COMPILER_TRANSLATOR_REGENERATESTRUCTNAMES_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveSwitchFallThrough.cpp b/src/3rdparty/angle/src/compiler/translator/RemoveSwitchFallThrough.cpp new file mode 100644 index 0000000000..b278b53436 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/RemoveSwitchFallThrough.cpp @@ -0,0 +1,157 @@ +// +// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/RemoveSwitchFallThrough.h" + +TIntermAggregate *RemoveSwitchFallThrough::removeFallThrough(TIntermAggregate *statementList) +{ + RemoveSwitchFallThrough rm(statementList); + ASSERT(statementList); + statementList->traverse(&rm); + bool lastStatementWasBreak = rm.mLastStatementWasBreak; + rm.mLastStatementWasBreak = true; + rm.handlePreviousCase(); + if (!lastStatementWasBreak) + { + TIntermBranch *finalBreak = new TIntermBranch(EOpBreak, nullptr); + rm.mStatementListOut->getSequence()->push_back(finalBreak); + } + return rm.mStatementListOut; +} + +RemoveSwitchFallThrough::RemoveSwitchFallThrough(TIntermAggregate *statementList) + : TIntermTraverser(true, false, false), + mStatementList(statementList), + mLastStatementWasBreak(false), + mPreviousCase(nullptr) +{ + mStatementListOut = new TIntermAggregate(); + mStatementListOut->setOp(EOpSequence); +} + +void RemoveSwitchFallThrough::visitSymbol(TIntermSymbol *node) +{ + // Note that this assumes that switch statements which don't begin by a case statement + // have already been weeded out in validation. + mPreviousCase->getSequence()->push_back(node); + mLastStatementWasBreak = false; +} + +void RemoveSwitchFallThrough::visitConstantUnion(TIntermConstantUnion *node) +{ + // Conditions of case labels are not traversed, so this is some other constant + // Could be just a statement like "0;" + mPreviousCase->getSequence()->push_back(node); + mLastStatementWasBreak = false; +} + +bool RemoveSwitchFallThrough::visitBinary(Visit, TIntermBinary *node) +{ + mPreviousCase->getSequence()->push_back(node); + mLastStatementWasBreak = false; + return false; +} + +bool RemoveSwitchFallThrough::visitUnary(Visit, TIntermUnary *node) +{ + mPreviousCase->getSequence()->push_back(node); + mLastStatementWasBreak = false; + return false; +} + +bool RemoveSwitchFallThrough::visitSelection(Visit, TIntermSelection *node) +{ + mPreviousCase->getSequence()->push_back(node); + mLastStatementWasBreak = false; + return false; +} + +bool RemoveSwitchFallThrough::visitSwitch(Visit, TIntermSwitch *node) +{ + mPreviousCase->getSequence()->push_back(node); + mLastStatementWasBreak = false; + // Don't go into nested switch statements + return false; +} + +void RemoveSwitchFallThrough::outputSequence(TIntermSequence *sequence, size_t startIndex) +{ + for (size_t i = startIndex; i < sequence->size(); ++i) + { + mStatementListOut->getSequence()->push_back(sequence->at(i)); + } +} + +void RemoveSwitchFallThrough::handlePreviousCase() +{ + if (mPreviousCase) + mCasesSharingBreak.push_back(mPreviousCase); + if (mLastStatementWasBreak) + { + bool labelsWithNoStatements = true; + for (size_t i = 0; i < mCasesSharingBreak.size(); ++i) + { + if (mCasesSharingBreak.at(i)->getSequence()->size() > 1) + { + labelsWithNoStatements = false; + } + if (labelsWithNoStatements) + { + // Fall-through is allowed in case the label has no statements. + outputSequence(mCasesSharingBreak.at(i)->getSequence(), 0); + } + else + { + // Include all the statements that this case can fall through under the same label. + for (size_t j = i; j < mCasesSharingBreak.size(); ++j) + { + size_t startIndex = j > i ? 1 : 0; // Add the label only from the first sequence. + outputSequence(mCasesSharingBreak.at(j)->getSequence(), startIndex); + + } + } + } + mCasesSharingBreak.clear(); + } + mLastStatementWasBreak = false; + mPreviousCase = nullptr; +} + +bool RemoveSwitchFallThrough::visitCase(Visit, TIntermCase *node) +{ + handlePreviousCase(); + mPreviousCase = new TIntermAggregate(); + mPreviousCase->setOp(EOpSequence); + mPreviousCase->getSequence()->push_back(node); + // Don't traverse the condition of the case statement + return false; +} + +bool RemoveSwitchFallThrough::visitAggregate(Visit, TIntermAggregate *node) +{ + if (node != mStatementList) + { + mPreviousCase->getSequence()->push_back(node); + mLastStatementWasBreak = false; + return false; + } + return true; +} + +bool RemoveSwitchFallThrough::visitLoop(Visit, TIntermLoop *node) +{ + mPreviousCase->getSequence()->push_back(node); + mLastStatementWasBreak = false; + return false; +} + +bool RemoveSwitchFallThrough::visitBranch(Visit, TIntermBranch *node) +{ + mPreviousCase->getSequence()->push_back(node); + // TODO: Verify that accepting return or continue statements here doesn't cause problems. + mLastStatementWasBreak = true; + return false; +} diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveSwitchFallThrough.h b/src/3rdparty/angle/src/compiler/translator/RemoveSwitchFallThrough.h new file mode 100644 index 0000000000..db8699327c --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/RemoveSwitchFallThrough.h @@ -0,0 +1,43 @@ +// +// Copyright (c) 2002-2015 The ANGLE Project 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_TRANSLATOR_REMOVESWITCHFALLTHROUGH_H_ +#define COMPILER_TRANSLATOR_REMOVESWITCHFALLTHROUGH_H_ + +#include "compiler/translator/IntermNode.h" + +class RemoveSwitchFallThrough : public TIntermTraverser +{ + public: + // When given a statementList from a switch AST node, return an updated + // statementList that has fall-through removed. + static TIntermAggregate *removeFallThrough(TIntermAggregate *statementList); + + private: + RemoveSwitchFallThrough(TIntermAggregate *statementList); + + void visitSymbol(TIntermSymbol *node) override; + void visitConstantUnion(TIntermConstantUnion *node) override; + bool visitBinary(Visit, TIntermBinary *node) override; + bool visitUnary(Visit, TIntermUnary *node) override; + bool visitSelection(Visit visit, TIntermSelection *node) override; + bool visitSwitch(Visit, TIntermSwitch *node) override; + bool visitCase(Visit, TIntermCase *node) override; + bool visitAggregate(Visit, TIntermAggregate *node) override; + bool visitLoop(Visit, TIntermLoop *node) override; + bool visitBranch(Visit, TIntermBranch *node) override; + + void outputSequence(TIntermSequence *sequence, size_t startIndex); + void handlePreviousCase(); + + TIntermAggregate *mStatementList; + TIntermAggregate *mStatementListOut; + bool mLastStatementWasBreak; + TIntermAggregate *mPreviousCase; + std::vector mCasesSharingBreak; +}; + +#endif // COMPILER_TRANSLATOR_REMOVESWITCHFALLTHROUGH_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveTree.cpp b/src/3rdparty/angle/src/compiler/translator/RemoveTree.cpp deleted file mode 100644 index 0cf6910aa2..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/RemoveTree.cpp +++ /dev/null @@ -1,29 +0,0 @@ -// -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/translator/IntermNode.h" -#include "compiler/translator/RemoveTree.h" - -// -// Code to delete the intermediate tree. -// -void RemoveAllTreeNodes(TIntermNode* root) -{ - std::queue nodeQueue; - - nodeQueue.push(root); - - while (!nodeQueue.empty()) - { - TIntermNode *node = nodeQueue.front(); - nodeQueue.pop(); - - node->enqueueChildren(&nodeQueue); - - delete node; - } -} - diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveTree.h b/src/3rdparty/angle/src/compiler/translator/RemoveTree.h deleted file mode 100644 index 97a821679c..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/RemoveTree.h +++ /dev/null @@ -1,7 +0,0 @@ -// -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -void RemoveAllTreeNodes(TIntermNode*); diff --git a/src/3rdparty/angle/src/compiler/translator/RenameFunction.h b/src/3rdparty/angle/src/compiler/translator/RenameFunction.h index d43e6ef7be..868e5d566b 100644 --- a/src/3rdparty/angle/src/compiler/translator/RenameFunction.h +++ b/src/3rdparty/angle/src/compiler/translator/RenameFunction.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef COMPILER_RENAME_FUNCTION -#define COMPILER_RENAME_FUNCTION +#ifndef COMPILER_TRANSLATOR_RENAMEFUNCTION_H_ +#define COMPILER_TRANSLATOR_RENAMEFUNCTION_H_ #include "compiler/translator/IntermNode.h" @@ -33,4 +33,4 @@ private: const TString mNewFunctionName; }; -#endif // COMPILER_RENAME_FUNCTION +#endif // COMPILER_TRANSLATOR_RENAMEFUNCTION_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.h b/src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.h index d87baea0fe..5527d27f83 100644 --- a/src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.h +++ b/src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.h @@ -7,8 +7,8 @@ // all if-else blocks to if-if blocks. // -#ifndef COMPILER_REWRITE_ELSE_BLOCKS_H_ -#define COMPILER_REWRITE_ELSE_BLOCKS_H_ +#ifndef COMPILER_TRANSLATOR_REWRITEELSEBLOCKS_H_ +#define COMPILER_TRANSLATOR_REWRITEELSEBLOCKS_H_ #include "compiler/translator/IntermNode.h" @@ -19,4 +19,4 @@ void RewriteElseBlocks(TIntermNode *node); } -#endif // COMPILER_REWRITE_ELSE_BLOCKS_H_ +#endif // COMPILER_TRANSLATOR_REWRITEELSEBLOCKS_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.h b/src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.h index 7c6d09c1bb..0726ed4c64 100644 --- a/src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.h +++ b/src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef COMPILER_TRANSLATOR_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS_H_ -#define COMPILER_TRANSLATOR_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS_H_ +#ifndef COMPILER_TRANSLATOR_SCALARIZEVECANDMATCONSTRUCTORARGS_H_ +#define COMPILER_TRANSLATOR_SCALARIZEVECANDMATCONSTRUCTORARGS_H_ #include "compiler/translator/IntermNode.h" @@ -44,4 +44,4 @@ class ScalarizeVecAndMatConstructorArgs : public TIntermTraverser bool mFragmentPrecisionHigh; }; -#endif // COMPILER_TRANSLATOR_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS_H_ +#endif // COMPILER_TRANSLATOR_SCALARIZEVECANDMATCONSTRUCTORARGS_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/SearchSymbol.cpp b/src/3rdparty/angle/src/compiler/translator/SearchSymbol.cpp index f78c84e370..fb7a6cdb9b 100644 --- a/src/3rdparty/angle/src/compiler/translator/SearchSymbol.cpp +++ b/src/3rdparty/angle/src/compiler/translator/SearchSymbol.cpp @@ -9,7 +9,6 @@ #include "compiler/translator/SearchSymbol.h" #include "compiler/translator/InfoSink.h" -#include "compiler/translator/OutputHLSL.h" namespace sh { diff --git a/src/3rdparty/angle/src/compiler/translator/SearchSymbol.h b/src/3rdparty/angle/src/compiler/translator/SearchSymbol.h index 029ac30b9a..36d5191058 100644 --- a/src/3rdparty/angle/src/compiler/translator/SearchSymbol.h +++ b/src/3rdparty/angle/src/compiler/translator/SearchSymbol.h @@ -6,8 +6,8 @@ // SearchSymbol is an AST traverser to detect the use of a given symbol name // -#ifndef COMPILER_SEARCHSYMBOL_H_ -#define COMPILER_SEARCHSYMBOL_H_ +#ifndef COMPILER_TRANSLATOR_SEARCHSYMBOL_H_ +#define COMPILER_TRANSLATOR_SEARCHSYMBOL_H_ #include "compiler/translator/IntermNode.h" #include "compiler/translator/ParseContext.h" @@ -30,4 +30,4 @@ class SearchSymbol : public TIntermTraverser }; } -#endif // COMPILER_SEARCHSYMBOL_H_ +#endif // COMPILER_TRANSLATOR_SEARCHSYMBOL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/ShaderLang.cpp b/src/3rdparty/angle/src/compiler/translator/ShaderLang.cpp index 0d6a1d64cf..b8040da7f9 100644 --- a/src/3rdparty/angle/src/compiler/translator/ShaderLang.cpp +++ b/src/3rdparty/angle/src/compiler/translator/ShaderLang.cpp @@ -14,7 +14,9 @@ #include "compiler/translator/Compiler.h" #include "compiler/translator/InitializeDll.h" #include "compiler/translator/length_limits.h" +#ifdef ANGLE_ENABLE_HLSL #include "compiler/translator/TranslatorHLSL.h" +#endif // ANGLE_ENABLE_HLSL #include "compiler/translator/VariablePacker.h" #include "angle_gl.h" @@ -92,6 +94,7 @@ TCompiler *GetCompilerFromHandle(ShHandle handle) return base->getAsCompiler(); } +#ifdef ANGLE_ENABLE_HLSL TranslatorHLSL *GetTranslatorHLSLFromHandle(ShHandle handle) { if (!handle) @@ -99,6 +102,7 @@ TranslatorHLSL *GetTranslatorHLSLFromHandle(ShHandle handle) TShHandleBase *base = static_cast(handle); return base->getAsTranslatorHLSL(); } +#endif // ANGLE_ENABLE_HLSL } // namespace anonymous @@ -153,6 +157,10 @@ void ShInitBuiltInResources(ShBuiltInResources* resources) resources->EXT_draw_buffers = 0; resources->EXT_frag_depth = 0; resources->EXT_shader_texture_lod = 0; + resources->WEBGL_debug_shader_precision = 0; + resources->EXT_shader_framebuffer_fetch = 0; + resources->NV_shader_framebuffer_fetch = 0; + resources->ARM_shader_framebuffer_fetch = 0; resources->NV_draw_buffers = 0; @@ -323,6 +331,7 @@ bool ShGetInterfaceBlockRegister(const ShHandle handle, const std::string &interfaceBlockName, unsigned int *indexOut) { +#ifdef ANGLE_ENABLE_HLSL ASSERT(indexOut); TranslatorHLSL *translator = GetTranslatorHLSLFromHandle(handle); @@ -335,12 +344,16 @@ bool ShGetInterfaceBlockRegister(const ShHandle handle, *indexOut = translator->getInterfaceBlockRegister(interfaceBlockName); return true; +#else + return false; +#endif // ANGLE_ENABLE_HLSL } bool ShGetUniformRegister(const ShHandle handle, const std::string &uniformName, unsigned int *indexOut) { +#ifdef ANGLE_ENABLE_HLSL ASSERT(indexOut); TranslatorHLSL *translator = GetTranslatorHLSLFromHandle(handle); ASSERT(translator); @@ -352,4 +365,7 @@ bool ShGetUniformRegister(const ShHandle handle, *indexOut = translator->getUniformRegister(uniformName); return true; +#else + return false; +#endif // ANGLE_ENABLE_HLSL } diff --git a/src/3rdparty/angle/src/compiler/translator/ShaderVars.cpp b/src/3rdparty/angle/src/compiler/translator/ShaderVars.cpp index 3098a7f0c9..0dbbc9e7f6 100644 --- a/src/3rdparty/angle/src/compiler/translator/ShaderVars.cpp +++ b/src/3rdparty/angle/src/compiler/translator/ShaderVars.cpp @@ -14,6 +14,23 @@ namespace sh { +namespace +{ + +InterpolationType GetNonAuxiliaryInterpolationType(InterpolationType interpolation) +{ + return (interpolation == INTERPOLATION_CENTROID ? INTERPOLATION_SMOOTH : interpolation); +} + +} +// The ES 3.0 spec is not clear on this point, but the ES 3.1 spec, and discussion +// on Khronos.org, clarifies that a smooth/flat mismatch produces a link error, +// but auxiliary qualifier mismatch (centroid) does not. +bool InterpolationTypesMatch(InterpolationType a, InterpolationType b) +{ + return (GetNonAuxiliaryInterpolationType(a) == GetNonAuxiliaryInterpolationType(b)); +} + ShaderVariable::ShaderVariable() : type(0), precision(0), @@ -86,7 +103,6 @@ bool ShaderVariable::findInfoByMappedName( // 2) the top variable is an array; // 3) otherwise. size_t pos = mappedFullName.find_first_of(".["); - std::string topName; if (pos == std::string::npos) { diff --git a/src/3rdparty/angle/src/compiler/translator/SimplifyArrayAssignment.cpp b/src/3rdparty/angle/src/compiler/translator/SimplifyArrayAssignment.cpp new file mode 100644 index 0000000000..ac5eb67070 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/SimplifyArrayAssignment.cpp @@ -0,0 +1,38 @@ +// +// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/SimplifyArrayAssignment.h" + +bool SimplifyArrayAssignment::visitBinary(Visit visit, TIntermBinary *node) +{ + switch (node->getOp()) + { + case EOpAssign: + { + TIntermNode *parent = getParentNode(); + if (node->getLeft()->isArray() && parent != nullptr) + { + TIntermAggregate *parentAgg = parent->getAsAggregate(); + if (parentAgg != nullptr && parentAgg->getOp() == EOpSequence) + { + // This case is fine, the result of the assignment is not used. + break; + } + + // The result of the assignment needs to be stored into a temporary variable, + // the assignment needs to be replaced with a reference to the temporary variable, + // and the temporary variable needs to finally be assigned to the target variable. + + // This also needs to interact correctly with unfolding short circuiting operators. + UNIMPLEMENTED(); + } + } + break; + default: + break; + } + return true; +} diff --git a/src/3rdparty/angle/src/compiler/translator/SimplifyArrayAssignment.h b/src/3rdparty/angle/src/compiler/translator/SimplifyArrayAssignment.h new file mode 100644 index 0000000000..247eb88d72 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/SimplifyArrayAssignment.h @@ -0,0 +1,25 @@ +// +// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// SimplifyArrayAssignment is an AST traverser to replace statements where +// the return value of array assignment is used with statements where +// the return value of array assignment is not used. +// + +#ifndef COMPILER_TRANSLATOR_SIMPLIFYARRAYASSIGNMENT_H_ +#define COMPILER_TRANSLATOR_SIMPLIFYARRAYASSIGNMENT_H_ + +#include "common/angleutils.h" +#include "compiler/translator/IntermNode.h" + +class SimplifyArrayAssignment : public TIntermTraverser +{ + public: + SimplifyArrayAssignment() { } + + virtual bool visitBinary(Visit visit, TIntermBinary *node); +}; + +#endif // COMPILER_TRANSLATOR_SIMPLIFYARRAYASSIGNMENT_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/StructureHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/StructureHLSL.cpp index 48929affe6..fd1a29c1cd 100644 --- a/src/3rdparty/angle/src/compiler/translator/StructureHLSL.cpp +++ b/src/3rdparty/angle/src/compiler/translator/StructureHLSL.cpp @@ -21,9 +21,23 @@ Std140PaddingHelper::Std140PaddingHelper(const std::map &structEle unsigned *uniqueCounter) : mPaddingCounter(uniqueCounter), mElementIndex(0), - mStructElementIndexes(structElementIndexes) + mStructElementIndexes(&structElementIndexes) {} +Std140PaddingHelper::Std140PaddingHelper(const Std140PaddingHelper &other) + : mPaddingCounter(other.mPaddingCounter), + mElementIndex(other.mElementIndex), + mStructElementIndexes(other.mStructElementIndexes) +{} + +Std140PaddingHelper &Std140PaddingHelper::operator=(const Std140PaddingHelper &other) +{ + mPaddingCounter = other.mPaddingCounter; + mElementIndex = other.mElementIndex; + mStructElementIndexes = other.mStructElementIndexes; + return *this; +} + TString Std140PaddingHelper::next() { unsigned value = (*mPaddingCounter)++; @@ -107,7 +121,7 @@ TString Std140PaddingHelper::postPaddingString(const TType &type, bool useHLSLRo { const TString &structName = QualifiedStructNameString(*structure, useHLSLRowMajorPacking, true); - numComponents = mStructElementIndexes.find(structName)->second; + numComponents = mStructElementIndexes->find(structName)->second; if (numComponents == 0) { @@ -274,9 +288,9 @@ void StructureHLSL::addConstructor(const TType &type, const TString &name, const for (unsigned int parameter = 0; parameter < ctorParameters.size(); parameter++) { - const TType &type = ctorParameters[parameter]; + const TType ¶mType = ctorParameters[parameter]; - constructor += TypeString(type) + " x" + str(parameter) + ArrayString(type); + constructor += TypeString(paramType) + " x" + str(parameter) + ArrayString(paramType); if (parameter < ctorParameters.size() - 1) { diff --git a/src/3rdparty/angle/src/compiler/translator/StructureHLSL.h b/src/3rdparty/angle/src/compiler/translator/StructureHLSL.h index ed002fef30..cffe2a41ae 100644 --- a/src/3rdparty/angle/src/compiler/translator/StructureHLSL.h +++ b/src/3rdparty/angle/src/compiler/translator/StructureHLSL.h @@ -7,8 +7,8 @@ // Interfaces of methods for HLSL translation of GLSL structures. // -#ifndef TRANSLATOR_STRUCTUREHLSL_H_ -#define TRANSLATOR_STRUCTUREHLSL_H_ +#ifndef COMPILER_TRANSLATOR_STRUCTUREHLSL_H_ +#define COMPILER_TRANSLATOR_STRUCTUREHLSL_H_ #include "compiler/translator/Common.h" #include "compiler/translator/IntermNode.h" @@ -27,7 +27,9 @@ class Std140PaddingHelper { public: explicit Std140PaddingHelper(const std::map &structElementIndexes, - unsigned *uniqueCounter); + unsigned int *uniqueCounter); + Std140PaddingHelper(const Std140PaddingHelper &other); + Std140PaddingHelper &operator=(const Std140PaddingHelper &other); int elementIndex() const { return mElementIndex; } int prePadding(const TType &type); @@ -39,10 +41,10 @@ class Std140PaddingHelper unsigned *mPaddingCounter; int mElementIndex; - const std::map &mStructElementIndexes; + const std::map *mStructElementIndexes; }; -class StructureHLSL +class StructureHLSL : angle::NonCopyable { public: StructureHLSL(); @@ -76,4 +78,4 @@ class StructureHLSL } -#endif // COMPILER_STRUCTUREHLSL_H_ +#endif // COMPILER_TRANSLATOR_STRUCTUREHLSL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/SymbolTable.cpp b/src/3rdparty/angle/src/compiler/translator/SymbolTable.cpp index 028da21151..0eb663f018 100644 --- a/src/3rdparty/angle/src/compiler/translator/SymbolTable.cpp +++ b/src/3rdparty/angle/src/compiler/translator/SymbolTable.cpp @@ -48,6 +48,16 @@ bool TSymbolTableLevel::insert(TSymbol *symbol) return result.second; } +bool TSymbolTableLevel::insertUnmangled(TFunction *function) +{ + function->setUniqueId(TSymbolTable::nextUniqueId()); + + // returning true means symbol was added to the table + tInsertResult result = level.insert(tLevelPair(function->getName(), function)); + + return result.second; +} + TSymbol *TSymbolTableLevel::find(const TString &name) const { tLevel::const_iterator it = level.find(name); @@ -57,47 +67,6 @@ TSymbol *TSymbolTableLevel::find(const TString &name) const return (*it).second; } -// -// Change all function entries in the table with the non-mangled name -// to be related to the provided built-in operation. This is a low -// performance operation, and only intended for symbol tables that -// live across a large number of compiles. -// -void TSymbolTableLevel::relateToOperator(const char *name, TOperator op) -{ - for (tLevel::iterator it = level.begin(); it != level.end(); ++it) - { - if ((*it).second->isFunction()) - { - TFunction *function = static_cast((*it).second); - if (function->getName() == name) - function->relateToOperator(op); - } - } -} - -// -// Change all function entries in the table with the non-mangled name -// to be related to the provided built-in extension. This is a low -// performance operation, and only intended for symbol tables that -// live across a large number of compiles. -// -void TSymbolTableLevel::relateToExtension(const char *name, const TString &ext) -{ - for (tLevel::iterator it = level.begin(); it != level.end(); ++it) - { - TSymbol *symbol = it->second; - if (symbol->getName() == name) - symbol->relateToExtension(ext); - } -} - -TSymbol::TSymbol(const TSymbol ©Of) -{ - name = NewPoolTString(copyOf.name->c_str()); - uniqueId = copyOf.uniqueId; -} - TSymbol *TSymbolTable::find(const TString &name, int shaderVersion, bool *builtIn, bool *sameScope) const { @@ -148,68 +117,149 @@ TSymbolTable::~TSymbolTable() pop(); } -void TSymbolTable::insertBuiltIn( - ESymbolLevel level, TType *rvalue, const char *name, - TType *ptype1, TType *ptype2, TType *ptype3, TType *ptype4, TType *ptype5) +bool IsGenType(const TType *type) +{ + if (type) + { + TBasicType basicType = type->getBasicType(); + return basicType == EbtGenType || basicType == EbtGenIType || basicType == EbtGenUType || basicType == EbtGenBType; + } + + return false; +} + +bool IsVecType(const TType *type) +{ + if (type) + { + TBasicType basicType = type->getBasicType(); + return basicType == EbtVec || basicType == EbtIVec || basicType == EbtUVec || basicType == EbtBVec; + } + + return false; +} + +TType *SpecificType(TType *type, int size) +{ + ASSERT(size >= 1 && size <= 4); + + if (!type) + { + return nullptr; + } + + ASSERT(!IsVecType(type)); + + switch(type->getBasicType()) + { + case EbtGenType: return new TType(EbtFloat, size); + case EbtGenIType: return new TType(EbtInt, size); + case EbtGenUType: return new TType(EbtUInt, size); + case EbtGenBType: return new TType(EbtBool, size); + default: return type; + } +} + +TType *VectorType(TType *type, int size) +{ + ASSERT(size >= 2 && size <= 4); + + if (!type) + { + return nullptr; + } + + ASSERT(!IsGenType(type)); + + switch(type->getBasicType()) + { + case EbtVec: return new TType(EbtFloat, size); + case EbtIVec: return new TType(EbtInt, size); + case EbtUVec: return new TType(EbtUInt, size); + case EbtBVec: return new TType(EbtBool, size); + default: return type; + } +} + +void TSymbolTable::insertBuiltIn(ESymbolLevel level, TOperator op, const char *ext, TType *rvalue, const char *name, + TType *ptype1, TType *ptype2, TType *ptype3, TType *ptype4, TType *ptype5) { if (ptype1->getBasicType() == EbtGSampler2D) { bool gvec4 = (rvalue->getBasicType() == EbtGVec4); - insertBuiltIn(level, gvec4 ? new TType(EbtFloat, 4) : rvalue, name, - new TType(EbtSampler2D), ptype2, ptype3, ptype4, ptype5); - insertBuiltIn(level, gvec4 ? new TType(EbtInt, 4) : rvalue, name, - new TType(EbtISampler2D), ptype2, ptype3, ptype4, ptype5); - insertBuiltIn(level, gvec4 ? new TType(EbtUInt, 4) : rvalue, name, - new TType(EbtUSampler2D), ptype2, ptype3, ptype4, ptype5); - return; + insertBuiltIn(level, gvec4 ? new TType(EbtFloat, 4) : rvalue, name, new TType(EbtSampler2D), ptype2, ptype3, ptype4, ptype5); + insertBuiltIn(level, gvec4 ? new TType(EbtInt, 4) : rvalue, name, new TType(EbtISampler2D), ptype2, ptype3, ptype4, ptype5); + insertBuiltIn(level, gvec4 ? new TType(EbtUInt, 4) : rvalue, name, new TType(EbtUSampler2D), ptype2, ptype3, ptype4, ptype5); } - if (ptype1->getBasicType() == EbtGSampler3D) + else if (ptype1->getBasicType() == EbtGSampler3D) { bool gvec4 = (rvalue->getBasicType() == EbtGVec4); - insertBuiltIn(level, gvec4 ? new TType(EbtFloat, 4) : rvalue, name, - new TType(EbtSampler3D), ptype2, ptype3, ptype4, ptype5); - insertBuiltIn(level, gvec4 ? new TType(EbtInt, 4) : rvalue, name, - new TType(EbtISampler3D), ptype2, ptype3, ptype4, ptype5); - insertBuiltIn(level, gvec4 ? new TType(EbtUInt, 4) : rvalue, name, - new TType(EbtUSampler3D), ptype2, ptype3, ptype4, ptype5); - return; + insertBuiltIn(level, gvec4 ? new TType(EbtFloat, 4) : rvalue, name, new TType(EbtSampler3D), ptype2, ptype3, ptype4, ptype5); + insertBuiltIn(level, gvec4 ? new TType(EbtInt, 4) : rvalue, name, new TType(EbtISampler3D), ptype2, ptype3, ptype4, ptype5); + insertBuiltIn(level, gvec4 ? new TType(EbtUInt, 4) : rvalue, name, new TType(EbtUSampler3D), ptype2, ptype3, ptype4, ptype5); } - if (ptype1->getBasicType() == EbtGSamplerCube) + else if (ptype1->getBasicType() == EbtGSamplerCube) { bool gvec4 = (rvalue->getBasicType() == EbtGVec4); - insertBuiltIn(level, gvec4 ? new TType(EbtFloat, 4) : rvalue, name, - new TType(EbtSamplerCube), ptype2, ptype3, ptype4, ptype5); - insertBuiltIn(level, gvec4 ? new TType(EbtInt, 4) : rvalue, name, - new TType(EbtISamplerCube), ptype2, ptype3, ptype4, ptype5); - insertBuiltIn(level, gvec4 ? new TType(EbtUInt, 4) : rvalue, name, - new TType(EbtUSamplerCube), ptype2, ptype3, ptype4, ptype5); - return; + insertBuiltIn(level, gvec4 ? new TType(EbtFloat, 4) : rvalue, name, new TType(EbtSamplerCube), ptype2, ptype3, ptype4, ptype5); + insertBuiltIn(level, gvec4 ? new TType(EbtInt, 4) : rvalue, name, new TType(EbtISamplerCube), ptype2, ptype3, ptype4, ptype5); + insertBuiltIn(level, gvec4 ? new TType(EbtUInt, 4) : rvalue, name, new TType(EbtUSamplerCube), ptype2, ptype3, ptype4, ptype5); } - if (ptype1->getBasicType() == EbtGSampler2DArray) + else if (ptype1->getBasicType() == EbtGSampler2DArray) { bool gvec4 = (rvalue->getBasicType() == EbtGVec4); - insertBuiltIn(level, gvec4 ? new TType(EbtFloat, 4) : rvalue, name, - new TType(EbtSampler2DArray), ptype2, ptype3, ptype4, ptype5); - insertBuiltIn(level, gvec4 ? new TType(EbtInt, 4) : rvalue, name, - new TType(EbtISampler2DArray), ptype2, ptype3, ptype4, ptype5); - insertBuiltIn(level, gvec4 ? new TType(EbtUInt, 4) : rvalue, name, - new TType(EbtUSampler2DArray), ptype2, ptype3, ptype4, ptype5); - return; + insertBuiltIn(level, gvec4 ? new TType(EbtFloat, 4) : rvalue, name, new TType(EbtSampler2DArray), ptype2, ptype3, ptype4, ptype5); + insertBuiltIn(level, gvec4 ? new TType(EbtInt, 4) : rvalue, name, new TType(EbtISampler2DArray), ptype2, ptype3, ptype4, ptype5); + insertBuiltIn(level, gvec4 ? new TType(EbtUInt, 4) : rvalue, name, new TType(EbtUSampler2DArray), ptype2, ptype3, ptype4, ptype5); + } + else if (IsGenType(rvalue) || IsGenType(ptype1) || IsGenType(ptype2) || IsGenType(ptype3)) + { + ASSERT(!ptype4 && !ptype5); + insertBuiltIn(level, op, ext, SpecificType(rvalue, 1), name, SpecificType(ptype1, 1), SpecificType(ptype2, 1), SpecificType(ptype3, 1)); + insertBuiltIn(level, op, ext, SpecificType(rvalue, 2), name, SpecificType(ptype1, 2), SpecificType(ptype2, 2), SpecificType(ptype3, 2)); + insertBuiltIn(level, op, ext, SpecificType(rvalue, 3), name, SpecificType(ptype1, 3), SpecificType(ptype2, 3), SpecificType(ptype3, 3)); + insertBuiltIn(level, op, ext, SpecificType(rvalue, 4), name, SpecificType(ptype1, 4), SpecificType(ptype2, 4), SpecificType(ptype3, 4)); + } + else if (IsVecType(rvalue) || IsVecType(ptype1) || IsVecType(ptype2) || IsVecType(ptype3)) + { + ASSERT(!ptype4 && !ptype5); + insertBuiltIn(level, op, ext, VectorType(rvalue, 2), name, VectorType(ptype1, 2), VectorType(ptype2, 2), VectorType(ptype3, 2)); + insertBuiltIn(level, op, ext, VectorType(rvalue, 3), name, VectorType(ptype1, 3), VectorType(ptype2, 3), VectorType(ptype3, 3)); + insertBuiltIn(level, op, ext, VectorType(rvalue, 4), name, VectorType(ptype1, 4), VectorType(ptype2, 4), VectorType(ptype3, 4)); } + else + { + TFunction *function = new TFunction(NewPoolTString(name), *rvalue, op, ext); - TFunction *function = new TFunction(NewPoolTString(name), *rvalue); + TParameter param1 = {0, ptype1}; + function->addParameter(param1); - TType *types[] = {ptype1, ptype2, ptype3, ptype4, ptype5}; - for (size_t ii = 0; ii < sizeof(types) / sizeof(types[0]); ++ii) - { - if (types[ii]) + if (ptype2) { - TParameter param = {NULL, types[ii]}; - function->addParameter(param); + TParameter param2 = {0, ptype2}; + function->addParameter(param2); } - } - insert(level, function); + if (ptype3) + { + TParameter param3 = {0, ptype3}; + function->addParameter(param3); + } + + if (ptype4) + { + TParameter param4 = {0, ptype4}; + function->addParameter(param4); + } + + if (ptype5) + { + TParameter param5 = {0, ptype5}; + function->addParameter(param5); + } + + insert(level, function); + } } TPrecision TSymbolTable::getDefaultPrecision(TBasicType type) const diff --git a/src/3rdparty/angle/src/compiler/translator/SymbolTable.h b/src/3rdparty/angle/src/compiler/translator/SymbolTable.h index 9cd74218dc..dfc65cb957 100644 --- a/src/3rdparty/angle/src/compiler/translator/SymbolTable.h +++ b/src/3rdparty/angle/src/compiler/translator/SymbolTable.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef _SYMBOL_TABLE_INCLUDED_ -#define _SYMBOL_TABLE_INCLUDED_ +#ifndef COMPILER_TRANSLATOR_SYMBOLTABLE_H_ +#define COMPILER_TRANSLATOR_SYMBOLTABLE_H_ // // Symbol table for parsing. Has these design characteristics: @@ -38,7 +38,7 @@ #include "compiler/translator/IntermNode.h" // Symbol base class. (Can build functions or variables out of these...) -class TSymbol +class TSymbol : angle::NonCopyable { public: POOL_ALLOCATOR_NEW_DELETE(); @@ -86,8 +86,6 @@ class TSymbol } private: - DISALLOW_COPY_AND_ASSIGN(TSymbol); - int uniqueId; // For real comparing during code generation const TString *name; TString extension; @@ -158,8 +156,6 @@ class TVariable : public TSymbol } private: - DISALLOW_COPY_AND_ASSIGN(TVariable); - TType type; bool userType; // we are assuming that Pool Allocator will free the memory @@ -186,13 +182,14 @@ class TFunction : public TSymbol defined(false) { } - TFunction(const TString *name, const TType &retType, TOperator tOp = EOpNull) + TFunction(const TString *name, const TType &retType, TOperator tOp = EOpNull, const char *ext = "") : TSymbol(name), returnType(retType), mangledName(TFunction::mangleName(*name)), op(tOp), defined(false) { + relateToExtension(ext); } virtual ~TFunction(); virtual bool isFunction() const @@ -224,10 +221,6 @@ class TFunction : public TSymbol return returnType; } - void relateToOperator(TOperator o) - { - op = o; - } TOperator getBuiltInOp() const { return op; @@ -252,8 +245,6 @@ class TFunction : public TSymbol } private: - DISALLOW_COPY_AND_ASSIGN(TFunction); - typedef TVector TParamList; TParamList parameters; TType returnType; @@ -291,10 +282,10 @@ class TSymbolTableLevel bool insert(TSymbol *symbol); - TSymbol *find(const TString &name) const; + // Insert a function using its unmangled name as the key. + bool insertUnmangled(TFunction *function); - void relateToOperator(const char *name, TOperator op); - void relateToExtension(const char *name, const TString &ext); + TSymbol *find(const TString &name) const; protected: tLevel level; @@ -310,7 +301,7 @@ const int ESSL3_BUILTINS = 2; const int LAST_BUILTIN_LEVEL = ESSL3_BUILTINS; const int GLOBAL_LEVEL = 3; -class TSymbolTable +class TSymbolTable : angle::NonCopyable { public: TSymbolTable() @@ -363,6 +354,12 @@ class TSymbolTable return table[level]->insert(symbol); } + bool insert(ESymbolLevel level, const char *ext, TSymbol *symbol) + { + symbol->relateToExtension(ext); + return table[level]->insert(symbol); + } + bool insertConstInt(ESymbolLevel level, const char *name, int value) { TVariable *constant = new TVariable( @@ -371,9 +368,26 @@ class TSymbolTable return insert(level, constant); } + void insertBuiltIn(ESymbolLevel level, TOperator op, const char *ext, TType *rvalue, const char *name, + TType *ptype1, TType *ptype2 = 0, TType *ptype3 = 0, TType *ptype4 = 0, TType *ptype5 = 0); + void insertBuiltIn(ESymbolLevel level, TType *rvalue, const char *name, - TType *ptype1, TType *ptype2 = 0, TType *ptype3 = 0, - TType *ptype4 = 0, TType *ptype5 = 0); + TType *ptype1, TType *ptype2 = 0, TType *ptype3 = 0, TType *ptype4 = 0, TType *ptype5 = 0) + { + insertBuiltIn(level, EOpNull, "", rvalue, name, ptype1, ptype2, ptype3, ptype4, ptype5); + } + + void insertBuiltIn(ESymbolLevel level, const char *ext, TType *rvalue, const char *name, + TType *ptype1, TType *ptype2 = 0, TType *ptype3 = 0, TType *ptype4 = 0, TType *ptype5 = 0) + { + insertBuiltIn(level, EOpNull, ext, rvalue, name, ptype1, ptype2, ptype3, ptype4, ptype5); + } + + void insertBuiltIn(ESymbolLevel level, TOperator op, TType *rvalue, const char *name, + TType *ptype1, TType *ptype2 = 0, TType *ptype3 = 0, TType *ptype4 = 0, TType *ptype5 = 0) + { + insertBuiltIn(level, op, "", rvalue, name, ptype1, ptype2, ptype3, ptype4, ptype5); + } TSymbol *find(const TString &name, int shaderVersion, bool *builtIn = NULL, bool *sameScope = NULL) const; @@ -385,14 +399,6 @@ class TSymbolTable return table[currentLevel() - 1]; } - void relateToOperator(ESymbolLevel level, const char *name, TOperator op) - { - table[level]->relateToOperator(name, op); - } - void relateToExtension(ESymbolLevel level, const char *name, const TString &ext) - { - table[level]->relateToExtension(name, ext); - } void dump(TInfoSink &infoSink) const; bool setDefaultPrecision(const TPublicType &type, TPrecision prec) @@ -413,7 +419,7 @@ class TSymbolTable // This records invariant varyings declared through // "invariant varying_name;". - void addInvariantVarying(const TString &originalName) + void addInvariantVarying(const std::string &originalName) { mInvariantVaryings.insert(originalName); } @@ -421,7 +427,7 @@ class TSymbolTable // if it is set as invariant during the varying variable // declaration - this piece of information is stored in the // variable's type, not here. - bool isVaryingInvariant(const TString &originalName) const + bool isVaryingInvariant(const std::string &originalName) const { return (mGlobalInvariant || mInvariantVaryings.count(originalName) > 0); @@ -445,10 +451,10 @@ class TSymbolTable typedef TMap PrecisionStackLevel; std::vector< PrecisionStackLevel *> precisionStack; - std::set mInvariantVaryings; + std::set mInvariantVaryings; bool mGlobalInvariant; static int uniqueIdCounter; }; -#endif // _SYMBOL_TABLE_INCLUDED_ +#endif // COMPILER_TRANSLATOR_SYMBOLTABLE_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.cpp b/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.cpp index dcbf3cea1d..238bc97576 100644 --- a/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.cpp +++ b/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.cpp @@ -6,40 +6,91 @@ #include "compiler/translator/TranslatorESSL.h" +#include "compiler/translator/BuiltInFunctionEmulatorGLSL.h" +#include "compiler/translator/EmulatePrecision.h" #include "compiler/translator/OutputESSL.h" #include "angle_gl.h" TranslatorESSL::TranslatorESSL(sh::GLenum type, ShShaderSpec spec) - : TCompiler(type, spec, SH_ESSL_OUTPUT) { + : TCompiler(type, spec, SH_ESSL_OUTPUT) +{ } -void TranslatorESSL::translate(TIntermNode* root) { +void TranslatorESSL::initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu, int compileOptions) +{ + if (compileOptions & SH_EMULATE_BUILT_IN_FUNCTIONS) + InitBuiltInFunctionEmulatorForGLSL(emu, getShaderType()); +} + +void TranslatorESSL::translate(TIntermNode *root, int) { TInfoSinkBase& sink = getInfoSink().obj; + int shaderVersion = getShaderVersion(); + if (shaderVersion > 100) + { + sink << "#version " << shaderVersion << " es\n"; + } + writePragma(); // Write built-in extension behaviors. writeExtensionBehavior(); + bool precisionEmulation = getResources().WEBGL_debug_shader_precision && getPragma().debugShaderPrecision; + + if (precisionEmulation) + { + EmulatePrecision emulatePrecision; + root->traverse(&emulatePrecision); + emulatePrecision.updateTree(); + emulatePrecision.writeEmulationHelpers(sink, SH_ESSL_OUTPUT); + } + // Write emulated built-in functions if needed. - getBuiltInFunctionEmulator().OutputEmulatedFunctionDefinition( - sink, getShaderType() == GL_FRAGMENT_SHADER); + if (!getBuiltInFunctionEmulator().IsOutputEmpty()) + { + sink << "// BEGIN: Generated code for built-in function emulation\n\n"; + if (getShaderType() == GL_FRAGMENT_SHADER) + { + sink << "#if defined(GL_FRAGMENT_PRECISION_HIGH)\n" + << "#define webgl_emu_precision highp\n" + << "#else\n" + << "#define webgl_emu_precision mediump\n" + << "#endif\n\n"; + } + else + { + sink << "#define webgl_emu_precision highp\n"; + } + + getBuiltInFunctionEmulator().OutputEmulatedFunctions(sink); + sink << "// END: Generated code for built-in function emulation\n\n"; + } // Write array bounds clamping emulation if needed. getArrayBoundsClamper().OutputClampingFunctionDefinition(sink); // Write translated shader. - TOutputESSL outputESSL(sink, getArrayIndexClampingStrategy(), getHashFunction(), getNameMap(), getSymbolTable(), getShaderVersion()); + TOutputESSL outputESSL(sink, + getArrayIndexClampingStrategy(), + getHashFunction(), + getNameMap(), + getSymbolTable(), + shaderVersion, + precisionEmulation); root->traverse(&outputESSL); } void TranslatorESSL::writeExtensionBehavior() { TInfoSinkBase& sink = getInfoSink().obj; - const TExtensionBehavior& extensionBehavior = getExtensionBehavior(); - for (TExtensionBehavior::const_iterator iter = extensionBehavior.begin(); - iter != extensionBehavior.end(); ++iter) { + const TExtensionBehavior& extBehavior = getExtensionBehavior(); + for (TExtensionBehavior::const_iterator iter = extBehavior.begin(); + iter != extBehavior.end(); ++iter) { if (iter->second != EBhUndefined) { - if (getResources().NV_draw_buffers && iter->first == "GL_EXT_draw_buffers") { + if (getResources().NV_shader_framebuffer_fetch && iter->first == "GL_EXT_shader_framebuffer_fetch") { + sink << "#extension GL_NV_shader_framebuffer_fetch : " + << getBehaviorString(iter->second) << "\n"; + } else if (getResources().NV_draw_buffers && iter->first == "GL_EXT_draw_buffers") { sink << "#extension GL_NV_draw_buffers : " << getBehaviorString(iter->second) << "\n"; } else { diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.h b/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.h index 55766822d1..89a3e473e9 100644 --- a/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.h +++ b/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.h @@ -4,20 +4,23 @@ // found in the LICENSE file. // -#ifndef COMPILER_TRANSLATORESSL_H_ -#define COMPILER_TRANSLATORESSL_H_ +#ifndef COMPILER_TRANSLATOR_TRANSLATORESSL_H_ +#define COMPILER_TRANSLATOR_TRANSLATORESSL_H_ #include "compiler/translator/Compiler.h" -class TranslatorESSL : public TCompiler { -public: +class TranslatorESSL : public TCompiler +{ + public: TranslatorESSL(sh::GLenum type, ShShaderSpec spec); -protected: - virtual void translate(TIntermNode* root); + protected: + void initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu, int compileOptions) override; -private: + virtual void translate(TIntermNode *root, int compileOptions); + + private: void writeExtensionBehavior(); }; -#endif // COMPILER_TRANSLATORESSL_H_ +#endif // COMPILER_TRANSLATOR_TRANSLATORESSL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.cpp b/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.cpp index 6acbf7c5a8..aea3f77c4e 100644 --- a/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.cpp +++ b/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.cpp @@ -6,14 +6,69 @@ #include "compiler/translator/TranslatorGLSL.h" +#include "angle_gl.h" +#include "compiler/translator/BuiltInFunctionEmulatorGLSL.h" +#include "compiler/translator/EmulatePrecision.h" #include "compiler/translator/OutputGLSL.h" #include "compiler/translator/VersionGLSL.h" -TranslatorGLSL::TranslatorGLSL(sh::GLenum type, ShShaderSpec spec) - : TCompiler(type, spec, SH_GLSL_OUTPUT) { +namespace +{ + +// To search for what output variables are used in a fragment shader. +// We handle gl_FragColor and gl_FragData at the moment. +class TFragmentOutSearcher : public TIntermTraverser +{ + public: + TFragmentOutSearcher() + : mUsesGlFragColor(false), + mUsesGlFragData(false) + { + } + + bool usesGlFragColor() const + { + return mUsesGlFragColor; + } + + bool usesGlFragData() const + { + return mUsesGlFragData; + } + + protected: + virtual void visitSymbol(TIntermSymbol *node) override + { + if (node->getSymbol() == "gl_FragColor") + { + mUsesGlFragColor = true; + } + else if (node->getSymbol() == "gl_FragData") + { + mUsesGlFragData = true; + } + } + + private: + bool mUsesGlFragColor; + bool mUsesGlFragData; +}; + +} // namespace anonymous + +TranslatorGLSL::TranslatorGLSL(sh::GLenum type, + ShShaderSpec spec, + ShShaderOutput output) + : TCompiler(type, spec, output) { +} + +void TranslatorGLSL::initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu, int compileOptions) +{ + if (compileOptions & SH_EMULATE_BUILT_IN_FUNCTIONS) + InitBuiltInFunctionEmulatorForGLSL(emu, getShaderType()); } -void TranslatorGLSL::translate(TIntermNode* root) { +void TranslatorGLSL::translate(TIntermNode *root, int) { TInfoSinkBase& sink = getInfoSink().obj; // Write GLSL version. @@ -24,21 +79,60 @@ void TranslatorGLSL::translate(TIntermNode* root) { // Write extension behaviour as needed writeExtensionBehavior(); + bool precisionEmulation = getResources().WEBGL_debug_shader_precision && getPragma().debugShaderPrecision; + + if (precisionEmulation) + { + EmulatePrecision emulatePrecision; + root->traverse(&emulatePrecision); + emulatePrecision.updateTree(); + emulatePrecision.writeEmulationHelpers(sink, getOutputType()); + } + // Write emulated built-in functions if needed. - getBuiltInFunctionEmulator().OutputEmulatedFunctionDefinition( - sink, false); + if (!getBuiltInFunctionEmulator().IsOutputEmpty()) + { + sink << "// BEGIN: Generated code for built-in function emulation\n\n"; + sink << "#define webgl_emu_precision\n\n"; + getBuiltInFunctionEmulator().OutputEmulatedFunctions(sink); + sink << "// END: Generated code for built-in function emulation\n\n"; + } // Write array bounds clamping emulation if needed. getArrayBoundsClamper().OutputClampingFunctionDefinition(sink); + // Declare gl_FragColor and glFragData as webgl_FragColor and webgl_FragData + // if it's core profile shaders and they are used. + if (getShaderType() == GL_FRAGMENT_SHADER && + getOutputType() == SH_GLSL_CORE_OUTPUT) + { + TFragmentOutSearcher searcher; + root->traverse(&searcher); + ASSERT(!(searcher.usesGlFragData() && searcher.usesGlFragColor())); + if (searcher.usesGlFragColor()) + { + sink << "out vec4 webgl_FragColor;\n"; + } + if (searcher.usesGlFragData()) + { + sink << "out vec4 webgl_FragData[gl_MaxDrawBuffers];\n"; + } + } + // Write translated shader. - TOutputGLSL outputGLSL(sink, getArrayIndexClampingStrategy(), getHashFunction(), getNameMap(), getSymbolTable(), getShaderVersion()); + TOutputGLSL outputGLSL(sink, + getArrayIndexClampingStrategy(), + getHashFunction(), + getNameMap(), + getSymbolTable(), + getShaderVersion(), + getOutputType()); root->traverse(&outputGLSL); } void TranslatorGLSL::writeVersion(TIntermNode *root) { - TVersionGLSL versionGLSL(getShaderType(), getPragma()); + TVersionGLSL versionGLSL(getShaderType(), getPragma(), getOutputType()); root->traverse(&versionGLSL); int version = versionGLSL.getVersion(); // We need to write version directive only if it is greater than 110. @@ -52,9 +146,9 @@ void TranslatorGLSL::writeVersion(TIntermNode *root) void TranslatorGLSL::writeExtensionBehavior() { TInfoSinkBase& sink = getInfoSink().obj; - const TExtensionBehavior& extensionBehavior = getExtensionBehavior(); - for (TExtensionBehavior::const_iterator iter = extensionBehavior.begin(); - iter != extensionBehavior.end(); ++iter) { + const TExtensionBehavior& extBehavior = getExtensionBehavior(); + for (TExtensionBehavior::const_iterator iter = extBehavior.begin(); + iter != extBehavior.end(); ++iter) { if (iter->second == EBhUndefined) continue; diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.h b/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.h index 766d8d910e..4a5a641096 100644 --- a/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.h +++ b/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.h @@ -4,22 +4,24 @@ // found in the LICENSE file. // -#ifndef COMPILER_TRANSLATORGLSL_H_ -#define COMPILER_TRANSLATORGLSL_H_ +#ifndef COMPILER_TRANSLATOR_TRANSLATORGLSL_H_ +#define COMPILER_TRANSLATOR_TRANSLATORGLSL_H_ #include "compiler/translator/Compiler.h" class TranslatorGLSL : public TCompiler { public: - TranslatorGLSL(sh::GLenum type, ShShaderSpec spec); + TranslatorGLSL(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output); protected: - virtual void translate(TIntermNode *root); + void initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu, int compileOptions) override; + + virtual void translate(TIntermNode *root, int compileOptions); private: void writeVersion(TIntermNode *root); void writeExtensionBehavior(); }; -#endif // COMPILER_TRANSLATORGLSL_H_ +#endif // COMPILER_TRANSLATOR_TRANSLATORGLSL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.cpp index 22bf60e86e..f6275defa1 100644 --- a/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.cpp +++ b/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.cpp @@ -6,20 +6,26 @@ #include "compiler/translator/TranslatorHLSL.h" -#include "compiler/translator/InitializeParseContext.h" #include "compiler/translator/OutputHLSL.h" +#include "compiler/translator/SimplifyArrayAssignment.h" TranslatorHLSL::TranslatorHLSL(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output) : TCompiler(type, spec, output) { } -void TranslatorHLSL::translate(TIntermNode *root) +void TranslatorHLSL::translate(TIntermNode *root, int compileOptions) { - TParseContext& parseContext = *GetGlobalParseContext(); - sh::OutputHLSL outputHLSL(parseContext, this); + const ShBuiltInResources &resources = getResources(); + int numRenderTargets = resources.EXT_draw_buffers ? resources.MaxDrawBuffers : 1; - outputHLSL.output(); + SimplifyArrayAssignment simplify; + root->traverse(&simplify); + + sh::OutputHLSL outputHLSL(getShaderType(), getShaderVersion(), getExtensionBehavior(), + getSourcePath(), getOutputType(), numRenderTargets, getUniforms(), compileOptions); + + outputHLSL.output(root, getInfoSink().obj); mInterfaceBlockRegisterMap = outputHLSL.getInterfaceBlockRegisterMap(); mUniformRegisterMap = outputHLSL.getUniformRegisterMap(); diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.h b/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.h index 11a042d83a..1920ed5755 100644 --- a/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.h +++ b/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef COMPILER_TRANSLATORHLSL_H_ -#define COMPILER_TRANSLATORHLSL_H_ +#ifndef COMPILER_TRANSLATOR_TRANSLATORHLSL_H_ +#define COMPILER_TRANSLATOR_TRANSLATORHLSL_H_ #include "compiler/translator/Compiler.h" @@ -22,10 +22,10 @@ class TranslatorHLSL : public TCompiler unsigned int getUniformRegister(const std::string &uniformName) const; protected: - virtual void translate(TIntermNode* root); + virtual void translate(TIntermNode *root, int compileOptions); std::map mInterfaceBlockRegisterMap; std::map mUniformRegisterMap; }; -#endif // COMPILER_TRANSLATORHLSL_H_ +#endif // COMPILER_TRANSLATOR_TRANSLATORHLSL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/Types.cpp b/src/3rdparty/angle/src/compiler/translator/Types.cpp index d36936fb23..b970bf5ac4 100644 --- a/src/3rdparty/angle/src/compiler/translator/Types.cpp +++ b/src/3rdparty/angle/src/compiler/translator/Types.cpp @@ -178,11 +178,12 @@ size_t TType::getObjectSize() const if (isArray()) { - size_t arraySize = getArraySize(); - if (arraySize > INT_MAX / totalSize) + // TODO: getArraySize() returns an int, not a size_t + size_t currentArraySize = getArraySize(); + if (currentArraySize > INT_MAX / totalSize) totalSize = INT_MAX; else - totalSize *= arraySize; + totalSize *= currentArraySize; } return totalSize; @@ -199,6 +200,17 @@ bool TStructure::containsArrays() const return false; } +bool TStructure::containsSamplers() const +{ + for (size_t i = 0; i < mFields->size(); ++i) + { + const TType *fieldType = (*mFields)[i]->type(); + if (IsSampler(fieldType->getBasicType()) || fieldType->isStructureContainingSamplers()) + return true; + } + return false; +} + TString TFieldListCollection::buildMangledName() const { TString mangledName(mangledNamePrefix()); diff --git a/src/3rdparty/angle/src/compiler/translator/Types.h b/src/3rdparty/angle/src/compiler/translator/Types.h index 075196daa3..044f22c3c1 100644 --- a/src/3rdparty/angle/src/compiler/translator/Types.h +++ b/src/3rdparty/angle/src/compiler/translator/Types.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef _TYPES_INCLUDED -#define _TYPES_INCLUDED +#ifndef COMPILER_TRANSLATOR_TYPES_H_ +#define COMPILER_TRANSLATOR_TYPES_H_ #include "common/angleutils.h" @@ -17,7 +17,7 @@ struct TPublicType; class TType; class TSymbol; -class TField +class TField : angle::NonCopyable { public: POOL_ALLOCATOR_NEW_DELETE(); @@ -49,7 +49,6 @@ class TField } private: - DISALLOW_COPY_AND_ASSIGN(TField); TType *mType; TString *mName; TSourceLoc mLine; @@ -62,7 +61,7 @@ inline TFieldList *NewPoolTFieldList() return new(memory) TFieldList; } -class TFieldListCollection +class TFieldListCollection : angle::NonCopyable { public: const TString &name() const @@ -113,7 +112,8 @@ class TStructure : public TFieldListCollection TStructure(const TString *name, TFieldList *fields) : TFieldListCollection(name, fields), mDeepestNesting(0), - mUniqueId(0) + mUniqueId(0), + mAtGlobalScope(false) { } @@ -124,6 +124,7 @@ class TStructure : public TFieldListCollection return mDeepestNesting; } bool containsArrays() const; + bool containsSamplers() const; bool equals(const TStructure &other) const; @@ -138,9 +139,17 @@ class TStructure : public TFieldListCollection return mUniqueId; } - private: - DISALLOW_COPY_AND_ASSIGN(TStructure); + void setAtGlobalScope(bool atGlobalScope) + { + mAtGlobalScope = atGlobalScope; + } + + bool atGlobalScope() const + { + return mAtGlobalScope; + } + private: // TODO(zmo): Find a way to get rid of the const_cast in function // setName(). At the moment keep this function private so only // friend class RegenerateStructNames may call it. @@ -159,6 +168,7 @@ class TStructure : public TFieldListCollection mutable int mDeepestNesting; int mUniqueId; + bool mAtGlobalScope; }; class TInterfaceBlock : public TFieldListCollection @@ -201,7 +211,6 @@ class TInterfaceBlock : public TFieldListCollection } private: - DISALLOW_COPY_AND_ASSIGN(TInterfaceBlock); virtual TString mangledNamePrefix() const { return "iblock-"; @@ -325,6 +334,10 @@ class TType { return primarySize > 1 && secondarySize > 1; } + bool isNonSquareMatrix() const + { + return isMatrix() && primarySize != secondarySize; + } bool isArray() const { return array ? true : false; @@ -464,6 +477,11 @@ class TType return structure ? structure->containsArrays() : false; } + bool isStructureContainingSamplers() const + { + return structure ? structure->containsSamplers() : false; + } + protected: TString buildMangledName() const; size_t getStructSize() const; @@ -584,4 +602,4 @@ struct TPublicType } }; -#endif // _TYPES_INCLUDED_ +#endif // COMPILER_TRANSLATOR_TYPES_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuit.cpp b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuit.cpp index 65f50c4cc3..f79f9dd7fb 100644 --- a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuit.cpp +++ b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuit.cpp @@ -16,7 +16,7 @@ namespace sh { -UnfoldShortCircuit::UnfoldShortCircuit(TParseContext &context, OutputHLSL *outputHLSL) : mContext(context), mOutputHLSL(outputHLSL) +UnfoldShortCircuit::UnfoldShortCircuit(OutputHLSL *outputHLSL) : mOutputHLSL(outputHLSL) { mTemporaryIndex = 0; } @@ -30,7 +30,7 @@ void UnfoldShortCircuit::traverse(TIntermNode *node) bool UnfoldShortCircuit::visitBinary(Visit visit, TIntermBinary *node) { - TInfoSinkBase &out = mOutputHLSL->getBodyStream(); + TInfoSinkBase &out = mOutputHLSL->getInfoSink(); // If our right node doesn't have side effects, we know we don't need to unfold this // expression: there will be no short-circuiting side effects to avoid @@ -111,7 +111,7 @@ bool UnfoldShortCircuit::visitBinary(Visit visit, TIntermBinary *node) bool UnfoldShortCircuit::visitSelection(Visit visit, TIntermSelection *node) { - TInfoSinkBase &out = mOutputHLSL->getBodyStream(); + TInfoSinkBase &out = mOutputHLSL->getInfoSink(); // Unfold "b ? x : y" into "type s; if(b) s = x; else s = y;" if (node->usesTernaryOperator()) diff --git a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuit.h b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuit.h index 6fd3b457bd..eaceb0a0b3 100644 --- a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuit.h +++ b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuit.h @@ -6,8 +6,8 @@ // UnfoldShortCircuit is an AST traverser to output short-circuiting operators as if-else statements // -#ifndef COMPILER_UNFOLDSHORTCIRCUIT_H_ -#define COMPILER_UNFOLDSHORTCIRCUIT_H_ +#ifndef COMPILER_TRANSLATOR_UNFOLDSHORTCIRCUIT_H_ +#define COMPILER_TRANSLATOR_UNFOLDSHORTCIRCUIT_H_ #include "compiler/translator/IntermNode.h" #include "compiler/translator/ParseContext.h" @@ -19,7 +19,7 @@ class OutputHLSL; class UnfoldShortCircuit : public TIntermTraverser { public: - UnfoldShortCircuit(TParseContext &context, OutputHLSL *outputHLSL); + UnfoldShortCircuit(OutputHLSL *outputHLSL); void traverse(TIntermNode *node); bool visitBinary(Visit visit, TIntermBinary*); @@ -29,11 +29,10 @@ class UnfoldShortCircuit : public TIntermTraverser int getNextTemporaryIndex(); protected: - TParseContext &mContext; OutputHLSL *const mOutputHLSL; int mTemporaryIndex; }; } -#endif // COMPILER_UNFOLDSHORTCIRCUIT_H_ +#endif // COMPILER_TRANSLATOR_UNFOLDSHORTCIRCUIT_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.cpp b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.cpp index 29c4397d56..d548d421d2 100644 --- a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.cpp +++ b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.cpp @@ -50,32 +50,8 @@ bool UnfoldShortCircuitAST::visitBinary(Visit visit, TIntermBinary *node) } if (replacement) { - replacements.push_back( - NodeUpdateEntry(getParentNode(), node, replacement)); + mReplacements.push_back( + NodeUpdateEntry(getParentNode(), node, replacement, false)); } return true; } - -void UnfoldShortCircuitAST::updateTree() -{ - for (size_t ii = 0; ii < replacements.size(); ++ii) - { - const NodeUpdateEntry& entry = replacements[ii]; - ASSERT(entry.parent); - bool replaced = entry.parent->replaceChildNode( - entry.original, entry.replacement); - ASSERT(replaced); - - // In AST traversing, a parent is visited before its children. - // After we replace a node, if an immediate child is to - // be replaced, we need to make sure we don't update the replaced - // node; instead, we update the replacement node. - for (size_t jj = ii + 1; jj < replacements.size(); ++jj) - { - NodeUpdateEntry& entry2 = replacements[jj]; - if (entry2.parent == entry.original) - entry2.parent = entry.replacement; - } - } -} - diff --git a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.h b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.h index 3acaf7ee7c..7b698ccb63 100644 --- a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.h +++ b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.h @@ -7,8 +7,8 @@ // operations with ternary operations. // -#ifndef COMPILER_UNFOLD_SHORT_CIRCUIT_AST_H_ -#define COMPILER_UNFOLD_SHORT_CIRCUIT_AST_H_ +#ifndef COMPILER_TRANSLATOR_UNFOLDSHORTCIRCUITAST_H_ +#define COMPILER_TRANSLATOR_UNFOLDSHORTCIRCUITAST_H_ #include "common/angleutils.h" #include "compiler/translator/IntermNode.h" @@ -23,29 +23,6 @@ class UnfoldShortCircuitAST : public TIntermTraverser UnfoldShortCircuitAST() { } virtual bool visitBinary(Visit visit, TIntermBinary *); - - void updateTree(); - - private: - struct NodeUpdateEntry - { - NodeUpdateEntry(TIntermNode *_parent, - TIntermNode *_original, - TIntermNode *_replacement) - : parent(_parent), - original(_original), - replacement(_replacement) {} - - TIntermNode *parent; - TIntermNode *original; - TIntermNode *replacement; - }; - - // During traversing, save all the replacements that need to happen; - // then replace them by calling updateNodes(). - std::vector replacements; - - DISALLOW_COPY_AND_ASSIGN(UnfoldShortCircuitAST); }; -#endif // COMPILER_UNFOLD_SHORT_CIRCUIT_AST_H_ +#endif // COMPILER_TRANSLATOR_UNFOLDSHORTCIRCUITAST_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/UniformHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/UniformHLSL.cpp index 61b6ed7455..71659fe354 100644 --- a/src/3rdparty/angle/src/compiler/translator/UniformHLSL.cpp +++ b/src/3rdparty/angle/src/compiler/translator/UniformHLSL.cpp @@ -7,14 +7,13 @@ // Methods for GLSL to HLSL translation for uniforms and interface blocks. // -#include "OutputHLSL.h" -#include "common/blocklayout.h" -#include "common/utilities.h" #include "compiler/translator/UniformHLSL.h" + +#include "common/utilities.h" #include "compiler/translator/StructureHLSL.h" -#include "compiler/translator/util.h" #include "compiler/translator/UtilsHLSL.h" -#include "compiler/translator/TranslatorHLSL.h" +#include "compiler/translator/blocklayoutHLSL.h" +#include "compiler/translator/util.h" namespace sh { @@ -61,13 +60,13 @@ static TString InterfaceBlockStructName(const TInterfaceBlock &interfaceBlock) return DecoratePrivate(interfaceBlock.name()) + "_type"; } -UniformHLSL::UniformHLSL(StructureHLSL *structureHLSL, TranslatorHLSL *translator) +UniformHLSL::UniformHLSL(StructureHLSL *structureHLSL, ShShaderOutput outputType, const std::vector &uniforms) : mUniformRegister(0), mInterfaceBlockRegister(0), mSamplerRegister(0), mStructureHLSL(structureHLSL), - mOutputType(translator->getOutputType()), - mUniforms(translator->getUniforms()) + mOutputType(outputType), + mUniforms(uniforms) {} void UniformHLSL::reserveUniformRegisters(unsigned int registerCount) @@ -105,7 +104,7 @@ unsigned int UniformHLSL::declareUniformAndAssignRegister(const TType &type, con unsigned int registerCount = HLSLVariableRegisterCount(*uniform, mOutputType); - if (gl::IsSampler(uniform->type)) + if (gl::IsSamplerType(uniform->type)) { mSamplerRegister += registerCount; } diff --git a/src/3rdparty/angle/src/compiler/translator/UniformHLSL.h b/src/3rdparty/angle/src/compiler/translator/UniformHLSL.h index 91fa51588b..4ab9ccdf53 100644 --- a/src/3rdparty/angle/src/compiler/translator/UniformHLSL.h +++ b/src/3rdparty/angle/src/compiler/translator/UniformHLSL.h @@ -7,19 +7,19 @@ // Methods for GLSL to HLSL translation for uniforms and interface blocks. // -#ifndef TRANSLATOR_UNIFORMHLSL_H_ -#define TRANSLATOR_UNIFORMHLSL_H_ +#ifndef COMPILER_TRANSLATOR_UNIFORMHLSL_H_ +#define COMPILER_TRANSLATOR_UNIFORMHLSL_H_ -#include "compiler/translator/Types.h" +#include "compiler/translator/OutputHLSL.h" namespace sh { class StructureHLSL; -class UniformHLSL +class UniformHLSL : angle::NonCopyable { public: - UniformHLSL(StructureHLSL *structureHLSL, TranslatorHLSL *translator); + UniformHLSL(StructureHLSL *structureHLSL, ShShaderOutput outputType, const std::vector &uniforms); void reserveUniformRegisters(unsigned int registerCount); void reserveInterfaceBlockRegisters(unsigned int registerCount); @@ -60,4 +60,4 @@ class UniformHLSL } -#endif // TRANSLATOR_UNIFORMHLSL_H_ +#endif // COMPILER_TRANSLATOR_UNIFORMHLSL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/UtilsHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/UtilsHLSL.cpp index de0c36ca65..94e19ac40d 100644 --- a/src/3rdparty/angle/src/compiler/translator/UtilsHLSL.cpp +++ b/src/3rdparty/angle/src/compiler/translator/UtilsHLSL.cpp @@ -175,6 +175,13 @@ TString StructNameString(const TStructure &structure) return ""; } + // For structures at global scope we use a consistent + // translation so that we can link between shader stages. + if (structure.atGlobalScope()) + { + return Decorate(structure.name()); + } + return "ss" + str(structure.uniqueId()) + "_" + structure.name(); } diff --git a/src/3rdparty/angle/src/compiler/translator/UtilsHLSL.h b/src/3rdparty/angle/src/compiler/translator/UtilsHLSL.h index aaa3ddf5d2..9800a3bbf3 100644 --- a/src/3rdparty/angle/src/compiler/translator/UtilsHLSL.h +++ b/src/3rdparty/angle/src/compiler/translator/UtilsHLSL.h @@ -7,8 +7,8 @@ // Utility methods for GLSL to HLSL translation. // -#ifndef TRANSLATOR_UTILSHLSL_H_ -#define TRANSLATOR_UTILSHLSL_H_ +#ifndef COMPILER_TRANSLATOR_UTILSHLSL_H_ +#define COMPILER_TRANSLATOR_UTILSHLSL_H_ #include #include "compiler/translator/Types.h" @@ -34,4 +34,4 @@ TString QualifierString(TQualifier qualifier); } -#endif // TRANSLATOR_UTILSHLSL_H_ +#endif // COMPILER_TRANSLATOR_UTILSHLSL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.cpp b/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.cpp index 896e1cd7a0..12367066e8 100644 --- a/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.cpp +++ b/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.cpp @@ -47,93 +47,6 @@ class ValidateConstIndexExpr : public TIntermTraverser TLoopStack& mLoopStack; }; -const char *GetOperatorString(TOperator op) -{ - switch (op) - { - case EOpInitialize: return "="; - case EOpAssign: return "="; - case EOpAddAssign: return "+="; - case EOpSubAssign: return "-="; - case EOpDivAssign: return "/="; - - // Fall-through. - case EOpMulAssign: - case EOpVectorTimesMatrixAssign: - case EOpVectorTimesScalarAssign: - case EOpMatrixTimesScalarAssign: - case EOpMatrixTimesMatrixAssign: return "*="; - - // Fall-through. - case EOpIndexDirect: - case EOpIndexIndirect: return "[]"; - - case EOpIndexDirectStruct: - case EOpIndexDirectInterfaceBlock: return "."; - case EOpVectorSwizzle: return "."; - case EOpAdd: return "+"; - case EOpSub: return "-"; - case EOpMul: return "*"; - case EOpDiv: return "/"; - case EOpMod: UNIMPLEMENTED(); break; - case EOpEqual: return "=="; - case EOpNotEqual: return "!="; - case EOpLessThan: return "<"; - case EOpGreaterThan: return ">"; - case EOpLessThanEqual: return "<="; - case EOpGreaterThanEqual: return ">="; - - // Fall-through. - case EOpVectorTimesScalar: - case EOpVectorTimesMatrix: - case EOpMatrixTimesVector: - case EOpMatrixTimesScalar: - case EOpMatrixTimesMatrix: return "*"; - - case EOpLogicalOr: return "||"; - case EOpLogicalXor: return "^^"; - case EOpLogicalAnd: return "&&"; - case EOpNegative: return "-"; - case EOpPositive: return "+"; - case EOpVectorLogicalNot: return "not"; - case EOpLogicalNot: return "!"; - case EOpPostIncrement: return "++"; - case EOpPostDecrement: return "--"; - case EOpPreIncrement: return "++"; - case EOpPreDecrement: return "--"; - - case EOpRadians: return "radians"; - case EOpDegrees: return "degrees"; - case EOpSin: return "sin"; - case EOpCos: return "cos"; - case EOpTan: return "tan"; - case EOpAsin: return "asin"; - case EOpAcos: return "acos"; - case EOpAtan: return "atan"; - case EOpExp: return "exp"; - case EOpLog: return "log"; - case EOpExp2: return "exp2"; - case EOpLog2: return "log2"; - case EOpSqrt: return "sqrt"; - case EOpInverseSqrt: return "inversesqrt"; - case EOpAbs: return "abs"; - case EOpSign: return "sign"; - case EOpFloor: return "floor"; - case EOpCeil: return "ceil"; - case EOpFract: return "fract"; - case EOpLength: return "length"; - case EOpNormalize: return "normalize"; - case EOpDFdx: return "dFdx"; - case EOpDFdy: return "dFdy"; - case EOpFwidth: return "fwidth"; - case EOpAny: return "any"; - case EOpAll: return "all"; - - default: break; - } - return ""; -} - } // namespace anonymous ValidateLimitations::ValidateLimitations(sh::GLenum shaderType, diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.h b/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.h index e6e8a9619f..59cccb565f 100644 --- a/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.h +++ b/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.h @@ -4,6 +4,9 @@ // found in the LICENSE file. // +#ifndef COMPILER_TRANSLATOR_VALIDATELIMITATIONS_H_ +#define COMPILER_TRANSLATOR_VALIDATELIMITATIONS_H_ + #include "compiler/translator/IntermNode.h" #include "compiler/translator/LoopInfo.h" @@ -53,3 +56,4 @@ class ValidateLimitations : public TIntermTraverser TLoopStack mLoopStack; }; +#endif // COMPILER_TRANSLATOR_VALIDATELIMITATIONS_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateOutputs.h b/src/3rdparty/angle/src/compiler/translator/ValidateOutputs.h index 0f808dbb97..1538e0f157 100644 --- a/src/3rdparty/angle/src/compiler/translator/ValidateOutputs.h +++ b/src/3rdparty/angle/src/compiler/translator/ValidateOutputs.h @@ -4,6 +4,9 @@ // found in the LICENSE file. // +#ifndef COMPILER_TRANSLATOR_VALIDATEOUTPUTS_H_ +#define COMPILER_TRANSLATOR_VALIDATEOUTPUTS_H_ + #include "compiler/translator/IntermNode.h" #include @@ -31,3 +34,5 @@ class ValidateOutputs : public TIntermTraverser void error(TSourceLoc loc, const char *reason, const char* token); }; + +#endif // COMPILER_TRANSLATOR_VALIDATEOUTPUTS_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateSwitch.cpp b/src/3rdparty/angle/src/compiler/translator/ValidateSwitch.cpp new file mode 100644 index 0000000000..9a4ed33632 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/ValidateSwitch.cpp @@ -0,0 +1,200 @@ +// +// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/ValidateSwitch.h" + +#include "compiler/translator/ParseContext.h" + +bool ValidateSwitch::validate(TBasicType switchType, TParseContext *context, + TIntermAggregate *statementList, const TSourceLoc &loc) +{ + ValidateSwitch validate(switchType, context); + ASSERT(statementList); + statementList->traverse(&validate); + return validate.validateInternal(loc); +} + +ValidateSwitch::ValidateSwitch(TBasicType switchType, TParseContext *context) + : TIntermTraverser(true, false, true), + mSwitchType(switchType), + mContext(context), + mCaseTypeMismatch(false), + mFirstCaseFound(false), + mStatementBeforeCase(false), + mLastStatementWasCase(false), + mControlFlowDepth(0), + mCaseInsideControlFlow(false), + mDefaultCount(0), + mDuplicateCases(false) +{} + +void ValidateSwitch::visitSymbol(TIntermSymbol *) +{ + if (!mFirstCaseFound) + mStatementBeforeCase = true; + mLastStatementWasCase = false; +} + +void ValidateSwitch::visitConstantUnion(TIntermConstantUnion *) +{ + // Conditions of case labels are not traversed, so this is some other constant + // Could be just a statement like "0;" + if (!mFirstCaseFound) + mStatementBeforeCase = true; + mLastStatementWasCase = false; +} + +bool ValidateSwitch::visitBinary(Visit, TIntermBinary *) +{ + if (!mFirstCaseFound) + mStatementBeforeCase = true; + mLastStatementWasCase = false; + return true; +} + +bool ValidateSwitch::visitUnary(Visit, TIntermUnary *) +{ + if (!mFirstCaseFound) + mStatementBeforeCase = true; + mLastStatementWasCase = false; + return true; +} + +bool ValidateSwitch::visitSelection(Visit visit, TIntermSelection *) +{ + if (visit == PreVisit) + ++mControlFlowDepth; + if (visit == PostVisit) + --mControlFlowDepth; + if (!mFirstCaseFound) + mStatementBeforeCase = true; + mLastStatementWasCase = false; + return true; +} + +bool ValidateSwitch::visitSwitch(Visit, TIntermSwitch *) +{ + if (!mFirstCaseFound) + mStatementBeforeCase = true; + mLastStatementWasCase = false; + // Don't go into nested switch statements + return false; +} + +bool ValidateSwitch::visitCase(Visit, TIntermCase *node) +{ + const char *nodeStr = node->hasCondition() ? "case" : "default"; + if (mControlFlowDepth > 0) + { + mContext->error(node->getLine(), "label statement nested inside control flow", nodeStr); + mCaseInsideControlFlow = true; + } + mFirstCaseFound = true; + mLastStatementWasCase = true; + if (!node->hasCondition()) + { + ++mDefaultCount; + if (mDefaultCount > 1) + { + mContext->error(node->getLine(), "duplicate default label", nodeStr); + } + } + else + { + TIntermConstantUnion *condition = node->getCondition()->getAsConstantUnion(); + if (condition == nullptr) + { + // This can happen in error cases. + return false; + } + TBasicType conditionType = condition->getBasicType(); + if (conditionType != mSwitchType) + { + mContext->error(condition->getLine(), + "case label type does not match switch init-expression type", nodeStr); + mCaseTypeMismatch = true; + } + + if (conditionType == EbtInt) + { + int iConst = condition->getIConst(0); + if (mCasesSigned.find(iConst) != mCasesSigned.end()) + { + mContext->error(condition->getLine(), "duplicate case label", nodeStr); + mDuplicateCases = true; + } + else + { + mCasesSigned.insert(iConst); + } + } + else if (conditionType == EbtUInt) + { + unsigned int uConst = condition->getUConst(0); + if (mCasesUnsigned.find(uConst) != mCasesUnsigned.end()) + { + mContext->error(condition->getLine(), "duplicate case label", nodeStr); + mDuplicateCases = true; + } + else + { + mCasesUnsigned.insert(uConst); + } + } + // Other types are possible only in error cases, where the error has already been generated + // when parsing the case statement. + } + // Don't traverse the condition of the case statement + return false; +} + +bool ValidateSwitch::visitAggregate(Visit visit, TIntermAggregate *) +{ + if (getParentNode() != nullptr) + { + // This is not the statementList node, but some other node. + if (!mFirstCaseFound) + mStatementBeforeCase = true; + mLastStatementWasCase = false; + } + return true; +} + +bool ValidateSwitch::visitLoop(Visit visit, TIntermLoop *) +{ + if (visit == PreVisit) + ++mControlFlowDepth; + if (visit == PostVisit) + --mControlFlowDepth; + if (!mFirstCaseFound) + mStatementBeforeCase = true; + mLastStatementWasCase = false; + return true; +} + +bool ValidateSwitch::visitBranch(Visit, TIntermBranch *) +{ + if (!mFirstCaseFound) + mStatementBeforeCase = true; + mLastStatementWasCase = false; + return true; +} + +bool ValidateSwitch::validateInternal(const TSourceLoc &loc) +{ + if (mStatementBeforeCase) + { + mContext->error(loc, + "statement before the first label", "switch"); + } + if (mLastStatementWasCase) + { + mContext->error(loc, + "no statement between the last label and the end of the switch statement", "switch"); + } + return !mStatementBeforeCase && !mLastStatementWasCase && !mCaseInsideControlFlow && + !mCaseTypeMismatch && mDefaultCount <= 1 && !mDuplicateCases; +} diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateSwitch.h b/src/3rdparty/angle/src/compiler/translator/ValidateSwitch.h new file mode 100644 index 0000000000..88b68a500e --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/ValidateSwitch.h @@ -0,0 +1,52 @@ +// +// Copyright (c) 2002-2015 The ANGLE Project 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_TRANSLATOR_VALIDATESWITCH_H_ +#define COMPILER_TRANSLATOR_VALIDATESWITCH_H_ + +#include "compiler/translator/IntermNode.h" + +struct TParseContext; + +class ValidateSwitch : public TIntermTraverser +{ + public: + // Check for errors and output messages any remaining errors on the context. + // Returns true if there are no errors. + static bool validate(TBasicType switchType, TParseContext *context, + TIntermAggregate *statementList, const TSourceLoc &loc); + + void visitSymbol(TIntermSymbol *) override; + void visitConstantUnion(TIntermConstantUnion *) override; + bool visitBinary(Visit, TIntermBinary *) override; + bool visitUnary(Visit, TIntermUnary *) override; + bool visitSelection(Visit visit, TIntermSelection *) override; + bool visitSwitch(Visit, TIntermSwitch *) override; + bool visitCase(Visit, TIntermCase *node) override; + bool visitAggregate(Visit, TIntermAggregate *) override; + bool visitLoop(Visit visit, TIntermLoop *) override; + bool visitBranch(Visit, TIntermBranch *) override; + + private: + ValidateSwitch(TBasicType switchType, TParseContext *context); + + bool validateInternal(const TSourceLoc &loc); + + TBasicType mSwitchType; + TParseContext *mContext; + bool mCaseTypeMismatch; + bool mFirstCaseFound; + bool mStatementBeforeCase; + bool mLastStatementWasCase; + int mControlFlowDepth; + bool mCaseInsideControlFlow; + int mDefaultCount; + std::set mCasesSigned; + std::set mCasesUnsigned; + bool mDuplicateCases; +}; + +#endif // COMPILER_TRANSLATOR_VALIDATESWITCH_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/VariableInfo.cpp b/src/3rdparty/angle/src/compiler/translator/VariableInfo.cpp index d8e13788b7..cf229ec96a 100644 --- a/src/3rdparty/angle/src/compiler/translator/VariableInfo.cpp +++ b/src/3rdparty/angle/src/compiler/translator/VariableInfo.cpp @@ -142,8 +142,10 @@ CollectVariables::CollectVariables(std::vector *attribs, mPointCoordAdded(false), mFrontFacingAdded(false), mFragCoordAdded(false), + mInstanceIDAdded(false), mPositionAdded(false), mPointSizeAdded(false), + mLastFragDataAdded(false), mHashFunction(hashFunction), mSymbolTable(symbolTable) { @@ -249,6 +251,22 @@ void CollectVariables::visitSymbol(TIntermSymbol *symbol) mPointCoordAdded = true; } return; + case EvqInstanceID: + if (!mInstanceIDAdded) + { + Attribute info; + const char kName[] = "gl_InstanceID"; + info.name = kName; + info.mappedName = kName; + info.type = GL_INT; + info.arraySize = 0; + info.precision = GL_HIGH_INT; // Defined by spec. + info.staticUse = true; + info.location = -1; + mAttribs->push_back(info); + mInstanceIDAdded = true; + } + return; case EvqPosition: if (!mPositionAdded) { @@ -281,6 +299,22 @@ void CollectVariables::visitSymbol(TIntermSymbol *symbol) mPointSizeAdded = true; } return; + case EvqLastFragData: + if (!mLastFragDataAdded) + { + Varying info; + const char kName[] = "gl_LastFragData"; + info.name = kName; + info.mappedName = kName; + info.type = GL_FLOAT_VEC4; + info.arraySize = static_cast(mSymbolTable.findBuiltIn("gl_MaxDrawBuffers", 100))->getConstPointer()->getIConst(); + info.precision = GL_MEDIUM_FLOAT; // Defined by spec. + info.staticUse = true; + info.isInvariant = mSymbolTable.isVaryingInvariant(kName); + mVaryings->push_back(info); + mLastFragDataAdded = true; + } + return; default: break; } @@ -301,8 +335,6 @@ class NameHashingTraverser : public GetVariableTraverser {} private: - DISALLOW_COPY_AND_ASSIGN(NameHashingTraverser); - virtual void visitVariable(ShaderVariable *variable) { TString stringName = TString(variable->name.c_str()); diff --git a/src/3rdparty/angle/src/compiler/translator/VariableInfo.h b/src/3rdparty/angle/src/compiler/translator/VariableInfo.h index 92d376d879..bb1328a507 100644 --- a/src/3rdparty/angle/src/compiler/translator/VariableInfo.h +++ b/src/3rdparty/angle/src/compiler/translator/VariableInfo.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef COMPILER_VARIABLE_INFO_H_ -#define COMPILER_VARIABLE_INFO_H_ +#ifndef COMPILER_TRANSLATOR_VARIABLEINFO_H_ +#define COMPILER_TRANSLATOR_VARIABLEINFO_H_ #include @@ -51,8 +51,10 @@ class CollectVariables : public TIntermTraverser bool mFrontFacingAdded; bool mFragCoordAdded; + bool mInstanceIDAdded; bool mPositionAdded; bool mPointSizeAdded; + bool mLastFragDataAdded; ShHashFunction64 mHashFunction; @@ -65,4 +67,4 @@ void ExpandUniforms(const std::vector &compact, } -#endif // COMPILER_VARIABLE_INFO_H_ +#endif // COMPILER_TRANSLATOR_VARIABLEINFO_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/VariablePacker.h b/src/3rdparty/angle/src/compiler/translator/VariablePacker.h index 1de5332d8a..9c80eea618 100644 --- a/src/3rdparty/angle/src/compiler/translator/VariablePacker.h +++ b/src/3rdparty/angle/src/compiler/translator/VariablePacker.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef _VARIABLEPACKER_INCLUDED_ -#define _VARIABLEPACKER_INCLUDED_ +#ifndef COMPILER_TRANSLATOR_VARIABLEPACKER_H_ +#define COMPILER_TRANSLATOR_VARIABLEPACKER_H_ #include #include "compiler/translator/VariableInfo.h" @@ -38,4 +38,4 @@ class VariablePacker { std::vector rows_; }; -#endif // _VARIABLEPACKER_INCLUDED_ +#endif // COMPILER_TRANSLATOR_VARIABLEPACKER_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/VersionGLSL.cpp b/src/3rdparty/angle/src/compiler/translator/VersionGLSL.cpp index 05b111a7a7..f6f568897d 100644 --- a/src/3rdparty/angle/src/compiler/translator/VersionGLSL.cpp +++ b/src/3rdparty/angle/src/compiler/translator/VersionGLSL.cpp @@ -8,6 +8,7 @@ static const int GLSL_VERSION_110 = 110; static const int GLSL_VERSION_120 = 120; +static const int GLSL_VERSION_150 = 150; // We need to scan for the following: // 1. "invariant" keyword: This can occur in both - vertex and fragment shaders @@ -26,12 +27,22 @@ static const int GLSL_VERSION_120 = 120; // GLSL 1.2 relaxed the restriction on arrays, section 5.8: "Variables that // are built-in types, entire structures or arrays... are all l-values." // -TVersionGLSL::TVersionGLSL(sh::GLenum type, const TPragma &pragma) +TVersionGLSL::TVersionGLSL(sh::GLenum type, + const TPragma &pragma, + ShShaderOutput output) { - if (pragma.stdgl.invariantAll) - mVersion = GLSL_VERSION_120; + if (output == SH_GLSL_CORE_OUTPUT) + { + mVersion = GLSL_VERSION_150; + } else - mVersion = GLSL_VERSION_110; + { + ASSERT(output == SH_GLSL_COMPATIBILITY_OUTPUT); + if (pragma.stdgl.invariantAll) + mVersion = GLSL_VERSION_120; + else + mVersion = GLSL_VERSION_110; + } } void TVersionGLSL::visitSymbol(TIntermSymbol *node) diff --git a/src/3rdparty/angle/src/compiler/translator/VersionGLSL.h b/src/3rdparty/angle/src/compiler/translator/VersionGLSL.h index 72368e39d6..2b63d5f25d 100644 --- a/src/3rdparty/angle/src/compiler/translator/VersionGLSL.h +++ b/src/3rdparty/angle/src/compiler/translator/VersionGLSL.h @@ -29,14 +29,16 @@ class TVersionGLSL : public TIntermTraverser { public: - TVersionGLSL(sh::GLenum type, const TPragma &pragma); - - // Returns 120 if the following is used the shader: - // - "invariant", - // - "gl_PointCoord", - // - matrix/matrix constructors - // - array "out" parameters - // Else 110 is returned. + TVersionGLSL(sh::GLenum type, const TPragma &pragma, ShShaderOutput output); + + // If output is core profile, returns 150. + // If output is legacy profile, + // Returns 120 if the following is used the shader: + // - "invariant", + // - "gl_PointCoord", + // - matrix/matrix constructors + // - array "out" parameters + // Else 110 is returned. int getVersion() { return mVersion; } virtual void visitSymbol(TIntermSymbol *); diff --git a/src/3rdparty/angle/src/compiler/translator/blocklayout.cpp b/src/3rdparty/angle/src/compiler/translator/blocklayout.cpp new file mode 100644 index 0000000000..7c74105680 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/blocklayout.cpp @@ -0,0 +1,123 @@ +// +// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// blocklayout.cpp: +// Implementation for block layout classes and methods. +// + +#include "compiler/translator/blocklayout.h" + +#include "common/mathutil.h" +#include "common/utilities.h" + +namespace sh +{ + +BlockLayoutEncoder::BlockLayoutEncoder() + : mCurrentOffset(0) +{ +} + +BlockMemberInfo BlockLayoutEncoder::encodeType(GLenum type, unsigned int arraySize, bool isRowMajorMatrix) +{ + int arrayStride; + int matrixStride; + + getBlockLayoutInfo(type, arraySize, isRowMajorMatrix, &arrayStride, &matrixStride); + + const BlockMemberInfo memberInfo(mCurrentOffset * BytesPerComponent, arrayStride * BytesPerComponent, matrixStride * BytesPerComponent, isRowMajorMatrix); + + advanceOffset(type, arraySize, isRowMajorMatrix, arrayStride, matrixStride); + + return memberInfo; +} + +// static +size_t BlockLayoutEncoder::getBlockRegister(const BlockMemberInfo &info) +{ + return (info.offset / BytesPerComponent) / ComponentsPerRegister; +} + +// static +size_t BlockLayoutEncoder::getBlockRegisterElement(const BlockMemberInfo &info) +{ + return (info.offset / BytesPerComponent) % ComponentsPerRegister; +} + +void BlockLayoutEncoder::nextRegister() +{ + mCurrentOffset = rx::roundUp(mCurrentOffset, ComponentsPerRegister); +} + +Std140BlockEncoder::Std140BlockEncoder() +{ +} + +void Std140BlockEncoder::enterAggregateType() +{ + nextRegister(); +} + +void Std140BlockEncoder::exitAggregateType() +{ + nextRegister(); +} + +void Std140BlockEncoder::getBlockLayoutInfo(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut) +{ + // We assume we are only dealing with 4 byte components (no doubles or half-words currently) + ASSERT(gl::VariableComponentSize(gl::VariableComponentType(type)) == BytesPerComponent); + + size_t baseAlignment = 0; + int matrixStride = 0; + int arrayStride = 0; + + if (gl::IsMatrixType(type)) + { + baseAlignment = ComponentsPerRegister; + matrixStride = ComponentsPerRegister; + + if (arraySize > 0) + { + const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix); + arrayStride = ComponentsPerRegister * numRegisters; + } + } + else if (arraySize > 0) + { + baseAlignment = ComponentsPerRegister; + arrayStride = ComponentsPerRegister; + } + else + { + const int numComponents = gl::VariableComponentCount(type); + baseAlignment = (numComponents == 3 ? 4u : static_cast(numComponents)); + } + + mCurrentOffset = rx::roundUp(mCurrentOffset, baseAlignment); + + *matrixStrideOut = matrixStride; + *arrayStrideOut = arrayStride; +} + +void Std140BlockEncoder::advanceOffset(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride) +{ + if (arraySize > 0) + { + mCurrentOffset += arrayStride * arraySize; + } + else if (gl::IsMatrixType(type)) + { + ASSERT(matrixStride == ComponentsPerRegister); + const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix); + mCurrentOffset += ComponentsPerRegister * numRegisters; + } + else + { + mCurrentOffset += gl::VariableComponentCount(type); + } +} + +} diff --git a/src/3rdparty/angle/src/compiler/translator/blocklayout.h b/src/3rdparty/angle/src/compiler/translator/blocklayout.h new file mode 100644 index 0000000000..c11357fe66 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/blocklayout.h @@ -0,0 +1,94 @@ +// +// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// blocklayout.h: +// Methods and classes related to uniform layout and packing in GLSL and HLSL. +// + +#ifndef COMMON_BLOCKLAYOUT_H_ +#define COMMON_BLOCKLAYOUT_H_ + +#include +#include + +#include "angle_gl.h" +#include + +namespace sh +{ +struct ShaderVariable; +struct InterfaceBlockField; +struct Uniform; +struct Varying; +struct InterfaceBlock; + +struct COMPILER_EXPORT BlockMemberInfo +{ + BlockMemberInfo(int offset, int arrayStride, int matrixStride, bool isRowMajorMatrix) + : offset(offset), + arrayStride(arrayStride), + matrixStride(matrixStride), + isRowMajorMatrix(isRowMajorMatrix) + {} + + static BlockMemberInfo getDefaultBlockInfo() + { + return BlockMemberInfo(-1, -1, -1, false); + } + + int offset; + int arrayStride; + int matrixStride; + bool isRowMajorMatrix; +}; + +class COMPILER_EXPORT BlockLayoutEncoder +{ + public: + BlockLayoutEncoder(); + + BlockMemberInfo encodeType(GLenum type, unsigned int arraySize, bool isRowMajorMatrix); + + size_t getBlockSize() const { return mCurrentOffset * BytesPerComponent; } + size_t getCurrentRegister() const { return mCurrentOffset / ComponentsPerRegister; } + size_t getCurrentElement() const { return mCurrentOffset % ComponentsPerRegister; } + + virtual void enterAggregateType() = 0; + virtual void exitAggregateType() = 0; + + static const size_t BytesPerComponent = 4u; + static const unsigned int ComponentsPerRegister = 4u; + + static size_t getBlockRegister(const BlockMemberInfo &info); + static size_t getBlockRegisterElement(const BlockMemberInfo &info); + + protected: + size_t mCurrentOffset; + + void nextRegister(); + + virtual void getBlockLayoutInfo(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut) = 0; + virtual void advanceOffset(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride) = 0; +}; + +// Block layout according to the std140 block layout +// See "Standard Uniform Block Layout" in Section 2.11.6 of the OpenGL ES 3.0 specification + +class COMPILER_EXPORT Std140BlockEncoder : public BlockLayoutEncoder +{ + public: + Std140BlockEncoder(); + + virtual void enterAggregateType(); + virtual void exitAggregateType(); + + protected: + virtual void getBlockLayoutInfo(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut); + virtual void advanceOffset(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride); +}; + +} + +#endif // COMMON_BLOCKLAYOUT_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/blocklayoutHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/blocklayoutHLSL.cpp new file mode 100644 index 0000000000..f32cf2cf89 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/blocklayoutHLSL.cpp @@ -0,0 +1,165 @@ +// +// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// blocklayout.cpp: +// Implementation for block layout classes and methods. +// + +#include "compiler/translator/blocklayoutHLSL.h" + +#include "common/mathutil.h" +#include "common/utilities.h" + +namespace sh +{ + +HLSLBlockEncoder::HLSLBlockEncoder(HLSLBlockEncoderStrategy strategy) + : mEncoderStrategy(strategy), + mTransposeMatrices(false) +{ +} + +void HLSLBlockEncoder::enterAggregateType() +{ + nextRegister(); +} + +void HLSLBlockEncoder::exitAggregateType() +{ +} + +void HLSLBlockEncoder::getBlockLayoutInfo(GLenum typeIn, unsigned int arraySize, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut) +{ + GLenum type = (mTransposeMatrices ? gl::TransposeMatrixType(typeIn) : typeIn); + + // We assume we are only dealing with 4 byte components (no doubles or half-words currently) + ASSERT(gl::VariableComponentSize(gl::VariableComponentType(type)) == BytesPerComponent); + + int matrixStride = 0; + int arrayStride = 0; + + // if variables are not to be packed, or we're about to + // pack a matrix or array, skip to the start of the next + // register + if (!isPacked() || + gl::IsMatrixType(type) || + arraySize > 0) + { + nextRegister(); + } + + if (gl::IsMatrixType(type)) + { + matrixStride = ComponentsPerRegister; + + if (arraySize > 0) + { + const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix); + arrayStride = ComponentsPerRegister * numRegisters; + } + } + else if (arraySize > 0) + { + arrayStride = ComponentsPerRegister; + } + else if (isPacked()) + { + int numComponents = gl::VariableComponentCount(type); + if ((numComponents + (mCurrentOffset % ComponentsPerRegister)) > ComponentsPerRegister) + { + nextRegister(); + } + } + + *matrixStrideOut = matrixStride; + *arrayStrideOut = arrayStride; +} + +void HLSLBlockEncoder::advanceOffset(GLenum typeIn, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride) +{ + GLenum type = (mTransposeMatrices ? gl::TransposeMatrixType(typeIn) : typeIn); + + if (arraySize > 0) + { + mCurrentOffset += arrayStride * (arraySize - 1); + } + + if (gl::IsMatrixType(type)) + { + ASSERT(matrixStride == ComponentsPerRegister); + const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix); + const int numComponents = gl::MatrixComponentCount(type, isRowMajorMatrix); + mCurrentOffset += ComponentsPerRegister * (numRegisters - 1); + mCurrentOffset += numComponents; + } + else if (isPacked()) + { + mCurrentOffset += gl::VariableComponentCount(type); + } + else + { + mCurrentOffset += ComponentsPerRegister; + } +} + +void HLSLBlockEncoder::skipRegisters(unsigned int numRegisters) +{ + mCurrentOffset += (numRegisters * ComponentsPerRegister); +} + +HLSLBlockEncoder::HLSLBlockEncoderStrategy HLSLBlockEncoder::GetStrategyFor(ShShaderOutput outputType) +{ + switch (outputType) + { + case SH_HLSL9_OUTPUT: return ENCODE_LOOSE; + case SH_HLSL11_OUTPUT: return ENCODE_PACKED; + default: UNREACHABLE(); return ENCODE_PACKED; + } +} + +template +void HLSLVariableRegisterCount(const ShaderVarType &variable, HLSLBlockEncoder *encoder) +{ + if (variable.isStruct()) + { + for (size_t arrayElement = 0; arrayElement < variable.elementCount(); arrayElement++) + { + encoder->enterAggregateType(); + + for (size_t fieldIndex = 0; fieldIndex < variable.fields.size(); fieldIndex++) + { + HLSLVariableRegisterCount(variable.fields[fieldIndex], encoder); + } + + encoder->exitAggregateType(); + } + } + else + { + // We operate only on varyings and uniforms, which do not have matrix layout qualifiers + encoder->encodeType(variable.type, variable.arraySize, false); + } +} + +unsigned int HLSLVariableRegisterCount(const Varying &variable, bool transposeMatrices) +{ + HLSLBlockEncoder encoder(HLSLBlockEncoder::ENCODE_PACKED); + encoder.setTransposeMatrices(transposeMatrices); + HLSLVariableRegisterCount(variable, &encoder); + + const size_t registerBytes = (encoder.BytesPerComponent * encoder.ComponentsPerRegister); + return static_cast(rx::roundUp(encoder.getBlockSize(), registerBytes) / registerBytes); +} + +unsigned int HLSLVariableRegisterCount(const Uniform &variable, ShShaderOutput outputType) +{ + HLSLBlockEncoder encoder(HLSLBlockEncoder::GetStrategyFor(outputType)); + HLSLVariableRegisterCount(variable, &encoder); + + const size_t registerBytes = (encoder.BytesPerComponent * encoder.ComponentsPerRegister); + return static_cast(rx::roundUp(encoder.getBlockSize(), registerBytes) / registerBytes); +} + +} diff --git a/src/3rdparty/angle/src/compiler/translator/blocklayoutHLSL.h b/src/3rdparty/angle/src/compiler/translator/blocklayoutHLSL.h new file mode 100644 index 0000000000..c61cb1ae57 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/blocklayoutHLSL.h @@ -0,0 +1,62 @@ +// +// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// blocklayout.h: +// Methods and classes related to uniform layout and packing in GLSL and HLSL. +// + +#ifndef COMMON_BLOCKLAYOUTHLSL_H_ +#define COMMON_BLOCKLAYOUTHLSL_H_ + +#include +#include + +#include "angle_gl.h" +#include "blocklayout.h" +#include + +namespace sh +{ +// Block layout packed according to the D3D9 or default D3D10+ register packing rules +// See http://msdn.microsoft.com/en-us/library/windows/desktop/bb509632(v=vs.85).aspx +// The strategy should be ENCODE_LOOSE for D3D9 constant blocks, and ENCODE_PACKED +// for everything else (D3D10+ constant blocks and all attributes/varyings). + +class COMPILER_EXPORT HLSLBlockEncoder : public BlockLayoutEncoder +{ + public: + enum HLSLBlockEncoderStrategy + { + ENCODE_PACKED, + ENCODE_LOOSE + }; + + HLSLBlockEncoder(HLSLBlockEncoderStrategy strategy); + + virtual void enterAggregateType(); + virtual void exitAggregateType(); + void skipRegisters(unsigned int numRegisters); + + bool isPacked() const { return mEncoderStrategy == ENCODE_PACKED; } + void setTransposeMatrices(bool enabled) { mTransposeMatrices = enabled; } + + static HLSLBlockEncoderStrategy GetStrategyFor(ShShaderOutput outputType); + + protected: + virtual void getBlockLayoutInfo(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut); + virtual void advanceOffset(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride); + + HLSLBlockEncoderStrategy mEncoderStrategy; + bool mTransposeMatrices; +}; + +// This method returns the number of used registers for a ShaderVariable. It is dependent on the HLSLBlockEncoder +// class to count the number of used registers in a struct (which are individually packed according to the same rules). +COMPILER_EXPORT unsigned int HLSLVariableRegisterCount(const Varying &variable, bool transposeMatrices); +COMPILER_EXPORT unsigned int HLSLVariableRegisterCount(const Uniform &variable, ShShaderOutput outputType); + +} + +#endif // COMMON_BLOCKLAYOUTHLSL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/compilerdebug.h b/src/3rdparty/angle/src/compiler/translator/compilerdebug.h index 7a371516af..84a12ad2f8 100644 --- a/src/3rdparty/angle/src/compiler/translator/compilerdebug.h +++ b/src/3rdparty/angle/src/compiler/translator/compilerdebug.h @@ -6,8 +6,8 @@ // debug.h: Debugging utilities. -#ifndef COMPILER_DEBUG_H_ -#define COMPILER_DEBUG_H_ +#ifndef COMPILER_TRANSLATOR_COMPILERDEBUG_H_ +#define COMPILER_TRANSLATOR_COMPILERDEBUG_H_ #include @@ -49,5 +49,5 @@ void Trace(const char* format, ...); assert(false); \ } while(0) -#endif // COMPILER_DEBUG_H_ +#endif // COMPILER_TRANSLATOR_COMPILERDEBUG_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraph.h b/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraph.h index bc25fe7cbc..22db633678 100644 --- a/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraph.h +++ b/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraph.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_H -#define COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_H +#ifndef COMPILER_TRANSLATOR_DEPGRAPH_DEPENDENCYGRAPH_H_ +#define COMPILER_TRANSLATOR_DEPGRAPH_DEPENDENCYGRAPH_H_ #include "compiler/translator/IntermNode.h" @@ -186,7 +186,7 @@ private: // // When using this, just fill in the methods for nodes you want visited. // -class TDependencyGraphTraverser { +class TDependencyGraphTraverser : angle::NonCopyable { public: TDependencyGraphTraverser() : mDepth(0) {} @@ -209,4 +209,4 @@ private: TGraphNodeSet mVisited; }; -#endif +#endif // COMPILER_TRANSLATOR_DEPGRAPH_DEPENDENCYGRAPH_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphBuilder.h b/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphBuilder.h index b76f075e68..f7b3bd4b43 100644 --- a/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphBuilder.h +++ b/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphBuilder.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef COMPILER_TRANSLATOR_DEPGRAPH_DEPENDENCY_GRAPH_BUILDER_H -#define COMPILER_TRANSLATOR_DEPGRAPH_DEPENDENCY_GRAPH_BUILDER_H +#ifndef COMPILER_TRANSLATOR_DEPGRAPH_DEPENDENCYGRAPHBUILDER_H_ +#define COMPILER_TRANSLATOR_DEPGRAPH_DEPENDENCYGRAPHBUILDER_H_ #include "compiler/translator/depgraph/DependencyGraph.h" @@ -104,7 +104,7 @@ class TDependencyGraphBuilder : public TIntermTraverser // An instance of this class pushes a new node set when instantiated. // When the instance goes out of scope, it and pops the node set. // - class TNodeSetMaintainer + class TNodeSetMaintainer : angle::NonCopyable { public: TNodeSetMaintainer(TDependencyGraphBuilder *factory) @@ -122,7 +122,7 @@ class TDependencyGraphBuilder : public TIntermTraverser // When the instance goes out of scope, it and pops the top node set and adds // its contents to the new top node set. // - class TNodeSetPropagatingMaintainer + class TNodeSetPropagatingMaintainer : angle::NonCopyable { public: TNodeSetPropagatingMaintainer(TDependencyGraphBuilder *factory) @@ -147,7 +147,7 @@ class TDependencyGraphBuilder : public TIntermTraverser // kRightSubtree will never be replaced by a real symbol because we are tracking // the leftmost symbol. // - class TLeftmostSymbolMaintainer + class TLeftmostSymbolMaintainer : angle::NonCopyable { public: TLeftmostSymbolMaintainer( @@ -196,4 +196,4 @@ class TDependencyGraphBuilder : public TIntermTraverser TSymbolStack mLeftmostSymbols; }; -#endif // COMPILER_TRANSLATOR_DEPGRAPH_DEPENDENCY_GRAPH_BUILDER_H +#endif // COMPILER_TRANSLATOR_DEPGRAPH_DEPENDENCYGRAPHBUILDER_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphOutput.h b/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphOutput.h index c3a4112278..b201e0a671 100644 --- a/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphOutput.h +++ b/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphOutput.h @@ -4,27 +4,28 @@ // found in the LICENSE file. // -#ifndef COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_OUTPUT_H -#define COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_OUTPUT_H +#ifndef COMPILER_TRANSLATOR_DEPGRAPH_DEPENDENCYGRAPHOUTPUT_H_ +#define COMPILER_TRANSLATOR_DEPGRAPH_DEPENDENCYGRAPHOUTPUT_H_ #include "compiler/translator/depgraph/DependencyGraph.h" #include "compiler/translator/InfoSink.h" -class TDependencyGraphOutput : public TDependencyGraphTraverser { -public: +class TDependencyGraphOutput : public TDependencyGraphTraverser +{ + public: TDependencyGraphOutput(TInfoSinkBase& sink) : mSink(sink) {} - virtual void visitSymbol(TGraphSymbol* symbol); - virtual void visitArgument(TGraphArgument* parameter); - virtual void visitFunctionCall(TGraphFunctionCall* functionCall); - virtual void visitSelection(TGraphSelection* selection); - virtual void visitLoop(TGraphLoop* loop); - virtual void visitLogicalOp(TGraphLogicalOp* logicalOp); + void visitSymbol(TGraphSymbol* symbol) override; + void visitArgument(TGraphArgument* parameter) override; + void visitFunctionCall(TGraphFunctionCall* functionCall) override; + void visitSelection(TGraphSelection* selection) override; + void visitLoop(TGraphLoop* loop) override; + void visitLogicalOp(TGraphLogicalOp* logicalOp) override; void outputAllSpanningTrees(TDependencyGraph& graph); -private: + private: void outputIndentation(); TInfoSinkBase& mSink; }; -#endif // COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_OUTPUT_H +#endif // COMPILER_TRANSLATOR_DEPGRAPH_DEPENDENCYGRAPHOUTPUT_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/glslang.h b/src/3rdparty/angle/src/compiler/translator/glslang.h index f221199093..db31e6946c 100644 --- a/src/3rdparty/angle/src/compiler/translator/glslang.h +++ b/src/3rdparty/angle/src/compiler/translator/glslang.h @@ -4,6 +4,9 @@ // found in the LICENSE file. // +#ifndef COMPILER_TRANSLATOR_GLSLANG_H_ +#define COMPILER_TRANSLATOR_GLSLANG_H_ + struct TParseContext; extern int glslang_initialize(TParseContext* context); extern int glslang_finalize(TParseContext* context); @@ -14,3 +17,4 @@ extern int glslang_scan(size_t count, TParseContext* context); extern int glslang_parse(TParseContext* context); +#endif // COMPILER_TRANSLATOR_GLSLANG_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/glslang.l b/src/3rdparty/angle/src/compiler/translator/glslang.l index 518b78df11..ee4d28b6d6 100644 --- a/src/3rdparty/angle/src/compiler/translator/glslang.l +++ b/src/3rdparty/angle/src/compiler/translator/glslang.l @@ -32,6 +32,7 @@ WHICH GENERATES THE GLSL ES LEXER (glslang_lex.cpp). #pragma warning(disable: 4189) #pragma warning(disable: 4505) #pragma warning(disable: 4701) +#pragma warning(disable: 4702) #endif } @@ -70,6 +71,7 @@ static int floatsuffix_check(TParseContext* context); %option noyywrap nounput never-interactive %option yylineno reentrant bison-bridge bison-locations %option extra-type="TParseContext*" +%x FIELDS D [0-9] L [a-zA-Z_] @@ -358,7 +360,7 @@ O [0-7] ")" { return RIGHT_PAREN; } ("["|"<:") { return LEFT_BRACKET; } ("]"|":>") { return RIGHT_BRACKET; } -"." { return DOT; } +"." { BEGIN(FIELDS); return DOT; } "!" { return BANG; } "-" { return DASH; } "~" { return TILDE; } @@ -373,9 +375,16 @@ O [0-7] "&" { return AMPERSAND; } "?" { return QUESTION; } +{L}({L}|{D})* { + BEGIN(INITIAL); + yylval->lex.string = NewPoolTString(yytext); + return FIELD_SELECTION; +} +[ \t\v\f\r] {} + [ \t\v\n\f\r] { } -<> { yyterminate(); } -. { assert(false); return 0; } +<*><> { yyterminate(); } +<*>. { assert(false); return 0; } %% @@ -492,8 +501,8 @@ int floatsuffix_check(TParseContext* context) return(FLOATCONSTANT); } -void yyerror(YYLTYPE* lloc, TParseContext* context, const char* reason) { - context->error(*lloc, reason, yyget_text(context->scanner)); +void yyerror(YYLTYPE* lloc, TParseContext* context, void *scanner, const char* reason) { + context->error(*lloc, reason, yyget_text(scanner)); context->recover(); } diff --git a/src/3rdparty/angle/src/compiler/translator/glslang.y b/src/3rdparty/angle/src/compiler/translator/glslang.y index e271de978c..6024898cb0 100644 --- a/src/3rdparty/angle/src/compiler/translator/glslang.y +++ b/src/3rdparty/angle/src/compiler/translator/glslang.y @@ -32,6 +32,7 @@ WHICH GENERATES THE GLSL ES PARSER (glslang_tab.cpp AND glslang_tab.h). #pragma warning(disable: 4189) #pragma warning(disable: 4505) #pragma warning(disable: 4701) +#pragma warning(disable: 4702) #endif #include "angle_gl.h" @@ -41,12 +42,11 @@ WHICH GENERATES THE GLSL ES PARSER (glslang_tab.cpp AND glslang_tab.h). #define YYENABLE_NLS 0 -#define YYLEX_PARAM context->scanner - %} %expect 1 /* One shift reduce conflict because of if | else */ -%pure-parser %parse-param {TParseContext* context} +%param {void *scanner} +%define api.pure full %locations %code requires { @@ -72,6 +72,8 @@ WHICH GENERATES THE GLSL ES PARSER (glslang_tab.cpp AND glslang_tab.h). TIntermNodePair nodePair; TIntermTyped* intermTypedNode; TIntermAggregate* intermAggregate; + TIntermSwitch* intermSwitch; + TIntermCase* intermCase; }; union { TPublicType type; @@ -88,11 +90,11 @@ WHICH GENERATES THE GLSL ES PARSER (glslang_tab.cpp AND glslang_tab.h). %{ extern int yylex(YYSTYPE* yylval, YYLTYPE* yylloc, void* yyscanner); -extern void yyerror(YYLTYPE* yylloc, TParseContext* context, const char* reason); +extern void yyerror(YYLTYPE* yylloc, TParseContext* context, void *scanner, const char* reason); #define YYLLOC_DEFAULT(Current, Rhs, N) \ do { \ - if (YYID(N)) { \ + if (N) { \ (Current).first_file = YYRHSLOC(Rhs, 1).first_file; \ (Current).first_line = YYRHSLOC(Rhs, 1).first_line; \ (Current).last_file = YYRHSLOC(Rhs, N).last_file; \ @@ -179,6 +181,8 @@ extern void yyerror(YYLTYPE* yylloc, TParseContext* context, const char* reason) %type declaration external_declaration %type for_init_statement compound_statement_no_new_scope %type selection_rest_statement for_rest_statement +%type switch_statement +%type case_label %type iteration_statement jump_statement statement_no_new_scope statement_with_scope %type single_declaration init_declarator_list @@ -269,28 +273,14 @@ postfix_expression | function_call { $$ = $1; } - | postfix_expression DOT identifier { + | postfix_expression DOT FIELD_SELECTION { $$ = context->addFieldSelectionExpression($1, @2, *$3.string, @3); } | postfix_expression INC_OP { - if (context->lValueErrorCheck(@2, "++", $1)) - context->recover(); - $$ = context->intermediate.addUnaryMath(EOpPostIncrement, $1, @2); - if ($$ == 0) { - context->unaryOpError(@2, "++", $1->getCompleteString()); - context->recover(); - $$ = $1; - } + $$ = context->addUnaryMathLValue(EOpPostIncrement, $1, @2); } | postfix_expression DEC_OP { - if (context->lValueErrorCheck(@2, "--", $1)) - context->recover(); - $$ = context->intermediate.addUnaryMath(EOpPostDecrement, $1, @2); - if ($$ == 0) { - context->unaryOpError(@2, "--", $1->getCompleteString()); - context->recover(); - $$ = $1; - } + $$ = context->addUnaryMathLValue(EOpPostDecrement, $1, @2); } ; @@ -304,118 +294,12 @@ integer_expression function_call : function_call_or_method { - TFunction* fnCall = $1.function; - TOperator op = fnCall->getBuiltInOp(); - - if (op != EOpNull) + bool fatalError = false; + $$ = context->addFunctionCallOrMethod($1.function, $1.intermNode, @1, &fatalError); + if (fatalError) { - // - // Then this should be a constructor. - // Don't go through the symbol table for constructors. - // Their parameters will be verified algorithmically. - // - TType type(EbtVoid, EbpUndefined); // use this to get the type back - if (context->constructorErrorCheck(@1, $1.intermNode, *fnCall, op, &type)) { - $$ = 0; - } else { - // - // It's a constructor, of type 'type'. - // - $$ = context->addConstructor($1.intermNode, &type, op, fnCall, @1); - } - - if ($$ == 0) { - context->recover(); - $$ = context->intermediate.setAggregateOperator(0, op, @1); - } - $$->setType(type); - } else { - // - // Not a constructor. Find it in the symbol table. - // - const TFunction* fnCandidate; - bool builtIn; - fnCandidate = context->findFunction(@1, fnCall, context->shaderVersion, &builtIn); - if (fnCandidate) { - // - // A declared function. - // - if (builtIn && !fnCandidate->getExtension().empty() && - context->extensionErrorCheck(@1, fnCandidate->getExtension())) { - context->recover(); - } - op = fnCandidate->getBuiltInOp(); - if (builtIn && op != EOpNull) { - // - // A function call mapped to a built-in operation. - // - if (fnCandidate->getParamCount() == 1) { - // - // Treat it like a built-in unary operator. - // - $$ = context->intermediate.addUnaryMath(op, $1.intermNode, @1); - const TType& returnType = fnCandidate->getReturnType(); - if (returnType.getBasicType() == EbtBool) { - // Bool types should not have precision, so we'll override any precision - // that might have been set by addUnaryMath. - $$->setType(returnType); - } else { - // addUnaryMath has set the precision of the node based on the operand. - $$->setTypePreservePrecision(returnType); - } - if ($$ == 0) { - std::stringstream extraInfoStream; - extraInfoStream << "built in unary operator function. Type: " << static_cast($1.intermNode)->getCompleteString(); - std::string extraInfo = extraInfoStream.str(); - context->error($1.intermNode->getLine(), " wrong operand type", "Internal Error", extraInfo.c_str()); - YYERROR; - } - } else { - TIntermAggregate *aggregate = context->intermediate.setAggregateOperator($1.intermAggregate, op, @1); - aggregate->setType(fnCandidate->getReturnType()); - aggregate->setPrecisionFromChildren(); - $$ = aggregate; - } - } else { - // This is a real function call - - TIntermAggregate *aggregate = context->intermediate.setAggregateOperator($1.intermAggregate, EOpFunctionCall, @1); - aggregate->setType(fnCandidate->getReturnType()); - - // this is how we know whether the given function is a builtIn function or a user defined function - // if builtIn == false, it's a userDefined -> could be an overloaded builtIn function also - // if builtIn == true, it's definitely a builtIn function with EOpNull - if (!builtIn) - aggregate->setUserDefined(); - aggregate->setName(fnCandidate->getMangledName()); - - // This needs to happen after the name is set - if (builtIn) - aggregate->setBuiltInFunctionPrecision(); - - $$ = aggregate; - - TQualifier qual; - for (size_t i = 0; i < fnCandidate->getParamCount(); ++i) { - qual = fnCandidate->getParam(i).type->getQualifier(); - if (qual == EvqOut || qual == EvqInOut) { - if (context->lValueErrorCheck($$->getLine(), "assign", (*($$->getAsAggregate()->getSequence()))[i]->getAsTyped())) { - context->error($1.intermNode->getLine(), "Constant value cannot be passed for 'out' or 'inout' parameters.", "Error"); - context->recover(); - } - } - } - } - } else { - // error message was put out by PaFindFunction() - // Put on a dummy node for error recovery - ConstantUnion *unionArray = new ConstantUnion[1]; - unionArray->setFConst(0.0f); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), @1); - context->recover(); - } + YYERROR; } - delete fnCall; } ; @@ -484,6 +368,13 @@ function_identifier TFunction *function = new TFunction($1.string, type); $$ = function; } + | FIELD_SELECTION { + if (context->reservedErrorCheck(@1, *$1.string)) + context->recover(); + TType type(EbtVoid, EbpUndefined); + TFunction *function = new TFunction($1.string, type); + $$ = function; + } ; unary_expression @@ -491,40 +382,14 @@ unary_expression $$ = $1; } | INC_OP unary_expression { - if (context->lValueErrorCheck(@1, "++", $2)) - context->recover(); - $$ = context->intermediate.addUnaryMath(EOpPreIncrement, $2, @1); - if ($$ == 0) { - context->unaryOpError(@1, "++", $2->getCompleteString()); - context->recover(); - $$ = $2; - } + $$ = context->addUnaryMathLValue(EOpPreIncrement, $2, @1); } | DEC_OP unary_expression { - if (context->lValueErrorCheck(@1, "--", $2)) - context->recover(); - $$ = context->intermediate.addUnaryMath(EOpPreDecrement, $2, @1); - if ($$ == 0) { - context->unaryOpError(@1, "--", $2->getCompleteString()); - context->recover(); - $$ = $2; - } + $$ = context->addUnaryMathLValue(EOpPreDecrement, $2, @1); } | unary_operator unary_expression { if ($1.op != EOpNull) { - $$ = context->intermediate.addUnaryMath($1.op, $2, @1); - if ($$ == 0) { - const char* errorOp = ""; - switch($1.op) { - case EOpNegative: errorOp = "-"; break; - case EOpPositive: errorOp = "+"; break; - case EOpLogicalNot: errorOp = "!"; break; - default: break; - } - context->unaryOpError(@1, errorOp, $2->getCompleteString()); - context->recover(); - $$ = $2; - } + $$ = context->addUnaryMath($1.op, $2, @1); } else $$ = $2; } @@ -535,172 +400,117 @@ unary_operator : PLUS { $$.op = EOpPositive; } | DASH { $$.op = EOpNegative; } | BANG { $$.op = EOpLogicalNot; } + | TILDE { + ES3_ONLY("~", @$, "bit-wise operator"); + $$.op = EOpBitwiseNot; + } ; // Grammar Note: No '*' or '&' unary ops. Pointers are not supported. multiplicative_expression : unary_expression { $$ = $1; } | multiplicative_expression STAR unary_expression { - $$ = context->intermediate.addBinaryMath(EOpMul, $1, $3, @2); - if ($$ == 0) { - context->binaryOpError(@2, "*", $1->getCompleteString(), $3->getCompleteString()); - context->recover(); - $$ = $1; - } + $$ = context->addBinaryMath(EOpMul, $1, $3, @2); } | multiplicative_expression SLASH unary_expression { - $$ = context->intermediate.addBinaryMath(EOpDiv, $1, $3, @2); - if ($$ == 0) { - context->binaryOpError(@2, "/", $1->getCompleteString(), $3->getCompleteString()); - context->recover(); - $$ = $1; - } + $$ = context->addBinaryMath(EOpDiv, $1, $3, @2); + } + | multiplicative_expression PERCENT unary_expression { + ES3_ONLY("%", @2, "integer modulus operator"); + $$ = context->addBinaryMath(EOpIMod, $1, $3, @2); } ; additive_expression : multiplicative_expression { $$ = $1; } | additive_expression PLUS multiplicative_expression { - $$ = context->intermediate.addBinaryMath(EOpAdd, $1, $3, @2); - if ($$ == 0) { - context->binaryOpError(@2, "+", $1->getCompleteString(), $3->getCompleteString()); - context->recover(); - $$ = $1; - } + $$ = context->addBinaryMath(EOpAdd, $1, $3, @2); } | additive_expression DASH multiplicative_expression { - $$ = context->intermediate.addBinaryMath(EOpSub, $1, $3, @2); - if ($$ == 0) { - context->binaryOpError(@2, "-", $1->getCompleteString(), $3->getCompleteString()); - context->recover(); - $$ = $1; - } + $$ = context->addBinaryMath(EOpSub, $1, $3, @2); } ; shift_expression : additive_expression { $$ = $1; } + | shift_expression LEFT_OP additive_expression { + ES3_ONLY("<<", @2, "bit-wise operator"); + $$ = context->addBinaryMath(EOpBitShiftLeft, $1, $3, @2); + } + | shift_expression RIGHT_OP additive_expression { + ES3_ONLY(">>", @2, "bit-wise operator"); + $$ = context->addBinaryMath(EOpBitShiftRight, $1, $3, @2); + } ; relational_expression : shift_expression { $$ = $1; } | relational_expression LEFT_ANGLE shift_expression { - $$ = context->intermediate.addBinaryMath(EOpLessThan, $1, $3, @2); - if ($$ == 0) { - context->binaryOpError(@2, "<", $1->getCompleteString(), $3->getCompleteString()); - context->recover(); - ConstantUnion *unionArray = new ConstantUnion[1]; - unionArray->setBConst(false); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2); - } + $$ = context->addBinaryMathBooleanResult(EOpLessThan, $1, $3, @2); } | relational_expression RIGHT_ANGLE shift_expression { - $$ = context->intermediate.addBinaryMath(EOpGreaterThan, $1, $3, @2); - if ($$ == 0) { - context->binaryOpError(@2, ">", $1->getCompleteString(), $3->getCompleteString()); - context->recover(); - ConstantUnion *unionArray = new ConstantUnion[1]; - unionArray->setBConst(false); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2); - } + $$ = context->addBinaryMathBooleanResult(EOpGreaterThan, $1, $3, @2); } | relational_expression LE_OP shift_expression { - $$ = context->intermediate.addBinaryMath(EOpLessThanEqual, $1, $3, @2); - if ($$ == 0) { - context->binaryOpError(@2, "<=", $1->getCompleteString(), $3->getCompleteString()); - context->recover(); - ConstantUnion *unionArray = new ConstantUnion[1]; - unionArray->setBConst(false); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2); - } + $$ = context->addBinaryMathBooleanResult(EOpLessThanEqual, $1, $3, @2); } | relational_expression GE_OP shift_expression { - $$ = context->intermediate.addBinaryMath(EOpGreaterThanEqual, $1, $3, @2); - if ($$ == 0) { - context->binaryOpError(@2, ">=", $1->getCompleteString(), $3->getCompleteString()); - context->recover(); - ConstantUnion *unionArray = new ConstantUnion[1]; - unionArray->setBConst(false); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2); - } + $$ = context->addBinaryMathBooleanResult(EOpGreaterThanEqual, $1, $3, @2); } ; equality_expression : relational_expression { $$ = $1; } | equality_expression EQ_OP relational_expression { - $$ = context->intermediate.addBinaryMath(EOpEqual, $1, $3, @2); - if ($$ == 0) { - context->binaryOpError(@2, "==", $1->getCompleteString(), $3->getCompleteString()); - context->recover(); - ConstantUnion *unionArray = new ConstantUnion[1]; - unionArray->setBConst(false); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2); - } + $$ = context->addBinaryMathBooleanResult(EOpEqual, $1, $3, @2); } | equality_expression NE_OP relational_expression { - $$ = context->intermediate.addBinaryMath(EOpNotEqual, $1, $3, @2); - if ($$ == 0) { - context->binaryOpError(@2, "!=", $1->getCompleteString(), $3->getCompleteString()); - context->recover(); - ConstantUnion *unionArray = new ConstantUnion[1]; - unionArray->setBConst(false); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2); - } + $$ = context->addBinaryMathBooleanResult(EOpNotEqual, $1, $3, @2); } ; and_expression : equality_expression { $$ = $1; } + | and_expression AMPERSAND equality_expression { + ES3_ONLY("&", @2, "bit-wise operator"); + $$ = context->addBinaryMath(EOpBitwiseAnd, $1, $3, @2); + } ; exclusive_or_expression : and_expression { $$ = $1; } + | exclusive_or_expression CARET and_expression { + ES3_ONLY("^", @2, "bit-wise operator"); + $$ = context->addBinaryMath(EOpBitwiseXor, $1, $3, @2); + } ; inclusive_or_expression : exclusive_or_expression { $$ = $1; } + | inclusive_or_expression VERTICAL_BAR exclusive_or_expression { + ES3_ONLY("|", @2, "bit-wise operator"); + $$ = context->addBinaryMath(EOpBitwiseOr, $1, $3, @2); + } ; logical_and_expression : inclusive_or_expression { $$ = $1; } | logical_and_expression AND_OP inclusive_or_expression { - $$ = context->intermediate.addBinaryMath(EOpLogicalAnd, $1, $3, @2); - if ($$ == 0) { - context->binaryOpError(@2, "&&", $1->getCompleteString(), $3->getCompleteString()); - context->recover(); - ConstantUnion *unionArray = new ConstantUnion[1]; - unionArray->setBConst(false); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2); - } + $$ = context->addBinaryMathBooleanResult(EOpLogicalAnd, $1, $3, @2); } ; logical_xor_expression : logical_and_expression { $$ = $1; } | logical_xor_expression XOR_OP logical_and_expression { - $$ = context->intermediate.addBinaryMath(EOpLogicalXor, $1, $3, @2); - if ($$ == 0) { - context->binaryOpError(@2, "^^", $1->getCompleteString(), $3->getCompleteString()); - context->recover(); - ConstantUnion *unionArray = new ConstantUnion[1]; - unionArray->setBConst(false); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2); - } + $$ = context->addBinaryMathBooleanResult(EOpLogicalXor, $1, $3, @2); } ; logical_or_expression : logical_xor_expression { $$ = $1; } | logical_or_expression OR_OP logical_xor_expression { - $$ = context->intermediate.addBinaryMath(EOpLogicalOr, $1, $3, @2); - if ($$ == 0) { - context->binaryOpError(@2, "||", $1->getCompleteString(), $3->getCompleteString()); - context->recover(); - ConstantUnion *unionArray = new ConstantUnion[1]; - unionArray->setBConst(false); - $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2); - } + $$ = context->addBinaryMathBooleanResult(EOpLogicalOr, $1, $3, @2); } ; @@ -727,12 +537,7 @@ assignment_expression | unary_expression assignment_operator assignment_expression { if (context->lValueErrorCheck(@2, "assign", $1)) context->recover(); - $$ = context->intermediate.addAssign($2.op, $1, $3, @2); - if ($$ == 0) { - context->assignError(@2, "assign", $1->getCompleteString(), $3->getCompleteString()); - context->recover(); - $$ = $1; - } + $$ = context->addAssign($2.op, $1, $3, @2); } ; @@ -740,8 +545,32 @@ assignment_operator : EQUAL { $$.op = EOpAssign; } | MUL_ASSIGN { $$.op = EOpMulAssign; } | DIV_ASSIGN { $$.op = EOpDivAssign; } + | MOD_ASSIGN { + ES3_ONLY("%=", @$, "integer modulus operator"); + $$.op = EOpIModAssign; + } | ADD_ASSIGN { $$.op = EOpAddAssign; } | SUB_ASSIGN { $$.op = EOpSubAssign; } + | LEFT_ASSIGN { + ES3_ONLY("<<=", @$, "bit-wise operator"); + $$.op = EOpBitShiftLeftAssign; + } + | RIGHT_ASSIGN { + ES3_ONLY(">>=", @$, "bit-wise operator"); + $$.op = EOpBitShiftRightAssign; + } + | AND_ASSIGN { + ES3_ONLY("&=", @$, "bit-wise operator"); + $$.op = EOpBitwiseAndAssign; + } + | XOR_ASSIGN { + ES3_ONLY("^=", @$, "bit-wise operator"); + $$.op = EOpBitwiseXorAssign; + } + | OR_ASSIGN { + ES3_ONLY("|=", @$, "bit-wise operator"); + $$.op = EOpBitwiseOrAssign; + } ; expression @@ -877,7 +706,7 @@ function_prototype { // Insert the unmangled name to detect potential future redefinition as a variable. TFunction *function = new TFunction(NewPoolTString($1->getName().c_str()), $1->getReturnType()); - context->symbolTable.getOuterLevel()->insert(function); + context->symbolTable.getOuterLevel()->insertUnmangled(function); } // @@ -1599,12 +1428,14 @@ statement | simple_statement { $$ = $1; } ; -// Grammar Note: No labeled statements; 'goto' is not supported. +// Grammar Note: Labeled statements for SWITCH only; 'goto' is not supported. simple_statement : declaration_statement { $$ = $1; } | expression_statement { $$ = $1; } | selection_statement { $$ = $1; } + | switch_statement { $$ = $1; } + | case_label { $$ = $1; } | iteration_statement { $$ = $1; } | jump_statement { $$ = $1; } ; @@ -1677,7 +1508,21 @@ selection_rest_statement } ; -// Grammar Note: No 'switch'. Switch statements not supported. +switch_statement + : SWITCH LEFT_PAREN expression RIGHT_PAREN { ++context->mSwitchNestingLevel; } compound_statement { + $$ = context->addSwitch($3, $6, @1); + --context->mSwitchNestingLevel; + } + ; + +case_label + : CASE constant_expression COLON { + $$ = context->addCase($2, @1); + } + | DEFAULT COLON { + $$ = context->addDefault(@1); + } + ; condition // In 1996 c++ draft, conditions can include single declarations @@ -1703,22 +1548,22 @@ condition ; iteration_statement - : WHILE LEFT_PAREN { context->symbolTable.push(); ++context->loopNestingLevel; } condition RIGHT_PAREN statement_no_new_scope { + : WHILE LEFT_PAREN { context->symbolTable.push(); ++context->mLoopNestingLevel; } condition RIGHT_PAREN statement_no_new_scope { context->symbolTable.pop(); $$ = context->intermediate.addLoop(ELoopWhile, 0, $4, 0, $6, @1); - --context->loopNestingLevel; + --context->mLoopNestingLevel; } - | DO { ++context->loopNestingLevel; } statement_with_scope WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON { + | DO { ++context->mLoopNestingLevel; } statement_with_scope WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON { if (context->boolErrorCheck(@8, $6)) context->recover(); $$ = context->intermediate.addLoop(ELoopDoWhile, 0, $6, 0, $3, @4); - --context->loopNestingLevel; + --context->mLoopNestingLevel; } - | FOR LEFT_PAREN { context->symbolTable.push(); ++context->loopNestingLevel; } for_init_statement for_rest_statement RIGHT_PAREN statement_no_new_scope { + | FOR LEFT_PAREN { context->symbolTable.push(); ++context->mLoopNestingLevel; } for_init_statement for_rest_statement RIGHT_PAREN statement_no_new_scope { context->symbolTable.pop(); $$ = context->intermediate.addLoop(ELoopFor, $4, reinterpret_cast($5.node1), reinterpret_cast($5.node2), $7, @1); - --context->loopNestingLevel; + --context->mLoopNestingLevel; } ; @@ -1753,40 +1598,20 @@ for_rest_statement jump_statement : CONTINUE SEMICOLON { - if (context->loopNestingLevel <= 0) { - context->error(@1, "continue statement only allowed in loops", ""); - context->recover(); - } - $$ = context->intermediate.addBranch(EOpContinue, @1); + $$ = context->addBranch(EOpContinue, @1); } | BREAK SEMICOLON { - if (context->loopNestingLevel <= 0) { - context->error(@1, "break statement only allowed in loops", ""); - context->recover(); - } - $$ = context->intermediate.addBranch(EOpBreak, @1); + $$ = context->addBranch(EOpBreak, @1); } | RETURN SEMICOLON { - $$ = context->intermediate.addBranch(EOpReturn, @1); - if (context->currentFunctionType->getBasicType() != EbtVoid) { - context->error(@1, "non-void function must return a value", "return"); - context->recover(); - } + $$ = context->addBranch(EOpReturn, @1); } | RETURN expression SEMICOLON { - $$ = context->intermediate.addBranch(EOpReturn, $2, @1); - context->functionReturnsValue = true; - if (context->currentFunctionType->getBasicType() == EbtVoid) { - context->error(@1, "void function cannot return a value", "return"); - context->recover(); - } else if (*(context->currentFunctionType) != $2->getType()) { - context->error(@1, "function return is not matching type:", "return"); - context->recover(); - } + $$ = context->addBranch(EOpReturn, $2, @1); } | DISCARD SEMICOLON { FRAG_ONLY("discard", @1); - $$ = context->intermediate.addBranch(EOpKill, @1); + $$ = context->addBranch(EOpKill, @1); } ; @@ -1857,7 +1682,7 @@ function_definition // Remember the return type for later checking for RETURN statements. // context->currentFunctionType = &(prevDec->getReturnType()); - context->functionReturnsValue = false; + context->mFunctionReturnsValue = false; // // Insert parameters into the symbol table. @@ -1896,12 +1721,12 @@ function_definition } context->intermediate.setAggregateOperator(paramNodes, EOpParameters, @1); $1.intermAggregate = paramNodes; - context->loopNestingLevel = 0; + context->mLoopNestingLevel = 0; } compound_statement_no_new_scope { //?? Check that all paths return a value if return type != void ? // May be best done as post process phase on intermediate code - if (context->currentFunctionType->getBasicType() != EbtVoid && ! context->functionReturnsValue) { + if (context->currentFunctionType->getBasicType() != EbtVoid && ! context->mFunctionReturnsValue) { context->error(@1, "function does not return a value:", "", $1.function->getName().c_str()); context->recover(); } @@ -1923,5 +1748,5 @@ function_definition %% int glslang_parse(TParseContext* context) { - return yyparse(context); + return yyparse(context, context->scanner); } diff --git a/src/3rdparty/angle/src/compiler/translator/intermOut.cpp b/src/3rdparty/angle/src/compiler/translator/intermOut.cpp index 00780f0454..07c50f0ce5 100644 --- a/src/3rdparty/angle/src/compiler/translator/intermOut.cpp +++ b/src/3rdparty/angle/src/compiler/translator/intermOut.cpp @@ -131,6 +131,25 @@ bool TOutputTraverser::visitBinary(Visit visit, TIntermBinary *node) case EOpDivAssign: out << "divide second child into first child"; break; + case EOpIModAssign: + out << "modulo second child into first child"; + break; + case EOpBitShiftLeftAssign: + out << "bit-wise shift first child left by second child"; + break; + case EOpBitShiftRightAssign: + out << "bit-wise shift first child right by second child"; + break; + case EOpBitwiseAndAssign: + out << "bit-wise and second child into first child"; + break; + case EOpBitwiseXorAssign: + out << "bit-wise xor second child into first child"; + break; + case EOpBitwiseOrAssign: + out << "bit-wise or second child into first child"; + break; + case EOpIndexDirect: out << "direct index"; break; @@ -159,6 +178,25 @@ bool TOutputTraverser::visitBinary(Visit visit, TIntermBinary *node) case EOpDiv: out << "divide"; break; + case EOpIMod: + out << "modulo"; + break; + case EOpBitShiftLeft: + out << "bit-wise shift left"; + break; + case EOpBitShiftRight: + out << "bit-wise shift right"; + break; + case EOpBitwiseAnd: + out << "bit-wise and"; + break; + case EOpBitwiseXor: + out << "bit-wise xor"; + break; + case EOpBitwiseOr: + out << "bit-wise or"; + break; + case EOpEqual: out << "Compare Equal"; break; @@ -211,6 +249,36 @@ bool TOutputTraverser::visitBinary(Visit visit, TIntermBinary *node) out << "\n"; + // Special handling for direct indexes. Because constant + // unions are not aware they are struct indexes, treat them + // here where we have that contextual knowledge. + if (node->getOp() == EOpIndexDirectStruct || + node->getOp() == EOpIndexDirectInterfaceBlock) + { + mDepth++; + node->getLeft()->traverse(this); + mDepth--; + + TIntermConstantUnion *intermConstantUnion = node->getRight()->getAsConstantUnion(); + ASSERT(intermConstantUnion); + + OutputTreeText(out, intermConstantUnion, mDepth + 1); + + // The following code finds the field name from the constant union + const ConstantUnion *constantUnion = intermConstantUnion->getUnionArrayPointer(); + const TStructure *structure = node->getLeft()->getType().getStruct(); + const TInterfaceBlock *interfaceBlock = node->getLeft()->getType().getInterfaceBlock(); + ASSERT(structure || interfaceBlock); + + const TFieldList &fields = structure ? structure->fields() : interfaceBlock->fields(); + + const TField *field = fields[constantUnion->getIConst()]; + + out << constantUnion->getIConst() << " (field '" << field->name() << "')"; + + return false; + } + return true; } @@ -226,6 +294,7 @@ bool TOutputTraverser::visitUnary(Visit visit, TIntermUnary *node) case EOpPositive: out << "Positive sign"; break; case EOpVectorLogicalNot: case EOpLogicalNot: out << "Negate conditional"; break; + case EOpBitwiseNot: out << "bit-wise not"; break; case EOpPostIncrement: out << "Post-Increment"; break; case EOpPostDecrement: out << "Post-Decrement"; break; @@ -241,6 +310,13 @@ bool TOutputTraverser::visitUnary(Visit visit, TIntermUnary *node) case EOpAcos: out << "arc cosine"; break; case EOpAtan: out << "arc tangent"; break; + case EOpSinh: out << "hyperbolic sine"; break; + case EOpCosh: out << "hyperbolic cosine"; break; + case EOpTanh: out << "hyperbolic tangent"; break; + case EOpAsinh: out << "arc hyperbolic sine"; break; + case EOpAcosh: out << "arc hyperbolic cosine"; break; + case EOpAtanh: out << "arc hyperbolic tangent"; break; + case EOpExp: out << "exp"; break; case EOpLog: out << "log"; break; case EOpExp2: out << "exp2"; break; @@ -251,8 +327,26 @@ bool TOutputTraverser::visitUnary(Visit visit, TIntermUnary *node) case EOpAbs: out << "Absolute value"; break; case EOpSign: out << "Sign"; break; case EOpFloor: out << "Floor"; break; + case EOpTrunc: out << "Truncate"; break; + case EOpRound: out << "Round"; break; + case EOpRoundEven: out << "Round half even"; break; case EOpCeil: out << "Ceiling"; break; case EOpFract: out << "Fraction"; break; + case EOpIsNan: out << "Is not a number"; break; + case EOpIsInf: out << "Is infinity"; break; + + case EOpFloatBitsToInt: out << "float bits to int"; break; + case EOpFloatBitsToUint: out << "float bits to uint"; break; + case EOpIntBitsToFloat: out << "int bits to float"; break; + case EOpUintBitsToFloat: out << "uint bits to float"; break; + + case EOpPackSnorm2x16: out << "pack Snorm 2x16"; break; + case EOpPackUnorm2x16: out << "pack Unorm 2x16"; break; + case EOpPackHalf2x16: out << "pack half 2x16"; break; + + case EOpUnpackSnorm2x16: out << "unpack Snorm 2x16"; break; + case EOpUnpackUnorm2x16: out << "unpack Unorm 2x16"; break; + case EOpUnpackHalf2x16: out << "unpack half 2x16"; break; case EOpLength: out << "length"; break; case EOpNormalize: out << "normalize"; break; @@ -260,6 +354,10 @@ bool TOutputTraverser::visitUnary(Visit visit, TIntermUnary *node) // case EOpDPdy: out << "dPdy"; break; // case EOpFwidth: out << "fwidth"; break; + case EOpDeterminant: out << "determinant"; break; + case EOpTranspose: out << "transpose"; break; + case EOpInverse: out << "inverse"; break; + case EOpAny: out << "any"; break; case EOpAll: out << "all"; break; @@ -326,6 +424,7 @@ bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate *node) case EOpVectorNotEqual: out << "NotEqual"; break; case EOpMod: out << "mod"; break; + case EOpModf: out << "modf"; break; case EOpPow: out << "pow"; break; case EOpAtan: out << "arc tangent"; break; @@ -345,6 +444,8 @@ bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate *node) case EOpRefract: out << "refract"; break; case EOpMul: out << "component-wise multiply"; break; + case EOpOuterProduct: out << "outer product"; break; + case EOpDeclaration: out << "Declaration: "; break; case EOpInvariantDeclaration: out << "Invariant Declaration: "; break; @@ -518,14 +619,13 @@ bool TOutputTraverser::visitBranch(Visit visit, TIntermBranch *node) // // This function is the one to call externally to start the traversal. // Individual functions can be initialized to 0 to skip processing of that -// type of node. It's children will still be processed. +// type of node. Its children will still be processed. // -void TIntermediate::outputTree(TIntermNode *root) +void TIntermediate::outputTree(TIntermNode *root, TInfoSinkBase &infoSink) { - if (root == NULL) - return; + TOutputTraverser it(infoSink); - TOutputTraverser it(mInfoSink.info); + ASSERT(root); root->traverse(&it); } diff --git a/src/3rdparty/angle/src/compiler/translator/intermediate.h b/src/3rdparty/angle/src/compiler/translator/intermediate.h deleted file mode 100644 index 3b7e7bd802..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/intermediate.h +++ /dev/null @@ -1,67 +0,0 @@ -// -// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_TRANSLATOR_LOCAL_INTERMEDIATE_H_ -#define COMPILER_TRANSLATOR_LOCAL_INTERMEDIATE_H_ - -#include "compiler/translator/IntermNode.h" - -struct TVectorFields -{ - int offsets[4]; - int num; -}; - -// -// Set of helper functions to help parse and build the tree. -// -class TInfoSink; -class TIntermediate -{ - public: - POOL_ALLOCATOR_NEW_DELETE(); - TIntermediate(TInfoSink &i) - : mInfoSink(i) { } - - TIntermSymbol *addSymbol( - int id, const TString &, const TType &, const TSourceLoc &); - TIntermTyped *addBinaryMath( - TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &); - TIntermTyped *addAssign( - TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &); - TIntermTyped *addIndex( - TOperator op, TIntermTyped *base, TIntermTyped *index, const TSourceLoc &); - TIntermTyped *addUnaryMath( - TOperator op, TIntermNode *child, const TSourceLoc &); - TIntermAggregate *growAggregate( - TIntermNode *left, TIntermNode *right, const TSourceLoc &); - TIntermAggregate *makeAggregate(TIntermNode *node, const TSourceLoc &); - TIntermAggregate *setAggregateOperator(TIntermNode *, TOperator, const TSourceLoc &); - TIntermNode *addSelection(TIntermTyped *cond, TIntermNodePair code, const TSourceLoc &); - TIntermTyped *addSelection( - TIntermTyped *cond, TIntermTyped *trueBlock, TIntermTyped *falseBlock, const TSourceLoc &); - TIntermTyped *addComma( - TIntermTyped *left, TIntermTyped *right, const TSourceLoc &); - TIntermConstantUnion *addConstantUnion(ConstantUnion *, const TType &, const TSourceLoc &); - // TODO(zmo): Get rid of default value. - bool parseConstTree(const TSourceLoc &, TIntermNode *, ConstantUnion *, - TOperator, TType, bool singleConstantParam = false); - TIntermNode *addLoop(TLoopType, TIntermNode *, TIntermTyped *, TIntermTyped *, - TIntermNode *, const TSourceLoc &); - TIntermBranch *addBranch(TOperator, const TSourceLoc &); - TIntermBranch *addBranch(TOperator, TIntermTyped *, const TSourceLoc &); - TIntermTyped *addSwizzle(TVectorFields &, const TSourceLoc &); - bool postProcess(TIntermNode *); - void remove(TIntermNode *); - void outputTree(TIntermNode *); - - private: - void operator=(TIntermediate &); // prevent assignments - - TInfoSink & mInfoSink; -}; - -#endif // COMPILER_TRANSLATOR_LOCAL_INTERMEDIATE_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/length_limits.h b/src/3rdparty/angle/src/compiler/translator/length_limits.h index df70ee5d84..88634381fa 100644 --- a/src/3rdparty/angle/src/compiler/translator/length_limits.h +++ b/src/3rdparty/angle/src/compiler/translator/length_limits.h @@ -8,8 +8,8 @@ // length_limits.h // -#if !defined(__LENGTH_LIMITS_H) -#define __LENGTH_LIMITS_H 1 +#ifndef COMPILER_TRANSLATOR_LENGTHLIMITS_H_ +#define COMPILER_TRANSLATOR_LENGTHLIMITS_H_ #include "GLSLANG/ShaderLang.h" @@ -18,4 +18,4 @@ size_t GetGlobalMaxTokenSize(ShShaderSpec spec); -#endif // !(defined(__LENGTH_LIMITS_H) +#endif // COMPILER_TRANSLATOR_LENGTHLIMITS_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.h b/src/3rdparty/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.h index 80d5f7fa7f..b8c7e82956 100644 --- a/src/3rdparty/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.h +++ b/src/3rdparty/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.h @@ -4,35 +4,36 @@ // found in the LICENSE file. // -#ifndef COMPILER_TIMING_RESTRICT_FRAGMENT_SHADER_TIMING_H_ -#define COMPILER_TIMING_RESTRICT_FRAGMENT_SHADER_TIMING_H_ +#ifndef COMPILER_TRANSLATOR_TIMING_RESTRICTFRAGMENTSHADERTIMING_H_ +#define COMPILER_TRANSLATOR_TIMING_RESTRICTFRAGMENTSHADERTIMING_H_ #include "compiler/translator/IntermNode.h" #include "compiler/translator/depgraph/DependencyGraph.h" class TInfoSinkBase; -class RestrictFragmentShaderTiming : TDependencyGraphTraverser { -public: - RestrictFragmentShaderTiming(TInfoSinkBase& sink); - void enforceRestrictions(const TDependencyGraph& graph); +class RestrictFragmentShaderTiming : TDependencyGraphTraverser +{ + public: + RestrictFragmentShaderTiming(TInfoSinkBase &sink); + void enforceRestrictions(const TDependencyGraph &graph); int numErrors() const { return mNumErrors; } - virtual void visitArgument(TGraphArgument* parameter); - virtual void visitSelection(TGraphSelection* selection); - virtual void visitLoop(TGraphLoop* loop); - virtual void visitLogicalOp(TGraphLogicalOp* logicalOp); + void visitArgument(TGraphArgument *parameter) override; + void visitSelection(TGraphSelection *selection) override; + void visitLoop(TGraphLoop *loop) override; + void visitLogicalOp(TGraphLogicalOp *logicalOp) override; -private: - void beginError(const TIntermNode* node); - void validateUserDefinedFunctionCallUsage(const TDependencyGraph& graph); - bool isSamplingOp(const TIntermAggregate* intermFunctionCall) const; + private: + void beginError(const TIntermNode *node); + void validateUserDefinedFunctionCallUsage(const TDependencyGraph &graph); + bool isSamplingOp(const TIntermAggregate *intermFunctionCall) const; - TInfoSinkBase& mSink; + TInfoSinkBase &mSink; int mNumErrors; typedef std::set StringSet; StringSet mSamplingOps; }; -#endif // COMPILER_TIMING_RESTRICT_FRAGMENT_SHADER_TIMING_H_ +#endif // COMPILER_TRANSLATOR_TIMING_RESTRICTFRAGMENTSHADERTIMING_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/timing/RestrictVertexShaderTiming.h b/src/3rdparty/angle/src/compiler/translator/timing/RestrictVertexShaderTiming.h index a6263567b4..74bfd0b5c2 100644 --- a/src/3rdparty/angle/src/compiler/translator/timing/RestrictVertexShaderTiming.h +++ b/src/3rdparty/angle/src/compiler/translator/timing/RestrictVertexShaderTiming.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef COMPILER_TIMING_RESTRICT_VERTEX_SHADER_TIMING_H_ -#define COMPILER_TIMING_RESTRICT_VERTEX_SHADER_TIMING_H_ +#ifndef COMPILER_TRANSLATOR_TIMING_RESTRICTVERTEXSHADERTIMING_H_ +#define COMPILER_TRANSLATOR_TIMING_RESTRICTVERTEXSHADERTIMING_H_ #include "compiler/translator/IntermNode.h" #include "compiler/translator/InfoSink.h" @@ -28,4 +28,4 @@ private: int mNumErrors; }; -#endif // COMPILER_TIMING_RESTRICT_VERTEX_SHADER_TIMING_H_ +#endif // COMPILER_TRANSLATOR_TIMING_RESTRICTVERTEXSHADERTIMING_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/util.cpp b/src/3rdparty/angle/src/compiler/translator/util.cpp index 8cc06a658a..42a995ee6f 100644 --- a/src/3rdparty/angle/src/compiler/translator/util.cpp +++ b/src/3rdparty/angle/src/compiler/translator/util.cpp @@ -307,7 +307,7 @@ void GetVariableTraverser::setTypeSpecificInfo( break; case EvqVaryingIn: case EvqVaryingOut: - if (mSymbolTable.isVaryingInvariant(name)) + if (mSymbolTable.isVaryingInvariant(std::string(name.c_str()))) { variable->isInvariant = true; } diff --git a/src/3rdparty/angle/src/compiler/translator/util.h b/src/3rdparty/angle/src/compiler/translator/util.h index fb5308759e..68bae66168 100644 --- a/src/3rdparty/angle/src/compiler/translator/util.h +++ b/src/3rdparty/angle/src/compiler/translator/util.h @@ -4,8 +4,8 @@ // found in the LICENSE file. // -#ifndef COMPILER_UTIL_H -#define COMPILER_UTIL_H +#ifndef COMPILER_TRANSLATOR_UTIL_H_ +#define COMPILER_TRANSLATOR_UTIL_H_ #include @@ -37,7 +37,7 @@ bool IsVarying(TQualifier qualifier); InterpolationType GetInterpolationType(TQualifier qualifier); TString ArrayString(const TType &type); -class GetVariableTraverser +class GetVariableTraverser : angle::NonCopyable { public: GetVariableTraverser(const TSymbolTable &symbolTable); @@ -57,10 +57,8 @@ class GetVariableTraverser const TType &type, const TString &name, VarT *variable) {} const TSymbolTable &mSymbolTable; - - DISALLOW_COPY_AND_ASSIGN(GetVariableTraverser); }; } -#endif // COMPILER_UTIL_H +#endif // COMPILER_TRANSLATOR_UTIL_H_ diff --git a/src/3rdparty/angle/src/id/commit.h b/src/3rdparty/angle/src/id/commit.h new file mode 100644 index 0000000000..fd9a011d0c --- /dev/null +++ b/src/3rdparty/angle/src/id/commit.h @@ -0,0 +1,3 @@ +#define ANGLE_COMMIT_HASH "99f075dade7c" +#define ANGLE_COMMIT_HASH_SIZE 12 +#define ANGLE_COMMIT_DATE "2015-04-02 17:07:24 +0000" diff --git a/src/3rdparty/angle/src/libANGLE/AttributeMap.cpp b/src/3rdparty/angle/src/libANGLE/AttributeMap.cpp new file mode 100644 index 0000000000..651a012037 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/AttributeMap.cpp @@ -0,0 +1,53 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "libANGLE/AttributeMap.h" + +namespace egl +{ + +AttributeMap::AttributeMap() +{ +} + +AttributeMap::AttributeMap(const EGLint *attributes) +{ + if (attributes) + { + for (const EGLint *curAttrib = attributes; curAttrib[0] != EGL_NONE; curAttrib += 2) + { + insert(curAttrib[0], curAttrib[1]); + } + } +} + +void AttributeMap::insert(EGLint key, EGLint value) +{ + mAttributes[key] = value; +} + +bool AttributeMap::contains(EGLint key) const +{ + return (mAttributes.find(key) != mAttributes.end()); +} + +EGLint AttributeMap::get(EGLint key, EGLint defaultValue) const +{ + std::map::const_iterator iter = mAttributes.find(key); + return (mAttributes.find(key) != mAttributes.end()) ? iter->second : defaultValue; +} + +AttributeMap::const_iterator AttributeMap::begin() const +{ + return mAttributes.begin(); +} + +AttributeMap::const_iterator AttributeMap::end() const +{ + return mAttributes.end(); +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/AttributeMap.h b/src/3rdparty/angle/src/libANGLE/AttributeMap.h new file mode 100644 index 0000000000..72b6edc3c7 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/AttributeMap.h @@ -0,0 +1,39 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef LIBANGLE_ATTRIBUTEMAP_H_ +#define LIBANGLE_ATTRIBUTEMAP_H_ + + +#include + +#include + +namespace egl +{ + +class AttributeMap +{ + public: + AttributeMap(); + explicit AttributeMap(const EGLint *attributes); + + virtual void insert(EGLint key, EGLint value); + virtual bool contains(EGLint key) const; + virtual EGLint get(EGLint key, EGLint defaultValue) const; + + typedef std::map::const_iterator const_iterator; + + const_iterator begin() const; + const_iterator end() const; + + private: + std::map mAttributes; +}; + +} + +#endif // LIBANGLE_ATTRIBUTEMAP_H_ diff --git a/src/3rdparty/angle/src/libANGLE/BinaryStream.h b/src/3rdparty/angle/src/libANGLE/BinaryStream.h new file mode 100644 index 0000000000..50392e1d3f --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/BinaryStream.h @@ -0,0 +1,218 @@ +// +// 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. +// + +// BinaryStream.h: Provides binary serialization of simple types. + +#ifndef LIBANGLE_BINARYSTREAM_H_ +#define LIBANGLE_BINARYSTREAM_H_ + +#include "common/angleutils.h" +#include "common/mathutil.h" + +#include +#include +#include +#include + +template +void StaticAssertIsFundamental() +{ + // c++11 STL is not available on OSX or Android +#if !defined(ANGLE_PLATFORM_APPLE) && !defined(ANGLE_PLATFORM_ANDROID) + static_assert(std::is_fundamental::value, "T must be a fundamental type."); +#else + union { T dummy; } dummy; + static_cast(dummy); +#endif +} + +namespace gl +{ + +class BinaryInputStream : angle::NonCopyable +{ + public: + BinaryInputStream(const void *data, size_t length) + { + mError = false; + mOffset = 0; + mData = static_cast(data); + mLength = length; + } + + // readInt will generate an error for bool types + template + IntT readInt() + { + int value; + read(&value); + return static_cast(value); + } + + template + void readInt(IntT *outValue) + { + *outValue = readInt(); + } + + bool readBool() + { + int value; + read(&value); + return (value > 0); + } + + void readBool(bool *outValue) + { + *outValue = readBool(); + } + + void readBytes(unsigned char outArray[], size_t count) + { + read(outArray, count); + } + + std::string readString() + { + std::string outString; + readString(&outString); + return outString; + } + + void readString(std::string *v) + { + size_t length; + readInt(&length); + + if (mError) + { + return; + } + + if (mOffset + length > mLength) + { + mError = true; + return; + } + + v->assign(reinterpret_cast(mData) + mOffset, length); + mOffset += length; + } + + void skip(size_t length) + { + if (mOffset + length > mLength) + { + mError = true; + return; + } + + mOffset += length; + } + + size_t offset() const + { + return mOffset; + } + + bool error() const + { + return mError; + } + + bool endOfStream() const + { + return mOffset == mLength; + } + + const uint8_t *data() + { + return mData; + } + + private: + bool mError; + size_t mOffset; + const uint8_t *mData; + size_t mLength; + + template + void read(T *v, size_t num) + { + StaticAssertIsFundamental(); + + size_t length = num * sizeof(T); + + if (mOffset + length > mLength) + { + mError = true; + return; + } + + memcpy(v, mData + mOffset, length); + mOffset += length; + } + + template + void read(T *v) + { + read(v, 1); + } + +}; + +class BinaryOutputStream : angle::NonCopyable +{ + public: + BinaryOutputStream() + { + } + + // writeInt also handles bool types + template + void writeInt(IntT param) + { + ASSERT(rx::IsIntegerCastSafe(param)); + int intValue = static_cast(param); + write(&intValue, 1); + } + + void writeString(const std::string &v) + { + writeInt(v.length()); + write(v.c_str(), v.length()); + } + + void writeBytes(const unsigned char *bytes, size_t count) + { + write(bytes, count); + } + + size_t length() const + { + return mData.size(); + } + + const void* data() const + { + return mData.size() ? &mData[0] : NULL; + } + + private: + std::vector mData; + + template + void write(const T *v, size_t num) + { + StaticAssertIsFundamental(); + const char *asBytes = reinterpret_cast(v); + mData.insert(mData.end(), asBytes, asBytes + num * sizeof(T)); + } + +}; +} + +#endif // LIBANGLE_BINARYSTREAM_H_ diff --git a/src/3rdparty/angle/src/libANGLE/Buffer.cpp b/src/3rdparty/angle/src/libANGLE/Buffer.cpp new file mode 100644 index 0000000000..f394a6b1d1 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/Buffer.cpp @@ -0,0 +1,121 @@ +// +// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Buffer.cpp: Implements the gl::Buffer class, representing storage of vertex and/or +// index data. Implements GL buffer objects and related functionality. +// [OpenGL ES 2.0.24] section 2.9 page 21. + +#include "libANGLE/Buffer.h" +#include "libANGLE/renderer/BufferImpl.h" +#include "libANGLE/renderer/Renderer.h" + +namespace gl +{ + +Buffer::Buffer(rx::BufferImpl *impl, GLuint id) + : RefCountObject(id), + mBuffer(impl), + mUsage(GL_DYNAMIC_DRAW), + mSize(0), + mAccessFlags(0), + mMapped(GL_FALSE), + mMapPointer(NULL), + mMapOffset(0), + mMapLength(0) +{ +} + +Buffer::~Buffer() +{ + SafeDelete(mBuffer); +} + +Error Buffer::bufferData(const void *data, GLsizeiptr size, GLenum usage) +{ + gl::Error error = mBuffer->setData(data, size, usage); + if (error.isError()) + { + return error; + } + + mIndexRangeCache.clear(); + mUsage = usage; + mSize = size; + + return error; +} + +Error Buffer::bufferSubData(const void *data, GLsizeiptr size, GLintptr offset) +{ + gl::Error error = mBuffer->setSubData(data, size, offset); + if (error.isError()) + { + return error; + } + + mIndexRangeCache.invalidateRange(offset, size); + + return error; +} + +Error Buffer::copyBufferSubData(Buffer* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size) +{ + gl::Error error = mBuffer->copySubData(source->getImplementation(), sourceOffset, destOffset, size); + if (error.isError()) + { + return error; + } + + mIndexRangeCache.invalidateRange(destOffset, size); + + return error; +} + +Error Buffer::mapRange(GLintptr offset, GLsizeiptr length, GLbitfield access) +{ + ASSERT(!mMapped); + ASSERT(offset + length <= mSize); + + Error error = mBuffer->map(offset, length, access, &mMapPointer); + if (error.isError()) + { + mMapPointer = NULL; + return error; + } + + mMapped = GL_TRUE; + mMapOffset = static_cast(offset); + mMapLength = static_cast(length); + mAccessFlags = static_cast(access); + + if ((access & GL_MAP_WRITE_BIT) > 0) + { + mIndexRangeCache.invalidateRange(offset, length); + } + + return error; +} + +Error Buffer::unmap() +{ + ASSERT(mMapped); + + Error error = mBuffer->unmap(); + if (error.isError()) + { + return error; + } + + mMapped = GL_FALSE; + mMapPointer = NULL; + mMapOffset = 0; + mMapLength = 0; + mAccessFlags = 0; + + return error; +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/Buffer.h b/src/3rdparty/angle/src/libANGLE/Buffer.h new file mode 100644 index 0000000000..6793028e3b --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/Buffer.h @@ -0,0 +1,70 @@ +// +// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Buffer.h: Defines the gl::Buffer class, representing storage of vertex and/or +// index data. Implements GL buffer objects and related functionality. +// [OpenGL ES 2.0.24] section 2.9 page 21. + +#ifndef LIBANGLE_BUFFER_H_ +#define LIBANGLE_BUFFER_H_ + +#include "libANGLE/Error.h" +#include "libANGLE/RefCountObject.h" +#include "libANGLE/renderer/IndexRangeCache.h" + +#include "common/angleutils.h" + +namespace rx +{ +class BufferImpl; +}; + +namespace gl +{ + +class Buffer : public RefCountObject +{ + public: + Buffer(rx::BufferImpl *impl, GLuint id); + + virtual ~Buffer(); + + Error bufferData(const void *data, GLsizeiptr size, GLenum usage); + Error bufferSubData(const void *data, GLsizeiptr size, GLintptr offset); + Error copyBufferSubData(Buffer* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size); + Error mapRange(GLintptr offset, GLsizeiptr length, GLbitfield access); + Error unmap(); + + GLenum getUsage() const { return mUsage; } + GLint getAccessFlags() const { return mAccessFlags; } + GLboolean isMapped() const { return mMapped; } + GLvoid *getMapPointer() const { return mMapPointer; } + GLint64 getMapOffset() const { return mMapOffset; } + GLint64 getMapLength() const { return mMapLength; } + GLint64 getSize() const { return mSize; } + + rx::BufferImpl *getImplementation() const { return mBuffer; } + + rx::IndexRangeCache *getIndexRangeCache() { return &mIndexRangeCache; } + const rx::IndexRangeCache *getIndexRangeCache() const { return &mIndexRangeCache; } + + private: + rx::BufferImpl *mBuffer; + + GLenum mUsage; + GLint64 mSize; + GLint mAccessFlags; + GLboolean mMapped; + GLvoid *mMapPointer; + GLint64 mMapOffset; + GLint64 mMapLength; + + rx::IndexRangeCache mIndexRangeCache; +}; + +} + +#endif // LIBANGLE_BUFFER_H_ diff --git a/src/3rdparty/angle/src/libANGLE/Caps.cpp b/src/3rdparty/angle/src/libANGLE/Caps.cpp new file mode 100644 index 0000000000..086d0a02a2 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/Caps.cpp @@ -0,0 +1,527 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "libANGLE/Caps.h" +#include "common/debug.h" +#include "common/angleutils.h" + +#include "angle_gl.h" + +#include +#include + +static void InsertExtensionString(const std::string &extension, bool supported, std::vector *extensionVector) +{ + if (supported) + { + extensionVector->push_back(extension); + } +} + +namespace gl +{ + +TextureCaps::TextureCaps() + : texturable(false), + filterable(false), + renderable(false), + sampleCounts() +{ +} + +GLuint TextureCaps::getMaxSamples() const +{ + return !sampleCounts.empty() ? *sampleCounts.rbegin() : 0; +} + +GLuint TextureCaps::getNearestSamples(GLuint requestedSamples) const +{ + if (requestedSamples == 0) + { + return 0; + } + + for (SupportedSampleSet::const_iterator i = sampleCounts.begin(); i != sampleCounts.end(); i++) + { + GLuint samples = *i; + if (samples >= requestedSamples) + { + return samples; + } + } + + return 0; +} + +void TextureCapsMap::insert(GLenum internalFormat, const TextureCaps &caps) +{ + mCapsMap.insert(std::make_pair(internalFormat, caps)); +} + +void TextureCapsMap::remove(GLenum internalFormat) +{ + InternalFormatToCapsMap::iterator i = mCapsMap.find(internalFormat); + if (i != mCapsMap.end()) + { + mCapsMap.erase(i); + } +} + +const TextureCaps &TextureCapsMap::get(GLenum internalFormat) const +{ + static TextureCaps defaultUnsupportedTexture; + InternalFormatToCapsMap::const_iterator iter = mCapsMap.find(internalFormat); + return (iter != mCapsMap.end()) ? iter->second : defaultUnsupportedTexture; +} + +TextureCapsMap::const_iterator TextureCapsMap::begin() const +{ + return mCapsMap.begin(); +} + +TextureCapsMap::const_iterator TextureCapsMap::end() const +{ + return mCapsMap.end(); +} + +size_t TextureCapsMap::size() const +{ + return mCapsMap.size(); +} + +Extensions::Extensions() + : elementIndexUint(false), + packedDepthStencil(false), + getProgramBinary(false), + rgb8rgba8(false), + textureFormatBGRA8888(false), + readFormatBGRA(false), + pixelBufferObject(false), + mapBuffer(false), + mapBufferRange(false), + textureHalfFloat(false), + textureHalfFloatLinear(false), + textureFloat(false), + textureFloatLinear(false), + textureRG(false), + textureCompressionDXT1(false), + textureCompressionDXT3(false), + textureCompressionDXT5(false), + depthTextures(false), + textureNPOT(false), + drawBuffers(false), + textureStorage(false), + textureFilterAnisotropic(false), + maxTextureAnisotropy(false), + occlusionQueryBoolean(false), + fence(false), + timerQuery(false), + robustness(false), + blendMinMax(false), + framebufferBlit(false), + framebufferMultisample(false), + instancedArrays(false), + packReverseRowOrder(false), + standardDerivatives(false), + shaderTextureLOD(false), + shaderFramebufferFetch(false), + ARMshaderFramebufferFetch(false), + NVshaderFramebufferFetch(false), + fragDepth(false), + textureUsage(false), + translatedShaderSource(false), + colorBufferFloat(false) +{ +} + +std::vector Extensions::getStrings() const +{ + std::vector extensionStrings; + + // | Extension name | Supported flag | Output vector | + InsertExtensionString("GL_OES_element_index_uint", elementIndexUint, &extensionStrings); + InsertExtensionString("GL_OES_packed_depth_stencil", packedDepthStencil, &extensionStrings); + InsertExtensionString("GL_OES_get_program_binary", getProgramBinary, &extensionStrings); + InsertExtensionString("GL_OES_rgb8_rgba8", rgb8rgba8, &extensionStrings); + InsertExtensionString("GL_EXT_texture_format_BGRA8888", textureFormatBGRA8888, &extensionStrings); + InsertExtensionString("GL_EXT_read_format_bgra", readFormatBGRA, &extensionStrings); + InsertExtensionString("GL_NV_pixel_buffer_object", pixelBufferObject, &extensionStrings); + InsertExtensionString("GL_OES_mapbuffer", mapBuffer, &extensionStrings); + InsertExtensionString("GL_EXT_map_buffer_range", mapBufferRange, &extensionStrings); + InsertExtensionString("GL_OES_texture_half_float", textureHalfFloat, &extensionStrings); + InsertExtensionString("GL_OES_texture_half_float_linear", textureHalfFloatLinear, &extensionStrings); + InsertExtensionString("GL_OES_texture_float", textureFloat, &extensionStrings); + InsertExtensionString("GL_OES_texture_float_linear", textureFloatLinear, &extensionStrings); + InsertExtensionString("GL_EXT_texture_rg", textureRG, &extensionStrings); + InsertExtensionString("GL_EXT_texture_compression_dxt1", textureCompressionDXT1, &extensionStrings); + InsertExtensionString("GL_ANGLE_texture_compression_dxt3", textureCompressionDXT3, &extensionStrings); + InsertExtensionString("GL_ANGLE_texture_compression_dxt5", textureCompressionDXT5, &extensionStrings); + InsertExtensionString("GL_EXT_sRGB", sRGB, &extensionStrings); + InsertExtensionString("GL_ANGLE_depth_texture", depthTextures, &extensionStrings); + InsertExtensionString("GL_EXT_texture_storage", textureStorage, &extensionStrings); + InsertExtensionString("GL_OES_texture_npot", textureNPOT, &extensionStrings); + InsertExtensionString("GL_EXT_draw_buffers", drawBuffers, &extensionStrings); + InsertExtensionString("GL_EXT_texture_filter_anisotropic", textureFilterAnisotropic, &extensionStrings); + InsertExtensionString("GL_EXT_occlusion_query_boolean", occlusionQueryBoolean, &extensionStrings); + InsertExtensionString("GL_NV_fence", fence, &extensionStrings); + InsertExtensionString("GL_ANGLE_timer_query", timerQuery, &extensionStrings); + InsertExtensionString("GL_EXT_robustness", robustness, &extensionStrings); + InsertExtensionString("GL_EXT_blend_minmax", blendMinMax, &extensionStrings); + InsertExtensionString("GL_ANGLE_framebuffer_blit", framebufferBlit, &extensionStrings); + InsertExtensionString("GL_ANGLE_framebuffer_multisample", framebufferMultisample, &extensionStrings); + InsertExtensionString("GL_ANGLE_instanced_arrays", instancedArrays, &extensionStrings); + InsertExtensionString("GL_ANGLE_pack_reverse_row_order", packReverseRowOrder, &extensionStrings); + InsertExtensionString("GL_OES_standard_derivatives", standardDerivatives, &extensionStrings); + InsertExtensionString("GL_EXT_shader_texture_lod", shaderTextureLOD, &extensionStrings); + InsertExtensionString("GL_NV_shader_framebuffer_fetch", NVshaderFramebufferFetch, &extensionStrings); + InsertExtensionString("GL_ARM_shader_framebuffer_fetch", ARMshaderFramebufferFetch,&extensionStrings); + InsertExtensionString("GL_EXT_shader_framebuffer_fetch", shaderFramebufferFetch, &extensionStrings); + InsertExtensionString("GL_EXT_frag_depth", fragDepth, &extensionStrings); + InsertExtensionString("GL_ANGLE_texture_usage", textureUsage, &extensionStrings); + InsertExtensionString("GL_ANGLE_translated_shader_source", translatedShaderSource, &extensionStrings); + InsertExtensionString("GL_EXT_color_buffer_float", colorBufferFloat, &extensionStrings); + + return extensionStrings; +} + +static bool GetFormatSupport(const TextureCapsMap &textureCaps, const std::vector &requiredFormats, + bool requiresTexturing, bool requiresFiltering, bool requiresRendering) +{ + for (size_t i = 0; i < requiredFormats.size(); i++) + { + const TextureCaps &cap = textureCaps.get(requiredFormats[i]); + + if (requiresTexturing && !cap.texturable) + { + return false; + } + + if (requiresFiltering && !cap.filterable) + { + return false; + } + + if (requiresRendering && !cap.renderable) + { + return false; + } + } + + return true; +} + +// Checks for GL_OES_rgb8_rgba8 support +static bool DetermineRGB8AndRGBA8TextureSupport(const TextureCapsMap &textureCaps) +{ + std::vector requiredFormats; + requiredFormats.push_back(GL_RGB8); + requiredFormats.push_back(GL_RGBA8); + + return GetFormatSupport(textureCaps, requiredFormats, true, true, true); +} + +// Checks for GL_EXT_texture_format_BGRA8888 support +static bool DetermineBGRA8TextureSupport(const TextureCapsMap &textureCaps) +{ + std::vector requiredFormats; + requiredFormats.push_back(GL_BGRA8_EXT); + + return GetFormatSupport(textureCaps, requiredFormats, true, true, true); +} + +// Checks for GL_OES_texture_half_float support +static bool DetermineHalfFloatTextureSupport(const TextureCapsMap &textureCaps) +{ + std::vector requiredFormats; + requiredFormats.push_back(GL_RGB16F); + requiredFormats.push_back(GL_RGBA16F); + + return GetFormatSupport(textureCaps, requiredFormats, true, false, true); +} + +// Checks for GL_OES_texture_half_float_linear support +static bool DetermineHalfFloatTextureFilteringSupport(const TextureCapsMap &textureCaps) +{ + std::vector requiredFormats; + requiredFormats.push_back(GL_RGB16F); + requiredFormats.push_back(GL_RGBA16F); + + return GetFormatSupport(textureCaps, requiredFormats, true, true, false); +} + +// Checks for GL_OES_texture_float support +static bool DetermineFloatTextureSupport(const TextureCapsMap &textureCaps) +{ + std::vector requiredFormats; + requiredFormats.push_back(GL_RGB32F); + requiredFormats.push_back(GL_RGBA32F); + + return GetFormatSupport(textureCaps, requiredFormats, true, false, true); +} + +// Checks for GL_OES_texture_float_linear support +static bool DetermineFloatTextureFilteringSupport(const TextureCapsMap &textureCaps) +{ + std::vector requiredFormats; + requiredFormats.push_back(GL_RGB32F); + requiredFormats.push_back(GL_RGBA32F); + + return GetFormatSupport(textureCaps, requiredFormats, true, true, false); +} + +// Checks for GL_EXT_texture_rg support +static bool DetermineRGTextureSupport(const TextureCapsMap &textureCaps, bool checkHalfFloatFormats, bool checkFloatFormats) +{ + std::vector requiredFormats; + requiredFormats.push_back(GL_R8); + requiredFormats.push_back(GL_RG8); + if (checkHalfFloatFormats) + { + requiredFormats.push_back(GL_R16F); + requiredFormats.push_back(GL_RG16F); + } + if (checkFloatFormats) + { + requiredFormats.push_back(GL_R32F); + requiredFormats.push_back(GL_RG32F); + } + + return GetFormatSupport(textureCaps, requiredFormats, true, true, false); +} + +// Check for GL_EXT_texture_compression_dxt1 +static bool DetermineDXT1TextureSupport(const TextureCapsMap &textureCaps) +{ + std::vector requiredFormats; + requiredFormats.push_back(GL_COMPRESSED_RGB_S3TC_DXT1_EXT); + requiredFormats.push_back(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT); + + return GetFormatSupport(textureCaps, requiredFormats, true, true, false); +} + +// Check for GL_ANGLE_texture_compression_dxt3 +static bool DetermineDXT3TextureSupport(const TextureCapsMap &textureCaps) +{ + std::vector requiredFormats; + requiredFormats.push_back(GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE); + + return GetFormatSupport(textureCaps, requiredFormats, true, true, false); +} + +// Check for GL_ANGLE_texture_compression_dxt5 +static bool DetermineDXT5TextureSupport(const TextureCapsMap &textureCaps) +{ + std::vector requiredFormats; + requiredFormats.push_back(GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE); + + return GetFormatSupport(textureCaps, requiredFormats, true, true, false); +} + +// Check for GL_ANGLE_texture_compression_dxt5 +static bool DetermineSRGBTextureSupport(const TextureCapsMap &textureCaps) +{ + std::vector requiredFilterFormats; + requiredFilterFormats.push_back(GL_SRGB8); + requiredFilterFormats.push_back(GL_SRGB8_ALPHA8); + + std::vector requiredRenderFormats; + requiredRenderFormats.push_back(GL_SRGB8_ALPHA8); + + return GetFormatSupport(textureCaps, requiredFilterFormats, true, true, false) && + GetFormatSupport(textureCaps, requiredRenderFormats, true, false, true); +} + +// Check for GL_ANGLE_depth_texture +static bool DetermineDepthTextureSupport(const TextureCapsMap &textureCaps) +{ + std::vector requiredFormats; + requiredFormats.push_back(GL_DEPTH_COMPONENT16); + requiredFormats.push_back(GL_DEPTH_COMPONENT32_OES); + requiredFormats.push_back(GL_DEPTH24_STENCIL8_OES); + + return GetFormatSupport(textureCaps, requiredFormats, true, true, true); +} + +// Check for GL_EXT_color_buffer_float +static bool DetermineColorBufferFloatSupport(const TextureCapsMap &textureCaps) +{ + std::vector requiredFormats; + requiredFormats.push_back(GL_R16F); + requiredFormats.push_back(GL_RG16F); + requiredFormats.push_back(GL_RGBA16F); + requiredFormats.push_back(GL_R32F); + requiredFormats.push_back(GL_RG32F); + requiredFormats.push_back(GL_RGBA32F); + requiredFormats.push_back(GL_R11F_G11F_B10F); + + return GetFormatSupport(textureCaps, requiredFormats, true, false, true); +} + +void Extensions::setTextureExtensionSupport(const TextureCapsMap &textureCaps) +{ + rgb8rgba8 = DetermineRGB8AndRGBA8TextureSupport(textureCaps); + textureFormatBGRA8888 = DetermineBGRA8TextureSupport(textureCaps); + textureHalfFloat = DetermineHalfFloatTextureSupport(textureCaps); + textureHalfFloatLinear = DetermineHalfFloatTextureFilteringSupport(textureCaps); + textureFloat = DetermineFloatTextureSupport(textureCaps); + textureFloatLinear = DetermineFloatTextureFilteringSupport(textureCaps); + textureRG = DetermineRGTextureSupport(textureCaps, textureHalfFloat, textureFloat); + textureCompressionDXT1 = DetermineDXT1TextureSupport(textureCaps); + textureCompressionDXT3 = DetermineDXT3TextureSupport(textureCaps); + textureCompressionDXT5 = DetermineDXT5TextureSupport(textureCaps); + sRGB = DetermineSRGBTextureSupport(textureCaps); + depthTextures = DetermineDepthTextureSupport(textureCaps); + colorBufferFloat = DetermineColorBufferFloatSupport(textureCaps); +} + +TypePrecision::TypePrecision() +{ + range[0] = 0; + range[1] = 0; + precision = 0; +} + +void TypePrecision::setIEEEFloat() +{ + range[0] = 127; + range[1] = 127; + precision = 23; +} + +void TypePrecision::setTwosComplementInt(unsigned int bits) +{ + range[0] = GLint(bits) - 1; + range[1] = GLint(bits) - 2; + precision = 0; +} + +void TypePrecision::setSimulatedInt(unsigned int r) +{ + range[0] = GLint(r); + range[1] = GLint(r); + precision = 0; +} + +void TypePrecision::get(GLint *returnRange, GLint *returnPrecision) const +{ + returnRange[0] = range[0]; + returnRange[1] = range[1]; + *returnPrecision = precision; +} + +Caps::Caps() + : maxElementIndex(0), + max3DTextureSize(0), + max2DTextureSize(0), + maxArrayTextureLayers(0), + maxLODBias(0), + maxCubeMapTextureSize(0), + maxRenderbufferSize(0), + maxDrawBuffers(0), + maxColorAttachments(0), + maxViewportWidth(0), + maxViewportHeight(0), + minAliasedPointSize(0), + maxAliasedPointSize(0), + minAliasedLineWidth(0), + // Table 6.29 + maxElementsIndices(0), + maxElementsVertices(0), + maxServerWaitTimeout(0), + // Table 6.31 + maxVertexAttributes(0), + maxVertexUniformComponents(0), + maxVertexUniformVectors(0), + maxVertexUniformBlocks(0), + maxVertexOutputComponents(0), + maxVertexTextureImageUnits(0), + // Table 6.32 + maxFragmentUniformComponents(0), + maxFragmentUniformVectors(0), + maxFragmentUniformBlocks(0), + maxFragmentInputComponents(0), + maxTextureImageUnits(0), + minProgramTexelOffset(0), + maxProgramTexelOffset(0), + + maxUniformBufferBindings(0), + maxUniformBlockSize(0), + uniformBufferOffsetAlignment(0), + maxCombinedUniformBlocks(0), + maxCombinedVertexUniformComponents(0), + maxCombinedFragmentUniformComponents(0), + maxVaryingComponents(0), + maxVaryingVectors(0), + maxCombinedTextureImageUnits(0), + + maxTransformFeedbackInterleavedComponents(0), + maxTransformFeedbackSeparateAttributes(0), + maxTransformFeedbackSeparateComponents(0) +{ +} + +} + +namespace egl +{ + +Caps::Caps() + : textureNPOT(false) +{ +} + +DisplayExtensions::DisplayExtensions() + : createContextRobustness(false), + d3dShareHandleClientBuffer(false), + surfaceD3DTexture2DShareHandle(false), + querySurfacePointer(false), + windowFixedSize(false), + postSubBuffer(false), + createContext(false) +{ +} + +std::vector DisplayExtensions::getStrings() const +{ + std::vector extensionStrings; + + // | Extension name | Supported flag | Output vector | + InsertExtensionString("EGL_EXT_create_context_robustness", createContextRobustness, &extensionStrings); + InsertExtensionString("EGL_ANGLE_d3d_share_handle_client_buffer", d3dShareHandleClientBuffer, &extensionStrings); + InsertExtensionString("EGL_ANGLE_surface_d3d_texture_2d_share_handle", surfaceD3DTexture2DShareHandle, &extensionStrings); + InsertExtensionString("EGL_ANGLE_query_surface_pointer", querySurfacePointer, &extensionStrings); + InsertExtensionString("EGL_ANGLE_window_fixed_size", windowFixedSize, &extensionStrings); + InsertExtensionString("EGL_NV_post_sub_buffer", postSubBuffer, &extensionStrings); + InsertExtensionString("EGL_KHR_create_context", createContext, &extensionStrings); + + return extensionStrings; +} + + +ClientExtensions::ClientExtensions() + : clientExtensions(false), + platformBase(false), + platformANGLE(false), + platformANGLED3D(false), + platformANGLEOpenGL(false) +{ +} + +std::vector ClientExtensions::getStrings() const +{ + std::vector extensionStrings; + + // | Extension name | Supported flag | Output vector | + InsertExtensionString("EGL_EXT_client_extensions", clientExtensions, &extensionStrings); + InsertExtensionString("EGL_EXT_platform_base", platformBase, &extensionStrings); + InsertExtensionString("EGL_ANGLE_platform_angle", platformANGLE, &extensionStrings); + InsertExtensionString("EGL_ANGLE_platform_angle_d3d", platformANGLED3D, &extensionStrings); + InsertExtensionString("EGL_ANGLE_platform_angle_opengl", platformANGLEOpenGL, &extensionStrings); + + return extensionStrings; +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/Caps.h b/src/3rdparty/angle/src/libANGLE/Caps.h new file mode 100644 index 0000000000..37a634226a --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/Caps.h @@ -0,0 +1,374 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef LIBANGLE_CAPS_H_ +#define LIBANGLE_CAPS_H_ + +#include "angle_gl.h" +#include "libANGLE/angletypes.h" + +#include +#include +#include +#include + +namespace gl +{ + +typedef std::set SupportedSampleSet; + +struct TextureCaps +{ + TextureCaps(); + + // Supports for basic texturing: glTexImage, glTexSubImage, etc + bool texturable; + + // Support for linear or anisotropic filtering + bool filterable; + + // Support for being used as a framebuffer attachment or renderbuffer format + bool renderable; + + SupportedSampleSet sampleCounts; + + // Get the maximum number of samples supported + GLuint getMaxSamples() const; + + // Get the number of supported samples that is at least as many as requested. Returns 0 if + // there are no sample counts available + GLuint getNearestSamples(GLuint requestedSamples) const; +}; + +class TextureCapsMap +{ + public: + typedef std::map::const_iterator const_iterator; + + void insert(GLenum internalFormat, const TextureCaps &caps); + void remove(GLenum internalFormat); + + const TextureCaps &get(GLenum internalFormat) const; + + const_iterator begin() const; + const_iterator end() const; + + size_t size() const; + + private: + typedef std::map InternalFormatToCapsMap; + InternalFormatToCapsMap mCapsMap; +}; + +struct Extensions +{ + Extensions(); + + // Generate a vector of supported extension strings + std::vector getStrings() const; + + // Set all texture related extension support based on the supported textures. + // Determines support for: + // GL_OES_rgb8_rgba8 + // GL_EXT_texture_format_BGRA8888 + // GL_OES_texture_half_float, GL_OES_texture_half_float_linear + // GL_OES_texture_float, GL_OES_texture_float_linear + // GL_EXT_texture_rg + // GL_EXT_texture_compression_dxt1, GL_ANGLE_texture_compression_dxt3, GL_ANGLE_texture_compression_dxt5 + // GL_EXT_sRGB + // GL_ANGLE_depth_texture + // GL_EXT_color_buffer_float + void setTextureExtensionSupport(const TextureCapsMap &textureCaps); + + // ES2 Extension support + + // GL_OES_element_index_uint + bool elementIndexUint; + + // GL_OES_packed_depth_stencil + bool packedDepthStencil; + + // GL_OES_get_program_binary + bool getProgramBinary; + + // GL_OES_rgb8_rgba8 + // Implies that TextureCaps for GL_RGB8 and GL_RGBA8 exist + bool rgb8rgba8; + + // GL_EXT_texture_format_BGRA8888 + // Implies that TextureCaps for GL_BGRA8 exist + bool textureFormatBGRA8888; + + // GL_EXT_read_format_bgra + bool readFormatBGRA; + + // GL_NV_pixel_buffer_object + bool pixelBufferObject; + + // GL_OES_mapbuffer and GL_EXT_map_buffer_range + bool mapBuffer; + bool mapBufferRange; + + // GL_OES_texture_half_float and GL_OES_texture_half_float_linear + // Implies that TextureCaps for GL_RGB16F, GL_RGBA16F, GL_ALPHA32F_EXT, GL_LUMINANCE32F_EXT and + // GL_LUMINANCE_ALPHA32F_EXT exist + bool textureHalfFloat; + bool textureHalfFloatLinear; + + // GL_OES_texture_float and GL_OES_texture_float_linear + // Implies that TextureCaps for GL_RGB32F, GL_RGBA32F, GL_ALPHA16F_EXT, GL_LUMINANCE16F_EXT and + // GL_LUMINANCE_ALPHA16F_EXT exist + bool textureFloat; + bool textureFloatLinear; + + // GL_EXT_texture_rg + // Implies that TextureCaps for GL_R8, GL_RG8 (and floating point R/RG texture formats if floating point extensions + // are also present) exist + bool textureRG; + + // GL_EXT_texture_compression_dxt1, GL_ANGLE_texture_compression_dxt3 and GL_ANGLE_texture_compression_dxt5 + // Implies that TextureCaps for GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT + // GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE and GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE + bool textureCompressionDXT1; + bool textureCompressionDXT3; + bool textureCompressionDXT5; + + // GL_EXT_sRGB + // Implies that TextureCaps for GL_SRGB8_ALPHA8 and GL_SRGB8 exist + // TODO: Don't advertise this extension in ES3 + bool sRGB; + + // GL_ANGLE_depth_texture + bool depthTextures; + + // GL_EXT_texture_storage + bool textureStorage; + + // GL_OES_texture_npot + bool textureNPOT; + + // GL_EXT_draw_buffers + bool drawBuffers; + + // GL_EXT_texture_filter_anisotropic + bool textureFilterAnisotropic; + GLfloat maxTextureAnisotropy; + + // GL_EXT_occlusion_query_boolean + bool occlusionQueryBoolean; + + // GL_NV_fence + bool fence; + + // GL_ANGLE_timer_query + bool timerQuery; + + // GL_EXT_robustness + bool robustness; + + // GL_EXT_blend_minmax + bool blendMinMax; + + // GL_ANGLE_framebuffer_blit + bool framebufferBlit; + + // GL_ANGLE_framebuffer_multisample + bool framebufferMultisample; + GLuint maxSamples; + + // GL_ANGLE_instanced_arrays + bool instancedArrays; + + // GL_ANGLE_pack_reverse_row_order + bool packReverseRowOrder; + + // GL_OES_standard_derivatives + bool standardDerivatives; + + // GL_EXT_shader_texture_lod + bool shaderTextureLOD; + + // GL_EXT_shader_framebuffer_fetch + bool shaderFramebufferFetch; + + // GL_ARM_shader_framebuffer_fetch + bool ARMshaderFramebufferFetch; + + // GL_NV_shader_framebuffer_fetch + bool NVshaderFramebufferFetch; + + // GL_EXT_frag_depth + bool fragDepth; + + // GL_ANGLE_texture_usage + bool textureUsage; + + // GL_ANGLE_translated_shader_source + bool translatedShaderSource; + + // ES3 Extension support + + // GL_EXT_color_buffer_float + bool colorBufferFloat; +}; + +struct TypePrecision +{ + TypePrecision(); + + void setIEEEFloat(); + void setTwosComplementInt(unsigned int bits); + void setSimulatedInt(unsigned int range); + + void get(GLint *returnRange, GLint *returnPrecision) const; + + GLint range[2]; + GLint precision; +}; + +struct Caps +{ + Caps(); + + // Table 6.28, implementation dependent values + GLuint64 maxElementIndex; + GLuint max3DTextureSize; + GLuint max2DTextureSize; + GLuint maxArrayTextureLayers; + GLfloat maxLODBias; + GLuint maxCubeMapTextureSize; + GLuint maxRenderbufferSize; + GLuint maxDrawBuffers; + GLuint maxColorAttachments; + GLuint maxViewportWidth; + GLuint maxViewportHeight; + GLfloat minAliasedPointSize; + GLfloat maxAliasedPointSize; + GLfloat minAliasedLineWidth; + GLfloat maxAliasedLineWidth; + + // Table 6.29, implementation dependent values (cont.) + GLuint maxElementsIndices; + GLuint maxElementsVertices; + std::vector compressedTextureFormats; + std::vector programBinaryFormats; + std::vector shaderBinaryFormats; + TypePrecision vertexHighpFloat; + TypePrecision vertexMediumpFloat; + TypePrecision vertexLowpFloat; + TypePrecision vertexHighpInt; + TypePrecision vertexMediumpInt; + TypePrecision vertexLowpInt; + TypePrecision fragmentHighpFloat; + TypePrecision fragmentMediumpFloat; + TypePrecision fragmentLowpFloat; + TypePrecision fragmentHighpInt; + TypePrecision fragmentMediumpInt; + TypePrecision fragmentLowpInt; + GLuint64 maxServerWaitTimeout; + + // Table 6.31, implementation dependent vertex shader limits + GLuint maxVertexAttributes; + GLuint maxVertexUniformComponents; + GLuint maxVertexUniformVectors; + GLuint maxVertexUniformBlocks; + GLuint maxVertexOutputComponents; + GLuint maxVertexTextureImageUnits; + + // Table 6.32, implementation dependent fragment shader limits + GLuint maxFragmentUniformComponents; + GLuint maxFragmentUniformVectors; + GLuint maxFragmentUniformBlocks; + GLuint maxFragmentInputComponents; + GLuint maxTextureImageUnits; + GLint minProgramTexelOffset; + GLint maxProgramTexelOffset; + + // Table 6.33, implementation dependent aggregate shader limits + GLuint maxUniformBufferBindings; + GLuint64 maxUniformBlockSize; + GLuint uniformBufferOffsetAlignment; + GLuint maxCombinedUniformBlocks; + GLuint64 maxCombinedVertexUniformComponents; + GLuint64 maxCombinedFragmentUniformComponents; + GLuint maxVaryingComponents; + GLuint maxVaryingVectors; + GLuint maxCombinedTextureImageUnits; + + // Table 6.34, implementation dependent transform feedback limits + GLuint maxTransformFeedbackInterleavedComponents; + GLuint maxTransformFeedbackSeparateAttributes; + GLuint maxTransformFeedbackSeparateComponents; +}; + +} + +namespace egl +{ + +struct Caps +{ + Caps(); + + // Support for NPOT surfaces + bool textureNPOT; +}; + +struct DisplayExtensions +{ + DisplayExtensions(); + + // Generate a vector of supported extension strings + std::vector getStrings() const; + + // EGL_EXT_create_context_robustness + bool createContextRobustness; + + // EGL_ANGLE_d3d_share_handle_client_buffer + bool d3dShareHandleClientBuffer; + + // EGL_ANGLE_surface_d3d_texture_2d_share_handle + bool surfaceD3DTexture2DShareHandle; + + // EGL_ANGLE_query_surface_pointer + bool querySurfacePointer; + + // EGL_ANGLE_window_fixed_size + bool windowFixedSize; + + // EGL_NV_post_sub_buffer + bool postSubBuffer; + + // EGL_KHR_create_context + bool createContext; +}; + +struct ClientExtensions +{ + ClientExtensions(); + + // Generate a vector of supported extension strings + std::vector getStrings() const; + + // EGL_EXT_client_extensions + bool clientExtensions; + + // EGL_EXT_platform_base + bool platformBase; + + // EGL_ANGLE_platform_angle + bool platformANGLE; + + // EGL_ANGLE_platform_angle_d3d + bool platformANGLED3D; + + // EGL_ANGLE_platform_angle_opengl + bool platformANGLEOpenGL; +}; + +} + +#endif // LIBANGLE_CAPS_H_ diff --git a/src/3rdparty/angle/src/libANGLE/Compiler.cpp b/src/3rdparty/angle/src/libANGLE/Compiler.cpp new file mode 100644 index 0000000000..7d0efea220 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/Compiler.cpp @@ -0,0 +1,38 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Compiler.cpp: implements the gl::Compiler class. + +#include "libANGLE/Compiler.h" +#include "libANGLE/renderer/CompilerImpl.h" + +#include "common/debug.h" + +namespace gl +{ + +Compiler::Compiler(rx::CompilerImpl *impl) + : mCompiler(impl) +{ + ASSERT(mCompiler); +} + +Compiler::~Compiler() +{ + SafeDelete(mCompiler); +} + +Error Compiler::release() +{ + return mCompiler->release(); +} + +rx::CompilerImpl *Compiler::getImplementation() +{ + return mCompiler; +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/Compiler.h b/src/3rdparty/angle/src/libANGLE/Compiler.h new file mode 100644 index 0000000000..05de15ec97 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/Compiler.h @@ -0,0 +1,39 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Compiler.h: Defines the gl::Compiler class, abstracting the ESSL compiler +// that a GL context holds. + +#ifndef LIBANGLE_COMPILER_H_ +#define LIBANGLE_COMPILER_H_ + +#include "libANGLE/Error.h" + +namespace rx +{ +class CompilerImpl; +} + +namespace gl +{ + +class Compiler final +{ + public: + explicit Compiler(rx::CompilerImpl *impl); + ~Compiler(); + + Error release(); + + rx::CompilerImpl *getImplementation(); + + private: + rx::CompilerImpl *mCompiler; +}; + +} + +#endif // LIBANGLE_COMPILER_H_ diff --git a/src/3rdparty/angle/src/libANGLE/Config.cpp b/src/3rdparty/angle/src/libANGLE/Config.cpp new file mode 100644 index 0000000000..1b1fc50cb3 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/Config.cpp @@ -0,0 +1,275 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Config.cpp: Implements the egl::Config class, describing the format, type +// and size for an egl::Surface. Implements EGLConfig and related functionality. +// [EGL 1.5] section 3.4 page 19. + +#include "libANGLE/Config.h" +#include "libANGLE/AttributeMap.h" + +#include +#include + +#include "angle_gl.h" +#include + +#include "common/debug.h" + +namespace egl +{ + +Config::Config() + : renderTargetFormat(GL_NONE), + depthStencilFormat(GL_NONE), + bufferSize(0), + redSize(0), + greenSize(0), + blueSize(0), + luminanceSize(0), + alphaSize(0), + alphaMaskSize(0), + bindToTextureRGB(EGL_FALSE), + bindToTextureRGBA(EGL_FALSE), + colorBufferType(EGL_NONE), + configCaveat(EGL_NONE), + configID(0), + conformant(0), + depthSize(0), + level(0), + matchNativePixmap(EGL_FALSE), + maxPBufferWidth(0), + maxPBufferHeight(0), + maxPBufferPixels(0), + maxSwapInterval(0), + minSwapInterval(0), + nativeRenderable(EGL_FALSE), + nativeVisualID(0), + nativeVisualType(0), + renderableType(0), + sampleBuffers(0), + samples(0), + stencilSize(0), + surfaceType(0), + transparentType(EGL_NONE), + transparentRedValue(0), + transparentGreenValue(0), + transparentBlueValue(0) +{ +} + +EGLint ConfigSet::add(const Config &config) +{ + // Set the config's ID to a small number that starts at 1 ([EGL 1.5] section 3.4) + EGLint id = mConfigs.size() + 1; + + Config copyConfig(config); + copyConfig.configID = id; + mConfigs.insert(std::make_pair(id, copyConfig)); + + return id; +} + +const Config &ConfigSet::get(EGLint id) const +{ + ASSERT(mConfigs.find(id) != mConfigs.end()); + return mConfigs.find(id)->second; +} + +void ConfigSet::clear() +{ + mConfigs.clear(); +} + +size_t ConfigSet::size() const +{ + return mConfigs.size(); +} + +bool ConfigSet::contains(const Config *config) const +{ + for (auto i = mConfigs.begin(); i != mConfigs.end(); i++) + { + const Config &item = i->second; + if (config == &item) + { + return true; + } + } + + return false; +} + +// Function object used by STL sorting routines for ordering Configs according to [EGL 1.5] section 3.4.1.2 page 28. +class ConfigSorter +{ + public: + explicit ConfigSorter(const AttributeMap &attributeMap) + : mWantRed(false), + mWantGreen(false), + mWantBlue(false), + mWantAlpha(false), + mWantLuminance(false) + { + scanForWantedComponents(attributeMap); + } + + bool operator()(const Config *x, const Config *y) const + { + return (*this)(*x, *y); + } + + bool operator()(const Config &x, const Config &y) const + { + #define SORT(attribute) \ + if (x.attribute != y.attribute) \ + { \ + return x.attribute < y.attribute; \ + } + + static_assert(EGL_NONE < EGL_SLOW_CONFIG && EGL_SLOW_CONFIG < EGL_NON_CONFORMANT_CONFIG, "Unexpected EGL enum value."); + SORT(configCaveat); + + static_assert(EGL_RGB_BUFFER < EGL_LUMINANCE_BUFFER, "Unexpected EGL enum value."); + SORT(colorBufferType); + + // By larger total number of color bits, only considering those that are requested to be > 0. + EGLint xComponentsSize = wantedComponentsSize(x); + EGLint yComponentsSize = wantedComponentsSize(y); + if (xComponentsSize != yComponentsSize) + { + return xComponentsSize > yComponentsSize; + } + + SORT(bufferSize); + SORT(sampleBuffers); + SORT(samples); + SORT(depthSize); + SORT(stencilSize); + SORT(alphaMaskSize); + SORT(nativeVisualType); + SORT(configID); + + #undef SORT + + return false; + } + + private: + void scanForWantedComponents(const AttributeMap &attributeMap) + { + // [EGL 1.5] section 3.4.1.2 page 30 + // Sorting rule #3: by larger total number of color bits, not considering + // components that are 0 or don't-care. + for (auto attribIter = attributeMap.begin(); attribIter != attributeMap.end(); attribIter++) + { + EGLint attributeKey = attribIter->first; + EGLint attributeValue = attribIter->second; + if (attributeKey != 0 && attributeValue != EGL_DONT_CARE) + { + switch (attributeKey) + { + case EGL_RED_SIZE: mWantRed = true; break; + case EGL_GREEN_SIZE: mWantGreen = true; break; + case EGL_BLUE_SIZE: mWantBlue = true; break; + case EGL_ALPHA_SIZE: mWantAlpha = true; break; + case EGL_LUMINANCE_SIZE: mWantLuminance = true; break; + } + } + } + } + + EGLint wantedComponentsSize(const Config &config) const + { + EGLint total = 0; + + if (mWantRed) total += config.redSize; + if (mWantGreen) total += config.greenSize; + if (mWantBlue) total += config.blueSize; + if (mWantAlpha) total += config.alphaSize; + if (mWantLuminance) total += config.luminanceSize; + + return total; + } + + bool mWantRed; + bool mWantGreen; + bool mWantBlue; + bool mWantAlpha; + bool mWantLuminance; +}; + +std::vector ConfigSet::filter(const AttributeMap &attributeMap) const +{ + std::vector result; + result.reserve(mConfigs.size()); + + for (auto configIter = mConfigs.begin(); configIter != mConfigs.end(); configIter++) + { + const Config &config = configIter->second; + bool match = true; + + for (auto attribIter = attributeMap.begin(); attribIter != attributeMap.end(); attribIter++) + { + EGLint attributeKey = attribIter->first; + EGLint attributeValue = attribIter->second; + + switch (attributeKey) + { + case EGL_BUFFER_SIZE: match = config.bufferSize >= attributeValue; break; + case EGL_ALPHA_SIZE: match = config.alphaSize >= attributeValue; break; + case EGL_BLUE_SIZE: match = config.blueSize >= attributeValue; break; + case EGL_GREEN_SIZE: match = config.greenSize >= attributeValue; break; + case EGL_RED_SIZE: match = config.redSize >= attributeValue; break; + case EGL_DEPTH_SIZE: match = config.depthSize >= attributeValue; break; + case EGL_STENCIL_SIZE: match = config.stencilSize >= attributeValue; break; + case EGL_CONFIG_CAVEAT: match = config.configCaveat == (EGLenum)attributeValue; break; + case EGL_CONFIG_ID: match = config.configID == attributeValue; break; + case EGL_LEVEL: match = config.level >= attributeValue; break; + case EGL_NATIVE_RENDERABLE: match = config.nativeRenderable == (EGLBoolean)attributeValue; break; + case EGL_NATIVE_VISUAL_TYPE: match = config.nativeVisualType == attributeValue; break; + case EGL_SAMPLES: match = config.samples >= attributeValue; break; + case EGL_SAMPLE_BUFFERS: match = config.sampleBuffers >= attributeValue; break; + case EGL_SURFACE_TYPE: match = (config.surfaceType & attributeValue) == attributeValue; break; + case EGL_TRANSPARENT_TYPE: match = config.transparentType == (EGLenum)attributeValue; break; + case EGL_TRANSPARENT_BLUE_VALUE: match = config.transparentBlueValue == attributeValue; break; + case EGL_TRANSPARENT_GREEN_VALUE: match = config.transparentGreenValue == attributeValue; break; + case EGL_TRANSPARENT_RED_VALUE: match = config.transparentRedValue == attributeValue; break; + case EGL_BIND_TO_TEXTURE_RGB: match = config.bindToTextureRGB == (EGLBoolean)attributeValue; break; + case EGL_BIND_TO_TEXTURE_RGBA: match = config.bindToTextureRGBA == (EGLBoolean)attributeValue; break; + case EGL_MIN_SWAP_INTERVAL: match = config.minSwapInterval == attributeValue; break; + case EGL_MAX_SWAP_INTERVAL: match = config.maxSwapInterval == attributeValue; break; + case EGL_LUMINANCE_SIZE: match = config.luminanceSize >= attributeValue; break; + case EGL_ALPHA_MASK_SIZE: match = config.alphaMaskSize >= attributeValue; break; + case EGL_COLOR_BUFFER_TYPE: match = config.colorBufferType == (EGLenum)attributeValue; break; + case EGL_RENDERABLE_TYPE: match = (config.renderableType & attributeValue) == attributeValue; break; + case EGL_MATCH_NATIVE_PIXMAP: match = false; UNIMPLEMENTED(); break; + case EGL_CONFORMANT: match = (config.conformant & attributeValue) == attributeValue; break; + case EGL_MAX_PBUFFER_WIDTH: match = config.maxPBufferWidth >= attributeValue; break; + case EGL_MAX_PBUFFER_HEIGHT: match = config.maxPBufferHeight >= attributeValue; break; + case EGL_MAX_PBUFFER_PIXELS: match = config.maxPBufferPixels >= attributeValue; break; + default: UNREACHABLE(); + } + + if (!match) + { + break; + } + } + + if (match) + { + result.push_back(&config); + } + } + + // Sort the result + std::sort(result.begin(), result.end(), ConfigSorter(attributeMap)); + + return result; +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/Config.h b/src/3rdparty/angle/src/libANGLE/Config.h new file mode 100644 index 0000000000..aed8aedb1d --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/Config.h @@ -0,0 +1,91 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Config.h: Defines the egl::Config class, describing the format, type +// and size for an egl::Surface. Implements EGLConfig and related functionality. +// [EGL 1.5] section 3.4 page 19. + +#ifndef INCLUDE_CONFIG_H_ +#define INCLUDE_CONFIG_H_ + +#include "libANGLE/AttributeMap.h" + +#include "common/angleutils.h" + +#include +#include + +#include +#include + +namespace egl +{ + +struct Config +{ + Config(); + + GLenum renderTargetFormat; // TODO(geofflang): remove this + GLenum depthStencilFormat; // TODO(geofflang): remove this + + EGLint bufferSize; // Depth of the color buffer + EGLint redSize; // Bits of Red in the color buffer + EGLint greenSize; // Bits of Green in the color buffer + EGLint blueSize; // Bits of Blue in the color buffer + EGLint luminanceSize; // Bits of Luminance in the color buffer + EGLint alphaSize; // Bits of Alpha in the color buffer + EGLint alphaMaskSize; // Bits of Alpha Mask in the mask buffer + EGLBoolean bindToTextureRGB; // True if bindable to RGB textures. + EGLBoolean bindToTextureRGBA; // True if bindable to RGBA textures. + EGLenum colorBufferType; // Color buffer type + EGLenum configCaveat; // Any caveats for the configuration + EGLint configID; // Unique EGLConfig identifier + EGLint conformant; // Whether contexts created with this config are conformant + EGLint depthSize; // Bits of Z in the depth buffer + EGLint level; // Frame buffer level + EGLBoolean matchNativePixmap; // Match the native pixmap format + EGLint maxPBufferWidth; // Maximum width of pbuffer + EGLint maxPBufferHeight; // Maximum height of pbuffer + EGLint maxPBufferPixels; // Maximum size of pbuffer + EGLint maxSwapInterval; // Maximum swap interval + EGLint minSwapInterval; // Minimum swap interval + EGLBoolean nativeRenderable; // EGL_TRUE if native rendering APIs can render to surface + EGLint nativeVisualID; // Handle of corresponding native visual + EGLint nativeVisualType; // Native visual type of the associated visual + EGLint renderableType; // Which client rendering APIs are supported. + EGLint sampleBuffers; // Number of multisample buffers + EGLint samples; // Number of samples per pixel + EGLint stencilSize; // Bits of Stencil in the stencil buffer + EGLint surfaceType; // Which types of EGL surfaces are supported. + EGLenum transparentType; // Type of transparency supported + EGLint transparentRedValue; // Transparent red value + EGLint transparentGreenValue; // Transparent green value + EGLint transparentBlueValue; // Transparent blue value +}; + +class ConfigSet +{ + public: + EGLint add(const Config &config); + const Config &get(EGLint id) const; + + void clear(); + + size_t size() const; + + bool contains(const Config *config) const; + + // Filter configurations based on the table in [EGL 1.5] section 3.4.1.2 page 29 + std::vector filter(const AttributeMap &attributeMap) const; + + private: + typedef std::map ConfigMap; + ConfigMap mConfigs; +}; + +} + +#endif // INCLUDE_CONFIG_H_ diff --git a/src/3rdparty/angle/src/libANGLE/Constants.h b/src/3rdparty/angle/src/libANGLE/Constants.h new file mode 100644 index 0000000000..dc8f9555b8 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/Constants.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. +// + +// Contants.h: Defines some implementation specific and gl constants + +#ifndef LIBANGLE_CONSTANTS_H_ +#define LIBANGLE_CONSTANTS_H_ + +namespace gl +{ + +enum +{ + MAX_VERTEX_ATTRIBS = 16, + + // Implementation upper limits, real maximums depend on the hardware + IMPLEMENTATION_MAX_VARYING_VECTORS = 32, + IMPLEMENTATION_MAX_DRAW_BUFFERS = 8, + IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS = IMPLEMENTATION_MAX_DRAW_BUFFERS + 2, // 2 extra for depth and/or stencil buffers + + IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS = 16, + IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS = 16, + IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS = IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS + + IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS, + + IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS = 4, + + // These are the maximums the implementation can support + // The actual GL caps are limited by the device caps + // and should be queried from the Context + IMPLEMENTATION_MAX_2D_TEXTURE_SIZE = 16384, + IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE = 16384, + IMPLEMENTATION_MAX_3D_TEXTURE_SIZE = 2048, + IMPLEMENTATION_MAX_2D_ARRAY_TEXTURE_LAYERS = 2048, + + IMPLEMENTATION_MAX_TEXTURE_LEVELS = 15 // 1+log2 of MAX_TEXTURE_SIZE +}; + +} + +#endif // LIBANGLE_CONSTANTS_H_ diff --git a/src/3rdparty/angle/src/libANGLE/Context.cpp b/src/3rdparty/angle/src/libANGLE/Context.cpp new file mode 100644 index 0000000000..1da5fdae95 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/Context.cpp @@ -0,0 +1,1587 @@ +// +// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Context.cpp: Implements the gl::Context class, managing all GL state and performing +// rendering operations. It is the GLES2 specific implementation of EGLContext. + +#include "libANGLE/Context.h" + +#include +#include + +#include "common/platform.h" +#include "common/utilities.h" +#include "libANGLE/Buffer.h" +#include "libANGLE/Compiler.h" +#include "libANGLE/Display.h" +#include "libANGLE/Fence.h" +#include "libANGLE/Framebuffer.h" +#include "libANGLE/FramebufferAttachment.h" +#include "libANGLE/Program.h" +#include "libANGLE/Query.h" +#include "libANGLE/Renderbuffer.h" +#include "libANGLE/ResourceManager.h" +#include "libANGLE/Sampler.h" +#include "libANGLE/Surface.h" +#include "libANGLE/Texture.h" +#include "libANGLE/TransformFeedback.h" +#include "libANGLE/VertexArray.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/validationES.h" +#include "libANGLE/renderer/Renderer.h" + +namespace gl +{ + +Context::Context(const egl::Config *config, int clientVersion, const Context *shareContext, rx::Renderer *renderer, bool notifyResets, bool robustAccess) + : mRenderer(renderer) +{ + ASSERT(robustAccess == false); // Unimplemented + + initCaps(clientVersion); + mState.initialize(mCaps, clientVersion); + + mClientVersion = clientVersion; + + mConfigID = config->configID; + mClientType = EGL_OPENGL_ES_API; + mRenderBuffer = EGL_NONE; + + mFenceNVHandleAllocator.setBaseHandle(0); + + if (shareContext != NULL) + { + mResourceManager = shareContext->mResourceManager; + mResourceManager->addRef(); + } + else + { + mResourceManager = new ResourceManager(mRenderer); + } + + // [OpenGL ES 2.0.24] section 3.7 page 83: + // In the initial state, TEXTURE_2D and TEXTURE_CUBE_MAP have twodimensional + // and cube map texture state vectors respectively associated with them. + // In order that access to these initial textures not be lost, they are treated as texture + // objects all of whose names are 0. + + Texture *zeroTexture2D = new Texture(mRenderer->createTexture(GL_TEXTURE_2D), 0, GL_TEXTURE_2D); + mZeroTextures[GL_TEXTURE_2D].set(zeroTexture2D); + + Texture *zeroTextureCube = new Texture(mRenderer->createTexture(GL_TEXTURE_CUBE_MAP), 0, GL_TEXTURE_CUBE_MAP); + mZeroTextures[GL_TEXTURE_CUBE_MAP].set(zeroTextureCube); + + if (mClientVersion >= 3) + { + // TODO: These could also be enabled via extension + Texture *zeroTexture3D = new Texture(mRenderer->createTexture(GL_TEXTURE_3D), 0, GL_TEXTURE_3D); + mZeroTextures[GL_TEXTURE_3D].set(zeroTexture3D); + + Texture *zeroTexture2DArray = new Texture(mRenderer->createTexture(GL_TEXTURE_2D_ARRAY), 0, GL_TEXTURE_2D_ARRAY); + mZeroTextures[GL_TEXTURE_2D_ARRAY].set(zeroTexture2DArray); + } + + mState.initializeZeroTextures(mZeroTextures); + + bindVertexArray(0); + bindArrayBuffer(0); + bindElementArrayBuffer(0); + + bindReadFramebuffer(0); + bindDrawFramebuffer(0); + bindRenderbuffer(0); + + bindGenericUniformBuffer(0); + for (unsigned int i = 0; i < mCaps.maxCombinedUniformBlocks; i++) + { + bindIndexedUniformBuffer(0, i, 0, -1); + } + + bindGenericTransformFeedbackBuffer(0); + for (unsigned int i = 0; i < mCaps.maxTransformFeedbackSeparateAttributes; i++) + { + bindIndexedTransformFeedbackBuffer(0, i, 0, -1); + } + + bindCopyReadBuffer(0); + bindCopyWriteBuffer(0); + bindPixelPackBuffer(0); + bindPixelUnpackBuffer(0); + + // [OpenGL ES 3.0.2] section 2.14.1 pg 85: + // In the initial state, a default transform feedback object is bound and treated as + // a transform feedback object with a name of zero. That object is bound any time + // BindTransformFeedback is called with id of zero + mTransformFeedbackZero.set(new TransformFeedback(mRenderer->createTransformFeedback(), 0)); + bindTransformFeedback(0); + + mHasBeenCurrent = false; + mContextLost = false; + mResetStatus = GL_NO_ERROR; + mResetStrategy = (notifyResets ? GL_LOSE_CONTEXT_ON_RESET_EXT : GL_NO_RESET_NOTIFICATION_EXT); + mRobustAccess = robustAccess; + + mCompiler = new Compiler(mRenderer->createCompiler(getData())); +} + +Context::~Context() +{ + mState.reset(); + + while (!mFramebufferMap.empty()) + { + // Delete the framebuffer in reverse order to destroy the framebuffer zero last. + deleteFramebuffer(mFramebufferMap.rbegin()->first); + } + + while (!mFenceNVMap.empty()) + { + deleteFenceNV(mFenceNVMap.begin()->first); + } + + while (!mQueryMap.empty()) + { + deleteQuery(mQueryMap.begin()->first); + } + + while (!mVertexArrayMap.empty()) + { + deleteVertexArray(mVertexArrayMap.begin()->first); + } + + mTransformFeedbackZero.set(NULL); + while (!mTransformFeedbackMap.empty()) + { + deleteTransformFeedback(mTransformFeedbackMap.begin()->first); + } + + for (auto it = mZeroTextures.begin(); it != mZeroTextures.end(); ++it) + { + it->second.set(NULL); + } + mZeroTextures.clear(); + + if (mResourceManager) + { + mResourceManager->release(); + } + + SafeDelete(mCompiler); +} + +void Context::makeCurrent(egl::Surface *surface) +{ + if (!mHasBeenCurrent) + { + initRendererString(); + initExtensionStrings(); + + mState.setViewportParams(0, 0, surface->getWidth(), surface->getHeight()); + mState.setScissorParams(0, 0, surface->getWidth(), surface->getHeight()); + + mHasBeenCurrent = true; + } + + // TODO(jmadill): do not allocate new pointers here + Framebuffer *framebufferZero = new DefaultFramebuffer(mCaps, mRenderer, surface); + + setFramebufferZero(framebufferZero); + + mRenderBuffer = surface->getRenderBuffer(); +} + +// NOTE: this function should not assume that this context is current! +void Context::markContextLost() +{ + if (mResetStrategy == GL_LOSE_CONTEXT_ON_RESET_EXT) + mResetStatus = GL_UNKNOWN_CONTEXT_RESET_EXT; + mContextLost = true; +} + +bool Context::isContextLost() +{ + return mContextLost; +} + +GLuint Context::createBuffer() +{ + return mResourceManager->createBuffer(); +} + +GLuint Context::createProgram() +{ + return mResourceManager->createProgram(); +} + +GLuint Context::createShader(GLenum type) +{ + return mResourceManager->createShader(getData(), type); +} + +GLuint Context::createTexture() +{ + return mResourceManager->createTexture(); +} + +GLuint Context::createRenderbuffer() +{ + return mResourceManager->createRenderbuffer(); +} + +GLsync Context::createFenceSync() +{ + GLuint handle = mResourceManager->createFenceSync(); + + return reinterpret_cast(static_cast(handle)); +} + +GLuint Context::createVertexArray() +{ + GLuint handle = mVertexArrayHandleAllocator.allocate(); + + // Although the spec states VAO state is not initialized until the object is bound, + // we create it immediately. The resulting behaviour is transparent to the application, + // since it's not currently possible to access the state until the object is bound. + VertexArray *vertexArray = new VertexArray(mRenderer->createVertexArray(), handle, MAX_VERTEX_ATTRIBS); + mVertexArrayMap[handle] = vertexArray; + return handle; +} + +GLuint Context::createSampler() +{ + return mResourceManager->createSampler(); +} + +GLuint Context::createTransformFeedback() +{ + GLuint handle = mTransformFeedbackAllocator.allocate(); + TransformFeedback *transformFeedback = new TransformFeedback(mRenderer->createTransformFeedback(), handle); + transformFeedback->addRef(); + mTransformFeedbackMap[handle] = transformFeedback; + return handle; +} + +// Returns an unused framebuffer name +GLuint Context::createFramebuffer() +{ + GLuint handle = mFramebufferHandleAllocator.allocate(); + + mFramebufferMap[handle] = NULL; + + return handle; +} + +GLuint Context::createFenceNV() +{ + GLuint handle = mFenceNVHandleAllocator.allocate(); + + mFenceNVMap[handle] = new FenceNV(mRenderer->createFenceNV()); + + return handle; +} + +// Returns an unused query name +GLuint Context::createQuery() +{ + GLuint handle = mQueryHandleAllocator.allocate(); + + mQueryMap[handle] = NULL; + + return handle; +} + +void Context::deleteBuffer(GLuint buffer) +{ + if (mResourceManager->getBuffer(buffer)) + { + detachBuffer(buffer); + } + + mResourceManager->deleteBuffer(buffer); +} + +void Context::deleteShader(GLuint shader) +{ + mResourceManager->deleteShader(shader); +} + +void Context::deleteProgram(GLuint program) +{ + mResourceManager->deleteProgram(program); +} + +void Context::deleteTexture(GLuint texture) +{ + if (mResourceManager->getTexture(texture)) + { + detachTexture(texture); + } + + mResourceManager->deleteTexture(texture); +} + +void Context::deleteRenderbuffer(GLuint renderbuffer) +{ + if (mResourceManager->getRenderbuffer(renderbuffer)) + { + detachRenderbuffer(renderbuffer); + } + + mResourceManager->deleteRenderbuffer(renderbuffer); +} + +void Context::deleteFenceSync(GLsync fenceSync) +{ + // The spec specifies the underlying Fence object is not deleted until all current + // wait commands finish. However, since the name becomes invalid, we cannot query the fence, + // and since our API is currently designed for being called from a single thread, we can delete + // the fence immediately. + mResourceManager->deleteFenceSync(reinterpret_cast(fenceSync)); +} + +void Context::deleteVertexArray(GLuint vertexArray) +{ + auto vertexArrayObject = mVertexArrayMap.find(vertexArray); + + if (vertexArrayObject != mVertexArrayMap.end()) + { + detachVertexArray(vertexArray); + + mVertexArrayHandleAllocator.release(vertexArrayObject->first); + delete vertexArrayObject->second; + mVertexArrayMap.erase(vertexArrayObject); + } +} + +void Context::deleteSampler(GLuint sampler) +{ + if (mResourceManager->getSampler(sampler)) + { + detachSampler(sampler); + } + + mResourceManager->deleteSampler(sampler); +} + +void Context::deleteTransformFeedback(GLuint transformFeedback) +{ + auto iter = mTransformFeedbackMap.find(transformFeedback); + if (iter != mTransformFeedbackMap.end()) + { + detachTransformFeedback(transformFeedback); + mTransformFeedbackAllocator.release(transformFeedback); + iter->second->release(); + mTransformFeedbackMap.erase(iter); + } +} + +void Context::deleteFramebuffer(GLuint framebuffer) +{ + FramebufferMap::iterator framebufferObject = mFramebufferMap.find(framebuffer); + + if (framebufferObject != mFramebufferMap.end()) + { + detachFramebuffer(framebuffer); + + mFramebufferHandleAllocator.release(framebufferObject->first); + delete framebufferObject->second; + mFramebufferMap.erase(framebufferObject); + } +} + +void Context::deleteFenceNV(GLuint fence) +{ + FenceNVMap::iterator fenceObject = mFenceNVMap.find(fence); + + if (fenceObject != mFenceNVMap.end()) + { + mFenceNVHandleAllocator.release(fenceObject->first); + delete fenceObject->second; + mFenceNVMap.erase(fenceObject); + } +} + +void Context::deleteQuery(GLuint query) +{ + QueryMap::iterator queryObject = mQueryMap.find(query); + if (queryObject != mQueryMap.end()) + { + mQueryHandleAllocator.release(queryObject->first); + if (queryObject->second) + { + queryObject->second->release(); + } + mQueryMap.erase(queryObject); + } +} + +Buffer *Context::getBuffer(GLuint handle) +{ + return mResourceManager->getBuffer(handle); +} + +Shader *Context::getShader(GLuint handle) const +{ + return mResourceManager->getShader(handle); +} + +Program *Context::getProgram(GLuint handle) const +{ + return mResourceManager->getProgram(handle); +} + +Texture *Context::getTexture(GLuint handle) const +{ + return mResourceManager->getTexture(handle); +} + +Renderbuffer *Context::getRenderbuffer(GLuint handle) +{ + return mResourceManager->getRenderbuffer(handle); +} + +FenceSync *Context::getFenceSync(GLsync handle) const +{ + return mResourceManager->getFenceSync(reinterpret_cast(handle)); +} + +VertexArray *Context::getVertexArray(GLuint handle) const +{ + auto vertexArray = mVertexArrayMap.find(handle); + + if (vertexArray == mVertexArrayMap.end()) + { + return NULL; + } + else + { + return vertexArray->second; + } +} + +Sampler *Context::getSampler(GLuint handle) const +{ + return mResourceManager->getSampler(handle); +} + +TransformFeedback *Context::getTransformFeedback(GLuint handle) const +{ + if (handle == 0) + { + return mTransformFeedbackZero.get(); + } + else + { + TransformFeedbackMap::const_iterator iter = mTransformFeedbackMap.find(handle); + return (iter != mTransformFeedbackMap.end()) ? iter->second : NULL; + } +} + +bool Context::isSampler(GLuint samplerName) const +{ + return mResourceManager->isSampler(samplerName); +} + +void Context::bindArrayBuffer(unsigned int buffer) +{ + mResourceManager->checkBufferAllocation(buffer); + + mState.setArrayBufferBinding(getBuffer(buffer)); +} + +void Context::bindElementArrayBuffer(unsigned int buffer) +{ + mResourceManager->checkBufferAllocation(buffer); + + mState.getVertexArray()->setElementArrayBuffer(getBuffer(buffer)); +} + +void Context::bindTexture(GLenum target, GLuint handle) +{ + Texture *texture = NULL; + + if (handle == 0) + { + texture = mZeroTextures[target].get(); + } + else + { + mResourceManager->checkTextureAllocation(handle, target); + texture = getTexture(handle); + } + + ASSERT(texture); + + mState.setSamplerTexture(target, texture); +} + +void Context::bindReadFramebuffer(GLuint framebuffer) +{ + if (!getFramebuffer(framebuffer)) + { + mFramebufferMap[framebuffer] = new Framebuffer(mCaps, mRenderer, framebuffer); + } + + mState.setReadFramebufferBinding(getFramebuffer(framebuffer)); +} + +void Context::bindDrawFramebuffer(GLuint framebuffer) +{ + if (!getFramebuffer(framebuffer)) + { + mFramebufferMap[framebuffer] = new Framebuffer(mCaps, mRenderer, framebuffer); + } + + mState.setDrawFramebufferBinding(getFramebuffer(framebuffer)); +} + +void Context::bindRenderbuffer(GLuint renderbuffer) +{ + mResourceManager->checkRenderbufferAllocation(renderbuffer); + + mState.setRenderbufferBinding(getRenderbuffer(renderbuffer)); +} + +void Context::bindVertexArray(GLuint vertexArray) +{ + if (!getVertexArray(vertexArray)) + { + VertexArray *vertexArrayObject = new VertexArray(mRenderer->createVertexArray(), vertexArray, MAX_VERTEX_ATTRIBS); + mVertexArrayMap[vertexArray] = vertexArrayObject; + } + + mState.setVertexArrayBinding(getVertexArray(vertexArray)); +} + +void Context::bindSampler(GLuint textureUnit, GLuint sampler) +{ + ASSERT(textureUnit < mCaps.maxCombinedTextureImageUnits); + mResourceManager->checkSamplerAllocation(sampler); + + mState.setSamplerBinding(textureUnit, getSampler(sampler)); +} + +void Context::bindGenericUniformBuffer(GLuint buffer) +{ + mResourceManager->checkBufferAllocation(buffer); + + mState.setGenericUniformBufferBinding(getBuffer(buffer)); +} + +void Context::bindIndexedUniformBuffer(GLuint buffer, GLuint index, GLintptr offset, GLsizeiptr size) +{ + mResourceManager->checkBufferAllocation(buffer); + + mState.setIndexedUniformBufferBinding(index, getBuffer(buffer), offset, size); +} + +void Context::bindGenericTransformFeedbackBuffer(GLuint buffer) +{ + mResourceManager->checkBufferAllocation(buffer); + + mState.setGenericTransformFeedbackBufferBinding(getBuffer(buffer)); +} + +void Context::bindIndexedTransformFeedbackBuffer(GLuint buffer, GLuint index, GLintptr offset, GLsizeiptr size) +{ + mResourceManager->checkBufferAllocation(buffer); + + mState.setIndexedTransformFeedbackBufferBinding(index, getBuffer(buffer), offset, size); +} + +void Context::bindCopyReadBuffer(GLuint buffer) +{ + mResourceManager->checkBufferAllocation(buffer); + + mState.setCopyReadBufferBinding(getBuffer(buffer)); +} + +void Context::bindCopyWriteBuffer(GLuint buffer) +{ + mResourceManager->checkBufferAllocation(buffer); + + mState.setCopyWriteBufferBinding(getBuffer(buffer)); +} + +void Context::bindPixelPackBuffer(GLuint buffer) +{ + mResourceManager->checkBufferAllocation(buffer); + + mState.setPixelPackBufferBinding(getBuffer(buffer)); +} + +void Context::bindPixelUnpackBuffer(GLuint buffer) +{ + mResourceManager->checkBufferAllocation(buffer); + + mState.setPixelUnpackBufferBinding(getBuffer(buffer)); +} + +void Context::useProgram(GLuint program) +{ + mState.setProgram(getProgram(program)); +} + +void Context::bindTransformFeedback(GLuint transformFeedback) +{ + mState.setTransformFeedbackBinding(getTransformFeedback(transformFeedback)); +} + +Error Context::beginQuery(GLenum target, GLuint query) +{ + Query *queryObject = getQuery(query, true, target); + ASSERT(queryObject); + + // begin query + Error error = queryObject->begin(); + if (error.isError()) + { + return error; + } + + // set query as active for specified target only if begin succeeded + mState.setActiveQuery(target, queryObject); + + return Error(GL_NO_ERROR); +} + +Error Context::endQuery(GLenum target) +{ + Query *queryObject = mState.getActiveQuery(target); + ASSERT(queryObject); + + gl::Error error = queryObject->end(); + + // Always unbind the query, even if there was an error. This may delete the query object. + mState.setActiveQuery(target, NULL); + + return error; +} + +void Context::setFramebufferZero(Framebuffer *buffer) +{ + // First, check to see if the old default framebuffer + // was set for draw or read framebuffer, and change + // the bindings to point to the new one before deleting it. + if (mState.getDrawFramebuffer()->id() == 0) + { + mState.setDrawFramebufferBinding(buffer); + } + + if (mState.getReadFramebuffer()->id() == 0) + { + mState.setReadFramebufferBinding(buffer); + } + + delete mFramebufferMap[0]; + mFramebufferMap[0] = buffer; +} + +Framebuffer *Context::getFramebuffer(unsigned int handle) const +{ + FramebufferMap::const_iterator framebuffer = mFramebufferMap.find(handle); + + if (framebuffer == mFramebufferMap.end()) + { + return NULL; + } + else + { + return framebuffer->second; + } +} + +FenceNV *Context::getFenceNV(unsigned int handle) +{ + FenceNVMap::iterator fence = mFenceNVMap.find(handle); + + if (fence == mFenceNVMap.end()) + { + return NULL; + } + else + { + return fence->second; + } +} + +Query *Context::getQuery(unsigned int handle, bool create, GLenum type) +{ + QueryMap::iterator query = mQueryMap.find(handle); + + if (query == mQueryMap.end()) + { + return NULL; + } + else + { + if (!query->second && create) + { + query->second = new Query(mRenderer->createQuery(type), handle); + query->second->addRef(); + } + return query->second; + } +} + +Texture *Context::getTargetTexture(GLenum target) const +{ + ASSERT(ValidTextureTarget(this, target)); + + return getSamplerTexture(mState.getActiveSampler(), target); +} + +Texture *Context::getSamplerTexture(unsigned int sampler, GLenum type) const +{ + return mState.getSamplerTexture(sampler, type); +} + +Compiler *Context::getCompiler() const +{ + return mCompiler; +} + +void Context::getBooleanv(GLenum pname, GLboolean *params) +{ + switch (pname) + { + case GL_SHADER_COMPILER: *params = GL_TRUE; break; + case GL_CONTEXT_ROBUST_ACCESS_EXT: *params = mRobustAccess ? GL_TRUE : GL_FALSE; break; + default: + mState.getBooleanv(pname, params); + break; + } +} + +void Context::getFloatv(GLenum pname, GLfloat *params) +{ + // Queries about context capabilities and maximums are answered by Context. + // Queries about current GL state values are answered by State. + switch (pname) + { + case GL_ALIASED_LINE_WIDTH_RANGE: + params[0] = mCaps.minAliasedLineWidth; + params[1] = mCaps.maxAliasedLineWidth; + break; + case GL_ALIASED_POINT_SIZE_RANGE: + params[0] = mCaps.minAliasedPointSize; + params[1] = mCaps.maxAliasedPointSize; + break; + case GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT: + ASSERT(mExtensions.textureFilterAnisotropic); + *params = mExtensions.maxTextureAnisotropy; + break; + default: + mState.getFloatv(pname, params); + break; + } +} + +void Context::getIntegerv(GLenum pname, GLint *params) +{ + // Queries about context capabilities and maximums are answered by Context. + // Queries about current GL state values are answered by State. + + switch (pname) + { + case GL_MAX_VERTEX_ATTRIBS: *params = mCaps.maxVertexAttributes; break; + case GL_MAX_VERTEX_UNIFORM_VECTORS: *params = mCaps.maxVertexUniformVectors; break; + case GL_MAX_VERTEX_UNIFORM_COMPONENTS: *params = mCaps.maxVertexUniformComponents; break; + case GL_MAX_VARYING_VECTORS: *params = mCaps.maxVaryingVectors; break; + case GL_MAX_VARYING_COMPONENTS: *params = mCaps.maxVertexOutputComponents; break; + case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: *params = mCaps.maxCombinedTextureImageUnits; break; + case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: *params = mCaps.maxVertexTextureImageUnits; break; + case GL_MAX_TEXTURE_IMAGE_UNITS: *params = mCaps.maxTextureImageUnits; break; + case GL_MAX_FRAGMENT_UNIFORM_VECTORS: *params = mCaps.maxFragmentUniformVectors; break; + case GL_MAX_FRAGMENT_UNIFORM_COMPONENTS: *params = mCaps.maxFragmentInputComponents; break; + case GL_MAX_RENDERBUFFER_SIZE: *params = mCaps.maxRenderbufferSize; break; + case GL_MAX_COLOR_ATTACHMENTS_EXT: *params = mCaps.maxColorAttachments; break; + case GL_MAX_DRAW_BUFFERS_EXT: *params = mCaps.maxDrawBuffers; break; + //case GL_FRAMEBUFFER_BINDING: // now equivalent to GL_DRAW_FRAMEBUFFER_BINDING_ANGLE + case GL_SUBPIXEL_BITS: *params = 4; break; + case GL_MAX_TEXTURE_SIZE: *params = mCaps.max2DTextureSize; break; + case GL_MAX_CUBE_MAP_TEXTURE_SIZE: *params = mCaps.maxCubeMapTextureSize; break; + case GL_MAX_3D_TEXTURE_SIZE: *params = mCaps.max3DTextureSize; break; + case GL_MAX_ARRAY_TEXTURE_LAYERS: *params = mCaps.maxArrayTextureLayers; break; + case GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT: *params = mCaps.uniformBufferOffsetAlignment; break; + case GL_MAX_UNIFORM_BUFFER_BINDINGS: *params = mCaps.maxUniformBufferBindings; break; + case GL_MAX_VERTEX_UNIFORM_BLOCKS: *params = mCaps.maxVertexUniformBlocks; break; + case GL_MAX_FRAGMENT_UNIFORM_BLOCKS: *params = mCaps.maxFragmentUniformBlocks; break; + case GL_MAX_COMBINED_UNIFORM_BLOCKS: *params = mCaps.maxCombinedTextureImageUnits; break; + case GL_MAJOR_VERSION: *params = mClientVersion; break; + case GL_MINOR_VERSION: *params = 0; break; + case GL_MAX_ELEMENTS_INDICES: *params = mCaps.maxElementsIndices; break; + case GL_MAX_ELEMENTS_VERTICES: *params = mCaps.maxElementsVertices; break; + case GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS: *params = mCaps.maxTransformFeedbackInterleavedComponents; break; + case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS: *params = mCaps.maxTransformFeedbackSeparateAttributes; break; + case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS: *params = mCaps.maxTransformFeedbackSeparateComponents; break; + case GL_NUM_COMPRESSED_TEXTURE_FORMATS: *params = mCaps.compressedTextureFormats.size(); break; + case GL_MAX_SAMPLES_ANGLE: *params = mExtensions.maxSamples; break; + case GL_MAX_VIEWPORT_DIMS: + { + params[0] = mCaps.maxViewportWidth; + params[1] = mCaps.maxViewportHeight; + } + break; + case GL_COMPRESSED_TEXTURE_FORMATS: + std::copy(mCaps.compressedTextureFormats.begin(), mCaps.compressedTextureFormats.end(), params); + break; + case GL_RESET_NOTIFICATION_STRATEGY_EXT: + *params = mResetStrategy; + break; + case GL_NUM_SHADER_BINARY_FORMATS: + *params = mCaps.shaderBinaryFormats.size(); + break; + case GL_SHADER_BINARY_FORMATS: + std::copy(mCaps.shaderBinaryFormats.begin(), mCaps.shaderBinaryFormats.end(), params); + break; + case GL_NUM_PROGRAM_BINARY_FORMATS: + *params = mCaps.programBinaryFormats.size(); + break; + case GL_PROGRAM_BINARY_FORMATS: + std::copy(mCaps.programBinaryFormats.begin(), mCaps.programBinaryFormats.end(), params); + break; + case GL_NUM_EXTENSIONS: + *params = static_cast(mExtensionStrings.size()); + break; + default: + mState.getIntegerv(getData(), pname, params); + break; + } +} + +void Context::getInteger64v(GLenum pname, GLint64 *params) +{ + // Queries about context capabilities and maximums are answered by Context. + // Queries about current GL state values are answered by State. + switch (pname) + { + case GL_MAX_ELEMENT_INDEX: + *params = mCaps.maxElementIndex; + break; + case GL_MAX_UNIFORM_BLOCK_SIZE: + *params = mCaps.maxUniformBlockSize; + break; + case GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS: + *params = mCaps.maxCombinedVertexUniformComponents; + break; + case GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS: + *params = mCaps.maxCombinedFragmentUniformComponents; + break; + case GL_MAX_SERVER_WAIT_TIMEOUT: + *params = mCaps.maxServerWaitTimeout; + break; + default: + UNREACHABLE(); + break; + } +} + +bool Context::getIndexedIntegerv(GLenum target, GLuint index, GLint *data) +{ + // Queries about context capabilities and maximums are answered by Context. + // Queries about current GL state values are answered by State. + // Indexed integer queries all refer to current state, so this function is a + // mere passthrough. + return mState.getIndexedIntegerv(target, index, data); +} + +bool Context::getIndexedInteger64v(GLenum target, GLuint index, GLint64 *data) +{ + // Queries about context capabilities and maximums are answered by Context. + // Queries about current GL state values are answered by State. + // Indexed integer queries all refer to current state, so this function is a + // mere passthrough. + return mState.getIndexedInteger64v(target, index, data); +} + +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 + // if returned from Context::getIntegerv. Since this conversion is already implemented + // in the case that one calls glGetIntegerv to retrieve a float-typed state variable, we + // place DEPTH_CLEAR_VALUE with the floats. This should make no difference to the calling + // application. + switch (pname) + { + case GL_COMPRESSED_TEXTURE_FORMATS: + { + *type = GL_INT; + *numParams = mCaps.compressedTextureFormats.size(); + } + return true; + case GL_PROGRAM_BINARY_FORMATS_OES: + { + *type = GL_INT; + *numParams = mCaps.programBinaryFormats.size(); + } + return true; + case GL_SHADER_BINARY_FORMATS: + { + *type = GL_INT; + *numParams = mCaps.shaderBinaryFormats.size(); + } + return true; + + case GL_MAX_VERTEX_ATTRIBS: + case GL_MAX_VERTEX_UNIFORM_VECTORS: + case GL_MAX_VARYING_VECTORS: + case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: + case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: + case GL_MAX_TEXTURE_IMAGE_UNITS: + case GL_MAX_FRAGMENT_UNIFORM_VECTORS: + case GL_MAX_RENDERBUFFER_SIZE: + case GL_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: + //case GL_FRAMEBUFFER_BINDING: // equivalent to DRAW_FRAMEBUFFER_BINDING_ANGLE + case GL_DRAW_FRAMEBUFFER_BINDING_ANGLE: + case GL_READ_FRAMEBUFFER_BINDING_ANGLE: + case GL_RENDERBUFFER_BINDING: + case GL_CURRENT_PROGRAM: + case GL_PACK_ALIGNMENT: + case GL_PACK_REVERSE_ROW_ORDER_ANGLE: + case GL_UNPACK_ALIGNMENT: + case GL_GENERATE_MIPMAP_HINT: + case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES: + case GL_RED_BITS: + case GL_GREEN_BITS: + case GL_BLUE_BITS: + case GL_ALPHA_BITS: + case GL_DEPTH_BITS: + case GL_STENCIL_BITS: + case GL_ELEMENT_ARRAY_BUFFER_BINDING: + case GL_CULL_FACE_MODE: + case GL_FRONT_FACE: + case GL_ACTIVE_TEXTURE: + case GL_STENCIL_FUNC: + case GL_STENCIL_VALUE_MASK: + case GL_STENCIL_REF: + case GL_STENCIL_FAIL: + case GL_STENCIL_PASS_DEPTH_FAIL: + case GL_STENCIL_PASS_DEPTH_PASS: + case GL_STENCIL_BACK_FUNC: + case GL_STENCIL_BACK_VALUE_MASK: + case GL_STENCIL_BACK_REF: + case GL_STENCIL_BACK_FAIL: + case GL_STENCIL_BACK_PASS_DEPTH_FAIL: + case GL_STENCIL_BACK_PASS_DEPTH_PASS: + case GL_DEPTH_FUNC: + case GL_BLEND_SRC_RGB: + case GL_BLEND_SRC_ALPHA: + case GL_BLEND_DST_RGB: + case GL_BLEND_DST_ALPHA: + case GL_BLEND_EQUATION_RGB: + case GL_BLEND_EQUATION_ALPHA: + case GL_STENCIL_WRITEMASK: + case GL_STENCIL_BACK_WRITEMASK: + case GL_STENCIL_CLEAR_VALUE: + case GL_SUBPIXEL_BITS: + case GL_MAX_TEXTURE_SIZE: + case GL_MAX_CUBE_MAP_TEXTURE_SIZE: + case GL_SAMPLE_BUFFERS: + case GL_SAMPLES: + case GL_IMPLEMENTATION_COLOR_READ_TYPE: + case GL_IMPLEMENTATION_COLOR_READ_FORMAT: + case GL_TEXTURE_BINDING_2D: + case GL_TEXTURE_BINDING_CUBE_MAP: + case GL_RESET_NOTIFICATION_STRATEGY_EXT: + case GL_NUM_PROGRAM_BINARY_FORMATS_OES: + { + *type = GL_INT; + *numParams = 1; + } + return true; + case GL_MAX_SAMPLES_ANGLE: + { + if (mExtensions.framebufferMultisample) + { + *type = GL_INT; + *numParams = 1; + } + else + { + return false; + } + } + return true; + case GL_PIXEL_PACK_BUFFER_BINDING: + case GL_PIXEL_UNPACK_BUFFER_BINDING: + { + if (mExtensions.pixelBufferObject) + { + *type = GL_INT; + *numParams = 1; + } + else + { + return false; + } + } + return true; + case GL_MAX_VIEWPORT_DIMS: + { + *type = GL_INT; + *numParams = 2; + } + return true; + case GL_VIEWPORT: + case GL_SCISSOR_BOX: + { + *type = GL_INT; + *numParams = 4; + } + return true; + case GL_SHADER_COMPILER: + case GL_SAMPLE_COVERAGE_INVERT: + case GL_DEPTH_WRITEMASK: + case GL_CULL_FACE: // CULL_FACE through DITHER are natural to IsEnabled, + case GL_POLYGON_OFFSET_FILL: // but can be retrieved through the Get{Type}v queries. + case GL_SAMPLE_ALPHA_TO_COVERAGE: // For this purpose, they are treated here as bool-natural + case GL_SAMPLE_COVERAGE: + case GL_SCISSOR_TEST: + case GL_STENCIL_TEST: + case GL_DEPTH_TEST: + case GL_BLEND: + case GL_DITHER: + case GL_CONTEXT_ROBUST_ACCESS_EXT: + { + *type = GL_BOOL; + *numParams = 1; + } + return true; + case GL_COLOR_WRITEMASK: + { + *type = GL_BOOL; + *numParams = 4; + } + return true; + case GL_POLYGON_OFFSET_FACTOR: + case GL_POLYGON_OFFSET_UNITS: + case GL_SAMPLE_COVERAGE_VALUE: + case GL_DEPTH_CLEAR_VALUE: + case GL_LINE_WIDTH: + { + *type = GL_FLOAT; + *numParams = 1; + } + return true; + case GL_ALIASED_LINE_WIDTH_RANGE: + case GL_ALIASED_POINT_SIZE_RANGE: + case GL_DEPTH_RANGE: + { + *type = GL_FLOAT; + *numParams = 2; + } + return true; + case GL_COLOR_CLEAR_VALUE: + case GL_BLEND_COLOR: + { + *type = GL_FLOAT; + *numParams = 4; + } + return true; + case GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT: + if (!mExtensions.maxTextureAnisotropy) + { + return false; + } + *type = GL_FLOAT; + *numParams = 1; + return true; + } + + if (mClientVersion < 3) + { + return false; + } + + // Check for ES3.0+ parameter names + switch (pname) + { + case GL_MAX_UNIFORM_BUFFER_BINDINGS: + case GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT: + case GL_UNIFORM_BUFFER_BINDING: + case GL_TRANSFORM_FEEDBACK_BINDING: + case GL_COPY_READ_BUFFER_BINDING: + case GL_COPY_WRITE_BUFFER_BINDING: + case GL_TEXTURE_BINDING_3D: + case GL_TEXTURE_BINDING_2D_ARRAY: + case GL_MAX_3D_TEXTURE_SIZE: + case GL_MAX_ARRAY_TEXTURE_LAYERS: + case GL_MAX_VERTEX_UNIFORM_BLOCKS: + case GL_MAX_FRAGMENT_UNIFORM_BLOCKS: + case GL_MAX_COMBINED_UNIFORM_BLOCKS: + case GL_MAX_VARYING_COMPONENTS: + case GL_VERTEX_ARRAY_BINDING: + case GL_MAX_VERTEX_UNIFORM_COMPONENTS: + case GL_MAX_FRAGMENT_UNIFORM_COMPONENTS: + case GL_NUM_EXTENSIONS: + case GL_MAJOR_VERSION: + case GL_MINOR_VERSION: + case GL_MAX_ELEMENTS_INDICES: + case GL_MAX_ELEMENTS_VERTICES: + case GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS: + case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS: + case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS: + { + *type = GL_INT; + *numParams = 1; + } + return true; + + case GL_MAX_ELEMENT_INDEX: + case GL_MAX_UNIFORM_BLOCK_SIZE: + case GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS: + case GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS: + case GL_MAX_SERVER_WAIT_TIMEOUT: + { + *type = GL_INT_64_ANGLEX; + *numParams = 1; + } + return true; + + case GL_TRANSFORM_FEEDBACK_ACTIVE: + case GL_TRANSFORM_FEEDBACK_PAUSED: + { + *type = GL_BOOL; + *numParams = 1; + } + return true; + } + + return false; +} + +bool Context::getIndexedQueryParameterInfo(GLenum target, GLenum *type, unsigned int *numParams) +{ + if (mClientVersion < 3) + { + return false; + } + + switch (target) + { + case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: + case GL_UNIFORM_BUFFER_BINDING: + { + *type = GL_INT; + *numParams = 1; + } + return true; + case GL_TRANSFORM_FEEDBACK_BUFFER_START: + case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE: + case GL_UNIFORM_BUFFER_START: + case GL_UNIFORM_BUFFER_SIZE: + { + *type = GL_INT_64_ANGLEX; + *numParams = 1; + } + } + + return false; +} + +Error Context::drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instances) +{ + return mRenderer->drawArrays(getData(), mode, first, count, instances); +} + +Error Context::drawElements(GLenum mode, GLsizei count, GLenum type, + const GLvoid *indices, GLsizei instances, + const rx::RangeUI &indexRange) +{ + return mRenderer->drawElements(getData(), mode, count, type, indices, instances, indexRange); +} + +Error Context::flush() +{ + return mRenderer->flush(); +} + +Error Context::finish() +{ + return mRenderer->finish(); +} + +void Context::recordError(const Error &error) +{ + if (error.isError()) + { + mErrors.insert(error.getCode()); + } +} + +// Get one of the recorded errors and clear its flag, if any. +// [OpenGL ES 2.0.24] section 2.5 page 13. +GLenum Context::getError() +{ + if (mErrors.empty()) + { + return GL_NO_ERROR; + } + else + { + GLenum error = *mErrors.begin(); + mErrors.erase(mErrors.begin()); + return error; + } +} + +GLenum Context::getResetStatus() +{ + //TODO(jmadill): needs MANGLE reworking + if (mResetStatus == GL_NO_ERROR && !mContextLost) + { + // mResetStatus will be set by the markContextLost callback + // in the case a notification is sent + if (mRenderer->testDeviceLost()) + { + mRenderer->notifyDeviceLost(); + } + } + + GLenum status = mResetStatus; + + if (mResetStatus != GL_NO_ERROR) + { + ASSERT(mContextLost); + + if (mRenderer->testDeviceResettable()) + { + mResetStatus = GL_NO_ERROR; + } + } + + return status; +} + +bool Context::isResetNotificationEnabled() +{ + return (mResetStrategy == GL_LOSE_CONTEXT_ON_RESET_EXT); +} + +int Context::getClientVersion() const +{ + return mClientVersion; +} + +EGLint Context::getConfigID() const +{ + return mConfigID; +} + +EGLenum Context::getClientType() const +{ + return mClientType; +} + +EGLenum Context::getRenderBuffer() const +{ + return mRenderBuffer; +} + +const Caps &Context::getCaps() const +{ + return mCaps; +} + +const TextureCapsMap &Context::getTextureCaps() const +{ + return mTextureCaps; +} + +const Extensions &Context::getExtensions() const +{ + return mExtensions; +} + +void Context::detachTexture(GLuint texture) +{ + // Simple pass-through to State's detachTexture method, as textures do not require + // allocation map management either here or in the resource manager at detach time. + // Zero textures are held by the Context, and we don't attempt to request them from + // the State. + mState.detachTexture(mZeroTextures, texture); +} + +void Context::detachBuffer(GLuint buffer) +{ + // Buffer detachment is handled by Context, because the buffer must also be + // attached from any VAOs in existence, and Context holds the VAO map. + + // [OpenGL ES 2.0.24] section 2.9 page 22: + // If a buffer object is deleted while it is bound, all bindings to that object in the current context + // (i.e. in the thread that called Delete-Buffers) are reset to zero. + + mState.removeArrayBufferBinding(buffer); + + // mark as freed among the vertex array objects + for (auto vaoIt = mVertexArrayMap.begin(); vaoIt != mVertexArrayMap.end(); vaoIt++) + { + vaoIt->second->detachBuffer(buffer); + } +} + +void Context::detachFramebuffer(GLuint framebuffer) +{ + // Framebuffer detachment is handled by Context, because 0 is a valid + // Framebuffer object, and a pointer to it must be passed from Context + // to State at binding time. + + // [OpenGL ES 2.0.24] section 4.4 page 107: + // If a framebuffer that is currently bound to the target FRAMEBUFFER is deleted, it is as though + // BindFramebuffer had been executed with the target of FRAMEBUFFER and framebuffer of zero. + + if (mState.removeReadFramebufferBinding(framebuffer) && framebuffer != 0) + { + bindReadFramebuffer(0); + } + + if (mState.removeDrawFramebufferBinding(framebuffer) && framebuffer != 0) + { + bindDrawFramebuffer(0); + } +} + +void Context::detachRenderbuffer(GLuint renderbuffer) +{ + mState.detachRenderbuffer(renderbuffer); +} + +void Context::detachVertexArray(GLuint vertexArray) +{ + // Vertex array detachment is handled by Context, because 0 is a valid + // VAO, and a pointer to it must be passed from Context to State at + // binding time. + + // [OpenGL ES 3.0.2] section 2.10 page 43: + // If a vertex array object that is currently bound is deleted, the binding + // for that object reverts to zero and the default vertex array becomes current. + if (mState.removeVertexArrayBinding(vertexArray)) + { + bindVertexArray(0); + } +} + +void Context::detachTransformFeedback(GLuint transformFeedback) +{ + mState.detachTransformFeedback(transformFeedback); +} + +void Context::detachSampler(GLuint sampler) +{ + mState.detachSampler(sampler); +} + +void Context::setVertexAttribDivisor(GLuint index, GLuint divisor) +{ + mState.getVertexArray()->setVertexAttribDivisor(index, divisor); +} + +void Context::samplerParameteri(GLuint sampler, GLenum pname, GLint param) +{ + mResourceManager->checkSamplerAllocation(sampler); + + Sampler *samplerObject = getSampler(sampler); + ASSERT(samplerObject); + + switch (pname) + { + case GL_TEXTURE_MIN_FILTER: samplerObject->setMinFilter(static_cast(param)); break; + case GL_TEXTURE_MAG_FILTER: samplerObject->setMagFilter(static_cast(param)); break; + case GL_TEXTURE_WRAP_S: samplerObject->setWrapS(static_cast(param)); break; + case GL_TEXTURE_WRAP_T: samplerObject->setWrapT(static_cast(param)); break; + case GL_TEXTURE_WRAP_R: samplerObject->setWrapR(static_cast(param)); break; + case GL_TEXTURE_MIN_LOD: samplerObject->setMinLod(static_cast(param)); break; + case GL_TEXTURE_MAX_LOD: samplerObject->setMaxLod(static_cast(param)); break; + case GL_TEXTURE_COMPARE_MODE: samplerObject->setComparisonMode(static_cast(param)); break; + case GL_TEXTURE_COMPARE_FUNC: samplerObject->setComparisonFunc(static_cast(param)); break; + default: UNREACHABLE(); break; + } +} + +void Context::samplerParameterf(GLuint sampler, GLenum pname, GLfloat param) +{ + mResourceManager->checkSamplerAllocation(sampler); + + Sampler *samplerObject = getSampler(sampler); + ASSERT(samplerObject); + + switch (pname) + { + case GL_TEXTURE_MIN_FILTER: samplerObject->setMinFilter(uiround(param)); break; + case GL_TEXTURE_MAG_FILTER: samplerObject->setMagFilter(uiround(param)); break; + case GL_TEXTURE_WRAP_S: samplerObject->setWrapS(uiround(param)); break; + case GL_TEXTURE_WRAP_T: samplerObject->setWrapT(uiround(param)); break; + case GL_TEXTURE_WRAP_R: samplerObject->setWrapR(uiround(param)); break; + case GL_TEXTURE_MIN_LOD: samplerObject->setMinLod(param); break; + case GL_TEXTURE_MAX_LOD: samplerObject->setMaxLod(param); break; + case GL_TEXTURE_COMPARE_MODE: samplerObject->setComparisonMode(uiround(param)); break; + case GL_TEXTURE_COMPARE_FUNC: samplerObject->setComparisonFunc(uiround(param)); break; + default: UNREACHABLE(); break; + } +} + +GLint Context::getSamplerParameteri(GLuint sampler, GLenum pname) +{ + mResourceManager->checkSamplerAllocation(sampler); + + Sampler *samplerObject = getSampler(sampler); + ASSERT(samplerObject); + + switch (pname) + { + case GL_TEXTURE_MIN_FILTER: return static_cast(samplerObject->getMinFilter()); + case GL_TEXTURE_MAG_FILTER: return static_cast(samplerObject->getMagFilter()); + case GL_TEXTURE_WRAP_S: return static_cast(samplerObject->getWrapS()); + case GL_TEXTURE_WRAP_T: return static_cast(samplerObject->getWrapT()); + case GL_TEXTURE_WRAP_R: return static_cast(samplerObject->getWrapR()); + case GL_TEXTURE_MIN_LOD: return uiround(samplerObject->getMinLod()); + case GL_TEXTURE_MAX_LOD: return uiround(samplerObject->getMaxLod()); + case GL_TEXTURE_COMPARE_MODE: return static_cast(samplerObject->getComparisonMode()); + case GL_TEXTURE_COMPARE_FUNC: return static_cast(samplerObject->getComparisonFunc()); + default: UNREACHABLE(); return 0; + } +} + +GLfloat Context::getSamplerParameterf(GLuint sampler, GLenum pname) +{ + mResourceManager->checkSamplerAllocation(sampler); + + Sampler *samplerObject = getSampler(sampler); + ASSERT(samplerObject); + + switch (pname) + { + case GL_TEXTURE_MIN_FILTER: return static_cast(samplerObject->getMinFilter()); + case GL_TEXTURE_MAG_FILTER: return static_cast(samplerObject->getMagFilter()); + case GL_TEXTURE_WRAP_S: return static_cast(samplerObject->getWrapS()); + case GL_TEXTURE_WRAP_T: return static_cast(samplerObject->getWrapT()); + case GL_TEXTURE_WRAP_R: return static_cast(samplerObject->getWrapR()); + case GL_TEXTURE_MIN_LOD: return samplerObject->getMinLod(); + case GL_TEXTURE_MAX_LOD: return samplerObject->getMaxLod(); + case GL_TEXTURE_COMPARE_MODE: return static_cast(samplerObject->getComparisonMode()); + case GL_TEXTURE_COMPARE_FUNC: return static_cast(samplerObject->getComparisonFunc()); + default: UNREACHABLE(); return 0; + } +} + +void Context::initRendererString() +{ + std::ostringstream rendererString; + rendererString << "ANGLE ("; + rendererString << mRenderer->getRendererDescription(); + rendererString << ")"; + + mRendererString = MakeStaticString(rendererString.str()); +} + +const std::string &Context::getRendererString() const +{ + return mRendererString; +} + +void Context::initExtensionStrings() +{ + mExtensionStrings = mExtensions.getStrings(); + + std::ostringstream combinedStringStream; + std::copy(mExtensionStrings.begin(), mExtensionStrings.end(), std::ostream_iterator(combinedStringStream, " ")); + mExtensionString = combinedStringStream.str(); +} + +const std::string &Context::getExtensionString() const +{ + return mExtensionString; +} + +const std::string &Context::getExtensionString(size_t idx) const +{ + return mExtensionStrings[idx]; +} + +size_t Context::getExtensionStringCount() const +{ + return mExtensionStrings.size(); +} + +void Context::initCaps(GLuint clientVersion) +{ + mCaps = mRenderer->getRendererCaps(); + + mExtensions = mRenderer->getRendererExtensions(); + + if (clientVersion < 3) + { + // Disable ES3+ extensions + mExtensions.colorBufferFloat = false; + } + + if (clientVersion > 2) + { + // FIXME(geofflang): Don't support EXT_sRGB in non-ES2 contexts + //mExtensions.sRGB = false; + } + + // Apply implementation limits + mCaps.maxVertexAttributes = std::min(mCaps.maxVertexAttributes, MAX_VERTEX_ATTRIBS); + mCaps.maxVertexUniformBlocks = std::min(mCaps.maxVertexUniformBlocks, IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS); + mCaps.maxVertexOutputComponents = std::min(mCaps.maxVertexOutputComponents, IMPLEMENTATION_MAX_VARYING_VECTORS * 4); + + mCaps.maxFragmentInputComponents = std::min(mCaps.maxFragmentInputComponents, IMPLEMENTATION_MAX_VARYING_VECTORS * 4); + + GLuint maxSamples = 0; + mCaps.compressedTextureFormats.clear(); + + const TextureCapsMap &rendererFormats = mRenderer->getRendererTextureCaps(); + for (TextureCapsMap::const_iterator i = rendererFormats.begin(); i != rendererFormats.end(); i++) + { + GLenum format = i->first; + TextureCaps formatCaps = i->second; + + const InternalFormat &formatInfo = GetInternalFormatInfo(format); + + // Update the format caps based on the client version and extensions + formatCaps.texturable = formatInfo.textureSupport(clientVersion, mExtensions); + formatCaps.renderable = formatInfo.renderSupport(clientVersion, mExtensions); + formatCaps.filterable = formatInfo.filterSupport(clientVersion, mExtensions); + + // OpenGL ES does not support multisampling with integer formats + if (!formatInfo.renderSupport || formatInfo.componentType == GL_INT || formatInfo.componentType == GL_UNSIGNED_INT) + { + formatCaps.sampleCounts.clear(); + } + maxSamples = std::max(maxSamples, formatCaps.getMaxSamples()); + + if (formatCaps.texturable && formatInfo.compressed) + { + mCaps.compressedTextureFormats.push_back(format); + } + + mTextureCaps.insert(format, formatCaps); + } + + mExtensions.maxSamples = maxSamples; +} + +Data Context::getData() const +{ + return Data(mClientVersion, mState, mCaps, mTextureCaps, mExtensions, mResourceManager); +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/Context.h b/src/3rdparty/angle/src/libANGLE/Context.h new file mode 100644 index 0000000000..eeada43355 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/Context.h @@ -0,0 +1,277 @@ +// +// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Context.h: Defines the gl::Context class, managing all GL state and performing +// rendering operations. It is the GLES2 specific implementation of EGLContext. + +#ifndef LIBANGLE_CONTEXT_H_ +#define LIBANGLE_CONTEXT_H_ + +#include "common/angleutils.h" +#include "libANGLE/RefCountObject.h" +#include "libANGLE/Caps.h" +#include "libANGLE/Constants.h" +#include "libANGLE/Data.h" +#include "libANGLE/Error.h" +#include "libANGLE/HandleAllocator.h" +#include "libANGLE/VertexAttribute.h" +#include "libANGLE/angletypes.h" + +#include "angle_gl.h" + +#include +#include +#include + +namespace rx +{ +class Renderer; +} + +namespace egl +{ +class Surface; +struct Config; +} + +namespace gl +{ +class Compiler; +class Shader; +class Program; +class Texture; +class Framebuffer; +class Renderbuffer; +class FenceNV; +class FenceSync; +class Query; +class ResourceManager; +class Buffer; +struct VertexAttribute; +class VertexArray; +class Sampler; +class TransformFeedback; + +class Context final : angle::NonCopyable +{ + public: + Context(const egl::Config *config, int clientVersion, const Context *shareContext, rx::Renderer *renderer, bool notifyResets, bool robustAccess); + + virtual ~Context(); + + void makeCurrent(egl::Surface *surface); + + virtual void markContextLost(); + bool isContextLost(); + + // These create and destroy methods are merely pass-throughs to + // ResourceManager, which owns these object types + GLuint createBuffer(); + GLuint createShader(GLenum type); + GLuint createProgram(); + GLuint createTexture(); + GLuint createRenderbuffer(); + GLuint createSampler(); + GLuint createTransformFeedback(); + GLsync createFenceSync(); + + void deleteBuffer(GLuint buffer); + void deleteShader(GLuint shader); + void deleteProgram(GLuint program); + void deleteTexture(GLuint texture); + void deleteRenderbuffer(GLuint renderbuffer); + void deleteSampler(GLuint sampler); + void deleteTransformFeedback(GLuint transformFeedback); + void deleteFenceSync(GLsync fenceSync); + + // Framebuffers are owned by the Context, so these methods do not pass through + GLuint createFramebuffer(); + void deleteFramebuffer(GLuint framebuffer); + + // NV Fences are owned by the Context. + GLuint createFenceNV(); + void deleteFenceNV(GLuint fence); + + // Queries are owned by the Context; + GLuint createQuery(); + void deleteQuery(GLuint query); + + // Vertex arrays are owned by the Context + GLuint createVertexArray(); + void deleteVertexArray(GLuint vertexArray); + + void bindArrayBuffer(GLuint buffer); + void bindElementArrayBuffer(GLuint buffer); + void bindTexture(GLenum target, GLuint handle); + void bindReadFramebuffer(GLuint framebuffer); + void bindDrawFramebuffer(GLuint framebuffer); + void bindRenderbuffer(GLuint renderbuffer); + void bindVertexArray(GLuint vertexArray); + void bindSampler(GLuint textureUnit, GLuint sampler); + void bindGenericUniformBuffer(GLuint buffer); + void bindIndexedUniformBuffer(GLuint buffer, GLuint index, GLintptr offset, GLsizeiptr size); + void bindGenericTransformFeedbackBuffer(GLuint buffer); + void bindIndexedTransformFeedbackBuffer(GLuint buffer, GLuint index, GLintptr offset, GLsizeiptr size); + void bindCopyReadBuffer(GLuint buffer); + void bindCopyWriteBuffer(GLuint buffer); + void bindPixelPackBuffer(GLuint buffer); + void bindPixelUnpackBuffer(GLuint buffer); + void useProgram(GLuint program); + void bindTransformFeedback(GLuint transformFeedback); + + Error beginQuery(GLenum target, GLuint query); + Error endQuery(GLenum target); + + void setFramebufferZero(Framebuffer *framebuffer); + + void setVertexAttribDivisor(GLuint index, GLuint divisor); + + void samplerParameteri(GLuint sampler, GLenum pname, GLint param); + void samplerParameterf(GLuint sampler, GLenum pname, GLfloat param); + GLint getSamplerParameteri(GLuint sampler, GLenum pname); + GLfloat getSamplerParameterf(GLuint sampler, GLenum pname); + + Buffer *getBuffer(GLuint handle); + FenceNV *getFenceNV(GLuint handle); + FenceSync *getFenceSync(GLsync handle) const; + Shader *getShader(GLuint handle) const; + Program *getProgram(GLuint handle) const; + Texture *getTexture(GLuint handle) const; + Framebuffer *getFramebuffer(GLuint handle) const; + Renderbuffer *getRenderbuffer(GLuint handle); + VertexArray *getVertexArray(GLuint handle) const; + Sampler *getSampler(GLuint handle) const; + Query *getQuery(GLuint handle, bool create, GLenum type); + TransformFeedback *getTransformFeedback(GLuint handle) const; + + Texture *getTargetTexture(GLenum target) const; + Texture *getSamplerTexture(unsigned int sampler, GLenum type) const; + + Compiler *getCompiler() const; + + bool isSampler(GLuint samplerName) const; + + void getBooleanv(GLenum pname, GLboolean *params); + void getFloatv(GLenum pname, GLfloat *params); + void getIntegerv(GLenum pname, GLint *params); + void getInteger64v(GLenum pname, GLint64 *params); + + bool getIndexedIntegerv(GLenum target, GLuint index, GLint *data); + bool getIndexedInteger64v(GLenum target, GLuint index, GLint64 *data); + + bool getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *numParams); + bool getIndexedQueryParameterInfo(GLenum target, GLenum *type, unsigned int *numParams); + + Error drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instances); + Error drawElements(GLenum mode, GLsizei count, GLenum type, + const GLvoid *indices, GLsizei instances, + const rx::RangeUI &indexRange); + Error flush(); + Error finish(); + + void recordError(const Error &error); + + GLenum getError(); + GLenum getResetStatus(); + virtual bool isResetNotificationEnabled(); + + virtual int getClientVersion() const; + + EGLint getConfigID() const; + EGLenum getClientType() const; + EGLenum getRenderBuffer() const; + + const Caps &getCaps() const; + const TextureCapsMap &getTextureCaps() const; + const Extensions &getExtensions() const; + + const std::string &getRendererString() const; + + const std::string &getExtensionString() const; + const std::string &getExtensionString(size_t idx) const; + size_t getExtensionStringCount() const; + + rx::Renderer *getRenderer() { return mRenderer; } + + State &getState() { return mState; } + const State &getState() const { return mState; } + + Data getData() const; + + private: + void detachBuffer(GLuint buffer); + void detachTexture(GLuint texture); + void detachFramebuffer(GLuint framebuffer); + void detachRenderbuffer(GLuint renderbuffer); + void detachVertexArray(GLuint vertexArray); + void detachTransformFeedback(GLuint transformFeedback); + void detachSampler(GLuint sampler); + + void initRendererString(); + void initExtensionStrings(); + + void initCaps(GLuint clientVersion); + + // Caps to use for validation + Caps mCaps; + TextureCapsMap mTextureCaps; + Extensions mExtensions; + + // Shader compiler + Compiler *mCompiler; + + rx::Renderer *const mRenderer; + State mState; + + int mClientVersion; + + EGLint mConfigID; + EGLenum mClientType; + EGLenum mRenderBuffer; + + TextureMap mZeroTextures; + + typedef std::map FramebufferMap; + FramebufferMap mFramebufferMap; + HandleAllocator mFramebufferHandleAllocator; + + typedef std::map FenceNVMap; + FenceNVMap mFenceNVMap; + HandleAllocator mFenceNVHandleAllocator; + + typedef std::map QueryMap; + QueryMap mQueryMap; + HandleAllocator mQueryHandleAllocator; + + typedef std::map VertexArrayMap; + VertexArrayMap mVertexArrayMap; + HandleAllocator mVertexArrayHandleAllocator; + + BindingPointer mTransformFeedbackZero; + typedef std::map TransformFeedbackMap; + TransformFeedbackMap mTransformFeedbackMap; + HandleAllocator mTransformFeedbackAllocator; + + std::string mRendererString; + std::string mExtensionString; + std::vector mExtensionStrings; + + // Recorded errors + typedef std::set ErrorSet; + ErrorSet mErrors; + + // Current/lost context flags + bool mHasBeenCurrent; + bool mContextLost; + GLenum mResetStatus; + GLenum mResetStrategy; + bool mRobustAccess; + + ResourceManager *mResourceManager; +}; +} + +#endif // LIBANGLE_CONTEXT_H_ diff --git a/src/3rdparty/angle/src/libANGLE/Data.cpp b/src/3rdparty/angle/src/libANGLE/Data.cpp new file mode 100644 index 0000000000..7832e21b23 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/Data.cpp @@ -0,0 +1,51 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Data.cpp: Container class for all GL relevant state, caps and objects + +#include "libANGLE/Data.h" +#include "libANGLE/ResourceManager.h" + +namespace gl +{ + +Data::Data(GLint clientVersionIn, const State &stateIn, const Caps &capsIn, + const TextureCapsMap &textureCapsIn, const Extensions &extensionsIn, + const ResourceManager *resourceManagerIn) + : clientVersion(clientVersionIn), + state(&stateIn), + caps(&capsIn), + textureCaps(&textureCapsIn), + extensions(&extensionsIn), + resourceManager(resourceManagerIn) +{} + +Data::~Data() +{ +} + +Data::Data(const Data &other) + : clientVersion(other.clientVersion), + state(other.state), + caps(other.caps), + textureCaps(other.textureCaps), + extensions(other.extensions), + resourceManager(other.resourceManager) +{ +} + +Data &Data::operator=(const Data &other) +{ + clientVersion = other.clientVersion; + state = other.state; + caps = other.caps; + textureCaps = other.textureCaps; + extensions = other.extensions; + resourceManager = other.resourceManager; + return *this; +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/Data.h b/src/3rdparty/angle/src/libANGLE/Data.h new file mode 100644 index 0000000000..7eb6827dfc --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/Data.h @@ -0,0 +1,38 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Data.h: Container class for all GL relevant state, caps and objects + +#ifndef LIBANGLE_DATA_H_ +#define LIBANGLE_DATA_H_ + +#include "libANGLE/State.h" + +namespace gl +{ + +struct Data final +{ + public: + Data(GLint clientVersion, const State &state, const Caps &caps, + const TextureCapsMap &textureCaps, const Extensions &extensions, + const ResourceManager *resourceManager); + ~Data(); + + Data(const Data &other); + Data &operator=(const Data &other); + + GLint clientVersion; + const State *state; + const Caps *caps; + const TextureCapsMap *textureCaps; + const Extensions *extensions; + const ResourceManager *resourceManager; +}; + +} + +#endif // LIBANGLE_DATA_H_ diff --git a/src/3rdparty/angle/src/libANGLE/Display.cpp b/src/3rdparty/angle/src/libANGLE/Display.cpp new file mode 100644 index 0000000000..1f54f82dea --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/Display.cpp @@ -0,0 +1,675 @@ +// +// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Display.cpp: Implements the egl::Display class, representing the abstract +// display on which graphics are drawn. Implements EGLDisplay. +// [EGL 1.4] section 2.1.2 page 3. + +#include "libANGLE/Display.h" + +#include +#include +#include +#include +#include + +#include +#include + +#include "common/debug.h" +#include "common/mathutil.h" +#include "common/platform.h" +#include "libANGLE/Context.h" +#include "libANGLE/Surface.h" +#include "libANGLE/renderer/DisplayImpl.h" + +#if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_D3D11) +# include "libANGLE/renderer/d3d/DisplayD3D.h" +#endif + +#if defined(ANGLE_ENABLE_OPENGL) +# if defined(ANGLE_PLATFORM_WINDOWS) +# include "libANGLE/renderer/gl/wgl/DisplayWGL.h" +# else +# error Unsupported OpenGL platform. +# endif +#endif + +namespace egl +{ + +namespace +{ + +class DefaultPlatform : public angle::Platform +{ +public: + DefaultPlatform() {} + ~DefaultPlatform() override {} +}; + +DefaultPlatform *defaultPlatform = nullptr; + +void InitDefaultPlatformImpl() +{ + if (ANGLEPlatformCurrent() == nullptr) + { + if (defaultPlatform == nullptr) + { + defaultPlatform = new DefaultPlatform(); + } + + ANGLEPlatformInitialize(defaultPlatform); + } +} + +void DeinitDefaultPlatformImpl() +{ + if (defaultPlatform != nullptr) + { + if (ANGLEPlatformCurrent() == defaultPlatform) + { + ANGLEPlatformShutdown(); + } + + SafeDelete(defaultPlatform); + } +} + +typedef std::map WindowSurfaceMap; +// Get a map of all EGL window surfaces to validate that no window has more than one EGL surface +// associated with it. +static WindowSurfaceMap *GetWindowSurfaces() +{ + static WindowSurfaceMap windowSurfaces; + return &windowSurfaces; +} + +typedef std::map DisplayMap; +static DisplayMap *GetDisplayMap() +{ + static DisplayMap displays; + return &displays; +} + +rx::DisplayImpl *CreateDisplayImpl(const AttributeMap &attribMap) +{ + rx::DisplayImpl *impl = nullptr; + EGLint displayType = attribMap.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE); + switch (displayType) + { + case EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE: +#if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_D3D11) + // Default to D3D displays + impl = new rx::DisplayD3D(); +#else + // No display available + UNREACHABLE(); +#endif + break; + + case EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE: + case EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE: +#if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_D3D11) + impl = new rx::DisplayD3D(); +#else + // A D3D display was requested on a platform that doesn't support it + UNREACHABLE(); +#endif + break; + + case EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE: +#if defined(ANGLE_ENABLE_OPENGL) +#if defined(ANGLE_PLATFORM_WINDOWS) + impl = new rx::DisplayWGL(); +#else +#error Unsupported OpenGL platform. +#endif +#else + UNREACHABLE(); +#endif + break; + + default: + UNREACHABLE(); + break; + } + + ASSERT(impl != nullptr); + return impl; +} + +} + +Display *Display::getDisplay(EGLNativeDisplayType displayId, const AttributeMap &attribMap) +{ + // Initialize the global platform if not already + InitDefaultPlatformImpl(); + + Display *display = NULL; + + DisplayMap *displays = GetDisplayMap(); + DisplayMap::const_iterator iter = displays->find(displayId); + if (iter != displays->end()) + { + display = iter->second; + } + + if (display == nullptr) + { + // Validate the native display + if (!Display::isValidNativeDisplay(displayId)) + { + return NULL; + } + + display = new Display(displayId); + displays->insert(std::make_pair(displayId, display)); + } + + // Apply new attributes if the display is not initialized yet. + if (!display->isInitialized()) + { + rx::DisplayImpl* impl = CreateDisplayImpl(attribMap); + display->setAttributes(impl, attribMap); + } + + return display; +} + +Display::Display(EGLNativeDisplayType displayId) + : mImplementation(nullptr), + mDisplayId(displayId), + mAttributeMap(), + mConfigSet(), + mContextSet(), + mInitialized(false), + mCaps(), + mDisplayExtensions(), + mDisplayExtensionString(), + mVendorString() +{ +} + +Display::~Display() +{ + terminate(); + + DisplayMap *displays = GetDisplayMap(); + DisplayMap::iterator iter = displays->find(mDisplayId); + if (iter != displays->end()) + { + displays->erase(iter); + } + + SafeDelete(mImplementation); +} + +void Display::setAttributes(rx::DisplayImpl *impl, const AttributeMap &attribMap) +{ + ASSERT(!mInitialized); + + ASSERT(impl != nullptr); + SafeDelete(mImplementation); + mImplementation = impl; + + mAttributeMap = attribMap; +} + +Error Display::initialize() +{ + ASSERT(mImplementation != nullptr); + + if (isInitialized()) + { + return Error(EGL_SUCCESS); + } + + Error error = mImplementation->initialize(this); + if (error.isError()) + { + return error; + } + + mCaps = mImplementation->getCaps(); + + mConfigSet = mImplementation->generateConfigs(); + if (mConfigSet.size() == 0) + { + mImplementation->terminate(); + return Error(EGL_NOT_INITIALIZED); + } + + initDisplayExtensions(); + initVendorString(); + + mInitialized = true; + return Error(EGL_SUCCESS); +} + +void Display::terminate() +{ + makeCurrent(nullptr, nullptr, nullptr); + + while (!mContextSet.empty()) + { + destroyContext(*mContextSet.begin()); + } + + mConfigSet.clear(); + + mImplementation->terminate(); + mInitialized = false; + + // De-init default platform + DeinitDefaultPlatformImpl(); +} + +std::vector Display::getConfigs(const egl::AttributeMap &attribs) const +{ + return mConfigSet.filter(attribs); +} + +bool Display::getConfigAttrib(const Config *configuration, EGLint attribute, EGLint *value) +{ + switch (attribute) + { + case EGL_BUFFER_SIZE: *value = configuration->bufferSize; break; + case EGL_ALPHA_SIZE: *value = configuration->alphaSize; break; + case EGL_BLUE_SIZE: *value = configuration->blueSize; break; + case EGL_GREEN_SIZE: *value = configuration->greenSize; break; + case EGL_RED_SIZE: *value = configuration->redSize; break; + case EGL_DEPTH_SIZE: *value = configuration->depthSize; break; + case EGL_STENCIL_SIZE: *value = configuration->stencilSize; break; + case EGL_CONFIG_CAVEAT: *value = configuration->configCaveat; break; + case EGL_CONFIG_ID: *value = configuration->configID; break; + case EGL_LEVEL: *value = configuration->level; break; + case EGL_NATIVE_RENDERABLE: *value = configuration->nativeRenderable; break; + case EGL_NATIVE_VISUAL_TYPE: *value = configuration->nativeVisualType; break; + case EGL_SAMPLES: *value = configuration->samples; break; + case EGL_SAMPLE_BUFFERS: *value = configuration->sampleBuffers; break; + case EGL_SURFACE_TYPE: *value = configuration->surfaceType; break; + case EGL_TRANSPARENT_TYPE: *value = configuration->transparentType; break; + case EGL_TRANSPARENT_BLUE_VALUE: *value = configuration->transparentBlueValue; break; + case EGL_TRANSPARENT_GREEN_VALUE: *value = configuration->transparentGreenValue; break; + case EGL_TRANSPARENT_RED_VALUE: *value = configuration->transparentRedValue; break; + case EGL_BIND_TO_TEXTURE_RGB: *value = configuration->bindToTextureRGB; break; + case EGL_BIND_TO_TEXTURE_RGBA: *value = configuration->bindToTextureRGBA; break; + case EGL_MIN_SWAP_INTERVAL: *value = configuration->minSwapInterval; break; + case EGL_MAX_SWAP_INTERVAL: *value = configuration->maxSwapInterval; break; + case EGL_LUMINANCE_SIZE: *value = configuration->luminanceSize; break; + case EGL_ALPHA_MASK_SIZE: *value = configuration->alphaMaskSize; break; + case EGL_COLOR_BUFFER_TYPE: *value = configuration->colorBufferType; break; + case EGL_RENDERABLE_TYPE: *value = configuration->renderableType; break; + case EGL_MATCH_NATIVE_PIXMAP: *value = false; UNIMPLEMENTED(); break; + case EGL_CONFORMANT: *value = configuration->conformant; break; + case EGL_MAX_PBUFFER_WIDTH: *value = configuration->maxPBufferWidth; break; + case EGL_MAX_PBUFFER_HEIGHT: *value = configuration->maxPBufferHeight; break; + case EGL_MAX_PBUFFER_PIXELS: *value = configuration->maxPBufferPixels; break; + default: + return false; + } + + return true; +} + +Error Display::createWindowSurface(const Config *configuration, EGLNativeWindowType window, const AttributeMap &attribs, + Surface **outSurface) +{ + if (mImplementation->testDeviceLost()) + { + Error error = restoreLostDevice(); + if (error.isError()) + { + return error; + } + } + + rx::SurfaceImpl *surfaceImpl = nullptr; + Error error = mImplementation->createWindowSurface(configuration, window, attribs, &surfaceImpl); + if (error.isError()) + { + return error; + } + + ASSERT(surfaceImpl != nullptr); + Surface *surface = new Surface(surfaceImpl, EGL_WINDOW_BIT, configuration, attribs); + mImplementation->getSurfaceSet().insert(surface); + + WindowSurfaceMap *windowSurfaces = GetWindowSurfaces(); + ASSERT(windowSurfaces && windowSurfaces->find(window) == windowSurfaces->end()); + windowSurfaces->insert(std::make_pair(window, surface)); + + ASSERT(outSurface != nullptr); + *outSurface = surface; + return Error(EGL_SUCCESS); +} + +Error Display::createPbufferSurface(const Config *configuration, const AttributeMap &attribs, Surface **outSurface) +{ + ASSERT(isInitialized()); + + if (mImplementation->testDeviceLost()) + { + Error error = restoreLostDevice(); + if (error.isError()) + { + return error; + } + } + + rx::SurfaceImpl *surfaceImpl = nullptr; + Error error = mImplementation->createPbufferSurface(configuration, attribs, &surfaceImpl); + if (error.isError()) + { + return error; + } + + ASSERT(surfaceImpl != nullptr); + Surface *surface = new Surface(surfaceImpl, EGL_PBUFFER_BIT, configuration, attribs); + mImplementation->getSurfaceSet().insert(surface); + + ASSERT(outSurface != nullptr); + *outSurface = surface; + return Error(EGL_SUCCESS); +} + +Error Display::createPbufferFromClientBuffer(const Config *configuration, EGLClientBuffer shareHandle, + const AttributeMap &attribs, Surface **outSurface) +{ + ASSERT(isInitialized()); + + if (mImplementation->testDeviceLost()) + { + Error error = restoreLostDevice(); + if (error.isError()) + { + return error; + } + } + + rx::SurfaceImpl *surfaceImpl = nullptr; + Error error = mImplementation->createPbufferFromClientBuffer(configuration, shareHandle, attribs, &surfaceImpl); + if (error.isError()) + { + return error; + } + + ASSERT(surfaceImpl != nullptr); + Surface *surface = new Surface(surfaceImpl, EGL_PBUFFER_BIT, configuration, attribs); + mImplementation->getSurfaceSet().insert(surface); + + ASSERT(outSurface != nullptr); + *outSurface = surface; + return Error(EGL_SUCCESS); +} + +Error Display::createPixmapSurface(const Config *configuration, NativePixmapType nativePixmap, const AttributeMap &attribs, + Surface **outSurface) +{ + ASSERT(isInitialized()); + + if (mImplementation->testDeviceLost()) + { + Error error = restoreLostDevice(); + if (error.isError()) + { + return error; + } + } + + rx::SurfaceImpl *surfaceImpl = nullptr; + Error error = mImplementation->createPixmapSurface(configuration, nativePixmap, attribs, &surfaceImpl); + if (error.isError()) + { + return error; + } + + ASSERT(surfaceImpl != nullptr); + Surface *surface = new Surface(surfaceImpl, EGL_PIXMAP_BIT, configuration, attribs); + mImplementation->getSurfaceSet().insert(surface); + + ASSERT(outSurface != nullptr); + *outSurface = surface; + return Error(EGL_SUCCESS); +} + +Error Display::createContext(const Config *configuration, gl::Context *shareContext, const AttributeMap &attribs, + gl::Context **outContext) +{ + ASSERT(isInitialized()); + + if (mImplementation->testDeviceLost()) + { + Error error = restoreLostDevice(); + if (error.isError()) + { + return error; + } + } + + gl::Context *context = nullptr; + Error error = mImplementation->createContext(configuration, shareContext, attribs, &context); + if (error.isError()) + { + return error; + } + + ASSERT(context != nullptr); + mContextSet.insert(context); + + ASSERT(outContext != nullptr); + *outContext = context; + return Error(EGL_SUCCESS); +} + +Error Display::makeCurrent(egl::Surface *drawSurface, egl::Surface *readSurface, gl::Context *context) +{ + Error error = mImplementation->makeCurrent(drawSurface, readSurface, context); + if (error.isError()) + { + return error; + } + + if (context && drawSurface) + { + context->makeCurrent(drawSurface); + } + + return egl::Error(EGL_SUCCESS); +} + +Error Display::restoreLostDevice() +{ + for (ContextSet::iterator ctx = mContextSet.begin(); ctx != mContextSet.end(); ctx++) + { + if ((*ctx)->isResetNotificationEnabled()) + { + // If reset notifications have been requested, application must delete all contexts first + return Error(EGL_CONTEXT_LOST); + } + } + + return mImplementation->restoreLostDevice(); +} + +void Display::destroySurface(Surface *surface) +{ + if (surface->getType() == EGL_WINDOW_BIT) + { + WindowSurfaceMap *windowSurfaces = GetWindowSurfaces(); + ASSERT(windowSurfaces); + + bool surfaceRemoved = false; + for (WindowSurfaceMap::iterator iter = windowSurfaces->begin(); iter != windowSurfaces->end(); iter++) + { + if (iter->second == surface) + { + windowSurfaces->erase(iter); + surfaceRemoved = true; + break; + } + } + + ASSERT(surfaceRemoved); + } + + mImplementation->destroySurface(surface); +} + +void Display::destroyContext(gl::Context *context) +{ + mContextSet.erase(context); + SafeDelete(context); +} + +bool Display::isDeviceLost() const +{ + ASSERT(isInitialized()); + return mImplementation->isDeviceLost(); +} + +bool Display::testDeviceLost() +{ + ASSERT(isInitialized()); + return mImplementation->testDeviceLost(); +} + +void Display::notifyDeviceLost() +{ + for (ContextSet::iterator context = mContextSet.begin(); context != mContextSet.end(); context++) + { + (*context)->markContextLost(); + } +} + +const Caps &Display::getCaps() const +{ + return mCaps; +} + +bool Display::isInitialized() const +{ + return mInitialized; +} + +bool Display::isValidConfig(const Config *config) const +{ + return mConfigSet.contains(config); +} + +bool Display::isValidContext(gl::Context *context) const +{ + return mContextSet.find(context) != mContextSet.end(); +} + +bool Display::isValidSurface(Surface *surface) const +{ + return mImplementation->getSurfaceSet().find(surface) != mImplementation->getSurfaceSet().end(); +} + +bool Display::hasExistingWindowSurface(EGLNativeWindowType window) +{ + WindowSurfaceMap *windowSurfaces = GetWindowSurfaces(); + ASSERT(windowSurfaces); + + return windowSurfaces->find(window) != windowSurfaces->end(); +} + +static ClientExtensions GenerateClientExtensions() +{ + ClientExtensions extensions; + + extensions.clientExtensions = true; + extensions.platformBase = true; + extensions.platformANGLE = true; + +#if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_D3D11) + extensions.platformANGLED3D = true; +#endif + +#if defined(ANGLE_ENABLE_OPENGL) + extensions.platformANGLEOpenGL = true; +#endif + + return extensions; +} + +template +static std::string GenerateExtensionsString(const T &extensions) +{ + std::vector extensionsVector = extensions.getStrings(); + + std::ostringstream stream; + std::copy(extensionsVector.begin(), extensionsVector.end(), std::ostream_iterator(stream, " ")); + return stream.str(); +} + +const ClientExtensions &Display::getClientExtensions() +{ + static const ClientExtensions clientExtensions = GenerateClientExtensions(); + return clientExtensions; +} + +const std::string &Display::getClientExtensionString() +{ + static const std::string clientExtensionsString = GenerateExtensionsString(getClientExtensions()); + return clientExtensionsString; +} + +void Display::initDisplayExtensions() +{ + mDisplayExtensions = mImplementation->getExtensions(); + mDisplayExtensionString = GenerateExtensionsString(mDisplayExtensions); +} + +bool Display::isValidNativeWindow(EGLNativeWindowType window) const +{ + return mImplementation->isValidNativeWindow(window); +} + +bool Display::isValidNativeDisplay(EGLNativeDisplayType display) +{ + // TODO(jmadill): handle this properly + if (display == EGL_DEFAULT_DISPLAY) + { + return true; + } + +#if defined(ANGLE_PLATFORM_WINDOWS) && !defined(ANGLE_ENABLE_WINDOWS_STORE) + if (display == EGL_SOFTWARE_DISPLAY_ANGLE || + display == EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE || + display == EGL_D3D11_ONLY_DISPLAY_ANGLE) + { + return true; + } + return (WindowFromDC(display) != NULL); +#else + return true; +#endif +} + +void Display::initVendorString() +{ + mVendorString = mImplementation->getVendorString(); +} + +const DisplayExtensions &Display::getExtensions() const +{ + return mDisplayExtensions; +} + +const std::string &Display::getExtensionString() const +{ + return mDisplayExtensionString; +} + +const std::string &Display::getVendorString() const +{ + return mVendorString; +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/Display.h b/src/3rdparty/angle/src/libANGLE/Display.h new file mode 100644 index 0000000000..5ab3f9c0e9 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/Display.h @@ -0,0 +1,124 @@ +// +// 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. +// + +// Display.h: Defines the egl::Display class, representing the abstract +// display on which graphics are drawn. Implements EGLDisplay. +// [EGL 1.4] section 2.1.2 page 3. + +#ifndef LIBANGLE_DISPLAY_H_ +#define LIBANGLE_DISPLAY_H_ + +#include +#include + +#include "libANGLE/Error.h" +#include "libANGLE/Caps.h" +#include "libANGLE/Config.h" +#include "libANGLE/AttributeMap.h" + +namespace gl +{ +class Context; +} + +namespace rx +{ +class DisplayImpl; +} + +namespace egl +{ +class Surface; + +class Display final : angle::NonCopyable +{ + public: + ~Display(); + + Error initialize(); + void terminate(); + + static egl::Display *getDisplay(EGLNativeDisplayType displayId, const AttributeMap &attribMap); + + static const ClientExtensions &getClientExtensions(); + static const std::string &getClientExtensionString(); + + std::vector getConfigs(const egl::AttributeMap &attribs) const; + bool getConfigAttrib(const Config *configuration, EGLint attribute, EGLint *value); + + Error createWindowSurface(const Config *configuration, EGLNativeWindowType window, const AttributeMap &attribs, + Surface **outSurface); + Error createPbufferSurface(const Config *configuration, const AttributeMap &attribs, Surface **outSurface); + Error createPbufferFromClientBuffer(const Config *configuration, EGLClientBuffer shareHandle, const AttributeMap &attribs, + Surface **outSurface); + Error createPixmapSurface(const Config *configuration, NativePixmapType nativePixmap, const AttributeMap &attribs, + Surface **outSurface); + + Error createContext(const Config *configuration, gl::Context *shareContext, const AttributeMap &attribs, + gl::Context **outContext); + + Error makeCurrent(egl::Surface *drawSurface, egl::Surface *readSurface, gl::Context *context); + + void destroySurface(egl::Surface *surface); + void destroyContext(gl::Context *context); + + bool isInitialized() const; + bool isValidConfig(const Config *config) const; + bool isValidContext(gl::Context *context) const; + bool isValidSurface(egl::Surface *surface) const; + bool isValidNativeWindow(EGLNativeWindowType window) const; + + static bool isValidNativeDisplay(EGLNativeDisplayType display); + static bool hasExistingWindowSurface(EGLNativeWindowType window); + + bool isDeviceLost() const; + bool testDeviceLost(); + void notifyDeviceLost(); + + const Caps &getCaps() const; + + const DisplayExtensions &getExtensions() const; + const std::string &getExtensionString() const; + const std::string &getVendorString() const; + + const AttributeMap &getAttributeMap() const { return mAttributeMap; } + EGLNativeDisplayType getNativeDisplayId() const { return mDisplayId; } + + rx::DisplayImpl *getImplementation() { return mImplementation; } + + private: + Display(EGLNativeDisplayType displayId); + + void setAttributes(rx::DisplayImpl *impl, const AttributeMap &attribMap); + + Error restoreLostDevice(); + + void initDisplayExtensions(); + void initVendorString(); + + rx::DisplayImpl *mImplementation; + + EGLNativeDisplayType mDisplayId; + AttributeMap mAttributeMap; + + ConfigSet mConfigSet; + + typedef std::set ContextSet; + ContextSet mContextSet; + + bool mInitialized; + + Caps mCaps; + + DisplayExtensions mDisplayExtensions; + std::string mDisplayExtensionString; + + std::string mVendorString; +}; + +} + +#endif // LIBANGLE_DISPLAY_H_ diff --git a/src/3rdparty/angle/src/libANGLE/Error.cpp b/src/3rdparty/angle/src/libANGLE/Error.cpp new file mode 100644 index 0000000000..e17f26bec4 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/Error.cpp @@ -0,0 +1,86 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Error.cpp: Implements the egl::Error and gl::Error classes which encapsulate API errors +// and optional error messages. + +#include "libANGLE/Error.h" + +#include "common/angleutils.h" + +#include + +namespace gl +{ + +Error::Error(GLenum errorCode, const char *msg, ...) + : mCode(errorCode), + mMessage(nullptr) +{ + va_list vararg; + va_start(vararg, msg); + createMessageString(); + *mMessage = FormatString(msg, vararg); + va_end(vararg); +} + +void Error::createMessageString() const +{ + if (mMessage == nullptr) + { + mMessage = new std::string(); + } +} + +const std::string &Error::getMessage() const +{ + createMessageString(); + return *mMessage; +} + +} + +namespace egl +{ + +Error::Error(EGLint errorCode, const char *msg, ...) + : mCode(errorCode), + mID(0), + mMessage(nullptr) +{ + va_list vararg; + va_start(vararg, msg); + createMessageString(); + *mMessage = FormatString(msg, vararg); + va_end(vararg); +} + +Error::Error(EGLint errorCode, EGLint id, const char *msg, ...) + : mCode(errorCode), + mID(id), + mMessage(nullptr) +{ + va_list vararg; + va_start(vararg, msg); + createMessageString(); + *mMessage = FormatString(msg, vararg); + va_end(vararg); +} +void Error::createMessageString() const +{ + if (mMessage == nullptr) + { + mMessage = new std::string(); + } +} + +const std::string &Error::getMessage() const +{ + createMessageString(); + return *mMessage; +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/Error.h b/src/3rdparty/angle/src/libANGLE/Error.h new file mode 100644 index 0000000000..896b777567 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/Error.h @@ -0,0 +1,83 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Error.h: Defines the egl::Error and gl::Error classes which encapsulate API errors +// and optional error messages. + +#ifndef LIBANGLE_ERROR_H_ +#define LIBANGLE_ERROR_H_ + +#include "angle_gl.h" +#include "common/platform.h" +#include + +#include + +namespace gl +{ + +class Error final +{ + public: + explicit inline Error(GLenum errorCode); + Error(GLenum errorCode, const char *msg, ...); + inline Error(const Error &other); + inline Error(Error &&other); + + inline ~Error(); + + inline Error &operator=(const Error &other); + inline Error &operator=(Error &&other); + + inline GLenum getCode() const; + inline bool isError() const; + + const std::string &getMessage() const; + + private: + void createMessageString() const; + + GLenum mCode; + mutable std::string *mMessage; +}; + +} + +namespace egl +{ + +class Error final +{ + public: + explicit inline Error(EGLint errorCode); + Error(EGLint errorCode, const char *msg, ...); + Error(EGLint errorCode, EGLint id, const char *msg, ...); + inline Error(const Error &other); + inline Error(Error &&other); + + inline ~Error(); + + inline Error &operator=(const Error &other); + inline Error &operator=(Error &&other); + + inline EGLint getCode() const; + inline EGLint getID() const; + inline bool isError() const; + + const std::string &getMessage() const; + + private: + void createMessageString() const; + + EGLint mCode; + EGLint mID; + mutable std::string *mMessage; +}; + +} + +#include "Error.inl" + +#endif // LIBANGLE_ERROR_H_ diff --git a/src/3rdparty/angle/src/libANGLE/Error.inl b/src/3rdparty/angle/src/libANGLE/Error.inl new file mode 100644 index 0000000000..32e8f05828 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/Error.inl @@ -0,0 +1,163 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Error.inl: Inline definitions of egl::Error and gl::Error classes which encapsulate API errors +// and optional error messages. + +#include "common/angleutils.h" + +#include + +namespace gl +{ + +Error::Error(GLenum errorCode) + : mCode(errorCode), + mMessage(nullptr) +{ +} + +Error::Error(const Error &other) + : mCode(other.mCode), + mMessage(nullptr) +{ + if (other.mMessage != nullptr) + { + createMessageString(); + *mMessage = *(other.mMessage); + } +} + +Error::Error(Error &&other) + : mCode(other.mCode), + mMessage(other.mMessage) +{ + other.mMessage = nullptr; +} + +Error::~Error() +{ + SafeDelete(mMessage); +} + +Error &Error::operator=(const Error &other) +{ + mCode = other.mCode; + + if (other.mMessage != nullptr) + { + createMessageString(); + *mMessage = *(other.mMessage); + } + else + { + SafeDelete(mMessage); + } + + return *this; +} + +Error &Error::operator=(Error &&other) +{ + mCode = other.mCode; + mMessage = other.mMessage; + + other.mMessage = nullptr; + + return *this; +} + +GLenum Error::getCode() const +{ + return mCode; +} + +bool Error::isError() const +{ + return (mCode != GL_NO_ERROR); +} + +} + +namespace egl +{ + +Error::Error(EGLint errorCode) + : mCode(errorCode), + mID(0), + mMessage(nullptr) +{ +} + +Error::Error(const Error &other) + : mCode(other.mCode), + mID(other.mID), + mMessage(nullptr) +{ + if (other.mMessage != nullptr) + { + createMessageString(); + *mMessage = *(other.mMessage); + } +} + +Error::Error(Error &&other) + : mCode(other.mCode), + mID(other.mID), + mMessage(other.mMessage) +{ + other.mMessage = nullptr; +} + +Error::~Error() +{ + SafeDelete(mMessage); +} + +Error &Error::operator=(const Error &other) +{ + mCode = other.mCode; + mID = other.mID; + + if (other.mMessage != nullptr) + { + createMessageString(); + *mMessage = *(other.mMessage); + } + else + { + SafeDelete(mMessage); + } + + return *this; +} + +Error &Error::operator=(Error &&other) +{ + mCode = other.mCode; + mID = other.mID; + mMessage = other.mMessage; + + other.mMessage = nullptr; + + return *this; +} + +EGLint Error::getCode() const +{ + return mCode; +} + +EGLint Error::getID() const +{ + return mID; +} + +bool Error::isError() const +{ + return (mCode != EGL_SUCCESS); +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/Fence.cpp b/src/3rdparty/angle/src/libANGLE/Fence.cpp new file mode 100644 index 0000000000..8ab4cc9daa --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/Fence.cpp @@ -0,0 +1,117 @@ +// +// 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. +// + +// Fence.cpp: Implements the gl::FenceNV and gl::FenceSync classes, which support the GL_NV_fence +// extension and GLES3 sync objects. + +#include "libANGLE/Fence.h" + +#include "libANGLE/renderer/FenceNVImpl.h" +#include "libANGLE/renderer/FenceSyncImpl.h" +#include "libANGLE/renderer/Renderer.h" +#include "common/utilities.h" + +#include "angle_gl.h" + +namespace gl +{ + +FenceNV::FenceNV(rx::FenceNVImpl *impl) + : mFence(impl), + mIsSet(false), + mStatus(GL_FALSE), + mCondition(GL_NONE) +{ +} + +FenceNV::~FenceNV() +{ + SafeDelete(mFence); +} + +GLboolean FenceNV::isFence() const +{ + // GL_NV_fence spec: + // A name returned by GenFencesNV, but not yet set via SetFenceNV, is not the name of an existing fence. + return (mIsSet ? GL_TRUE : GL_FALSE); +} + +Error FenceNV::setFence(GLenum condition) +{ + Error error = mFence->set(); + if (error.isError()) + { + return error; + } + + mCondition = condition; + mStatus = GL_FALSE; + mIsSet = true; + + return Error(GL_NO_ERROR); +} + +Error FenceNV::testFence(GLboolean *outResult) +{ + // Flush the command buffer by default + Error error = mFence->test(true, &mStatus); + if (error.isError()) + { + return error; + } + + *outResult = mStatus; + return Error(GL_NO_ERROR); +} + +Error FenceNV::finishFence() +{ + ASSERT(mIsSet); + + return mFence->finishFence(&mStatus); +} + +FenceSync::FenceSync(rx::FenceSyncImpl *impl, GLuint id) + : RefCountObject(id), + mFence(impl), + mCondition(GL_NONE) +{ +} + +FenceSync::~FenceSync() +{ + SafeDelete(mFence); +} + +Error FenceSync::set(GLenum condition) +{ + Error error = mFence->set(); + if (error.isError()) + { + return error; + } + + mCondition = condition; + return Error(GL_NO_ERROR); +} + +Error FenceSync::clientWait(GLbitfield flags, GLuint64 timeout, GLenum *outResult) +{ + ASSERT(mCondition != GL_NONE); + return mFence->clientWait(flags, timeout, outResult); +} + +Error FenceSync::serverWait(GLbitfield flags, GLuint64 timeout) +{ + return mFence->serverWait(flags, timeout); +} + +Error FenceSync::getStatus(GLint *outResult) const +{ + return mFence->getStatus(outResult); +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/Fence.h b/src/3rdparty/angle/src/libANGLE/Fence.h new file mode 100644 index 0000000000..bcd66b6831 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/Fence.h @@ -0,0 +1,71 @@ +// +// 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. +// + +// Fence.h: Defines the gl::FenceNV and gl::FenceSync classes, which support the GL_NV_fence +// extension and GLES3 sync objects. + +#ifndef LIBANGLE_FENCE_H_ +#define LIBANGLE_FENCE_H_ + +#include "libANGLE/Error.h" +#include "libANGLE/RefCountObject.h" + +#include "common/angleutils.h" + +namespace rx +{ +class FenceNVImpl; +class FenceSyncImpl; +} + +namespace gl +{ + +class FenceNV final : angle::NonCopyable +{ + public: + explicit FenceNV(rx::FenceNVImpl *impl); + virtual ~FenceNV(); + + GLboolean isFence() const; + Error setFence(GLenum condition); + Error testFence(GLboolean *outResult); + Error finishFence(); + + GLboolean getStatus() const { return mStatus; } + GLenum getCondition() const { return mCondition; } + + private: + rx::FenceNVImpl *mFence; + + bool mIsSet; + + GLboolean mStatus; + GLenum mCondition; +}; + +class FenceSync final : public RefCountObject +{ + public: + explicit FenceSync(rx::FenceSyncImpl *impl, GLuint id); + virtual ~FenceSync(); + + Error set(GLenum condition); + Error clientWait(GLbitfield flags, GLuint64 timeout, GLenum *outResult); + Error serverWait(GLbitfield flags, GLuint64 timeout); + Error getStatus(GLint *outResult) const; + + GLenum getCondition() const { return mCondition; } + + private: + rx::FenceSyncImpl *mFence; + + GLenum mCondition; +}; + +} + +#endif // LIBANGLE_FENCE_H_ diff --git a/src/3rdparty/angle/src/libANGLE/Float16ToFloat32.cpp b/src/3rdparty/angle/src/libANGLE/Float16ToFloat32.cpp new file mode 100644 index 0000000000..5bf7b3fce8 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/Float16ToFloat32.cpp @@ -0,0 +1,2203 @@ +// +// 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 automatically generated. + +namespace gl +{ + +const static unsigned g_mantissa[2048] = { + 0x00000000, + 0x33800000, + 0x34000000, + 0x34400000, + 0x34800000, + 0x34a00000, + 0x34c00000, + 0x34e00000, + 0x35000000, + 0x35100000, + 0x35200000, + 0x35300000, + 0x35400000, + 0x35500000, + 0x35600000, + 0x35700000, + 0x35800000, + 0x35880000, + 0x35900000, + 0x35980000, + 0x35a00000, + 0x35a80000, + 0x35b00000, + 0x35b80000, + 0x35c00000, + 0x35c80000, + 0x35d00000, + 0x35d80000, + 0x35e00000, + 0x35e80000, + 0x35f00000, + 0x35f80000, + 0x36000000, + 0x36040000, + 0x36080000, + 0x360c0000, + 0x36100000, + 0x36140000, + 0x36180000, + 0x361c0000, + 0x36200000, + 0x36240000, + 0x36280000, + 0x362c0000, + 0x36300000, + 0x36340000, + 0x36380000, + 0x363c0000, + 0x36400000, + 0x36440000, + 0x36480000, + 0x364c0000, + 0x36500000, + 0x36540000, + 0x36580000, + 0x365c0000, + 0x36600000, + 0x36640000, + 0x36680000, + 0x366c0000, + 0x36700000, + 0x36740000, + 0x36780000, + 0x367c0000, + 0x36800000, + 0x36820000, + 0x36840000, + 0x36860000, + 0x36880000, + 0x368a0000, + 0x368c0000, + 0x368e0000, + 0x36900000, + 0x36920000, + 0x36940000, + 0x36960000, + 0x36980000, + 0x369a0000, + 0x369c0000, + 0x369e0000, + 0x36a00000, + 0x36a20000, + 0x36a40000, + 0x36a60000, + 0x36a80000, + 0x36aa0000, + 0x36ac0000, + 0x36ae0000, + 0x36b00000, + 0x36b20000, + 0x36b40000, + 0x36b60000, + 0x36b80000, + 0x36ba0000, + 0x36bc0000, + 0x36be0000, + 0x36c00000, + 0x36c20000, + 0x36c40000, + 0x36c60000, + 0x36c80000, + 0x36ca0000, + 0x36cc0000, + 0x36ce0000, + 0x36d00000, + 0x36d20000, + 0x36d40000, + 0x36d60000, + 0x36d80000, + 0x36da0000, + 0x36dc0000, + 0x36de0000, + 0x36e00000, + 0x36e20000, + 0x36e40000, + 0x36e60000, + 0x36e80000, + 0x36ea0000, + 0x36ec0000, + 0x36ee0000, + 0x36f00000, + 0x36f20000, + 0x36f40000, + 0x36f60000, + 0x36f80000, + 0x36fa0000, + 0x36fc0000, + 0x36fe0000, + 0x37000000, + 0x37010000, + 0x37020000, + 0x37030000, + 0x37040000, + 0x37050000, + 0x37060000, + 0x37070000, + 0x37080000, + 0x37090000, + 0x370a0000, + 0x370b0000, + 0x370c0000, + 0x370d0000, + 0x370e0000, + 0x370f0000, + 0x37100000, + 0x37110000, + 0x37120000, + 0x37130000, + 0x37140000, + 0x37150000, + 0x37160000, + 0x37170000, + 0x37180000, + 0x37190000, + 0x371a0000, + 0x371b0000, + 0x371c0000, + 0x371d0000, + 0x371e0000, + 0x371f0000, + 0x37200000, + 0x37210000, + 0x37220000, + 0x37230000, + 0x37240000, + 0x37250000, + 0x37260000, + 0x37270000, + 0x37280000, + 0x37290000, + 0x372a0000, + 0x372b0000, + 0x372c0000, + 0x372d0000, + 0x372e0000, + 0x372f0000, + 0x37300000, + 0x37310000, + 0x37320000, + 0x37330000, + 0x37340000, + 0x37350000, + 0x37360000, + 0x37370000, + 0x37380000, + 0x37390000, + 0x373a0000, + 0x373b0000, + 0x373c0000, + 0x373d0000, + 0x373e0000, + 0x373f0000, + 0x37400000, + 0x37410000, + 0x37420000, + 0x37430000, + 0x37440000, + 0x37450000, + 0x37460000, + 0x37470000, + 0x37480000, + 0x37490000, + 0x374a0000, + 0x374b0000, + 0x374c0000, + 0x374d0000, + 0x374e0000, + 0x374f0000, + 0x37500000, + 0x37510000, + 0x37520000, + 0x37530000, + 0x37540000, + 0x37550000, + 0x37560000, + 0x37570000, + 0x37580000, + 0x37590000, + 0x375a0000, + 0x375b0000, + 0x375c0000, + 0x375d0000, + 0x375e0000, + 0x375f0000, + 0x37600000, + 0x37610000, + 0x37620000, + 0x37630000, + 0x37640000, + 0x37650000, + 0x37660000, + 0x37670000, + 0x37680000, + 0x37690000, + 0x376a0000, + 0x376b0000, + 0x376c0000, + 0x376d0000, + 0x376e0000, + 0x376f0000, + 0x37700000, + 0x37710000, + 0x37720000, + 0x37730000, + 0x37740000, + 0x37750000, + 0x37760000, + 0x37770000, + 0x37780000, + 0x37790000, + 0x377a0000, + 0x377b0000, + 0x377c0000, + 0x377d0000, + 0x377e0000, + 0x377f0000, + 0x37800000, + 0x37808000, + 0x37810000, + 0x37818000, + 0x37820000, + 0x37828000, + 0x37830000, + 0x37838000, + 0x37840000, + 0x37848000, + 0x37850000, + 0x37858000, + 0x37860000, + 0x37868000, + 0x37870000, + 0x37878000, + 0x37880000, + 0x37888000, + 0x37890000, + 0x37898000, + 0x378a0000, + 0x378a8000, + 0x378b0000, + 0x378b8000, + 0x378c0000, + 0x378c8000, + 0x378d0000, + 0x378d8000, + 0x378e0000, + 0x378e8000, + 0x378f0000, + 0x378f8000, + 0x37900000, + 0x37908000, + 0x37910000, + 0x37918000, + 0x37920000, + 0x37928000, + 0x37930000, + 0x37938000, + 0x37940000, + 0x37948000, + 0x37950000, + 0x37958000, + 0x37960000, + 0x37968000, + 0x37970000, + 0x37978000, + 0x37980000, + 0x37988000, + 0x37990000, + 0x37998000, + 0x379a0000, + 0x379a8000, + 0x379b0000, + 0x379b8000, + 0x379c0000, + 0x379c8000, + 0x379d0000, + 0x379d8000, + 0x379e0000, + 0x379e8000, + 0x379f0000, + 0x379f8000, + 0x37a00000, + 0x37a08000, + 0x37a10000, + 0x37a18000, + 0x37a20000, + 0x37a28000, + 0x37a30000, + 0x37a38000, + 0x37a40000, + 0x37a48000, + 0x37a50000, + 0x37a58000, + 0x37a60000, + 0x37a68000, + 0x37a70000, + 0x37a78000, + 0x37a80000, + 0x37a88000, + 0x37a90000, + 0x37a98000, + 0x37aa0000, + 0x37aa8000, + 0x37ab0000, + 0x37ab8000, + 0x37ac0000, + 0x37ac8000, + 0x37ad0000, + 0x37ad8000, + 0x37ae0000, + 0x37ae8000, + 0x37af0000, + 0x37af8000, + 0x37b00000, + 0x37b08000, + 0x37b10000, + 0x37b18000, + 0x37b20000, + 0x37b28000, + 0x37b30000, + 0x37b38000, + 0x37b40000, + 0x37b48000, + 0x37b50000, + 0x37b58000, + 0x37b60000, + 0x37b68000, + 0x37b70000, + 0x37b78000, + 0x37b80000, + 0x37b88000, + 0x37b90000, + 0x37b98000, + 0x37ba0000, + 0x37ba8000, + 0x37bb0000, + 0x37bb8000, + 0x37bc0000, + 0x37bc8000, + 0x37bd0000, + 0x37bd8000, + 0x37be0000, + 0x37be8000, + 0x37bf0000, + 0x37bf8000, + 0x37c00000, + 0x37c08000, + 0x37c10000, + 0x37c18000, + 0x37c20000, + 0x37c28000, + 0x37c30000, + 0x37c38000, + 0x37c40000, + 0x37c48000, + 0x37c50000, + 0x37c58000, + 0x37c60000, + 0x37c68000, + 0x37c70000, + 0x37c78000, + 0x37c80000, + 0x37c88000, + 0x37c90000, + 0x37c98000, + 0x37ca0000, + 0x37ca8000, + 0x37cb0000, + 0x37cb8000, + 0x37cc0000, + 0x37cc8000, + 0x37cd0000, + 0x37cd8000, + 0x37ce0000, + 0x37ce8000, + 0x37cf0000, + 0x37cf8000, + 0x37d00000, + 0x37d08000, + 0x37d10000, + 0x37d18000, + 0x37d20000, + 0x37d28000, + 0x37d30000, + 0x37d38000, + 0x37d40000, + 0x37d48000, + 0x37d50000, + 0x37d58000, + 0x37d60000, + 0x37d68000, + 0x37d70000, + 0x37d78000, + 0x37d80000, + 0x37d88000, + 0x37d90000, + 0x37d98000, + 0x37da0000, + 0x37da8000, + 0x37db0000, + 0x37db8000, + 0x37dc0000, + 0x37dc8000, + 0x37dd0000, + 0x37dd8000, + 0x37de0000, + 0x37de8000, + 0x37df0000, + 0x37df8000, + 0x37e00000, + 0x37e08000, + 0x37e10000, + 0x37e18000, + 0x37e20000, + 0x37e28000, + 0x37e30000, + 0x37e38000, + 0x37e40000, + 0x37e48000, + 0x37e50000, + 0x37e58000, + 0x37e60000, + 0x37e68000, + 0x37e70000, + 0x37e78000, + 0x37e80000, + 0x37e88000, + 0x37e90000, + 0x37e98000, + 0x37ea0000, + 0x37ea8000, + 0x37eb0000, + 0x37eb8000, + 0x37ec0000, + 0x37ec8000, + 0x37ed0000, + 0x37ed8000, + 0x37ee0000, + 0x37ee8000, + 0x37ef0000, + 0x37ef8000, + 0x37f00000, + 0x37f08000, + 0x37f10000, + 0x37f18000, + 0x37f20000, + 0x37f28000, + 0x37f30000, + 0x37f38000, + 0x37f40000, + 0x37f48000, + 0x37f50000, + 0x37f58000, + 0x37f60000, + 0x37f68000, + 0x37f70000, + 0x37f78000, + 0x37f80000, + 0x37f88000, + 0x37f90000, + 0x37f98000, + 0x37fa0000, + 0x37fa8000, + 0x37fb0000, + 0x37fb8000, + 0x37fc0000, + 0x37fc8000, + 0x37fd0000, + 0x37fd8000, + 0x37fe0000, + 0x37fe8000, + 0x37ff0000, + 0x37ff8000, + 0x38000000, + 0x38004000, + 0x38008000, + 0x3800c000, + 0x38010000, + 0x38014000, + 0x38018000, + 0x3801c000, + 0x38020000, + 0x38024000, + 0x38028000, + 0x3802c000, + 0x38030000, + 0x38034000, + 0x38038000, + 0x3803c000, + 0x38040000, + 0x38044000, + 0x38048000, + 0x3804c000, + 0x38050000, + 0x38054000, + 0x38058000, + 0x3805c000, + 0x38060000, + 0x38064000, + 0x38068000, + 0x3806c000, + 0x38070000, + 0x38074000, + 0x38078000, + 0x3807c000, + 0x38080000, + 0x38084000, + 0x38088000, + 0x3808c000, + 0x38090000, + 0x38094000, + 0x38098000, + 0x3809c000, + 0x380a0000, + 0x380a4000, + 0x380a8000, + 0x380ac000, + 0x380b0000, + 0x380b4000, + 0x380b8000, + 0x380bc000, + 0x380c0000, + 0x380c4000, + 0x380c8000, + 0x380cc000, + 0x380d0000, + 0x380d4000, + 0x380d8000, + 0x380dc000, + 0x380e0000, + 0x380e4000, + 0x380e8000, + 0x380ec000, + 0x380f0000, + 0x380f4000, + 0x380f8000, + 0x380fc000, + 0x38100000, + 0x38104000, + 0x38108000, + 0x3810c000, + 0x38110000, + 0x38114000, + 0x38118000, + 0x3811c000, + 0x38120000, + 0x38124000, + 0x38128000, + 0x3812c000, + 0x38130000, + 0x38134000, + 0x38138000, + 0x3813c000, + 0x38140000, + 0x38144000, + 0x38148000, + 0x3814c000, + 0x38150000, + 0x38154000, + 0x38158000, + 0x3815c000, + 0x38160000, + 0x38164000, + 0x38168000, + 0x3816c000, + 0x38170000, + 0x38174000, + 0x38178000, + 0x3817c000, + 0x38180000, + 0x38184000, + 0x38188000, + 0x3818c000, + 0x38190000, + 0x38194000, + 0x38198000, + 0x3819c000, + 0x381a0000, + 0x381a4000, + 0x381a8000, + 0x381ac000, + 0x381b0000, + 0x381b4000, + 0x381b8000, + 0x381bc000, + 0x381c0000, + 0x381c4000, + 0x381c8000, + 0x381cc000, + 0x381d0000, + 0x381d4000, + 0x381d8000, + 0x381dc000, + 0x381e0000, + 0x381e4000, + 0x381e8000, + 0x381ec000, + 0x381f0000, + 0x381f4000, + 0x381f8000, + 0x381fc000, + 0x38200000, + 0x38204000, + 0x38208000, + 0x3820c000, + 0x38210000, + 0x38214000, + 0x38218000, + 0x3821c000, + 0x38220000, + 0x38224000, + 0x38228000, + 0x3822c000, + 0x38230000, + 0x38234000, + 0x38238000, + 0x3823c000, + 0x38240000, + 0x38244000, + 0x38248000, + 0x3824c000, + 0x38250000, + 0x38254000, + 0x38258000, + 0x3825c000, + 0x38260000, + 0x38264000, + 0x38268000, + 0x3826c000, + 0x38270000, + 0x38274000, + 0x38278000, + 0x3827c000, + 0x38280000, + 0x38284000, + 0x38288000, + 0x3828c000, + 0x38290000, + 0x38294000, + 0x38298000, + 0x3829c000, + 0x382a0000, + 0x382a4000, + 0x382a8000, + 0x382ac000, + 0x382b0000, + 0x382b4000, + 0x382b8000, + 0x382bc000, + 0x382c0000, + 0x382c4000, + 0x382c8000, + 0x382cc000, + 0x382d0000, + 0x382d4000, + 0x382d8000, + 0x382dc000, + 0x382e0000, + 0x382e4000, + 0x382e8000, + 0x382ec000, + 0x382f0000, + 0x382f4000, + 0x382f8000, + 0x382fc000, + 0x38300000, + 0x38304000, + 0x38308000, + 0x3830c000, + 0x38310000, + 0x38314000, + 0x38318000, + 0x3831c000, + 0x38320000, + 0x38324000, + 0x38328000, + 0x3832c000, + 0x38330000, + 0x38334000, + 0x38338000, + 0x3833c000, + 0x38340000, + 0x38344000, + 0x38348000, + 0x3834c000, + 0x38350000, + 0x38354000, + 0x38358000, + 0x3835c000, + 0x38360000, + 0x38364000, + 0x38368000, + 0x3836c000, + 0x38370000, + 0x38374000, + 0x38378000, + 0x3837c000, + 0x38380000, + 0x38384000, + 0x38388000, + 0x3838c000, + 0x38390000, + 0x38394000, + 0x38398000, + 0x3839c000, + 0x383a0000, + 0x383a4000, + 0x383a8000, + 0x383ac000, + 0x383b0000, + 0x383b4000, + 0x383b8000, + 0x383bc000, + 0x383c0000, + 0x383c4000, + 0x383c8000, + 0x383cc000, + 0x383d0000, + 0x383d4000, + 0x383d8000, + 0x383dc000, + 0x383e0000, + 0x383e4000, + 0x383e8000, + 0x383ec000, + 0x383f0000, + 0x383f4000, + 0x383f8000, + 0x383fc000, + 0x38400000, + 0x38404000, + 0x38408000, + 0x3840c000, + 0x38410000, + 0x38414000, + 0x38418000, + 0x3841c000, + 0x38420000, + 0x38424000, + 0x38428000, + 0x3842c000, + 0x38430000, + 0x38434000, + 0x38438000, + 0x3843c000, + 0x38440000, + 0x38444000, + 0x38448000, + 0x3844c000, + 0x38450000, + 0x38454000, + 0x38458000, + 0x3845c000, + 0x38460000, + 0x38464000, + 0x38468000, + 0x3846c000, + 0x38470000, + 0x38474000, + 0x38478000, + 0x3847c000, + 0x38480000, + 0x38484000, + 0x38488000, + 0x3848c000, + 0x38490000, + 0x38494000, + 0x38498000, + 0x3849c000, + 0x384a0000, + 0x384a4000, + 0x384a8000, + 0x384ac000, + 0x384b0000, + 0x384b4000, + 0x384b8000, + 0x384bc000, + 0x384c0000, + 0x384c4000, + 0x384c8000, + 0x384cc000, + 0x384d0000, + 0x384d4000, + 0x384d8000, + 0x384dc000, + 0x384e0000, + 0x384e4000, + 0x384e8000, + 0x384ec000, + 0x384f0000, + 0x384f4000, + 0x384f8000, + 0x384fc000, + 0x38500000, + 0x38504000, + 0x38508000, + 0x3850c000, + 0x38510000, + 0x38514000, + 0x38518000, + 0x3851c000, + 0x38520000, + 0x38524000, + 0x38528000, + 0x3852c000, + 0x38530000, + 0x38534000, + 0x38538000, + 0x3853c000, + 0x38540000, + 0x38544000, + 0x38548000, + 0x3854c000, + 0x38550000, + 0x38554000, + 0x38558000, + 0x3855c000, + 0x38560000, + 0x38564000, + 0x38568000, + 0x3856c000, + 0x38570000, + 0x38574000, + 0x38578000, + 0x3857c000, + 0x38580000, + 0x38584000, + 0x38588000, + 0x3858c000, + 0x38590000, + 0x38594000, + 0x38598000, + 0x3859c000, + 0x385a0000, + 0x385a4000, + 0x385a8000, + 0x385ac000, + 0x385b0000, + 0x385b4000, + 0x385b8000, + 0x385bc000, + 0x385c0000, + 0x385c4000, + 0x385c8000, + 0x385cc000, + 0x385d0000, + 0x385d4000, + 0x385d8000, + 0x385dc000, + 0x385e0000, + 0x385e4000, + 0x385e8000, + 0x385ec000, + 0x385f0000, + 0x385f4000, + 0x385f8000, + 0x385fc000, + 0x38600000, + 0x38604000, + 0x38608000, + 0x3860c000, + 0x38610000, + 0x38614000, + 0x38618000, + 0x3861c000, + 0x38620000, + 0x38624000, + 0x38628000, + 0x3862c000, + 0x38630000, + 0x38634000, + 0x38638000, + 0x3863c000, + 0x38640000, + 0x38644000, + 0x38648000, + 0x3864c000, + 0x38650000, + 0x38654000, + 0x38658000, + 0x3865c000, + 0x38660000, + 0x38664000, + 0x38668000, + 0x3866c000, + 0x38670000, + 0x38674000, + 0x38678000, + 0x3867c000, + 0x38680000, + 0x38684000, + 0x38688000, + 0x3868c000, + 0x38690000, + 0x38694000, + 0x38698000, + 0x3869c000, + 0x386a0000, + 0x386a4000, + 0x386a8000, + 0x386ac000, + 0x386b0000, + 0x386b4000, + 0x386b8000, + 0x386bc000, + 0x386c0000, + 0x386c4000, + 0x386c8000, + 0x386cc000, + 0x386d0000, + 0x386d4000, + 0x386d8000, + 0x386dc000, + 0x386e0000, + 0x386e4000, + 0x386e8000, + 0x386ec000, + 0x386f0000, + 0x386f4000, + 0x386f8000, + 0x386fc000, + 0x38700000, + 0x38704000, + 0x38708000, + 0x3870c000, + 0x38710000, + 0x38714000, + 0x38718000, + 0x3871c000, + 0x38720000, + 0x38724000, + 0x38728000, + 0x3872c000, + 0x38730000, + 0x38734000, + 0x38738000, + 0x3873c000, + 0x38740000, + 0x38744000, + 0x38748000, + 0x3874c000, + 0x38750000, + 0x38754000, + 0x38758000, + 0x3875c000, + 0x38760000, + 0x38764000, + 0x38768000, + 0x3876c000, + 0x38770000, + 0x38774000, + 0x38778000, + 0x3877c000, + 0x38780000, + 0x38784000, + 0x38788000, + 0x3878c000, + 0x38790000, + 0x38794000, + 0x38798000, + 0x3879c000, + 0x387a0000, + 0x387a4000, + 0x387a8000, + 0x387ac000, + 0x387b0000, + 0x387b4000, + 0x387b8000, + 0x387bc000, + 0x387c0000, + 0x387c4000, + 0x387c8000, + 0x387cc000, + 0x387d0000, + 0x387d4000, + 0x387d8000, + 0x387dc000, + 0x387e0000, + 0x387e4000, + 0x387e8000, + 0x387ec000, + 0x387f0000, + 0x387f4000, + 0x387f8000, + 0x387fc000, + 0x38000000, + 0x38002000, + 0x38004000, + 0x38006000, + 0x38008000, + 0x3800a000, + 0x3800c000, + 0x3800e000, + 0x38010000, + 0x38012000, + 0x38014000, + 0x38016000, + 0x38018000, + 0x3801a000, + 0x3801c000, + 0x3801e000, + 0x38020000, + 0x38022000, + 0x38024000, + 0x38026000, + 0x38028000, + 0x3802a000, + 0x3802c000, + 0x3802e000, + 0x38030000, + 0x38032000, + 0x38034000, + 0x38036000, + 0x38038000, + 0x3803a000, + 0x3803c000, + 0x3803e000, + 0x38040000, + 0x38042000, + 0x38044000, + 0x38046000, + 0x38048000, + 0x3804a000, + 0x3804c000, + 0x3804e000, + 0x38050000, + 0x38052000, + 0x38054000, + 0x38056000, + 0x38058000, + 0x3805a000, + 0x3805c000, + 0x3805e000, + 0x38060000, + 0x38062000, + 0x38064000, + 0x38066000, + 0x38068000, + 0x3806a000, + 0x3806c000, + 0x3806e000, + 0x38070000, + 0x38072000, + 0x38074000, + 0x38076000, + 0x38078000, + 0x3807a000, + 0x3807c000, + 0x3807e000, + 0x38080000, + 0x38082000, + 0x38084000, + 0x38086000, + 0x38088000, + 0x3808a000, + 0x3808c000, + 0x3808e000, + 0x38090000, + 0x38092000, + 0x38094000, + 0x38096000, + 0x38098000, + 0x3809a000, + 0x3809c000, + 0x3809e000, + 0x380a0000, + 0x380a2000, + 0x380a4000, + 0x380a6000, + 0x380a8000, + 0x380aa000, + 0x380ac000, + 0x380ae000, + 0x380b0000, + 0x380b2000, + 0x380b4000, + 0x380b6000, + 0x380b8000, + 0x380ba000, + 0x380bc000, + 0x380be000, + 0x380c0000, + 0x380c2000, + 0x380c4000, + 0x380c6000, + 0x380c8000, + 0x380ca000, + 0x380cc000, + 0x380ce000, + 0x380d0000, + 0x380d2000, + 0x380d4000, + 0x380d6000, + 0x380d8000, + 0x380da000, + 0x380dc000, + 0x380de000, + 0x380e0000, + 0x380e2000, + 0x380e4000, + 0x380e6000, + 0x380e8000, + 0x380ea000, + 0x380ec000, + 0x380ee000, + 0x380f0000, + 0x380f2000, + 0x380f4000, + 0x380f6000, + 0x380f8000, + 0x380fa000, + 0x380fc000, + 0x380fe000, + 0x38100000, + 0x38102000, + 0x38104000, + 0x38106000, + 0x38108000, + 0x3810a000, + 0x3810c000, + 0x3810e000, + 0x38110000, + 0x38112000, + 0x38114000, + 0x38116000, + 0x38118000, + 0x3811a000, + 0x3811c000, + 0x3811e000, + 0x38120000, + 0x38122000, + 0x38124000, + 0x38126000, + 0x38128000, + 0x3812a000, + 0x3812c000, + 0x3812e000, + 0x38130000, + 0x38132000, + 0x38134000, + 0x38136000, + 0x38138000, + 0x3813a000, + 0x3813c000, + 0x3813e000, + 0x38140000, + 0x38142000, + 0x38144000, + 0x38146000, + 0x38148000, + 0x3814a000, + 0x3814c000, + 0x3814e000, + 0x38150000, + 0x38152000, + 0x38154000, + 0x38156000, + 0x38158000, + 0x3815a000, + 0x3815c000, + 0x3815e000, + 0x38160000, + 0x38162000, + 0x38164000, + 0x38166000, + 0x38168000, + 0x3816a000, + 0x3816c000, + 0x3816e000, + 0x38170000, + 0x38172000, + 0x38174000, + 0x38176000, + 0x38178000, + 0x3817a000, + 0x3817c000, + 0x3817e000, + 0x38180000, + 0x38182000, + 0x38184000, + 0x38186000, + 0x38188000, + 0x3818a000, + 0x3818c000, + 0x3818e000, + 0x38190000, + 0x38192000, + 0x38194000, + 0x38196000, + 0x38198000, + 0x3819a000, + 0x3819c000, + 0x3819e000, + 0x381a0000, + 0x381a2000, + 0x381a4000, + 0x381a6000, + 0x381a8000, + 0x381aa000, + 0x381ac000, + 0x381ae000, + 0x381b0000, + 0x381b2000, + 0x381b4000, + 0x381b6000, + 0x381b8000, + 0x381ba000, + 0x381bc000, + 0x381be000, + 0x381c0000, + 0x381c2000, + 0x381c4000, + 0x381c6000, + 0x381c8000, + 0x381ca000, + 0x381cc000, + 0x381ce000, + 0x381d0000, + 0x381d2000, + 0x381d4000, + 0x381d6000, + 0x381d8000, + 0x381da000, + 0x381dc000, + 0x381de000, + 0x381e0000, + 0x381e2000, + 0x381e4000, + 0x381e6000, + 0x381e8000, + 0x381ea000, + 0x381ec000, + 0x381ee000, + 0x381f0000, + 0x381f2000, + 0x381f4000, + 0x381f6000, + 0x381f8000, + 0x381fa000, + 0x381fc000, + 0x381fe000, + 0x38200000, + 0x38202000, + 0x38204000, + 0x38206000, + 0x38208000, + 0x3820a000, + 0x3820c000, + 0x3820e000, + 0x38210000, + 0x38212000, + 0x38214000, + 0x38216000, + 0x38218000, + 0x3821a000, + 0x3821c000, + 0x3821e000, + 0x38220000, + 0x38222000, + 0x38224000, + 0x38226000, + 0x38228000, + 0x3822a000, + 0x3822c000, + 0x3822e000, + 0x38230000, + 0x38232000, + 0x38234000, + 0x38236000, + 0x38238000, + 0x3823a000, + 0x3823c000, + 0x3823e000, + 0x38240000, + 0x38242000, + 0x38244000, + 0x38246000, + 0x38248000, + 0x3824a000, + 0x3824c000, + 0x3824e000, + 0x38250000, + 0x38252000, + 0x38254000, + 0x38256000, + 0x38258000, + 0x3825a000, + 0x3825c000, + 0x3825e000, + 0x38260000, + 0x38262000, + 0x38264000, + 0x38266000, + 0x38268000, + 0x3826a000, + 0x3826c000, + 0x3826e000, + 0x38270000, + 0x38272000, + 0x38274000, + 0x38276000, + 0x38278000, + 0x3827a000, + 0x3827c000, + 0x3827e000, + 0x38280000, + 0x38282000, + 0x38284000, + 0x38286000, + 0x38288000, + 0x3828a000, + 0x3828c000, + 0x3828e000, + 0x38290000, + 0x38292000, + 0x38294000, + 0x38296000, + 0x38298000, + 0x3829a000, + 0x3829c000, + 0x3829e000, + 0x382a0000, + 0x382a2000, + 0x382a4000, + 0x382a6000, + 0x382a8000, + 0x382aa000, + 0x382ac000, + 0x382ae000, + 0x382b0000, + 0x382b2000, + 0x382b4000, + 0x382b6000, + 0x382b8000, + 0x382ba000, + 0x382bc000, + 0x382be000, + 0x382c0000, + 0x382c2000, + 0x382c4000, + 0x382c6000, + 0x382c8000, + 0x382ca000, + 0x382cc000, + 0x382ce000, + 0x382d0000, + 0x382d2000, + 0x382d4000, + 0x382d6000, + 0x382d8000, + 0x382da000, + 0x382dc000, + 0x382de000, + 0x382e0000, + 0x382e2000, + 0x382e4000, + 0x382e6000, + 0x382e8000, + 0x382ea000, + 0x382ec000, + 0x382ee000, + 0x382f0000, + 0x382f2000, + 0x382f4000, + 0x382f6000, + 0x382f8000, + 0x382fa000, + 0x382fc000, + 0x382fe000, + 0x38300000, + 0x38302000, + 0x38304000, + 0x38306000, + 0x38308000, + 0x3830a000, + 0x3830c000, + 0x3830e000, + 0x38310000, + 0x38312000, + 0x38314000, + 0x38316000, + 0x38318000, + 0x3831a000, + 0x3831c000, + 0x3831e000, + 0x38320000, + 0x38322000, + 0x38324000, + 0x38326000, + 0x38328000, + 0x3832a000, + 0x3832c000, + 0x3832e000, + 0x38330000, + 0x38332000, + 0x38334000, + 0x38336000, + 0x38338000, + 0x3833a000, + 0x3833c000, + 0x3833e000, + 0x38340000, + 0x38342000, + 0x38344000, + 0x38346000, + 0x38348000, + 0x3834a000, + 0x3834c000, + 0x3834e000, + 0x38350000, + 0x38352000, + 0x38354000, + 0x38356000, + 0x38358000, + 0x3835a000, + 0x3835c000, + 0x3835e000, + 0x38360000, + 0x38362000, + 0x38364000, + 0x38366000, + 0x38368000, + 0x3836a000, + 0x3836c000, + 0x3836e000, + 0x38370000, + 0x38372000, + 0x38374000, + 0x38376000, + 0x38378000, + 0x3837a000, + 0x3837c000, + 0x3837e000, + 0x38380000, + 0x38382000, + 0x38384000, + 0x38386000, + 0x38388000, + 0x3838a000, + 0x3838c000, + 0x3838e000, + 0x38390000, + 0x38392000, + 0x38394000, + 0x38396000, + 0x38398000, + 0x3839a000, + 0x3839c000, + 0x3839e000, + 0x383a0000, + 0x383a2000, + 0x383a4000, + 0x383a6000, + 0x383a8000, + 0x383aa000, + 0x383ac000, + 0x383ae000, + 0x383b0000, + 0x383b2000, + 0x383b4000, + 0x383b6000, + 0x383b8000, + 0x383ba000, + 0x383bc000, + 0x383be000, + 0x383c0000, + 0x383c2000, + 0x383c4000, + 0x383c6000, + 0x383c8000, + 0x383ca000, + 0x383cc000, + 0x383ce000, + 0x383d0000, + 0x383d2000, + 0x383d4000, + 0x383d6000, + 0x383d8000, + 0x383da000, + 0x383dc000, + 0x383de000, + 0x383e0000, + 0x383e2000, + 0x383e4000, + 0x383e6000, + 0x383e8000, + 0x383ea000, + 0x383ec000, + 0x383ee000, + 0x383f0000, + 0x383f2000, + 0x383f4000, + 0x383f6000, + 0x383f8000, + 0x383fa000, + 0x383fc000, + 0x383fe000, + 0x38400000, + 0x38402000, + 0x38404000, + 0x38406000, + 0x38408000, + 0x3840a000, + 0x3840c000, + 0x3840e000, + 0x38410000, + 0x38412000, + 0x38414000, + 0x38416000, + 0x38418000, + 0x3841a000, + 0x3841c000, + 0x3841e000, + 0x38420000, + 0x38422000, + 0x38424000, + 0x38426000, + 0x38428000, + 0x3842a000, + 0x3842c000, + 0x3842e000, + 0x38430000, + 0x38432000, + 0x38434000, + 0x38436000, + 0x38438000, + 0x3843a000, + 0x3843c000, + 0x3843e000, + 0x38440000, + 0x38442000, + 0x38444000, + 0x38446000, + 0x38448000, + 0x3844a000, + 0x3844c000, + 0x3844e000, + 0x38450000, + 0x38452000, + 0x38454000, + 0x38456000, + 0x38458000, + 0x3845a000, + 0x3845c000, + 0x3845e000, + 0x38460000, + 0x38462000, + 0x38464000, + 0x38466000, + 0x38468000, + 0x3846a000, + 0x3846c000, + 0x3846e000, + 0x38470000, + 0x38472000, + 0x38474000, + 0x38476000, + 0x38478000, + 0x3847a000, + 0x3847c000, + 0x3847e000, + 0x38480000, + 0x38482000, + 0x38484000, + 0x38486000, + 0x38488000, + 0x3848a000, + 0x3848c000, + 0x3848e000, + 0x38490000, + 0x38492000, + 0x38494000, + 0x38496000, + 0x38498000, + 0x3849a000, + 0x3849c000, + 0x3849e000, + 0x384a0000, + 0x384a2000, + 0x384a4000, + 0x384a6000, + 0x384a8000, + 0x384aa000, + 0x384ac000, + 0x384ae000, + 0x384b0000, + 0x384b2000, + 0x384b4000, + 0x384b6000, + 0x384b8000, + 0x384ba000, + 0x384bc000, + 0x384be000, + 0x384c0000, + 0x384c2000, + 0x384c4000, + 0x384c6000, + 0x384c8000, + 0x384ca000, + 0x384cc000, + 0x384ce000, + 0x384d0000, + 0x384d2000, + 0x384d4000, + 0x384d6000, + 0x384d8000, + 0x384da000, + 0x384dc000, + 0x384de000, + 0x384e0000, + 0x384e2000, + 0x384e4000, + 0x384e6000, + 0x384e8000, + 0x384ea000, + 0x384ec000, + 0x384ee000, + 0x384f0000, + 0x384f2000, + 0x384f4000, + 0x384f6000, + 0x384f8000, + 0x384fa000, + 0x384fc000, + 0x384fe000, + 0x38500000, + 0x38502000, + 0x38504000, + 0x38506000, + 0x38508000, + 0x3850a000, + 0x3850c000, + 0x3850e000, + 0x38510000, + 0x38512000, + 0x38514000, + 0x38516000, + 0x38518000, + 0x3851a000, + 0x3851c000, + 0x3851e000, + 0x38520000, + 0x38522000, + 0x38524000, + 0x38526000, + 0x38528000, + 0x3852a000, + 0x3852c000, + 0x3852e000, + 0x38530000, + 0x38532000, + 0x38534000, + 0x38536000, + 0x38538000, + 0x3853a000, + 0x3853c000, + 0x3853e000, + 0x38540000, + 0x38542000, + 0x38544000, + 0x38546000, + 0x38548000, + 0x3854a000, + 0x3854c000, + 0x3854e000, + 0x38550000, + 0x38552000, + 0x38554000, + 0x38556000, + 0x38558000, + 0x3855a000, + 0x3855c000, + 0x3855e000, + 0x38560000, + 0x38562000, + 0x38564000, + 0x38566000, + 0x38568000, + 0x3856a000, + 0x3856c000, + 0x3856e000, + 0x38570000, + 0x38572000, + 0x38574000, + 0x38576000, + 0x38578000, + 0x3857a000, + 0x3857c000, + 0x3857e000, + 0x38580000, + 0x38582000, + 0x38584000, + 0x38586000, + 0x38588000, + 0x3858a000, + 0x3858c000, + 0x3858e000, + 0x38590000, + 0x38592000, + 0x38594000, + 0x38596000, + 0x38598000, + 0x3859a000, + 0x3859c000, + 0x3859e000, + 0x385a0000, + 0x385a2000, + 0x385a4000, + 0x385a6000, + 0x385a8000, + 0x385aa000, + 0x385ac000, + 0x385ae000, + 0x385b0000, + 0x385b2000, + 0x385b4000, + 0x385b6000, + 0x385b8000, + 0x385ba000, + 0x385bc000, + 0x385be000, + 0x385c0000, + 0x385c2000, + 0x385c4000, + 0x385c6000, + 0x385c8000, + 0x385ca000, + 0x385cc000, + 0x385ce000, + 0x385d0000, + 0x385d2000, + 0x385d4000, + 0x385d6000, + 0x385d8000, + 0x385da000, + 0x385dc000, + 0x385de000, + 0x385e0000, + 0x385e2000, + 0x385e4000, + 0x385e6000, + 0x385e8000, + 0x385ea000, + 0x385ec000, + 0x385ee000, + 0x385f0000, + 0x385f2000, + 0x385f4000, + 0x385f6000, + 0x385f8000, + 0x385fa000, + 0x385fc000, + 0x385fe000, + 0x38600000, + 0x38602000, + 0x38604000, + 0x38606000, + 0x38608000, + 0x3860a000, + 0x3860c000, + 0x3860e000, + 0x38610000, + 0x38612000, + 0x38614000, + 0x38616000, + 0x38618000, + 0x3861a000, + 0x3861c000, + 0x3861e000, + 0x38620000, + 0x38622000, + 0x38624000, + 0x38626000, + 0x38628000, + 0x3862a000, + 0x3862c000, + 0x3862e000, + 0x38630000, + 0x38632000, + 0x38634000, + 0x38636000, + 0x38638000, + 0x3863a000, + 0x3863c000, + 0x3863e000, + 0x38640000, + 0x38642000, + 0x38644000, + 0x38646000, + 0x38648000, + 0x3864a000, + 0x3864c000, + 0x3864e000, + 0x38650000, + 0x38652000, + 0x38654000, + 0x38656000, + 0x38658000, + 0x3865a000, + 0x3865c000, + 0x3865e000, + 0x38660000, + 0x38662000, + 0x38664000, + 0x38666000, + 0x38668000, + 0x3866a000, + 0x3866c000, + 0x3866e000, + 0x38670000, + 0x38672000, + 0x38674000, + 0x38676000, + 0x38678000, + 0x3867a000, + 0x3867c000, + 0x3867e000, + 0x38680000, + 0x38682000, + 0x38684000, + 0x38686000, + 0x38688000, + 0x3868a000, + 0x3868c000, + 0x3868e000, + 0x38690000, + 0x38692000, + 0x38694000, + 0x38696000, + 0x38698000, + 0x3869a000, + 0x3869c000, + 0x3869e000, + 0x386a0000, + 0x386a2000, + 0x386a4000, + 0x386a6000, + 0x386a8000, + 0x386aa000, + 0x386ac000, + 0x386ae000, + 0x386b0000, + 0x386b2000, + 0x386b4000, + 0x386b6000, + 0x386b8000, + 0x386ba000, + 0x386bc000, + 0x386be000, + 0x386c0000, + 0x386c2000, + 0x386c4000, + 0x386c6000, + 0x386c8000, + 0x386ca000, + 0x386cc000, + 0x386ce000, + 0x386d0000, + 0x386d2000, + 0x386d4000, + 0x386d6000, + 0x386d8000, + 0x386da000, + 0x386dc000, + 0x386de000, + 0x386e0000, + 0x386e2000, + 0x386e4000, + 0x386e6000, + 0x386e8000, + 0x386ea000, + 0x386ec000, + 0x386ee000, + 0x386f0000, + 0x386f2000, + 0x386f4000, + 0x386f6000, + 0x386f8000, + 0x386fa000, + 0x386fc000, + 0x386fe000, + 0x38700000, + 0x38702000, + 0x38704000, + 0x38706000, + 0x38708000, + 0x3870a000, + 0x3870c000, + 0x3870e000, + 0x38710000, + 0x38712000, + 0x38714000, + 0x38716000, + 0x38718000, + 0x3871a000, + 0x3871c000, + 0x3871e000, + 0x38720000, + 0x38722000, + 0x38724000, + 0x38726000, + 0x38728000, + 0x3872a000, + 0x3872c000, + 0x3872e000, + 0x38730000, + 0x38732000, + 0x38734000, + 0x38736000, + 0x38738000, + 0x3873a000, + 0x3873c000, + 0x3873e000, + 0x38740000, + 0x38742000, + 0x38744000, + 0x38746000, + 0x38748000, + 0x3874a000, + 0x3874c000, + 0x3874e000, + 0x38750000, + 0x38752000, + 0x38754000, + 0x38756000, + 0x38758000, + 0x3875a000, + 0x3875c000, + 0x3875e000, + 0x38760000, + 0x38762000, + 0x38764000, + 0x38766000, + 0x38768000, + 0x3876a000, + 0x3876c000, + 0x3876e000, + 0x38770000, + 0x38772000, + 0x38774000, + 0x38776000, + 0x38778000, + 0x3877a000, + 0x3877c000, + 0x3877e000, + 0x38780000, + 0x38782000, + 0x38784000, + 0x38786000, + 0x38788000, + 0x3878a000, + 0x3878c000, + 0x3878e000, + 0x38790000, + 0x38792000, + 0x38794000, + 0x38796000, + 0x38798000, + 0x3879a000, + 0x3879c000, + 0x3879e000, + 0x387a0000, + 0x387a2000, + 0x387a4000, + 0x387a6000, + 0x387a8000, + 0x387aa000, + 0x387ac000, + 0x387ae000, + 0x387b0000, + 0x387b2000, + 0x387b4000, + 0x387b6000, + 0x387b8000, + 0x387ba000, + 0x387bc000, + 0x387be000, + 0x387c0000, + 0x387c2000, + 0x387c4000, + 0x387c6000, + 0x387c8000, + 0x387ca000, + 0x387cc000, + 0x387ce000, + 0x387d0000, + 0x387d2000, + 0x387d4000, + 0x387d6000, + 0x387d8000, + 0x387da000, + 0x387dc000, + 0x387de000, + 0x387e0000, + 0x387e2000, + 0x387e4000, + 0x387e6000, + 0x387e8000, + 0x387ea000, + 0x387ec000, + 0x387ee000, + 0x387f0000, + 0x387f2000, + 0x387f4000, + 0x387f6000, + 0x387f8000, + 0x387fa000, + 0x387fc000, + 0x387fe000, +}; + +const static unsigned g_exponent[64] = { + 0x00000000, + 0x00800000, + 0x01000000, + 0x01800000, + 0x02000000, + 0x02800000, + 0x03000000, + 0x03800000, + 0x04000000, + 0x04800000, + 0x05000000, + 0x05800000, + 0x06000000, + 0x06800000, + 0x07000000, + 0x07800000, + 0x08000000, + 0x08800000, + 0x09000000, + 0x09800000, + 0x0a000000, + 0x0a800000, + 0x0b000000, + 0x0b800000, + 0x0c000000, + 0x0c800000, + 0x0d000000, + 0x0d800000, + 0x0e000000, + 0x0e800000, + 0x0f000000, + 0x47800000, + 0x80000000, + 0x80800000, + 0x81000000, + 0x81800000, + 0x82000000, + 0x82800000, + 0x83000000, + 0x83800000, + 0x84000000, + 0x84800000, + 0x85000000, + 0x85800000, + 0x86000000, + 0x86800000, + 0x87000000, + 0x87800000, + 0x88000000, + 0x88800000, + 0x89000000, + 0x89800000, + 0x8a000000, + 0x8a800000, + 0x8b000000, + 0x8b800000, + 0x8c000000, + 0x8c800000, + 0x8d000000, + 0x8d800000, + 0x8e000000, + 0x8e800000, + 0x8f000000, + 0xc7800000, +}; + +const static unsigned g_offset[64] = { + 0x00000000, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000000, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, + 0x00000400, +}; + +float float16ToFloat32(unsigned short h) +{ + unsigned i32 = g_mantissa[g_offset[h >> 10] + (h & 0x3ff)] + g_exponent[h >> 10]; + return *(float*) &i32; +} +} + diff --git a/src/3rdparty/angle/src/libANGLE/Framebuffer.cpp b/src/3rdparty/angle/src/libANGLE/Framebuffer.cpp new file mode 100644 index 0000000000..b1dd4a1b0f --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/Framebuffer.cpp @@ -0,0 +1,658 @@ +// +// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Framebuffer.cpp: Implements the gl::Framebuffer class. Implements GL framebuffer +// objects and related functionality. [OpenGL ES 2.0.24] section 4.4 page 105. + +#include "libANGLE/Framebuffer.h" + +#include "common/utilities.h" +#include "libANGLE/Config.h" +#include "libANGLE/Context.h" +#include "libANGLE/FramebufferAttachment.h" +#include "libANGLE/Renderbuffer.h" +#include "libANGLE/Surface.h" +#include "libANGLE/Texture.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/renderer/FramebufferImpl.h" +#include "libANGLE/renderer/ImplFactory.h" +#include "libANGLE/renderer/RenderbufferImpl.h" +#include "libANGLE/renderer/Workarounds.h" + +namespace gl +{ + +namespace +{ +void DeleteMatchingAttachment(FramebufferAttachment *&attachment, GLenum matchType, GLuint matchId) +{ + if (attachment && attachment->type() == matchType && attachment->id() == matchId) + { + SafeDelete(attachment); + } +} +} + +Framebuffer::Data::Data(const Caps &caps) + : mColorAttachments(caps.maxColorAttachments, nullptr), + mDepthAttachment(nullptr), + mStencilAttachment(nullptr), + mDrawBufferStates(caps.maxDrawBuffers, GL_NONE), + mReadBufferState(GL_COLOR_ATTACHMENT0_EXT) +{ + mDrawBufferStates[0] = GL_COLOR_ATTACHMENT0_EXT; +} + +Framebuffer::Data::~Data() +{ + for (auto it = mColorAttachments.begin(); it != mColorAttachments.end(); ++it) + { + SafeDelete(*it); + } + SafeDelete(mDepthAttachment); + SafeDelete(mStencilAttachment); +} + +FramebufferAttachment *Framebuffer::Data::getReadAttachment() const +{ + ASSERT(mReadBufferState == GL_BACK || (mReadBufferState >= GL_COLOR_ATTACHMENT0 && mReadBufferState <= GL_COLOR_ATTACHMENT15)); + size_t readIndex = (mReadBufferState == GL_BACK ? 0 : static_cast(mReadBufferState - GL_COLOR_ATTACHMENT0)); + ASSERT(readIndex < mColorAttachments.size()); + return mColorAttachments[readIndex]; +} + +FramebufferAttachment *Framebuffer::Data::getFirstColorAttachment() const +{ + for (auto it = mColorAttachments.cbegin(); it != mColorAttachments.cend(); ++it) + { + if (*it != nullptr) + { + return *it; + } + } + + return nullptr; +} + +FramebufferAttachment *Framebuffer::Data::getDepthOrStencilAttachment() const +{ + return (mDepthAttachment != nullptr ? mDepthAttachment : mStencilAttachment); +} + +Framebuffer::Framebuffer(const Caps &caps, rx::ImplFactory *factory, GLuint id) + : mData(caps), + mImpl(nullptr), + mId(id) +{ + if (mId == 0) + { + mImpl = factory->createDefaultFramebuffer(mData); + } + else + { + mImpl = factory->createFramebuffer(mData); + } + ASSERT(mImpl != nullptr); +} + +Framebuffer::~Framebuffer() +{ + SafeDelete(mImpl); +} + +void Framebuffer::detachTexture(GLuint textureId) +{ + detachResourceById(GL_TEXTURE, textureId); +} + +void Framebuffer::detachRenderbuffer(GLuint renderbufferId) +{ + detachResourceById(GL_RENDERBUFFER, renderbufferId); +} + +void Framebuffer::detachResourceById(GLenum resourceType, GLuint resourceId) +{ + for (auto it = mData.mColorAttachments.begin(); it != mData.mColorAttachments.end(); ++it) + { + DeleteMatchingAttachment(*it, resourceType, resourceId); + } + + DeleteMatchingAttachment(mData.mDepthAttachment, resourceType, resourceId); + DeleteMatchingAttachment(mData.mStencilAttachment, resourceType, resourceId); +} + +FramebufferAttachment *Framebuffer::getColorbuffer(unsigned int colorAttachment) const +{ + ASSERT(colorAttachment < mData.mColorAttachments.size()); + return mData.mColorAttachments[colorAttachment]; +} + +FramebufferAttachment *Framebuffer::getDepthbuffer() const +{ + return mData.mDepthAttachment; +} + +FramebufferAttachment *Framebuffer::getStencilbuffer() const +{ + return mData.mStencilAttachment; +} + +FramebufferAttachment *Framebuffer::getDepthStencilBuffer() const +{ + return (hasValidDepthStencil() ? mData.mDepthAttachment : NULL); +} + +FramebufferAttachment *Framebuffer::getDepthOrStencilbuffer() const +{ + return mData.getDepthOrStencilAttachment(); +} + +FramebufferAttachment *Framebuffer::getReadColorbuffer() const +{ + return mData.getReadAttachment(); +} + +GLenum Framebuffer::getReadColorbufferType() const +{ + FramebufferAttachment *readAttachment = mData.getReadAttachment(); + return (readAttachment ? readAttachment->type() : GL_NONE); +} + +FramebufferAttachment *Framebuffer::getFirstColorbuffer() const +{ + return mData.getFirstColorAttachment(); +} + +FramebufferAttachment *Framebuffer::getAttachment(GLenum attachment) const +{ + if (attachment >= GL_COLOR_ATTACHMENT0 && attachment <= GL_COLOR_ATTACHMENT15) + { + return getColorbuffer(attachment - GL_COLOR_ATTACHMENT0); + } + else + { + switch (attachment) + { + case GL_COLOR: + case GL_BACK: + return getColorbuffer(0); + case GL_DEPTH: + case GL_DEPTH_ATTACHMENT: + return getDepthbuffer(); + case GL_STENCIL: + case GL_STENCIL_ATTACHMENT: + return getStencilbuffer(); + case GL_DEPTH_STENCIL: + case GL_DEPTH_STENCIL_ATTACHMENT: + return getDepthStencilBuffer(); + default: + UNREACHABLE(); + return NULL; + } + } +} + +GLenum Framebuffer::getDrawBufferState(unsigned int colorAttachment) const +{ + ASSERT(colorAttachment < mData.mDrawBufferStates.size()); + return mData.mDrawBufferStates[colorAttachment]; +} + +void Framebuffer::setDrawBuffers(size_t count, const GLenum *buffers) +{ + auto &drawStates = mData.mDrawBufferStates; + + ASSERT(count <= drawStates.size()); + std::copy(buffers, buffers + count, drawStates.begin()); + std::fill(drawStates.begin() + count, drawStates.end(), GL_NONE); + mImpl->setDrawBuffers(count, buffers); +} + +GLenum Framebuffer::getReadBufferState() const +{ + return mData.mReadBufferState; +} + +void Framebuffer::setReadBuffer(GLenum buffer) +{ + ASSERT(buffer == GL_BACK || buffer == GL_NONE || + (buffer >= GL_COLOR_ATTACHMENT0 && + (buffer - GL_COLOR_ATTACHMENT0) < mData.mColorAttachments.size())); + mData.mReadBufferState = buffer; + mImpl->setReadBuffer(buffer); +} + +bool Framebuffer::isEnabledColorAttachment(unsigned int colorAttachment) const +{ + ASSERT(colorAttachment < mData.mColorAttachments.size()); + return (mData.mColorAttachments[colorAttachment] && + mData.mDrawBufferStates[colorAttachment] != GL_NONE); +} + +bool Framebuffer::hasEnabledColorAttachment() const +{ + for (size_t colorAttachment = 0; colorAttachment < mData.mColorAttachments.size(); ++colorAttachment) + { + if (isEnabledColorAttachment(colorAttachment)) + { + return true; + } + } + + return false; +} + +bool Framebuffer::hasStencil() const +{ + return (mData.mStencilAttachment && mData.mStencilAttachment->getStencilSize() > 0); +} + +bool Framebuffer::usingExtendedDrawBuffers() const +{ + for (size_t colorAttachment = 1; colorAttachment < mData.mColorAttachments.size(); ++colorAttachment) + { + if (isEnabledColorAttachment(colorAttachment)) + { + return true; + } + } + + return false; +} + +GLenum Framebuffer::checkStatus(const gl::Data &data) const +{ + // 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. + if (mId == 0) + { + return GL_FRAMEBUFFER_COMPLETE; + } + + int width = 0; + int height = 0; + unsigned int colorbufferSize = 0; + int samples = -1; + bool missingAttachment = true; + + for (auto it = mData.mColorAttachments.cbegin(); it != mData.mColorAttachments.cend(); ++it) + { + const auto &colorAttachment = *it; + if (colorAttachment != nullptr) + { + if (colorAttachment->getWidth() == 0 || colorAttachment->getHeight() == 0) + { + return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; + } + + GLenum internalformat = colorAttachment->getInternalFormat(); + const TextureCaps &formatCaps = data.textureCaps->get(internalformat); + const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat); + if (colorAttachment->type() == GL_TEXTURE) + { + if (!formatCaps.renderable) + { + return GL_FRAMEBUFFER_UNSUPPORTED; + } + + if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0) + { + return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; + } + } + else if (colorAttachment->type() == GL_RENDERBUFFER) + { + if (!formatCaps.renderable || formatInfo.depthBits > 0 || formatInfo.stencilBits > 0) + { + return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; + } + } + + if (!missingAttachment) + { + // all color attachments must have the same width and height + if (colorAttachment->getWidth() != width || colorAttachment->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 (colorAttachment->getSamples() != samples) + { + return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT; + } + + // in GLES 2.0, all color attachments attachments must have the same number of bitplanes + // in GLES 3.0, there is no such restriction + if (data.clientVersion < 3) + { + if (formatInfo.pixelBytes != colorbufferSize) + { + return GL_FRAMEBUFFER_UNSUPPORTED; + } + } + } + else + { + width = colorAttachment->getWidth(); + height = colorAttachment->getHeight(); + samples = colorAttachment->getSamples(); + colorbufferSize = formatInfo.pixelBytes; + missingAttachment = false; + } + } + } + + const FramebufferAttachment *depthAttachment = mData.mDepthAttachment; + if (depthAttachment != nullptr) + { + if (depthAttachment->getWidth() == 0 || depthAttachment->getHeight() == 0) + { + return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; + } + + GLenum internalformat = depthAttachment->getInternalFormat(); + const TextureCaps &formatCaps = data.textureCaps->get(internalformat); + const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat); + if (depthAttachment->type() == GL_TEXTURE) + { + // depth texture attachments require OES/ANGLE_depth_texture + if (!data.extensions->depthTextures) + { + return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; + } + + if (!formatCaps.renderable) + { + return GL_FRAMEBUFFER_UNSUPPORTED; + } + + if (formatInfo.depthBits == 0) + { + return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; + } + } + else if (depthAttachment->type() == GL_RENDERBUFFER) + { + if (!formatCaps.renderable || formatInfo.depthBits == 0) + { + return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; + } + } + + if (missingAttachment) + { + width = depthAttachment->getWidth(); + height = depthAttachment->getHeight(); + samples = depthAttachment->getSamples(); + missingAttachment = false; + } + else if (width != depthAttachment->getWidth() || height != depthAttachment->getHeight()) + { + return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS; + } + else if (samples != depthAttachment->getSamples()) + { + return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE; + } + } + + const FramebufferAttachment *stencilAttachment = mData.mStencilAttachment; + if (stencilAttachment) + { + if (stencilAttachment->getWidth() == 0 || stencilAttachment->getHeight() == 0) + { + return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; + } + + GLenum internalformat = stencilAttachment->getInternalFormat(); + const TextureCaps &formatCaps = data.textureCaps->get(internalformat); + const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat); + if (stencilAttachment->type() == GL_TEXTURE) + { + // texture stencil attachments come along as part + // of OES_packed_depth_stencil + OES/ANGLE_depth_texture + if (!data.extensions->depthTextures) + { + return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; + } + + if (!formatCaps.renderable) + { + return GL_FRAMEBUFFER_UNSUPPORTED; + } + + if (formatInfo.stencilBits == 0) + { + return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; + } + } + else if (stencilAttachment->type() == GL_RENDERBUFFER) + { + if (!formatCaps.renderable || formatInfo.stencilBits == 0) + { + return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; + } + } + + if (missingAttachment) + { + width = stencilAttachment->getWidth(); + height = stencilAttachment->getHeight(); + samples = stencilAttachment->getSamples(); + missingAttachment = false; + } + else if (width != stencilAttachment->getWidth() || height != stencilAttachment->getHeight()) + { + return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS; + } + else if (samples != stencilAttachment->getSamples()) + { + return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE; + } + } + + // if we have both a depth and stencil buffer, they must refer to the same object + // since we only support packed_depth_stencil and not separate depth and stencil + if (depthAttachment && stencilAttachment && !hasValidDepthStencil()) + { + return GL_FRAMEBUFFER_UNSUPPORTED; + } + + // we need to have at least one attachment to be complete + if (missingAttachment) + { + return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT; + } + + return mImpl->checkStatus(); +} + +Error Framebuffer::invalidate(size_t count, const GLenum *attachments) +{ + return mImpl->invalidate(count, attachments); +} + +Error Framebuffer::invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area) +{ + return mImpl->invalidateSub(count, attachments, area); +} + +Error Framebuffer::clear(const gl::Data &data, GLbitfield mask) +{ + return mImpl->clear(data, mask); +} + +Error Framebuffer::clearBufferfv(const State &state, GLenum buffer, GLint drawbuffer, const GLfloat *values) +{ + return mImpl->clearBufferfv(state, buffer, drawbuffer, values); +} + +Error Framebuffer::clearBufferuiv(const State &state, GLenum buffer, GLint drawbuffer, const GLuint *values) +{ + return mImpl->clearBufferuiv(state, buffer, drawbuffer, values); +} + +Error Framebuffer::clearBufferiv(const State &state, GLenum buffer, GLint drawbuffer, const GLint *values) +{ + return mImpl->clearBufferiv(state, buffer, drawbuffer, values); +} + +Error Framebuffer::clearBufferfi(const State &state, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) +{ + return mImpl->clearBufferfi(state, buffer, drawbuffer, depth, stencil); +} + +GLenum Framebuffer::getImplementationColorReadFormat() const +{ + return mImpl->getImplementationColorReadFormat(); +} + +GLenum Framebuffer::getImplementationColorReadType() const +{ + return mImpl->getImplementationColorReadType(); +} + +Error Framebuffer::readPixels(const gl::State &state, const gl::Rectangle &area, GLenum format, GLenum type, GLvoid *pixels) const +{ + return mImpl->readPixels(state, area, format, type, pixels); +} + +Error Framebuffer::blit(const gl::State &state, const gl::Rectangle &sourceArea, const gl::Rectangle &destArea, + GLbitfield mask, GLenum filter, const gl::Framebuffer *sourceFramebuffer) +{ + return mImpl->blit(state, sourceArea, destArea, mask, filter, sourceFramebuffer); +} + +int Framebuffer::getSamples(const gl::Data &data) const +{ + if (checkStatus(data) == GL_FRAMEBUFFER_COMPLETE) + { + // for a complete framebuffer, all attachments must have the same sample count + // in this case return the first nonzero sample size + for (auto it = mData.mColorAttachments.cbegin(); it != mData.mColorAttachments.cend(); ++it) + { + if (*it != nullptr) + { + return (*it)->getSamples(); + } + } + } + + return 0; +} + +bool Framebuffer::hasValidDepthStencil() const +{ + // A valid depth-stencil attachment has the same resource bound to both the + // depth and stencil attachment points. + return (mData.mDepthAttachment && mData.mStencilAttachment && + mData.mDepthAttachment->type() == mData.mStencilAttachment->type() && + mData.mDepthAttachment->id() == mData.mStencilAttachment->id()); +} + +void Framebuffer::setTextureAttachment(GLenum attachment, Texture *texture, const ImageIndex &imageIndex) +{ + setAttachment(attachment, new TextureAttachment(attachment, texture, imageIndex)); +} + +void Framebuffer::setRenderbufferAttachment(GLenum attachment, Renderbuffer *renderbuffer) +{ + setAttachment(attachment, new RenderbufferAttachment(attachment, renderbuffer)); +} + +void Framebuffer::setNULLAttachment(GLenum attachment) +{ + setAttachment(attachment, NULL); +} + +void Framebuffer::setAttachment(GLenum attachment, FramebufferAttachment *attachmentObj) +{ + if (attachment >= GL_COLOR_ATTACHMENT0 && attachment < (GL_COLOR_ATTACHMENT0 + mData.mColorAttachments.size())) + { + size_t colorAttachment = attachment - GL_COLOR_ATTACHMENT0; + SafeDelete(mData.mColorAttachments[colorAttachment]); + mData.mColorAttachments[colorAttachment] = attachmentObj; + mImpl->setColorAttachment(colorAttachment, attachmentObj); + } + else if (attachment == GL_BACK) + { + SafeDelete(mData.mColorAttachments[0]); + mData.mColorAttachments[0] = attachmentObj; + mImpl->setColorAttachment(0, attachmentObj); + } + else if (attachment == GL_DEPTH_ATTACHMENT || attachment == GL_DEPTH) + { + SafeDelete(mData.mDepthAttachment); + mData.mDepthAttachment = attachmentObj; + mImpl->setDepthAttachment(attachmentObj); + } + else if (attachment == GL_STENCIL_ATTACHMENT || attachment == GL_STENCIL) + { + SafeDelete(mData.mStencilAttachment); + mData.mStencilAttachment = attachmentObj; + mImpl->setStencilAttachment(attachmentObj); + } + else if (attachment == GL_DEPTH_STENCIL_ATTACHMENT || attachment == GL_DEPTH_STENCIL) + { + SafeDelete(mData.mDepthAttachment); + SafeDelete(mData.mStencilAttachment); + + // ensure this is a legitimate depth+stencil format + if (attachmentObj && attachmentObj->getDepthSize() > 0 && attachmentObj->getStencilSize() > 0) + { + mData.mDepthAttachment = attachmentObj; + mImpl->setDepthAttachment(attachmentObj); + + // Make a new attachment object to ensure we do not double-delete + // See angle issue 686 + if (attachmentObj->type() == GL_TEXTURE) + { + mData.mStencilAttachment = new TextureAttachment(GL_DEPTH_STENCIL_ATTACHMENT, attachmentObj->getTexture(), + *attachmentObj->getTextureImageIndex()); + mImpl->setStencilAttachment(mData.mStencilAttachment); + } + else if (attachmentObj->type() == GL_RENDERBUFFER) + { + mData.mStencilAttachment = new RenderbufferAttachment(GL_DEPTH_STENCIL_ATTACHMENT, attachmentObj->getRenderbuffer()); + mImpl->setStencilAttachment(mData.mStencilAttachment); + } + else + { + UNREACHABLE(); + } + } + } + else + { + UNREACHABLE(); + } +} + +DefaultFramebuffer::DefaultFramebuffer(const Caps &caps, rx::ImplFactory *factory, egl::Surface *surface) + : Framebuffer(caps, factory, 0) +{ + const egl::Config *config = surface->getConfig(); + + setAttachment(GL_BACK, new DefaultAttachment(GL_BACK, surface)); + + if (config->depthSize > 0) + { + setAttachment(GL_DEPTH, new DefaultAttachment(GL_DEPTH, surface)); + } + if (config->stencilSize > 0) + { + setAttachment(GL_STENCIL, new DefaultAttachment(GL_STENCIL, surface)); + } + + GLenum drawBufferState = GL_BACK; + setDrawBuffers(1, &drawBufferState); + + setReadBuffer(GL_BACK); +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/Framebuffer.h b/src/3rdparty/angle/src/libANGLE/Framebuffer.h new file mode 100644 index 0000000000..8b24cf984e --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/Framebuffer.h @@ -0,0 +1,144 @@ +// +// 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. +// + +// Framebuffer.h: Defines the gl::Framebuffer class. Implements GL framebuffer +// objects and related functionality. [OpenGL ES 2.0.24] section 4.4 page 105. + +#ifndef LIBANGLE_FRAMEBUFFER_H_ +#define LIBANGLE_FRAMEBUFFER_H_ + +#include + +#include "common/angleutils.h" +#include "libANGLE/Constants.h" +#include "libANGLE/Error.h" +#include "libANGLE/RefCountObject.h" + +namespace rx +{ +class ImplFactory; +class FramebufferImpl; +class RenderbufferImpl; +struct Workarounds; +} + +namespace egl +{ +class Surface; +} + +namespace gl +{ +class FramebufferAttachment; +class Renderbuffer; +class State; +class Texture; +class TextureCapsMap; +struct Caps; +struct Data; +struct Extensions; +struct ImageIndex; +struct Rectangle; + +typedef std::vector AttachmentList; + +class Framebuffer +{ + public: + + class Data final : angle::NonCopyable + { + public: + explicit Data(const Caps &caps); + ~Data(); + + FramebufferAttachment *getReadAttachment() const; + FramebufferAttachment *getFirstColorAttachment() const; + FramebufferAttachment *getDepthOrStencilAttachment() const; + + AttachmentList mColorAttachments; + FramebufferAttachment *mDepthAttachment; + FramebufferAttachment *mStencilAttachment; + + std::vector mDrawBufferStates; + GLenum mReadBufferState; + }; + + Framebuffer(const Caps &caps, rx::ImplFactory *factory, GLuint id); + virtual ~Framebuffer(); + + const rx::FramebufferImpl *getImplementation() const { return mImpl; } + rx::FramebufferImpl *getImplementation() { return mImpl; } + + GLuint id() const { return mId; } + + void setTextureAttachment(GLenum attachment, Texture *texture, const ImageIndex &imageIndex); + void setRenderbufferAttachment(GLenum attachment, Renderbuffer *renderbuffer); + void setNULLAttachment(GLenum attachment); + + void detachTexture(GLuint texture); + void detachRenderbuffer(GLuint renderbuffer); + + FramebufferAttachment *getColorbuffer(unsigned int colorAttachment) const; + FramebufferAttachment *getDepthbuffer() const; + FramebufferAttachment *getStencilbuffer() const; + FramebufferAttachment *getDepthStencilBuffer() const; + FramebufferAttachment *getDepthOrStencilbuffer() const; + FramebufferAttachment *getReadColorbuffer() const; + GLenum getReadColorbufferType() const; + FramebufferAttachment *getFirstColorbuffer() const; + + FramebufferAttachment *getAttachment(GLenum attachment) const; + + GLenum getDrawBufferState(unsigned int colorAttachment) const; + void setDrawBuffers(size_t count, const GLenum *buffers); + + GLenum getReadBufferState() const; + void setReadBuffer(GLenum buffer); + + bool isEnabledColorAttachment(unsigned int colorAttachment) const; + bool hasEnabledColorAttachment() const; + bool hasStencil() const; + int getSamples(const gl::Data &data) const; + bool usingExtendedDrawBuffers() const; + + GLenum checkStatus(const gl::Data &data) const; + bool hasValidDepthStencil() const; + + Error invalidate(size_t count, const GLenum *attachments); + Error invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area); + + Error clear(const gl::Data &data, GLbitfield mask); + Error clearBufferfv(const State &state, GLenum buffer, GLint drawbuffer, const GLfloat *values); + Error clearBufferuiv(const State &state, GLenum buffer, GLint drawbuffer, const GLuint *values); + Error clearBufferiv(const State &state, GLenum buffer, GLint drawbuffer, const GLint *values); + Error clearBufferfi(const State &state, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil); + + GLenum getImplementationColorReadFormat() const; + GLenum getImplementationColorReadType() const; + Error readPixels(const gl::State &state, const gl::Rectangle &area, GLenum format, GLenum type, GLvoid *pixels) const; + + Error blit(const gl::State &state, const gl::Rectangle &sourceArea, const gl::Rectangle &destArea, + GLbitfield mask, GLenum filter, const gl::Framebuffer *sourceFramebuffer); + + protected: + void setAttachment(GLenum attachment, FramebufferAttachment *attachmentObj); + void detachResourceById(GLenum resourceType, GLuint resourceId); + + Data mData; + rx::FramebufferImpl *mImpl; + GLuint mId; +}; + +class DefaultFramebuffer : public Framebuffer +{ + public: + DefaultFramebuffer(const gl::Caps &caps, rx::ImplFactory *factory, egl::Surface *surface); +}; + +} + +#endif // LIBANGLE_FRAMEBUFFER_H_ diff --git a/src/3rdparty/angle/src/libANGLE/FramebufferAttachment.cpp b/src/3rdparty/angle/src/libANGLE/FramebufferAttachment.cpp new file mode 100644 index 0000000000..e56fc750ad --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/FramebufferAttachment.cpp @@ -0,0 +1,302 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// FramebufferAttachment.cpp: the gl::FramebufferAttachment class and its derived classes +// objects and related functionality. [OpenGL ES 2.0.24] section 4.4.3 page 108. + +#include "libANGLE/FramebufferAttachment.h" + +#include "common/utilities.h" +#include "libANGLE/Config.h" +#include "libANGLE/Renderbuffer.h" +#include "libANGLE/Surface.h" +#include "libANGLE/Texture.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/renderer/FramebufferImpl.h" + +namespace gl +{ + +////// FramebufferAttachment Implementation ////// + +FramebufferAttachment::FramebufferAttachment(GLenum binding) + : mBinding(binding) +{ +} + +FramebufferAttachment::~FramebufferAttachment() +{ +} + +GLuint FramebufferAttachment::getRedSize() const +{ + return GetInternalFormatInfo(getInternalFormat()).redBits; +} + +GLuint FramebufferAttachment::getGreenSize() const +{ + return GetInternalFormatInfo(getInternalFormat()).greenBits; +} + +GLuint FramebufferAttachment::getBlueSize() const +{ + return GetInternalFormatInfo(getInternalFormat()).blueBits; +} + +GLuint FramebufferAttachment::getAlphaSize() const +{ + return GetInternalFormatInfo(getInternalFormat()).alphaBits; +} + +GLuint FramebufferAttachment::getDepthSize() const +{ + return GetInternalFormatInfo(getInternalFormat()).depthBits; +} + +GLuint FramebufferAttachment::getStencilSize() const +{ + return GetInternalFormatInfo(getInternalFormat()).stencilBits; +} + +GLenum FramebufferAttachment::getComponentType() const +{ + return GetInternalFormatInfo(getInternalFormat()).componentType; +} + +GLenum FramebufferAttachment::getColorEncoding() const +{ + return GetInternalFormatInfo(getInternalFormat()).colorEncoding; +} + +///// TextureAttachment Implementation //////// + +TextureAttachment::TextureAttachment(GLenum binding, Texture *texture, const ImageIndex &index) + : FramebufferAttachment(binding), + mIndex(index) +{ + mTexture.set(texture); +} + +TextureAttachment::~TextureAttachment() +{ + mTexture.set(NULL); +} + +GLsizei TextureAttachment::getSamples() const +{ + return 0; +} + +GLuint TextureAttachment::id() const +{ + return mTexture->id(); +} + +GLsizei TextureAttachment::getWidth() const +{ + return mTexture->getWidth(mIndex.type, mIndex.mipIndex); +} + +GLsizei TextureAttachment::getHeight() const +{ + return mTexture->getHeight(mIndex.type, mIndex.mipIndex); +} + +GLenum TextureAttachment::getInternalFormat() const +{ + return mTexture->getInternalFormat(mIndex.type, mIndex.mipIndex); +} + +GLenum TextureAttachment::type() const +{ + return GL_TEXTURE; +} + +GLint TextureAttachment::mipLevel() const +{ + return mIndex.mipIndex; +} + +GLenum TextureAttachment::cubeMapFace() const +{ + return IsCubeMapTextureTarget(mIndex.type) ? mIndex.type : GL_NONE; +} + +GLint TextureAttachment::layer() const +{ + return mIndex.layerIndex; +} + +Texture *TextureAttachment::getTexture() const +{ + return mTexture.get(); +} + +const ImageIndex *TextureAttachment::getTextureImageIndex() const +{ + return &mIndex; +} + +Renderbuffer *TextureAttachment::getRenderbuffer() const +{ + UNREACHABLE(); + return NULL; +} + +////// RenderbufferAttachment Implementation ////// + +RenderbufferAttachment::RenderbufferAttachment(GLenum binding, Renderbuffer *renderbuffer) + : FramebufferAttachment(binding) +{ + ASSERT(renderbuffer); + mRenderbuffer.set(renderbuffer); +} + +RenderbufferAttachment::~RenderbufferAttachment() +{ + mRenderbuffer.set(NULL); +} + +GLsizei RenderbufferAttachment::getWidth() const +{ + return mRenderbuffer->getWidth(); +} + +GLsizei RenderbufferAttachment::getHeight() const +{ + return mRenderbuffer->getHeight(); +} + +GLenum RenderbufferAttachment::getInternalFormat() const +{ + return mRenderbuffer->getInternalFormat(); +} + +GLsizei RenderbufferAttachment::getSamples() const +{ + return mRenderbuffer->getSamples(); +} + +GLuint RenderbufferAttachment::id() const +{ + return mRenderbuffer->id(); +} + +GLenum RenderbufferAttachment::type() const +{ + return GL_RENDERBUFFER; +} + +GLint RenderbufferAttachment::mipLevel() const +{ + return 0; +} + +GLenum RenderbufferAttachment::cubeMapFace() const +{ + return GL_NONE; +} + +GLint RenderbufferAttachment::layer() const +{ + return 0; +} + +Texture *RenderbufferAttachment::getTexture() const +{ + UNREACHABLE(); + return NULL; +} + +const ImageIndex *RenderbufferAttachment::getTextureImageIndex() const +{ + UNREACHABLE(); + return NULL; +} + +Renderbuffer *RenderbufferAttachment::getRenderbuffer() const +{ + return mRenderbuffer.get(); +} + + +DefaultAttachment::DefaultAttachment(GLenum binding, egl::Surface *surface) + : FramebufferAttachment(binding) +{ + mSurface.set(surface); +} + +DefaultAttachment::~DefaultAttachment() +{ + mSurface.set(nullptr); +} + +GLsizei DefaultAttachment::getWidth() const +{ + return mSurface->getWidth(); +} + +GLsizei DefaultAttachment::getHeight() const +{ + return mSurface->getHeight(); +} + +GLenum DefaultAttachment::getInternalFormat() const +{ + const egl::Config *config = mSurface->getConfig(); + return (getBinding() == GL_BACK ? config->renderTargetFormat : config->depthStencilFormat); +} + +GLsizei DefaultAttachment::getSamples() const +{ + const egl::Config *config = mSurface->getConfig(); + return config->samples; +} + +GLuint DefaultAttachment::id() const +{ + return 0; +} + +GLenum DefaultAttachment::type() const +{ + return GL_FRAMEBUFFER_DEFAULT; +} + +GLint DefaultAttachment::mipLevel() const +{ + return 0; +} + +GLenum DefaultAttachment::cubeMapFace() const +{ + return GL_NONE; +} + +GLint DefaultAttachment::layer() const +{ + return 0; +} + +Texture *DefaultAttachment::getTexture() const +{ + UNREACHABLE(); + return NULL; +} + +const ImageIndex *DefaultAttachment::getTextureImageIndex() const +{ + UNREACHABLE(); + return NULL; +} + +Renderbuffer *DefaultAttachment::getRenderbuffer() const +{ + UNREACHABLE(); + return NULL; +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/FramebufferAttachment.h b/src/3rdparty/angle/src/libANGLE/FramebufferAttachment.h new file mode 100644 index 0000000000..0662130931 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/FramebufferAttachment.h @@ -0,0 +1,154 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// FramebufferAttachment.h: Defines the wrapper class gl::FramebufferAttachment, as well as the +// objects and related functionality. [OpenGL ES 2.0.24] section 4.4.3 page 108. + +#ifndef LIBANGLE_FRAMEBUFFERATTACHMENT_H_ +#define LIBANGLE_FRAMEBUFFERATTACHMENT_H_ + +#include "libANGLE/Texture.h" +#include "libANGLE/RefCountObject.h" + +#include "common/angleutils.h" + +#include "angle_gl.h" + +namespace gl +{ +class Renderbuffer; + +// FramebufferAttachment implements a GL framebuffer attachment. +// Attachments are "light" containers, which store pointers to ref-counted GL objects. +// We support GL texture (2D/3D/Cube/2D array) and renderbuffer object attachments. +// Note: Our old naming scheme used the term "Renderbuffer" for both GL renderbuffers and for +// framebuffer attachments, which confused their usage. + +class FramebufferAttachment : angle::NonCopyable +{ + public: + explicit FramebufferAttachment(GLenum binding); + virtual ~FramebufferAttachment(); + + // Helper methods + GLuint getRedSize() const; + GLuint getGreenSize() const; + GLuint getBlueSize() const; + GLuint getAlphaSize() const; + GLuint getDepthSize() const; + GLuint getStencilSize() const; + GLenum getComponentType() const; + GLenum getColorEncoding() const; + + bool isTextureWithId(GLuint textureId) const { return type() == GL_TEXTURE && id() == textureId; } + bool isRenderbufferWithId(GLuint renderbufferId) const { return type() == GL_RENDERBUFFER && id() == renderbufferId; } + + GLenum getBinding() const { return mBinding; } + + // Child class interface + virtual GLsizei getWidth() const = 0; + virtual GLsizei getHeight() const = 0; + virtual GLenum getInternalFormat() const = 0; + virtual GLsizei getSamples() const = 0; + + virtual GLuint id() const = 0; + virtual GLenum type() const = 0; + virtual GLint mipLevel() const = 0; + virtual GLenum cubeMapFace() const = 0; + virtual GLint layer() const = 0; + + virtual Texture *getTexture() const = 0; + virtual const ImageIndex *getTextureImageIndex() const = 0; + virtual Renderbuffer *getRenderbuffer() const = 0; + + private: + GLenum mBinding; +}; + +class TextureAttachment : public FramebufferAttachment +{ + public: + TextureAttachment(GLenum binding, Texture *texture, const ImageIndex &index); + virtual ~TextureAttachment(); + + virtual GLsizei getSamples() const; + virtual GLuint id() const; + + virtual GLsizei getWidth() const; + virtual GLsizei getHeight() const; + virtual GLenum getInternalFormat() const; + + virtual GLenum type() const; + virtual GLint mipLevel() const; + virtual GLenum cubeMapFace() const; + virtual GLint layer() const; + + virtual Texture *getTexture() const; + virtual const ImageIndex *getTextureImageIndex() const; + virtual Renderbuffer *getRenderbuffer() const; + + private: + BindingPointer mTexture; + ImageIndex mIndex; +}; + +class RenderbufferAttachment : public FramebufferAttachment +{ + public: + RenderbufferAttachment(GLenum binding, Renderbuffer *renderbuffer); + + virtual ~RenderbufferAttachment(); + + virtual GLsizei getWidth() const; + virtual GLsizei getHeight() const; + virtual GLenum getInternalFormat() const; + virtual GLsizei getSamples() const; + + virtual GLuint id() const; + virtual GLenum type() const; + virtual GLint mipLevel() const; + virtual GLenum cubeMapFace() const; + virtual GLint layer() const; + + virtual Texture *getTexture() const; + virtual const ImageIndex *getTextureImageIndex() const; + virtual Renderbuffer *getRenderbuffer() const; + + private: + BindingPointer mRenderbuffer; +}; + +class DefaultAttachment : public FramebufferAttachment +{ + public: + DefaultAttachment(GLenum binding, egl::Surface *surface); + + virtual ~DefaultAttachment(); + + virtual GLsizei getWidth() const; + virtual GLsizei getHeight() const; + virtual GLenum getInternalFormat() const; + virtual GLsizei getSamples() const; + + virtual GLuint id() const; + virtual GLenum type() const; + virtual GLint mipLevel() const; + virtual GLenum cubeMapFace() const; + virtual GLint layer() const; + + virtual Texture *getTexture() const; + virtual const ImageIndex *getTextureImageIndex() const; + virtual Renderbuffer *getRenderbuffer() const; + + const egl::Surface *getSurface() const { return mSurface.get(); } + + private: + BindingPointer mSurface; +}; + +} + +#endif // LIBANGLE_FRAMEBUFFERATTACHMENT_H_ diff --git a/src/3rdparty/angle/src/libANGLE/HandleAllocator.cpp b/src/3rdparty/angle/src/libANGLE/HandleAllocator.cpp new file mode 100644 index 0000000000..59d3966758 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/HandleAllocator.cpp @@ -0,0 +1,133 @@ +// +// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// HandleAllocator.cpp: Implements the gl::HandleAllocator class, which is used +// to allocate GL handles. + +#include "libANGLE/HandleAllocator.h" + +#include + +#include "common/debug.h" + +namespace gl +{ + +struct HandleAllocator::HandleRangeComparator +{ + bool operator()(const HandleRange &range, GLuint handle) const + { + return (handle < range.begin); + } +}; + +HandleAllocator::HandleAllocator() : mBaseValue(1), mNextValue(1) +{ + mUnallocatedList.push_back(HandleRange(1, std::numeric_limits::max() - 1)); +} + +HandleAllocator::HandleAllocator(GLuint maximumHandleValue) : mBaseValue(1), mNextValue(1) +{ + mUnallocatedList.push_back(HandleRange(1, maximumHandleValue)); +} + +HandleAllocator::~HandleAllocator() +{ +} + +void HandleAllocator::setBaseHandle(GLuint value) +{ + ASSERT(mBaseValue == mNextValue); + mBaseValue = value; + mNextValue = value; +} + +GLuint HandleAllocator::allocate() +{ + ASSERT(!mUnallocatedList.empty() || !mReleasedList.empty()); + + // Allocate from released list, constant time. + if (!mReleasedList.empty()) + { + GLuint reusedHandle = mReleasedList.back(); + mReleasedList.pop_back(); + return reusedHandle; + } + + // Allocate from unallocated list, constant time. + auto listIt = mUnallocatedList.begin(); + + GLuint freeListHandle = listIt->begin; + ASSERT(freeListHandle > 0); + + listIt->begin++; + if (listIt->begin == listIt->end) + { + mUnallocatedList.erase(listIt); + } + + return freeListHandle; +} + +void HandleAllocator::release(GLuint handle) +{ + // Add to released list, constant time. + mReleasedList.push_back(handle); +} + +void HandleAllocator::reserve(GLuint handle) +{ + // Clear from released list -- might be a slow operation. + if (!mReleasedList.empty()) + { + auto releasedIt = std::find(mReleasedList.begin(), mReleasedList.end(), handle); + if (releasedIt != mReleasedList.end()) + { + mReleasedList.erase(releasedIt); + return; + } + } + + // Not in released list, reserve in the unallocated list. + auto boundIt = std::lower_bound(mUnallocatedList.begin(), mUnallocatedList.end(), handle, HandleRangeComparator()); + + ASSERT(boundIt != mUnallocatedList.end()); + + GLuint begin = boundIt->begin; + GLuint end = boundIt->end; + + if (handle == begin || handle == end) + { + if (begin + 1 == end) + { + mUnallocatedList.erase(boundIt); + } + else if (handle == begin) + { + boundIt->begin++; + } + else + { + ASSERT(handle == end); + boundIt->end--; + } + return; + } + + // need to split the range + auto placementIt = mUnallocatedList.erase(boundIt); + + if (begin != handle) + { + placementIt = mUnallocatedList.insert(placementIt, HandleRange(begin, handle)); + } + if (handle + 1 != end) + { + mUnallocatedList.insert(placementIt, HandleRange(handle + 1, end)); + } +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/HandleAllocator.h b/src/3rdparty/angle/src/libANGLE/HandleAllocator.h new file mode 100644 index 0000000000..c22f2ba61a --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/HandleAllocator.h @@ -0,0 +1,63 @@ +// +// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// HandleAllocator.h: Defines the gl::HandleAllocator class, which is used to +// allocate GL handles. + +#ifndef LIBANGLE_HANDLEALLOCATOR_H_ +#define LIBANGLE_HANDLEALLOCATOR_H_ + +#include "common/angleutils.h" + +#include "angle_gl.h" + +#include + +namespace gl +{ + +class HandleAllocator final : angle::NonCopyable +{ + public: + // Maximum handle = MAX_UINT-1 + HandleAllocator(); + // Specify maximum handle value + HandleAllocator(GLuint maximumHandleValue); + + ~HandleAllocator(); + + void setBaseHandle(GLuint value); + + GLuint allocate(); + void release(GLuint handle); + void reserve(GLuint handle); + + private: + GLuint mBaseValue; + GLuint mNextValue; + typedef std::vector HandleList; + HandleList mFreeValues; + + struct HandleRange + { + HandleRange(GLuint beginIn, GLuint endIn) : begin(beginIn), end(endIn) {} + + GLuint begin; + GLuint end; + }; + + struct HandleRangeComparator; + + // The freelist consists of never-allocated handles, stored + // as ranges, and handles that were previously allocated and + // released, stored in a stack. + std::vector mUnallocatedList; + std::vector mReleasedList; +}; + +} + +#endif // LIBANGLE_HANDLEALLOCATOR_H_ diff --git a/src/3rdparty/angle/src/libANGLE/ImageIndex.cpp b/src/3rdparty/angle/src/libANGLE/ImageIndex.cpp new file mode 100644 index 0000000000..ac7302d121 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/ImageIndex.cpp @@ -0,0 +1,170 @@ +// +// Copyright 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// ImageIndex.cpp: Implementation for ImageIndex methods. + +#include "libANGLE/ImageIndex.h" +#include "libANGLE/Constants.h" +#include "common/utilities.h" + +namespace gl +{ + +ImageIndex::ImageIndex(const ImageIndex &other) + : type(other.type), + mipIndex(other.mipIndex), + layerIndex(other.layerIndex) +{} + +ImageIndex &ImageIndex::operator=(const ImageIndex &other) +{ + type = other.type; + mipIndex = other.mipIndex; + layerIndex = other.layerIndex; + return *this; +} + +ImageIndex ImageIndex::Make2D(GLint mipIndex) +{ + return ImageIndex(GL_TEXTURE_2D, mipIndex, ENTIRE_LEVEL); +} + +ImageIndex ImageIndex::MakeCube(GLenum target, GLint mipIndex) +{ + ASSERT(gl::IsCubeMapTextureTarget(target)); + return ImageIndex(target, mipIndex, CubeMapTextureTargetToLayerIndex(target)); +} + +ImageIndex ImageIndex::Make2DArray(GLint mipIndex, GLint layerIndex) +{ + return ImageIndex(GL_TEXTURE_2D_ARRAY, mipIndex, layerIndex); +} + +ImageIndex ImageIndex::Make3D(GLint mipIndex, GLint layerIndex) +{ + return ImageIndex(GL_TEXTURE_3D, mipIndex, layerIndex); +} + +ImageIndex ImageIndex::MakeGeneric(GLenum target, GLint mipIndex) +{ + GLint layerIndex = IsCubeMapTextureTarget(target) ? CubeMapTextureTargetToLayerIndex(target) : ENTIRE_LEVEL; + return ImageIndex(target, mipIndex, layerIndex); +} + +ImageIndex ImageIndex::MakeInvalid() +{ + return ImageIndex(GL_NONE, -1, -1); +} + +bool ImageIndex::operator<(const ImageIndex &other) const +{ + if (type != other.type) + { + return type < other.type; + } + else if (mipIndex != other.mipIndex) + { + return mipIndex < other.mipIndex; + } + else + { + return layerIndex < other.layerIndex; + } +} + +ImageIndex::ImageIndex(GLenum typeIn, GLint mipIndexIn, GLint layerIndexIn) + : type(typeIn), + mipIndex(mipIndexIn), + layerIndex(layerIndexIn) +{} + +ImageIndexIterator ImageIndexIterator::Make2D(GLint minMip, GLint maxMip) +{ + return ImageIndexIterator(GL_TEXTURE_2D, rx::Range(minMip, maxMip), + rx::Range(ImageIndex::ENTIRE_LEVEL, ImageIndex::ENTIRE_LEVEL), NULL); +} + +ImageIndexIterator ImageIndexIterator::MakeCube(GLint minMip, GLint maxMip) +{ + return ImageIndexIterator(GL_TEXTURE_CUBE_MAP, rx::Range(minMip, maxMip), rx::Range(0, 6), NULL); +} + +ImageIndexIterator ImageIndexIterator::Make3D(GLint minMip, GLint maxMip, + GLint minLayer, GLint maxLayer) +{ + return ImageIndexIterator(GL_TEXTURE_3D, rx::Range(minMip, maxMip), rx::Range(minLayer, maxLayer), NULL); +} + +ImageIndexIterator ImageIndexIterator::Make2DArray(GLint minMip, GLint maxMip, + const GLsizei *layerCounts) +{ + return ImageIndexIterator(GL_TEXTURE_2D_ARRAY, rx::Range(minMip, maxMip), + rx::Range(0, IMPLEMENTATION_MAX_2D_ARRAY_TEXTURE_LAYERS), layerCounts); +} + +ImageIndexIterator::ImageIndexIterator(GLenum type, const rx::Range &mipRange, + const rx::Range &layerRange, const GLsizei *layerCounts) + : mType(type), + mMipRange(mipRange), + mLayerRange(layerRange), + mLayerCounts(layerCounts), + mCurrentMip(mipRange.start), + mCurrentLayer(layerRange.start) +{} + +GLint ImageIndexIterator::maxLayer() const +{ + return (mLayerCounts ? static_cast(mLayerCounts[mCurrentMip]) : mLayerRange.end); +} + +ImageIndex ImageIndexIterator::next() +{ + ASSERT(hasNext()); + + ImageIndex value = current(); + + // Iterate layers in the inner loop for now. We can add switchable + // layer or mip iteration if we need it. + + if (mCurrentLayer != ImageIndex::ENTIRE_LEVEL) + { + if (mCurrentLayer < maxLayer()-1) + { + mCurrentLayer++; + } + else if (mCurrentMip < mMipRange.end-1) + { + mCurrentMip++; + mCurrentLayer = mLayerRange.start; + } + } + else if (mCurrentMip < mMipRange.end-1) + { + mCurrentMip++; + mCurrentLayer = mLayerRange.start; + } + + return value; +} + +ImageIndex ImageIndexIterator::current() const +{ + ImageIndex value(mType, mCurrentMip, mCurrentLayer); + + if (mType == GL_TEXTURE_CUBE_MAP) + { + value.type = LayerIndexToCubeMapTextureTarget(mCurrentLayer); + } + + return value; +} + +bool ImageIndexIterator::hasNext() const +{ + return (mCurrentMip < mMipRange.end || mCurrentLayer < maxLayer()); +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/ImageIndex.h b/src/3rdparty/angle/src/libANGLE/ImageIndex.h new file mode 100644 index 0000000000..820c650f20 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/ImageIndex.h @@ -0,0 +1,79 @@ +// +// Copyright 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// ImageIndex.h: A helper struct for indexing into an Image array + +#ifndef LIBANGLE_IMAGE_INDEX_H_ +#define LIBANGLE_IMAGE_INDEX_H_ + +#include "common/mathutil.h" + +#include "angle_gl.h" + +namespace gl +{ + +class ImageIndexIterator; + +struct ImageIndex +{ + GLenum type; + GLint mipIndex; + GLint layerIndex; + + ImageIndex(const ImageIndex &other); + ImageIndex &operator=(const ImageIndex &other); + + bool hasLayer() const { return layerIndex != ENTIRE_LEVEL; } + + static ImageIndex Make2D(GLint mipIndex); + static ImageIndex MakeCube(GLenum target, GLint mipIndex); + static ImageIndex Make2DArray(GLint mipIndex, GLint layerIndex); + static ImageIndex Make3D(GLint mipIndex, GLint layerIndex = ENTIRE_LEVEL); + static ImageIndex MakeGeneric(GLenum target, GLint mipIndex); + + static ImageIndex MakeInvalid(); + + static const GLint ENTIRE_LEVEL = static_cast(-1); + + bool operator<(const ImageIndex &other) const; + + private: + friend class ImageIndexIterator; + + ImageIndex(GLenum typeIn, GLint mipIndexIn, GLint layerIndexIn); +}; + +class ImageIndexIterator +{ + public: + static ImageIndexIterator Make2D(GLint minMip, GLint maxMip); + static ImageIndexIterator MakeCube(GLint minMip, GLint maxMip); + static ImageIndexIterator Make3D(GLint minMip, GLint maxMip, GLint minLayer, GLint maxLayer); + static ImageIndexIterator Make2DArray(GLint minMip, GLint maxMip, const GLsizei *layerCounts); + + ImageIndex next(); + ImageIndex current() const; + bool hasNext() const; + + private: + + ImageIndexIterator(GLenum type, const rx::Range &mipRange, + const rx::Range &layerRange, const GLsizei *layerCounts); + + GLint maxLayer() const; + + GLenum mType; + rx::Range mMipRange; + rx::Range mLayerRange; + const GLsizei *mLayerCounts; + GLint mCurrentMip; + GLint mCurrentLayer; +}; + +} + +#endif // LIBANGLE_IMAGE_INDEX_H_ diff --git a/src/3rdparty/angle/src/libANGLE/Platform.cpp b/src/3rdparty/angle/src/libANGLE/Platform.cpp new file mode 100644 index 0000000000..ab75bbba5a --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/Platform.cpp @@ -0,0 +1,35 @@ +// +// Copyright 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Platform.cpp: Implementation methods for angle::Platform. + +#include + +#include "common/debug.h" + +namespace +{ +angle::Platform *currentPlatform = nullptr; +} + +// static +ANGLE_EXPORT angle::Platform *ANGLEPlatformCurrent() +{ + return currentPlatform; +} + +// static +ANGLE_EXPORT void ANGLEPlatformInitialize(angle::Platform *platformImpl) +{ + ASSERT(platformImpl != nullptr); + currentPlatform = platformImpl; +} + +// static +ANGLE_EXPORT void ANGLEPlatformShutdown() +{ + currentPlatform = nullptr; +} diff --git a/src/3rdparty/angle/src/libANGLE/Program.cpp b/src/3rdparty/angle/src/libANGLE/Program.cpp new file mode 100644 index 0000000000..daf0a403f0 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/Program.cpp @@ -0,0 +1,1617 @@ +// +// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Program.cpp: Implements the gl::Program class. Implements GL program objects +// and related functionality. [OpenGL ES 2.0.24] section 2.10.3 page 28. + +#include "libANGLE/Program.h" + +#include + +#include "common/debug.h" +#include "common/platform.h" +#include "common/utilities.h" +#include "common/version.h" +#include "compiler/translator/blocklayout.h" +#include "libANGLE/Data.h" +#include "libANGLE/ResourceManager.h" +#include "libANGLE/features.h" +#include "libANGLE/renderer/Renderer.h" +#include "libANGLE/renderer/ProgramImpl.h" + +namespace gl +{ +const char * const g_fakepath = "C:\\fakepath"; + +namespace +{ + +unsigned int ParseAndStripArrayIndex(std::string* name) +{ + unsigned int subscript = GL_INVALID_INDEX; + + // Strip any trailing array operator and retrieve the subscript + size_t open = name->find_last_of('['); + size_t close = name->find_last_of(']'); + if (open != std::string::npos && close == name->length() - 1) + { + subscript = atoi(name->substr(open + 1).c_str()); + name->erase(open); + } + + return subscript; +} + +} + +AttributeBindings::AttributeBindings() +{ +} + +AttributeBindings::~AttributeBindings() +{ +} + +InfoLog::InfoLog() : mInfoLog(NULL) +{ +} + +InfoLog::~InfoLog() +{ + delete[] mInfoLog; +} + + +int InfoLog::getLength() const +{ + if (!mInfoLog) + { + return 0; + } + else + { + return strlen(mInfoLog) + 1; + } +} + +void InfoLog::getLog(GLsizei bufSize, GLsizei *length, char *infoLog) +{ + int index = 0; + + if (bufSize > 0) + { + if (mInfoLog) + { + index = std::min(bufSize - 1, (int)strlen(mInfoLog)); + memcpy(infoLog, mInfoLog, index); + } + + infoLog[index] = '\0'; + } + + if (length) + { + *length = index; + } +} + +// append a santized message to the program info log. +// The D3D compiler includes a fake file path in some of the warning or error +// messages, so lets remove all occurrences of this fake file path from the log. +void InfoLog::appendSanitized(const char *message) +{ + std::string msg(message); + + size_t found; + do + { + found = msg.find(g_fakepath); + if (found != std::string::npos) + { + msg.erase(found, strlen(g_fakepath)); + } + } + while (found != std::string::npos); + + append("%s", msg.c_str()); +} + +void InfoLog::append(const char *format, ...) +{ + if (!format) + { + return; + } + + va_list vararg; + va_start(vararg, format); + size_t infoLength = vsnprintf(NULL, 0, format, vararg); + va_end(vararg); + + char *logPointer = NULL; + + if (!mInfoLog) + { + mInfoLog = new char[infoLength + 2]; + logPointer = mInfoLog; + } + else + { + size_t currentlogLength = strlen(mInfoLog); + char *newLog = new char[currentlogLength + infoLength + 2]; + strcpy(newLog, mInfoLog); + + delete[] mInfoLog; + mInfoLog = newLog; + + logPointer = mInfoLog + currentlogLength; + } + + va_start(vararg, format); + vsnprintf(logPointer, infoLength, format, vararg); + va_end(vararg); + + logPointer[infoLength] = 0; + strcpy(logPointer + infoLength, "\n"); +} + +void InfoLog::reset() +{ + if (mInfoLog) + { + delete [] mInfoLog; + mInfoLog = NULL; + } +} + +VariableLocation::VariableLocation() + : name(), element(0), index(0) +{ +} + +VariableLocation::VariableLocation(const std::string &name, unsigned int element, unsigned int index) + : name(name), element(element), index(index) +{ +} + +LinkedVarying::LinkedVarying() +{ +} + +LinkedVarying::LinkedVarying(const std::string &name, GLenum type, GLsizei size, const std::string &semanticName, + unsigned int semanticIndex, unsigned int semanticIndexCount) + : name(name), type(type), size(size), semanticName(semanticName), semanticIndex(semanticIndex), semanticIndexCount(semanticIndexCount) +{ +} + +Program::Program(rx::ProgramImpl *impl, ResourceManager *manager, GLuint handle) + : mProgram(impl), + mValidated(false), + mTransformFeedbackVaryings(), + mTransformFeedbackBufferMode(GL_NONE), + mFragmentShader(NULL), + mVertexShader(NULL), + mLinked(false), + mDeleteStatus(false), + mRefCount(0), + mResourceManager(manager), + mHandle(handle) +{ + ASSERT(mProgram); + + resetUniformBlockBindings(); + unlink(); +} + +Program::~Program() +{ + unlink(true); + + if (mVertexShader != NULL) + { + mVertexShader->release(); + } + + if (mFragmentShader != NULL) + { + mFragmentShader->release(); + } + + SafeDelete(mProgram); +} + +bool Program::attachShader(Shader *shader) +{ + if (shader->getType() == GL_VERTEX_SHADER) + { + if (mVertexShader) + { + return false; + } + + mVertexShader = shader; + mVertexShader->addRef(); + } + else if (shader->getType() == GL_FRAGMENT_SHADER) + { + if (mFragmentShader) + { + return false; + } + + mFragmentShader = shader; + mFragmentShader->addRef(); + } + else UNREACHABLE(); + + return true; +} + +bool Program::detachShader(Shader *shader) +{ + if (shader->getType() == GL_VERTEX_SHADER) + { + if (mVertexShader != shader) + { + return false; + } + + mVertexShader->release(); + mVertexShader = NULL; + } + else if (shader->getType() == GL_FRAGMENT_SHADER) + { + if (mFragmentShader != shader) + { + return false; + } + + mFragmentShader->release(); + mFragmentShader = NULL; + } + else UNREACHABLE(); + + return true; +} + +int Program::getAttachedShadersCount() const +{ + return (mVertexShader ? 1 : 0) + (mFragmentShader ? 1 : 0); +} + +void AttributeBindings::bindAttributeLocation(GLuint index, const char *name) +{ + if (index < MAX_VERTEX_ATTRIBS) + { + for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) + { + mAttributeBinding[i].erase(name); + } + + mAttributeBinding[index].insert(name); + } +} + +void Program::bindAttributeLocation(GLuint index, const char *name) +{ + mAttributeBindings.bindAttributeLocation(index, name); +} + +// Links the HLSL code of the vertex and pixel shader by matching up their varyings, +// compiling them into binaries, determining the attribute mappings, and collecting +// a list of uniforms +Error Program::link(const Data &data) +{ + unlink(false); + + mInfoLog.reset(); + resetUniformBlockBindings(); + + if (!mFragmentShader || !mFragmentShader->isCompiled()) + { + return Error(GL_NO_ERROR); + } + ASSERT(mFragmentShader->getType() == GL_FRAGMENT_SHADER); + + if (!mVertexShader || !mVertexShader->isCompiled()) + { + return Error(GL_NO_ERROR); + } + ASSERT(mVertexShader->getType() == GL_VERTEX_SHADER); + + if (!linkAttributes(mInfoLog, mAttributeBindings, mVertexShader)) + { + return Error(GL_NO_ERROR); + } + + int registers; + std::vector linkedVaryings; + rx::LinkResult result = mProgram->link(data, mInfoLog, mFragmentShader, mVertexShader, mTransformFeedbackVaryings, mTransformFeedbackBufferMode, + ®isters, &linkedVaryings, &mOutputVariables); + if (result.error.isError() || !result.linkSuccess) + { + return result.error; + } + + if (!mProgram->linkUniforms(mInfoLog, *mVertexShader, *mFragmentShader, *data.caps)) + { + return Error(GL_NO_ERROR); + } + + if (!linkUniformBlocks(mInfoLog, *mVertexShader, *mFragmentShader, *data.caps)) + { + return Error(GL_NO_ERROR); + } + + if (!gatherTransformFeedbackLinkedVaryings(mInfoLog, linkedVaryings, mTransformFeedbackVaryings, + mTransformFeedbackBufferMode, &mProgram->getTransformFeedbackLinkedVaryings(), *data.caps)) + { + return Error(GL_NO_ERROR); + } + + // TODO: The concept of "executables" is D3D only, and as such this belongs in ProgramD3D. It must be called, + // however, last in this function, so it can't simply be moved to ProgramD3D::link without further shuffling. + result = mProgram->compileProgramExecutables(mInfoLog, mFragmentShader, mVertexShader, registers); + if (result.error.isError() || !result.linkSuccess) + { + mInfoLog.append("Failed to create D3D shaders."); + unlink(false); + return result.error; + } + + mLinked = true; + return gl::Error(GL_NO_ERROR); +} + +int AttributeBindings::getAttributeBinding(const std::string &name) const +{ + for (int location = 0; location < MAX_VERTEX_ATTRIBS; location++) + { + if (mAttributeBinding[location].find(name) != mAttributeBinding[location].end()) + { + return location; + } + } + + return -1; +} + +// Returns the program object to an unlinked state, before re-linking, or at destruction +void Program::unlink(bool destroy) +{ + if (destroy) // Object being destructed + { + if (mFragmentShader) + { + mFragmentShader->release(); + mFragmentShader = NULL; + } + + if (mVertexShader) + { + mVertexShader->release(); + mVertexShader = NULL; + } + } + + std::fill(mLinkedAttribute, mLinkedAttribute + ArraySize(mLinkedAttribute), sh::Attribute()); + mOutputVariables.clear(); + + mProgram->reset(); + + mValidated = false; + + mLinked = false; +} + +bool Program::isLinked() +{ + return mLinked; +} + +Error Program::loadBinary(GLenum binaryFormat, const void *binary, GLsizei length) +{ + unlink(false); + +#if ANGLE_PROGRAM_BINARY_LOAD != ANGLE_ENABLED + return Error(GL_NO_ERROR); +#else + ASSERT(binaryFormat == mProgram->getBinaryFormat()); + + BinaryInputStream stream(binary, length); + + GLenum format = stream.readInt(); + if (format != mProgram->getBinaryFormat()) + { + mInfoLog.append("Invalid program binary format."); + return Error(GL_NO_ERROR); + } + + int majorVersion = stream.readInt(); + int minorVersion = stream.readInt(); + if (majorVersion != ANGLE_MAJOR_VERSION || minorVersion != ANGLE_MINOR_VERSION) + { + mInfoLog.append("Invalid program binary version."); + return Error(GL_NO_ERROR); + } + + unsigned char commitString[ANGLE_COMMIT_HASH_SIZE]; + stream.readBytes(commitString, ANGLE_COMMIT_HASH_SIZE); + if (memcmp(commitString, ANGLE_COMMIT_HASH, sizeof(unsigned char) * ANGLE_COMMIT_HASH_SIZE) != 0) + { + mInfoLog.append("Invalid program binary version."); + return Error(GL_NO_ERROR); + } + + for (int i = 0; i < MAX_VERTEX_ATTRIBS; ++i) + { + stream.readInt(&mLinkedAttribute[i].type); + stream.readString(&mLinkedAttribute[i].name); + stream.readInt(&mProgram->getShaderAttributes()[i].type); + stream.readString(&mProgram->getShaderAttributes()[i].name); + stream.readInt(&mProgram->getSemanticIndexes()[i]); + } + + rx::LinkResult result = mProgram->load(mInfoLog, &stream); + if (result.error.isError() || !result.linkSuccess) + { + return result.error; + } + + mLinked = true; + return Error(GL_NO_ERROR); +#endif // #if ANGLE_PROGRAM_BINARY_LOAD == ANGLE_ENABLED +} + +Error Program::saveBinary(GLenum *binaryFormat, void *binary, GLsizei bufSize, GLsizei *length) const +{ + if (binaryFormat) + { + *binaryFormat = mProgram->getBinaryFormat(); + } + + BinaryOutputStream stream; + + stream.writeInt(mProgram->getBinaryFormat()); + stream.writeInt(ANGLE_MAJOR_VERSION); + stream.writeInt(ANGLE_MINOR_VERSION); + stream.writeBytes(reinterpret_cast(ANGLE_COMMIT_HASH), ANGLE_COMMIT_HASH_SIZE); + + for (unsigned int i = 0; i < MAX_VERTEX_ATTRIBS; ++i) + { + stream.writeInt(mLinkedAttribute[i].type); + stream.writeString(mLinkedAttribute[i].name); + stream.writeInt(mProgram->getShaderAttributes()[i].type); + stream.writeString(mProgram->getShaderAttributes()[i].name); + stream.writeInt(mProgram->getSemanticIndexes()[i]); + } + + gl::Error error = mProgram->save(&stream); + if (error.isError()) + { + return error; + } + + GLsizei streamLength = stream.length(); + const void *streamData = stream.data(); + + if (streamLength > bufSize) + { + if (length) + { + *length = 0; + } + + // TODO: This should be moved to the validation layer but computing the size of the binary before saving + // it causes the save to happen twice. It may be possible to write the binary to a separate buffer, validate + // sizes and then copy it. + return Error(GL_INVALID_OPERATION); + } + + if (binary) + { + char *ptr = reinterpret_cast(binary); + + memcpy(ptr, streamData, streamLength); + ptr += streamLength; + + ASSERT(ptr - streamLength == binary); + } + + if (length) + { + *length = streamLength; + } + + return Error(GL_NO_ERROR); +} + +GLint Program::getBinaryLength() const +{ + GLint length; + Error error = saveBinary(NULL, NULL, std::numeric_limits::max(), &length); + if (error.isError()) + { + return 0; + } + + return length; +} + +void Program::release() +{ + mRefCount--; + + if (mRefCount == 0 && mDeleteStatus) + { + mResourceManager->deleteProgram(mHandle); + } +} + +void Program::addRef() +{ + mRefCount++; +} + +unsigned int Program::getRefCount() const +{ + return mRefCount; +} + +int Program::getInfoLogLength() const +{ + return mInfoLog.getLength(); +} + +void Program::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) +{ + return mInfoLog.getLog(bufSize, length, infoLog); +} + +void Program::getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders) +{ + int total = 0; + + if (mVertexShader) + { + if (total < maxCount) + { + shaders[total] = mVertexShader->getHandle(); + } + + total++; + } + + if (mFragmentShader) + { + if (total < maxCount) + { + shaders[total] = mFragmentShader->getHandle(); + } + + total++; + } + + if (count) + { + *count = total; + } +} + +GLuint Program::getAttributeLocation(const std::string &name) +{ + for (int index = 0; index < MAX_VERTEX_ATTRIBS; index++) + { + if (mLinkedAttribute[index].name == name) + { + return index; + } + } + + return static_cast(-1); +} + +int Program::getSemanticIndex(int attributeIndex) +{ + ASSERT(attributeIndex >= 0 && attributeIndex < MAX_VERTEX_ATTRIBS); + + return mProgram->getSemanticIndexes()[attributeIndex]; +} + +void Program::getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) +{ + if (mLinked) + { + // Skip over inactive attributes + unsigned int activeAttribute = 0; + unsigned int attribute; + for (attribute = 0; attribute < MAX_VERTEX_ATTRIBS; attribute++) + { + if (mLinkedAttribute[attribute].name.empty()) + { + continue; + } + + if (activeAttribute == index) + { + break; + } + + activeAttribute++; + } + + if (bufsize > 0) + { + const char *string = mLinkedAttribute[attribute].name.c_str(); + + strncpy(name, string, bufsize); + name[bufsize - 1] = '\0'; + + if (length) + { + *length = strlen(name); + } + } + + *size = 1; // Always a single 'type' instance + + *type = mLinkedAttribute[attribute].type; + } + else + { + if (bufsize > 0) + { + name[0] = '\0'; + } + + if (length) + { + *length = 0; + } + + *type = GL_NONE; + *size = 1; + } +} + +GLint Program::getActiveAttributeCount() +{ + int count = 0; + + if (mLinked) + { + for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++) + { + if (!mLinkedAttribute[attributeIndex].name.empty()) + { + count++; + } + } + } + + return count; +} + +GLint Program::getActiveAttributeMaxLength() +{ + int maxLength = 0; + + if (mLinked) + { + for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++) + { + if (!mLinkedAttribute[attributeIndex].name.empty()) + { + maxLength = std::max((int)(mLinkedAttribute[attributeIndex].name.length() + 1), maxLength); + } + } + } + + return maxLength; +} + +// Returns one more than the highest sampler index used. +GLint Program::getUsedSamplerRange(SamplerType type) +{ + return mProgram->getUsedSamplerRange(type); +} + +bool Program::usesPointSize() const +{ + return mProgram->usesPointSize(); +} + +GLint Program::getSamplerMapping(SamplerType type, unsigned int samplerIndex, const Caps &caps) +{ + return mProgram->getSamplerMapping(type, samplerIndex, caps); +} + +GLenum Program::getSamplerTextureType(SamplerType type, unsigned int samplerIndex) +{ + return mProgram->getSamplerTextureType(type, samplerIndex); +} + +GLint Program::getFragDataLocation(const std::string &name) const +{ + std::string baseName(name); + unsigned int arrayIndex = ParseAndStripArrayIndex(&baseName); + for (auto locationIt = mOutputVariables.begin(); locationIt != mOutputVariables.end(); locationIt++) + { + const VariableLocation &outputVariable = locationIt->second; + if (outputVariable.name == baseName && (arrayIndex == GL_INVALID_INDEX || arrayIndex == outputVariable.element)) + { + return static_cast(locationIt->first); + } + } + return -1; +} + +void Program::getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) +{ + if (mLinked) + { + ASSERT(index < mProgram->getUniforms().size()); // index must be smaller than getActiveUniformCount() + LinkedUniform *uniform = mProgram->getUniforms()[index]; + + if (bufsize > 0) + { + std::string string = uniform->name; + if (uniform->isArray()) + { + string += "[0]"; + } + + strncpy(name, string.c_str(), bufsize); + name[bufsize - 1] = '\0'; + + if (length) + { + *length = strlen(name); + } + } + + *size = uniform->elementCount(); + *type = uniform->type; + } + else + { + if (bufsize > 0) + { + name[0] = '\0'; + } + + if (length) + { + *length = 0; + } + + *size = 0; + *type = GL_NONE; + } +} + +GLint Program::getActiveUniformCount() +{ + if (mLinked) + { + return mProgram->getUniforms().size(); + } + else + { + return 0; + } +} + +GLint Program::getActiveUniformMaxLength() +{ + int maxLength = 0; + + if (mLinked) + { + unsigned int numUniforms = mProgram->getUniforms().size(); + for (unsigned int uniformIndex = 0; uniformIndex < numUniforms; uniformIndex++) + { + if (!mProgram->getUniforms()[uniformIndex]->name.empty()) + { + int length = (int)(mProgram->getUniforms()[uniformIndex]->name.length() + 1); + if (mProgram->getUniforms()[uniformIndex]->isArray()) + { + length += 3; // Counting in "[0]". + } + maxLength = std::max(length, maxLength); + } + } + } + + return maxLength; +} + +GLint Program::getActiveUniformi(GLuint index, GLenum pname) const +{ + const gl::LinkedUniform& uniform = *mProgram->getUniforms()[index]; + switch (pname) + { + case GL_UNIFORM_TYPE: return static_cast(uniform.type); + case GL_UNIFORM_SIZE: return static_cast(uniform.elementCount()); + case GL_UNIFORM_NAME_LENGTH: return static_cast(uniform.name.size() + 1 + (uniform.isArray() ? 3 : 0)); + case GL_UNIFORM_BLOCK_INDEX: return uniform.blockIndex; + case GL_UNIFORM_OFFSET: return uniform.blockInfo.offset; + case GL_UNIFORM_ARRAY_STRIDE: return uniform.blockInfo.arrayStride; + case GL_UNIFORM_MATRIX_STRIDE: return uniform.blockInfo.matrixStride; + case GL_UNIFORM_IS_ROW_MAJOR: return static_cast(uniform.blockInfo.isRowMajorMatrix); + default: + UNREACHABLE(); + break; + } + return 0; +} + +bool Program::isValidUniformLocation(GLint location) const +{ + ASSERT(rx::IsIntegerCastSafe(mProgram->getUniformIndices().size())); + return (location >= 0 && location < static_cast(mProgram->getUniformIndices().size())); +} + +LinkedUniform *Program::getUniformByLocation(GLint location) const +{ + return mProgram->getUniformByLocation(location); +} + +LinkedUniform *Program::getUniformByName(const std::string &name) const +{ + return mProgram->getUniformByName(name); +} + +GLint Program::getUniformLocation(const std::string &name) +{ + return mProgram->getUniformLocation(name); +} + +GLuint Program::getUniformIndex(const std::string &name) +{ + return mProgram->getUniformIndex(name); +} + +void Program::setUniform1fv(GLint location, GLsizei count, const GLfloat *v) +{ + mProgram->setUniform1fv(location, count, v); +} + +void Program::setUniform2fv(GLint location, GLsizei count, const GLfloat *v) +{ + mProgram->setUniform2fv(location, count, v); +} + +void Program::setUniform3fv(GLint location, GLsizei count, const GLfloat *v) +{ + mProgram->setUniform3fv(location, count, v); +} + +void Program::setUniform4fv(GLint location, GLsizei count, const GLfloat *v) +{ + mProgram->setUniform4fv(location, count, v); +} + +void Program::setUniform1iv(GLint location, GLsizei count, const GLint *v) +{ + mProgram->setUniform1iv(location, count, v); +} + +void Program::setUniform2iv(GLint location, GLsizei count, const GLint *v) +{ + mProgram->setUniform2iv(location, count, v); +} + +void Program::setUniform3iv(GLint location, GLsizei count, const GLint *v) +{ + mProgram->setUniform3iv(location, count, v); +} + +void Program::setUniform4iv(GLint location, GLsizei count, const GLint *v) +{ + mProgram->setUniform4iv(location, count, v); +} + +void Program::setUniform1uiv(GLint location, GLsizei count, const GLuint *v) +{ + mProgram->setUniform1uiv(location, count, v); +} + +void Program::setUniform2uiv(GLint location, GLsizei count, const GLuint *v) +{ + mProgram->setUniform2uiv(location, count, v); +} + +void Program::setUniform3uiv(GLint location, GLsizei count, const GLuint *v) +{ + mProgram->setUniform3uiv(location, count, v); +} + +void Program::setUniform4uiv(GLint location, GLsizei count, const GLuint *v) +{ + mProgram->setUniform4uiv(location, count, v); +} + +void Program::setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) +{ + mProgram->setUniformMatrix2fv(location, count, transpose, v); +} + +void Program::setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) +{ + mProgram->setUniformMatrix3fv(location, count, transpose, v); +} + +void Program::setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) +{ + mProgram->setUniformMatrix4fv(location, count, transpose, v); +} + +void Program::setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) +{ + mProgram->setUniformMatrix2x3fv(location, count, transpose, v); +} + +void Program::setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) +{ + mProgram->setUniformMatrix2x4fv(location, count, transpose, v); +} + +void Program::setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) +{ + mProgram->setUniformMatrix3x2fv(location, count, transpose, v); +} + +void Program::setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) +{ + mProgram->setUniformMatrix3x4fv(location, count, transpose, v); +} + +void Program::setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) +{ + mProgram->setUniformMatrix4x2fv(location, count, transpose, v); +} + +void Program::setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) +{ + mProgram->setUniformMatrix4x3fv(location, count, transpose, v); +} + +void Program::getUniformfv(GLint location, GLfloat *v) +{ + mProgram->getUniformfv(location, v); +} + +void Program::getUniformiv(GLint location, GLint *v) +{ + mProgram->getUniformiv(location, v); +} + +void Program::getUniformuiv(GLint location, GLuint *v) +{ + mProgram->getUniformuiv(location, v); +} + +// Applies all the uniforms set for this program object to the renderer +Error Program::applyUniforms() +{ + return mProgram->applyUniforms(); +} + +Error Program::applyUniformBuffers(const gl::Data &data) +{ + return mProgram->applyUniformBuffers(data, mUniformBlockBindings); +} + +void Program::flagForDeletion() +{ + mDeleteStatus = true; +} + +bool Program::isFlaggedForDeletion() const +{ + return mDeleteStatus; +} + +void Program::validate(const Caps &caps) +{ + mInfoLog.reset(); + mValidated = false; + + if (mLinked) + { + applyUniforms(); + mValidated = mProgram->validateSamplers(&mInfoLog, caps); + } + else + { + mInfoLog.append("Program has not been successfully linked."); + } +} + +bool Program::validateSamplers(InfoLog *infoLog, const Caps &caps) +{ + return mProgram->validateSamplers(infoLog, caps); +} + +bool Program::isValidated() const +{ + return mValidated; +} + +void Program::updateSamplerMapping() +{ + return mProgram->updateSamplerMapping(); +} + +GLuint Program::getActiveUniformBlockCount() +{ + return mProgram->getUniformBlocks().size(); +} + +void Program::getActiveUniformBlockName(GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName) const +{ + ASSERT(uniformBlockIndex < mProgram->getUniformBlocks().size()); // index must be smaller than getActiveUniformBlockCount() + + const UniformBlock &uniformBlock = *mProgram->getUniformBlocks()[uniformBlockIndex]; + + if (bufSize > 0) + { + std::string string = uniformBlock.name; + + if (uniformBlock.isArrayElement()) + { + string += ArrayString(uniformBlock.elementIndex); + } + + strncpy(uniformBlockName, string.c_str(), bufSize); + uniformBlockName[bufSize - 1] = '\0'; + + if (length) + { + *length = strlen(uniformBlockName); + } + } +} + +void Program::getActiveUniformBlockiv(GLuint uniformBlockIndex, GLenum pname, GLint *params) const +{ + ASSERT(uniformBlockIndex < mProgram->getUniformBlocks().size()); // index must be smaller than getActiveUniformBlockCount() + + const UniformBlock &uniformBlock = *mProgram->getUniformBlocks()[uniformBlockIndex]; + + switch (pname) + { + case GL_UNIFORM_BLOCK_DATA_SIZE: + *params = static_cast(uniformBlock.dataSize); + break; + case GL_UNIFORM_BLOCK_NAME_LENGTH: + *params = static_cast(uniformBlock.name.size() + 1 + (uniformBlock.isArrayElement() ? 3 : 0)); + break; + case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS: + *params = static_cast(uniformBlock.memberUniformIndexes.size()); + break; + case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES: + { + for (unsigned int blockMemberIndex = 0; blockMemberIndex < uniformBlock.memberUniformIndexes.size(); blockMemberIndex++) + { + params[blockMemberIndex] = static_cast(uniformBlock.memberUniformIndexes[blockMemberIndex]); + } + } + break; + case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER: + *params = static_cast(uniformBlock.isReferencedByVertexShader()); + break; + case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER: + *params = static_cast(uniformBlock.isReferencedByFragmentShader()); + break; + default: UNREACHABLE(); + } +} + +GLint Program::getActiveUniformBlockMaxLength() +{ + int maxLength = 0; + + if (mLinked) + { + unsigned int numUniformBlocks = mProgram->getUniformBlocks().size(); + for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < numUniformBlocks; uniformBlockIndex++) + { + const UniformBlock &uniformBlock = *mProgram->getUniformBlocks()[uniformBlockIndex]; + if (!uniformBlock.name.empty()) + { + const int length = uniformBlock.name.length() + 1; + + // Counting in "[0]". + const int arrayLength = (uniformBlock.isArrayElement() ? 3 : 0); + + maxLength = std::max(length + arrayLength, maxLength); + } + } + } + + return maxLength; +} + +GLuint Program::getUniformBlockIndex(const std::string &name) +{ + return mProgram->getUniformBlockIndex(name); +} + +const UniformBlock *Program::getUniformBlockByIndex(GLuint index) const +{ + return mProgram->getUniformBlockByIndex(index); +} + +void Program::bindUniformBlock(GLuint uniformBlockIndex, GLuint uniformBlockBinding) +{ + mUniformBlockBindings[uniformBlockIndex] = uniformBlockBinding; +} + +GLuint Program::getUniformBlockBinding(GLuint uniformBlockIndex) const +{ + return mUniformBlockBindings[uniformBlockIndex]; +} + +void Program::resetUniformBlockBindings() +{ + for (unsigned int blockId = 0; blockId < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS; blockId++) + { + mUniformBlockBindings[blockId] = 0; + } +} + +void Program::setTransformFeedbackVaryings(GLsizei count, const GLchar *const *varyings, GLenum bufferMode) +{ + mTransformFeedbackVaryings.resize(count); + for (GLsizei i = 0; i < count; i++) + { + mTransformFeedbackVaryings[i] = varyings[i]; + } + + mTransformFeedbackBufferMode = bufferMode; +} + +void Program::getTransformFeedbackVarying(GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name) const +{ + if (mLinked) + { + ASSERT(index < mProgram->getTransformFeedbackLinkedVaryings().size()); + const LinkedVarying &varying = mProgram->getTransformFeedbackLinkedVaryings()[index]; + GLsizei lastNameIdx = std::min(bufSize - 1, static_cast(varying.name.length())); + if (length) + { + *length = lastNameIdx; + } + if (size) + { + *size = varying.size; + } + if (type) + { + *type = varying.type; + } + if (name) + { + memcpy(name, varying.name.c_str(), lastNameIdx); + name[lastNameIdx] = '\0'; + } + } +} + +GLsizei Program::getTransformFeedbackVaryingCount() const +{ + if (mLinked) + { + return static_cast(mProgram->getTransformFeedbackLinkedVaryings().size()); + } + else + { + return 0; + } +} + +GLsizei Program::getTransformFeedbackVaryingMaxLength() const +{ + if (mLinked) + { + GLsizei maxSize = 0; + for (size_t i = 0; i < mProgram->getTransformFeedbackLinkedVaryings().size(); i++) + { + const LinkedVarying &varying = mProgram->getTransformFeedbackLinkedVaryings()[i]; + maxSize = std::max(maxSize, static_cast(varying.name.length() + 1)); + } + + return maxSize; + } + else + { + return 0; + } +} + +GLenum Program::getTransformFeedbackBufferMode() const +{ + return mTransformFeedbackBufferMode; +} + +bool Program::linkVaryings(InfoLog &infoLog, Shader *fragmentShader, Shader *vertexShader) +{ + std::vector &fragmentVaryings = fragmentShader->getVaryings(); + std::vector &vertexVaryings = vertexShader->getVaryings(); + + for (size_t fragVaryingIndex = 0; fragVaryingIndex < fragmentVaryings.size(); fragVaryingIndex++) + { + PackedVarying *input = &fragmentVaryings[fragVaryingIndex]; + bool matched = false; + + // Built-in varyings obey special rules + if (input->isBuiltIn()) + { + continue; + } + + for (size_t vertVaryingIndex = 0; vertVaryingIndex < vertexVaryings.size(); vertVaryingIndex++) + { + PackedVarying *output = &vertexVaryings[vertVaryingIndex]; + if (output->name == input->name) + { + if (!linkValidateVaryings(infoLog, output->name, *input, *output)) + { + return false; + } + + output->registerIndex = input->registerIndex; + output->columnIndex = input->columnIndex; + + matched = true; + break; + } + } + + // We permit unmatched, unreferenced varyings + if (!matched && input->staticUse) + { + infoLog.append("Fragment varying %s does not match any vertex varying", input->name.c_str()); + return false; + } + } + + return true; +} + +bool Program::linkValidateInterfaceBlockFields(InfoLog &infoLog, const std::string &uniformName, const sh::InterfaceBlockField &vertexUniform, const sh::InterfaceBlockField &fragmentUniform) +{ + if (!linkValidateVariablesBase(infoLog, uniformName, vertexUniform, fragmentUniform, true)) + { + return false; + } + + if (vertexUniform.isRowMajorLayout != fragmentUniform.isRowMajorLayout) + { + infoLog.append("Matrix packings for %s differ between vertex and fragment shaders", uniformName.c_str()); + return false; + } + + return true; +} + +// Determines the mapping between GL attributes and Direct3D 9 vertex stream usage indices +bool Program::linkAttributes(InfoLog &infoLog, const AttributeBindings &attributeBindings, const Shader *vertexShader) +{ + unsigned int usedLocations = 0; + const std::vector &shaderAttributes = vertexShader->getActiveAttributes(); + + // Link attributes that have a binding location + for (unsigned int attributeIndex = 0; attributeIndex < shaderAttributes.size(); attributeIndex++) + { + const sh::Attribute &attribute = shaderAttributes[attributeIndex]; + + ASSERT(attribute.staticUse); + + const int location = attribute.location == -1 ? attributeBindings.getAttributeBinding(attribute.name) : attribute.location; + + mProgram->getShaderAttributes()[attributeIndex] = attribute; + + if (location != -1) // Set by glBindAttribLocation or by location layout qualifier + { + const int rows = VariableRegisterCount(attribute.type); + + if (rows + location > MAX_VERTEX_ATTRIBS) + { + infoLog.append("Active attribute (%s) at location %d is too big to fit", attribute.name.c_str(), location); + + return false; + } + + for (int row = 0; row < rows; row++) + { + const int rowLocation = location + row; + sh::ShaderVariable &linkedAttribute = mLinkedAttribute[rowLocation]; + + // In GLSL 3.00, attribute aliasing produces a link error + // In GLSL 1.00, attribute aliasing is allowed + if (mProgram->getShaderVersion() >= 300) + { + if (!linkedAttribute.name.empty()) + { + infoLog.append("Attribute '%s' aliases attribute '%s' at location %d", attribute.name.c_str(), linkedAttribute.name.c_str(), rowLocation); + return false; + } + } + + linkedAttribute = attribute; + usedLocations |= 1 << rowLocation; + } + } + } + + // Link attributes that don't have a binding location + for (unsigned int attributeIndex = 0; attributeIndex < shaderAttributes.size(); attributeIndex++) + { + const sh::Attribute &attribute = shaderAttributes[attributeIndex]; + + ASSERT(attribute.staticUse); + + const int location = attribute.location == -1 ? attributeBindings.getAttributeBinding(attribute.name) : attribute.location; + + if (location == -1) // Not set by glBindAttribLocation or by location layout qualifier + { + int rows = VariableRegisterCount(attribute.type); + int availableIndex = AllocateFirstFreeBits(&usedLocations, rows, MAX_VERTEX_ATTRIBS); + + if (availableIndex == -1 || availableIndex + rows > MAX_VERTEX_ATTRIBS) + { + infoLog.append("Too many active attributes (%s)", attribute.name.c_str()); + + return false; // Fail to link + } + + mLinkedAttribute[availableIndex] = attribute; + } + } + + for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; ) + { + int index = vertexShader->getSemanticIndex(mLinkedAttribute[attributeIndex].name); + int rows = VariableRegisterCount(mLinkedAttribute[attributeIndex].type); + + for (int r = 0; r < rows; r++) + { + mProgram->getSemanticIndexes()[attributeIndex++] = index++; + } + } + + return true; +} + +bool Program::linkUniformBlocks(InfoLog &infoLog, const Shader &vertexShader, const Shader &fragmentShader, const Caps &caps) +{ + const std::vector &vertexInterfaceBlocks = vertexShader.getInterfaceBlocks(); + const std::vector &fragmentInterfaceBlocks = fragmentShader.getInterfaceBlocks(); + // Check that interface blocks defined in the vertex and fragment shaders are identical + typedef std::map UniformBlockMap; + UniformBlockMap linkedUniformBlocks; + for (unsigned int blockIndex = 0; blockIndex < vertexInterfaceBlocks.size(); blockIndex++) + { + const sh::InterfaceBlock &vertexInterfaceBlock = vertexInterfaceBlocks[blockIndex]; + linkedUniformBlocks[vertexInterfaceBlock.name] = &vertexInterfaceBlock; + } + for (unsigned int blockIndex = 0; blockIndex < fragmentInterfaceBlocks.size(); blockIndex++) + { + const sh::InterfaceBlock &fragmentInterfaceBlock = fragmentInterfaceBlocks[blockIndex]; + UniformBlockMap::const_iterator entry = linkedUniformBlocks.find(fragmentInterfaceBlock.name); + if (entry != linkedUniformBlocks.end()) + { + const sh::InterfaceBlock &vertexInterfaceBlock = *entry->second; + if (!areMatchingInterfaceBlocks(infoLog, vertexInterfaceBlock, fragmentInterfaceBlock)) + { + return false; + } + } + } + for (unsigned int blockIndex = 0; blockIndex < vertexInterfaceBlocks.size(); blockIndex++) + { + const sh::InterfaceBlock &interfaceBlock = vertexInterfaceBlocks[blockIndex]; + // Note: shared and std140 layouts are always considered active + if (interfaceBlock.staticUse || interfaceBlock.layout != sh::BLOCKLAYOUT_PACKED) + { + if (!mProgram->defineUniformBlock(infoLog, vertexShader, interfaceBlock, caps)) + { + return false; + } + } + } + for (unsigned int blockIndex = 0; blockIndex < fragmentInterfaceBlocks.size(); blockIndex++) + { + const sh::InterfaceBlock &interfaceBlock = fragmentInterfaceBlocks[blockIndex]; + // Note: shared and std140 layouts are always considered active + if (interfaceBlock.staticUse || interfaceBlock.layout != sh::BLOCKLAYOUT_PACKED) + { + if (!mProgram->defineUniformBlock(infoLog, fragmentShader, interfaceBlock, caps)) + { + return false; + } + } + } + return true; +} + +bool Program::areMatchingInterfaceBlocks(gl::InfoLog &infoLog, const sh::InterfaceBlock &vertexInterfaceBlock, + const sh::InterfaceBlock &fragmentInterfaceBlock) +{ + const char* blockName = vertexInterfaceBlock.name.c_str(); + // validate blocks for the same member types + if (vertexInterfaceBlock.fields.size() != fragmentInterfaceBlock.fields.size()) + { + infoLog.append("Types for interface block '%s' differ between vertex and fragment shaders", blockName); + return false; + } + if (vertexInterfaceBlock.arraySize != fragmentInterfaceBlock.arraySize) + { + infoLog.append("Array sizes differ for interface block '%s' between vertex and fragment shaders", blockName); + return false; + } + if (vertexInterfaceBlock.layout != fragmentInterfaceBlock.layout || vertexInterfaceBlock.isRowMajorLayout != fragmentInterfaceBlock.isRowMajorLayout) + { + infoLog.append("Layout qualifiers differ for interface block '%s' between vertex and fragment shaders", blockName); + return false; + } + const unsigned int numBlockMembers = vertexInterfaceBlock.fields.size(); + for (unsigned int blockMemberIndex = 0; blockMemberIndex < numBlockMembers; blockMemberIndex++) + { + const sh::InterfaceBlockField &vertexMember = vertexInterfaceBlock.fields[blockMemberIndex]; + const sh::InterfaceBlockField &fragmentMember = fragmentInterfaceBlock.fields[blockMemberIndex]; + if (vertexMember.name != fragmentMember.name) + { + infoLog.append("Name mismatch for field %d of interface block '%s': (in vertex: '%s', in fragment: '%s')", + blockMemberIndex, blockName, vertexMember.name.c_str(), fragmentMember.name.c_str()); + return false; + } + std::string memberName = "interface block '" + vertexInterfaceBlock.name + "' member '" + vertexMember.name + "'"; + if (!linkValidateInterfaceBlockFields(infoLog, memberName, vertexMember, fragmentMember)) + { + return false; + } + } + return true; +} + +bool Program::linkValidateVariablesBase(InfoLog &infoLog, const std::string &variableName, const sh::ShaderVariable &vertexVariable, + const sh::ShaderVariable &fragmentVariable, bool validatePrecision) +{ + if (vertexVariable.type != fragmentVariable.type) + { + infoLog.append("Types for %s differ between vertex and fragment shaders", variableName.c_str()); + return false; + } + if (vertexVariable.arraySize != fragmentVariable.arraySize) + { + infoLog.append("Array sizes for %s differ between vertex and fragment shaders", variableName.c_str()); + return false; + } + if (validatePrecision && vertexVariable.precision != fragmentVariable.precision) + { + infoLog.append("Precisions for %s differ between vertex and fragment shaders", variableName.c_str()); + return false; + } + + if (vertexVariable.fields.size() != fragmentVariable.fields.size()) + { + infoLog.append("Structure lengths for %s differ between vertex and fragment shaders", variableName.c_str()); + return false; + } + const unsigned int numMembers = vertexVariable.fields.size(); + for (unsigned int memberIndex = 0; memberIndex < numMembers; memberIndex++) + { + const sh::ShaderVariable &vertexMember = vertexVariable.fields[memberIndex]; + const sh::ShaderVariable &fragmentMember = fragmentVariable.fields[memberIndex]; + + if (vertexMember.name != fragmentMember.name) + { + infoLog.append("Name mismatch for field '%d' of %s: (in vertex: '%s', in fragment: '%s')", + memberIndex, variableName.c_str(), + vertexMember.name.c_str(), fragmentMember.name.c_str()); + return false; + } + + const std::string memberName = variableName.substr(0, variableName.length() - 1) + "." + + vertexMember.name + "'"; + + if (!linkValidateVariablesBase(infoLog, vertexMember.name, vertexMember, fragmentMember, validatePrecision)) + { + return false; + } + } + + return true; +} + +bool Program::linkValidateUniforms(InfoLog &infoLog, const std::string &uniformName, const sh::Uniform &vertexUniform, const sh::Uniform &fragmentUniform) +{ + if (!linkValidateVariablesBase(infoLog, uniformName, vertexUniform, fragmentUniform, true)) + { + return false; + } + + return true; +} + +bool Program::linkValidateVaryings(InfoLog &infoLog, const std::string &varyingName, const sh::Varying &vertexVarying, const sh::Varying &fragmentVarying) +{ + if (!linkValidateVariablesBase(infoLog, varyingName, vertexVarying, fragmentVarying, false)) + { + return false; + } + + if (!sh::InterpolationTypesMatch(vertexVarying.interpolation, fragmentVarying.interpolation)) + { + infoLog.append("Interpolation types for %s differ between vertex and fragment shaders", varyingName.c_str()); + return false; + } + + return true; +} + +bool Program::gatherTransformFeedbackLinkedVaryings(InfoLog &infoLog, const std::vector &linkedVaryings, + const std::vector &transformFeedbackVaryingNames, + GLenum transformFeedbackBufferMode, + std::vector *outTransformFeedbackLinkedVaryings, + const Caps &caps) const +{ + size_t totalComponents = 0; + + // Gather the linked varyings that are used for transform feedback, they should all exist. + outTransformFeedbackLinkedVaryings->clear(); + for (size_t i = 0; i < transformFeedbackVaryingNames.size(); i++) + { + bool found = false; + for (size_t j = 0; j < linkedVaryings.size(); j++) + { + if (transformFeedbackVaryingNames[i] == linkedVaryings[j].name) + { + for (size_t k = 0; k < outTransformFeedbackLinkedVaryings->size(); k++) + { + if (outTransformFeedbackLinkedVaryings->at(k).name == linkedVaryings[j].name) + { + infoLog.append("Two transform feedback varyings specify the same output variable (%s).", linkedVaryings[j].name.c_str()); + return false; + } + } + + size_t componentCount = linkedVaryings[j].semanticIndexCount * 4; + if (transformFeedbackBufferMode == GL_SEPARATE_ATTRIBS && + componentCount > caps.maxTransformFeedbackSeparateComponents) + { + infoLog.append("Transform feedback varying's %s components (%u) exceed the maximum separate components (%u).", + linkedVaryings[j].name.c_str(), componentCount, caps.maxTransformFeedbackSeparateComponents); + return false; + } + + totalComponents += componentCount; + + outTransformFeedbackLinkedVaryings->push_back(linkedVaryings[j]); + found = true; + break; + } + } + + // All transform feedback varyings are expected to exist since packVaryings checks for them. + ASSERT(found); + } + + if (transformFeedbackBufferMode == GL_INTERLEAVED_ATTRIBS && totalComponents > caps.maxTransformFeedbackInterleavedComponents) + { + infoLog.append("Transform feedback varying total components (%u) exceed the maximum interleaved components (%u).", + totalComponents, caps.maxTransformFeedbackInterleavedComponents); + return false; + } + + return true; +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/Program.h b/src/3rdparty/angle/src/libANGLE/Program.h new file mode 100644 index 0000000000..38fc83d29d --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/Program.h @@ -0,0 +1,276 @@ +// +// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Program.h: Defines the gl::Program class. Implements GL program objects +// and related functionality. [OpenGL ES 2.0.24] section 2.10.3 page 28. + +#ifndef LIBANGLE_PROGRAM_H_ +#define LIBANGLE_PROGRAM_H_ + +#include "libANGLE/angletypes.h" +#include "libANGLE/Constants.h" +#include "libANGLE/Error.h" +#include "libANGLE/RefCountObject.h" + +#include "common/angleutils.h" + +#include +#include + +#include +#include +#include + +namespace rx +{ +class Renderer; +class Renderer; +struct TranslatedAttribute; +class ProgramImpl; +} + +namespace gl +{ +struct Caps; +struct Data; +class ResourceManager; +class Shader; +class InfoLog; +class AttributeBindings; +class Buffer; +class Framebuffer; +struct UniformBlock; +struct LinkedUniform; + +extern const char * const g_fakepath; + +class AttributeBindings +{ + public: + AttributeBindings(); + ~AttributeBindings(); + + void bindAttributeLocation(GLuint index, const char *name); + int getAttributeBinding(const std::string &name) const; + + private: + std::set mAttributeBinding[MAX_VERTEX_ATTRIBS]; +}; + +class InfoLog : angle::NonCopyable +{ + public: + InfoLog(); + ~InfoLog(); + + int getLength() const; + void getLog(GLsizei bufSize, GLsizei *length, char *infoLog); + + void appendSanitized(const char *message); + void append(const char *info, ...); + void reset(); + private: + char *mInfoLog; +}; + +// Struct used for correlating uniforms/elements of uniform arrays to handles +struct VariableLocation +{ + VariableLocation(); + VariableLocation(const std::string &name, unsigned int element, unsigned int index); + + std::string name; + unsigned int element; + unsigned int index; +}; + +struct LinkedVarying +{ + LinkedVarying(); + LinkedVarying(const std::string &name, GLenum type, GLsizei size, const std::string &semanticName, + unsigned int semanticIndex, unsigned int semanticIndexCount); + + // Original GL name + std::string name; + + GLenum type; + GLsizei size; + + // DirectX semantic information + std::string semanticName; + unsigned int semanticIndex; + unsigned int semanticIndexCount; +}; + +class Program : angle::NonCopyable +{ + public: + Program(rx::ProgramImpl *impl, ResourceManager *manager, GLuint handle); + ~Program(); + + GLuint id() const { return mHandle; } + + rx::ProgramImpl *getImplementation() { return mProgram; } + const rx::ProgramImpl *getImplementation() const { return mProgram; } + + bool attachShader(Shader *shader); + bool detachShader(Shader *shader); + int getAttachedShadersCount() const; + + void bindAttributeLocation(GLuint index, const char *name); + + Error link(const Data &data); + bool isLinked(); + + Error loadBinary(GLenum binaryFormat, const void *binary, GLsizei length); + Error saveBinary(GLenum *binaryFormat, void *binary, GLsizei bufSize, GLsizei *length) const; + GLint getBinaryLength() const; + + int getInfoLogLength() const; + void getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog); + void getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders); + + GLuint getAttributeLocation(const std::string &name); + int getSemanticIndex(int attributeIndex); + + void getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name); + GLint getActiveAttributeCount(); + GLint getActiveAttributeMaxLength(); + + GLint getSamplerMapping(SamplerType type, unsigned int samplerIndex, const Caps &caps); + GLenum getSamplerTextureType(SamplerType type, unsigned int samplerIndex); + GLint getUsedSamplerRange(SamplerType type); + bool usesPointSize() const; + + GLint getFragDataLocation(const std::string &name) const; + + void getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name); + GLint getActiveUniformCount(); + GLint getActiveUniformMaxLength(); + GLint getActiveUniformi(GLuint index, GLenum pname) const; + bool isValidUniformLocation(GLint location) const; + LinkedUniform *getUniformByLocation(GLint location) const; + LinkedUniform *getUniformByName(const std::string &name) const; + + GLint getUniformLocation(const std::string &name); + GLuint getUniformIndex(const std::string &name); + void setUniform1fv(GLint location, GLsizei count, const GLfloat *v); + void setUniform2fv(GLint location, GLsizei count, const GLfloat *v); + void setUniform3fv(GLint location, GLsizei count, const GLfloat *v); + void setUniform4fv(GLint location, GLsizei count, const GLfloat *v); + void setUniform1iv(GLint location, GLsizei count, const GLint *v); + void setUniform2iv(GLint location, GLsizei count, const GLint *v); + void setUniform3iv(GLint location, GLsizei count, const GLint *v); + void setUniform4iv(GLint location, GLsizei count, const GLint *v); + void setUniform1uiv(GLint location, GLsizei count, const GLuint *v); + void setUniform2uiv(GLint location, GLsizei count, const GLuint *v); + void setUniform3uiv(GLint location, GLsizei count, const GLuint *v); + void setUniform4uiv(GLint location, GLsizei count, const GLuint *v); + void setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); + void setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); + void setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); + void setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); + void setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); + void setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); + void setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); + void setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); + void setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); + + void getUniformfv(GLint location, GLfloat *params); + void getUniformiv(GLint location, GLint *params); + void getUniformuiv(GLint location, GLuint *params); + + Error applyUniforms(); + Error applyUniformBuffers(const gl::Data &data); + + void getActiveUniformBlockName(GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName) const; + void getActiveUniformBlockiv(GLuint uniformBlockIndex, GLenum pname, GLint *params) const; + GLuint getActiveUniformBlockCount(); + GLint getActiveUniformBlockMaxLength(); + + GLuint getUniformBlockIndex(const std::string &name); + + void bindUniformBlock(GLuint uniformBlockIndex, GLuint uniformBlockBinding); + GLuint getUniformBlockBinding(GLuint uniformBlockIndex) const; + + const UniformBlock *getUniformBlockByIndex(GLuint index) const; + + void setTransformFeedbackVaryings(GLsizei count, const GLchar *const *varyings, GLenum bufferMode); + void getTransformFeedbackVarying(GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name) const; + GLsizei getTransformFeedbackVaryingCount() const; + GLsizei getTransformFeedbackVaryingMaxLength() const; + GLenum getTransformFeedbackBufferMode() const; + + static bool linkVaryings(InfoLog &infoLog, Shader *fragmentShader, Shader *vertexShader); + static bool linkValidateUniforms(InfoLog &infoLog, const std::string &uniformName, const sh::Uniform &vertexUniform, const sh::Uniform &fragmentUniform); + static bool linkValidateInterfaceBlockFields(InfoLog &infoLog, const std::string &uniformName, const sh::InterfaceBlockField &vertexUniform, const sh::InterfaceBlockField &fragmentUniform); + + void addRef(); + void release(); + unsigned int getRefCount() const; + void flagForDeletion(); + bool isFlaggedForDeletion() const; + + void validate(const Caps &caps); + bool validateSamplers(InfoLog *infoLog, const Caps &caps); + bool isValidated() const; + void updateSamplerMapping(); + + private: + void unlink(bool destroy = false); + void resetUniformBlockBindings(); + + bool linkAttributes(InfoLog &infoLog, const AttributeBindings &attributeBindings, const Shader *vertexShader); + bool linkUniformBlocks(InfoLog &infoLog, const Shader &vertexShader, const Shader &fragmentShader, const Caps &caps); + bool areMatchingInterfaceBlocks(gl::InfoLog &infoLog, const sh::InterfaceBlock &vertexInterfaceBlock, + const sh::InterfaceBlock &fragmentInterfaceBlock); + + static bool linkValidateVariablesBase(InfoLog &infoLog, + const std::string &variableName, + const sh::ShaderVariable &vertexVariable, + const sh::ShaderVariable &fragmentVariable, + bool validatePrecision); + + static bool linkValidateVaryings(InfoLog &infoLog, const std::string &varyingName, const sh::Varying &vertexVarying, const sh::Varying &fragmentVarying); + bool gatherTransformFeedbackLinkedVaryings(InfoLog &infoLog, const std::vector &linkedVaryings, + const std::vector &transformFeedbackVaryingNames, + GLenum transformFeedbackBufferMode, + std::vector *outTransformFeedbackLinkedVaryings, + const Caps &caps) const; + bool assignUniformBlockRegister(InfoLog &infoLog, UniformBlock *uniformBlock, GLenum shader, unsigned int registerIndex, const Caps &caps); + void defineOutputVariables(Shader *fragmentShader); + + rx::ProgramImpl *mProgram; + + sh::Attribute mLinkedAttribute[MAX_VERTEX_ATTRIBS]; + + std::map mOutputVariables; + + bool mValidated; + + Shader *mFragmentShader; + Shader *mVertexShader; + + AttributeBindings mAttributeBindings; + + GLuint mUniformBlockBindings[IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS]; + + std::vector mTransformFeedbackVaryings; + GLenum mTransformFeedbackBufferMode; + + bool mLinked; + bool mDeleteStatus; // Flag to indicate that the program can be deleted when no longer in use + + unsigned int mRefCount; + + ResourceManager *mResourceManager; + const GLuint mHandle; + + InfoLog mInfoLog; +}; +} + +#endif // LIBANGLE_PROGRAM_H_ diff --git a/src/3rdparty/angle/src/libANGLE/Query.cpp b/src/3rdparty/angle/src/libANGLE/Query.cpp new file mode 100644 index 0000000000..a402b732bf --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/Query.cpp @@ -0,0 +1,50 @@ +// +// 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. +// + +// Query.cpp: Implements the gl::Query class + +#include "libANGLE/Query.h" +#include "libANGLE/renderer/QueryImpl.h" + +namespace gl +{ +Query::Query(rx::QueryImpl *impl, GLuint id) + : RefCountObject(id), + mQuery(impl) +{ +} + +Query::~Query() +{ + SafeDelete(mQuery); +} + +Error Query::begin() +{ + return mQuery->begin(); +} + +Error Query::end() +{ + return mQuery->end(); +} + +Error Query::getResult(GLuint *params) +{ + return mQuery->getResult(params); +} + +Error Query::isResultAvailable(GLuint *available) +{ + return mQuery->isResultAvailable(available); +} + +GLenum Query::getType() const +{ + return mQuery->getType(); +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/Query.h b/src/3rdparty/angle/src/libANGLE/Query.h new file mode 100644 index 0000000000..8585fde0e2 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/Query.h @@ -0,0 +1,47 @@ +// +// 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. +// + +// Query.h: Defines the gl::Query class + +#ifndef LIBANGLE_QUERY_H_ +#define LIBANGLE_QUERY_H_ + +#include "libANGLE/Error.h" +#include "libANGLE/RefCountObject.h" + +#include "common/angleutils.h" + +#include "angle_gl.h" + +namespace rx +{ +class QueryImpl; +} + +namespace gl +{ + +class Query : public RefCountObject +{ + public: + Query(rx::QueryImpl *impl, GLuint id); + virtual ~Query(); + + Error begin(); + Error end(); + + Error getResult(GLuint *params); + Error isResultAvailable(GLuint *available); + + GLenum getType() const; + + private: + rx::QueryImpl *mQuery; +}; + +} + +#endif // LIBANGLE_QUERY_H_ diff --git a/src/3rdparty/angle/src/libANGLE/RefCountObject.cpp b/src/3rdparty/angle/src/libANGLE/RefCountObject.cpp new file mode 100644 index 0000000000..b1210200cf --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/RefCountObject.cpp @@ -0,0 +1,39 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// RefCountObject.cpp: Defines the gl::RefCountObject base class that provides +// lifecycle support for GL objects using the traditional BindObject scheme, but +// that need to be reference counted for correct cross-context deletion. +// (Concretely, textures, buffers and renderbuffers.) + +#include "RefCountObject.h" + +RefCountObject::RefCountObject(GLuint id) + : mId(id), + mRefCount(0) +{ +} + +RefCountObject::~RefCountObject() +{ + ASSERT(mRefCount == 0); +} + +void RefCountObject::addRef() const +{ + mRefCount++; +} + +void RefCountObject::release() const +{ + ASSERT(mRefCount > 0); + + if (--mRefCount == 0) + { + delete this; + } +} + diff --git a/src/3rdparty/angle/src/libANGLE/RefCountObject.h b/src/3rdparty/angle/src/libANGLE/RefCountObject.h new file mode 100644 index 0000000000..48c0338c3f --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/RefCountObject.h @@ -0,0 +1,110 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// RefCountObject.h: Defines the gl::RefCountObject base class that provides +// lifecycle support for GL objects using the traditional BindObject scheme, but +// that need to be reference counted for correct cross-context deletion. +// (Concretely, textures, buffers and renderbuffers.) + +#ifndef LIBANGLE_REFCOUNTOBJECT_H_ +#define LIBANGLE_REFCOUNTOBJECT_H_ + +#include "common/debug.h" + +#include "angle_gl.h" + +#include + +class RefCountObject : angle::NonCopyable +{ + public: + explicit RefCountObject(GLuint id); + virtual ~RefCountObject(); + + virtual void addRef() const; + virtual void release() const; + + GLuint id() const { return mId; } + + private: + GLuint mId; + + mutable std::size_t mRefCount; +}; + +template +class BindingPointer +{ +public: + BindingPointer() + : mObject(nullptr) + { + } + + BindingPointer(const BindingPointer &other) + : mObject(nullptr) + { + set(other.mObject); + } + + void operator=(const BindingPointer &other) + { + set(other.mObject); + } + + virtual ~BindingPointer() + { + // Objects have to be released before the resource manager is destroyed, so they must be explicitly cleaned up. + ASSERT(mObject == nullptr); + } + + virtual void set(ObjectType *newObject) + { + // addRef first in case newObject == mObject and this is the last reference to it. + if (newObject != nullptr) reinterpret_cast(newObject)->addRef(); + if (mObject != nullptr) reinterpret_cast(mObject)->release(); + mObject = newObject; + } + + ObjectType *get() const { return mObject; } + ObjectType *operator->() const { return mObject; } + + GLuint id() const { return (mObject != nullptr) ? mObject->id() : 0; } + bool operator!() const { return (mObject == nullptr); } + + private: + ObjectType *mObject; +}; + +template +class OffsetBindingPointer : public BindingPointer +{ + public: + OffsetBindingPointer() : mOffset(0), mSize(0) { } + + void set(ObjectType *newObject) override + { + BindingPointer::set(newObject); + mOffset = 0; + mSize = 0; + } + + void set(ObjectType *newObject, GLintptr offset, GLsizeiptr size) + { + BindingPointer::set(newObject); + mOffset = offset; + mSize = size; + } + + GLintptr getOffset() const { return mOffset; } + GLsizeiptr getSize() const { return mSize; } + + private: + GLintptr mOffset; + GLsizeiptr mSize; +}; + +#endif // LIBANGLE_REFCOUNTOBJECT_H_ diff --git a/src/3rdparty/angle/src/libANGLE/Renderbuffer.cpp b/src/3rdparty/angle/src/libANGLE/Renderbuffer.cpp new file mode 100644 index 0000000000..6a0cde812b --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/Renderbuffer.cpp @@ -0,0 +1,130 @@ +// +// 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. +// + +// Renderbuffer.cpp: Implements the renderer-agnostic gl::Renderbuffer class, +// GL renderbuffer objects and related functionality. +// [OpenGL ES 2.0.24] section 4.4.3 page 108. + +#include "libANGLE/Renderbuffer.h" + +#include "common/utilities.h" +#include "libANGLE/FramebufferAttachment.h" +#include "libANGLE/Texture.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/renderer/d3d/RenderTargetD3D.h" +#include "libANGLE/renderer/RenderbufferImpl.h" + +namespace gl +{ +Renderbuffer::Renderbuffer(rx::RenderbufferImpl *impl, GLuint id) + : RefCountObject(id), + mRenderbuffer(impl), + mWidth(0), + mHeight(0), + mInternalFormat(GL_RGBA4), + mSamples(0) +{ +} + +Renderbuffer::~Renderbuffer() +{ + SafeDelete(mRenderbuffer); +} + +Error Renderbuffer::setStorage(GLenum internalformat, size_t width, size_t height) +{ + Error error = mRenderbuffer->setStorage(internalformat, width, height); + if (error.isError()) + { + return error; + } + + mWidth = width; + mHeight = height; + mInternalFormat = internalformat; + mSamples = 0; + + return Error(GL_NO_ERROR); +} + +Error Renderbuffer::setStorageMultisample(size_t samples, GLenum internalformat, size_t width, size_t height) +{ + Error error = mRenderbuffer->setStorageMultisample(samples, internalformat, width, height); + if (error.isError()) + { + return error; + } + + mWidth = width; + mHeight = height; + mInternalFormat = internalformat; + mSamples = samples; + + return Error(GL_NO_ERROR); +} + +rx::RenderbufferImpl *Renderbuffer::getImplementation() +{ + ASSERT(mRenderbuffer); + return mRenderbuffer; +} + +const rx::RenderbufferImpl *Renderbuffer::getImplementation() const +{ + return mRenderbuffer; +} + +GLsizei Renderbuffer::getWidth() const +{ + return mWidth; +} + +GLsizei Renderbuffer::getHeight() const +{ + return mHeight; +} + +GLenum Renderbuffer::getInternalFormat() const +{ + return mInternalFormat; +} + +GLsizei Renderbuffer::getSamples() const +{ + return mSamples; +} + +GLuint Renderbuffer::getRedSize() const +{ + return GetInternalFormatInfo(mInternalFormat).redBits; +} + +GLuint Renderbuffer::getGreenSize() const +{ + return GetInternalFormatInfo(mInternalFormat).greenBits; +} + +GLuint Renderbuffer::getBlueSize() const +{ + return GetInternalFormatInfo(mInternalFormat).blueBits; +} + +GLuint Renderbuffer::getAlphaSize() const +{ + return GetInternalFormatInfo(mInternalFormat).alphaBits; +} + +GLuint Renderbuffer::getDepthSize() const +{ + return GetInternalFormatInfo(mInternalFormat).depthBits; +} + +GLuint Renderbuffer::getStencilSize() const +{ + return GetInternalFormatInfo(mInternalFormat).stencilBits; +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/Renderbuffer.h b/src/3rdparty/angle/src/libANGLE/Renderbuffer.h new file mode 100644 index 0000000000..98c7eb0f10 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/Renderbuffer.h @@ -0,0 +1,69 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Renderbuffer.h: Defines the renderer-agnostic container class gl::Renderbuffer. +// Implements GL renderbuffer objects and related functionality. +// [OpenGL ES 2.0.24] section 4.4.3 page 108. + +#ifndef LIBANGLE_RENDERBUFFER_H_ +#define LIBANGLE_RENDERBUFFER_H_ + +#include "angle_gl.h" + +#include "libANGLE/Error.h" +#include "libANGLE/RefCountObject.h" + +#include "common/angleutils.h" + +namespace rx +{ +class RenderbufferImpl; +} + +namespace gl +{ +class FramebufferAttachment; + +// A GL renderbuffer object is usually used as a depth or stencil buffer attachment +// for a framebuffer object. The renderbuffer itself is a distinct GL object, see +// FramebufferAttachment and Framebuffer for how they are applied to an FBO via an +// attachment point. + +class Renderbuffer : public RefCountObject +{ + public: + Renderbuffer(rx::RenderbufferImpl *impl, GLuint id); + virtual ~Renderbuffer(); + + Error setStorage(GLenum internalformat, size_t width, size_t height); + Error setStorageMultisample(size_t samples, GLenum internalformat, size_t width, size_t height); + + rx::RenderbufferImpl *getImplementation(); + const rx::RenderbufferImpl *getImplementation() const; + + GLsizei getWidth() const; + GLsizei getHeight() const; + GLenum getInternalFormat() const; + GLsizei getSamples() const; + GLuint getRedSize() const; + GLuint getGreenSize() const; + GLuint getBlueSize() const; + GLuint getAlphaSize() const; + GLuint getDepthSize() const; + GLuint getStencilSize() const; + + private: + rx::RenderbufferImpl *mRenderbuffer; + + GLsizei mWidth; + GLsizei mHeight; + GLenum mInternalFormat; + GLsizei mSamples; +}; + +} + +#endif // LIBANGLE_RENDERBUFFER_H_ diff --git a/src/3rdparty/angle/src/libANGLE/ResourceManager.cpp b/src/3rdparty/angle/src/libANGLE/ResourceManager.cpp new file mode 100644 index 0000000000..aaf144cfa9 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/ResourceManager.cpp @@ -0,0 +1,456 @@ +// +// 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. +// + +// ResourceManager.cpp: Implements the gl::ResourceManager class, which tracks and +// retrieves objects which may be shared by multiple Contexts. + +#include "libANGLE/ResourceManager.h" + +#include "libANGLE/Buffer.h" +#include "libANGLE/Program.h" +#include "libANGLE/Renderbuffer.h" +#include "libANGLE/Shader.h" +#include "libANGLE/Texture.h" +#include "libANGLE/Sampler.h" +#include "libANGLE/Fence.h" +#include "libANGLE/renderer/Renderer.h" + +namespace gl +{ +ResourceManager::ResourceManager(rx::ImplFactory *factory) + : mFactory(factory), + mRefCount(1) +{ +} + +ResourceManager::~ResourceManager() +{ + while (!mBufferMap.empty()) + { + deleteBuffer(mBufferMap.begin()->first); + } + + while (!mProgramMap.empty()) + { + deleteProgram(mProgramMap.begin()->first); + } + + while (!mShaderMap.empty()) + { + deleteShader(mShaderMap.begin()->first); + } + + while (!mRenderbufferMap.empty()) + { + deleteRenderbuffer(mRenderbufferMap.begin()->first); + } + + while (!mTextureMap.empty()) + { + deleteTexture(mTextureMap.begin()->first); + } + + while (!mSamplerMap.empty()) + { + deleteSampler(mSamplerMap.begin()->first); + } + + while (!mFenceSyncMap.empty()) + { + deleteFenceSync(mFenceSyncMap.begin()->first); + } +} + +void ResourceManager::addRef() +{ + mRefCount++; +} + +void ResourceManager::release() +{ + if (--mRefCount == 0) + { + delete this; + } +} + +// Returns an unused buffer name +GLuint ResourceManager::createBuffer() +{ + GLuint handle = mBufferHandleAllocator.allocate(); + + mBufferMap[handle] = NULL; + + return handle; +} + +// Returns an unused shader/program name +GLuint ResourceManager::createShader(const gl::Data &data, GLenum type) +{ + GLuint handle = mProgramShaderHandleAllocator.allocate(); + + if (type == GL_VERTEX_SHADER || type == GL_FRAGMENT_SHADER) + { + mShaderMap[handle] = new Shader(this, mFactory->createShader(type), type, handle); + } + else UNREACHABLE(); + + return handle; +} + +// Returns an unused program/shader name +GLuint ResourceManager::createProgram() +{ + GLuint handle = mProgramShaderHandleAllocator.allocate(); + + mProgramMap[handle] = new Program(mFactory->createProgram(), this, handle); + + return handle; +} + +// Returns an unused texture name +GLuint ResourceManager::createTexture() +{ + GLuint handle = mTextureHandleAllocator.allocate(); + + mTextureMap[handle] = NULL; + + return handle; +} + +// Returns an unused renderbuffer name +GLuint ResourceManager::createRenderbuffer() +{ + GLuint handle = mRenderbufferHandleAllocator.allocate(); + + mRenderbufferMap[handle] = NULL; + + return handle; +} + +// Returns an unused sampler name +GLuint ResourceManager::createSampler() +{ + GLuint handle = mSamplerHandleAllocator.allocate(); + + mSamplerMap[handle] = NULL; + + return handle; +} + +// Returns the next unused fence name, and allocates the fence +GLuint ResourceManager::createFenceSync() +{ + GLuint handle = mFenceSyncHandleAllocator.allocate(); + + FenceSync *fenceSync = new FenceSync(mFactory->createFenceSync(), handle); + fenceSync->addRef(); + mFenceSyncMap[handle] = fenceSync; + + return handle; +} + +void ResourceManager::deleteBuffer(GLuint buffer) +{ + BufferMap::iterator bufferObject = mBufferMap.find(buffer); + + if (bufferObject != mBufferMap.end()) + { + mBufferHandleAllocator.release(bufferObject->first); + if (bufferObject->second) bufferObject->second->release(); + mBufferMap.erase(bufferObject); + } +} + +void ResourceManager::deleteShader(GLuint shader) +{ + ShaderMap::iterator shaderObject = mShaderMap.find(shader); + + if (shaderObject != mShaderMap.end()) + { + if (shaderObject->second->getRefCount() == 0) + { + mProgramShaderHandleAllocator.release(shaderObject->first); + delete shaderObject->second; + mShaderMap.erase(shaderObject); + } + else + { + shaderObject->second->flagForDeletion(); + } + } +} + +void ResourceManager::deleteProgram(GLuint program) +{ + ProgramMap::iterator programObject = mProgramMap.find(program); + + if (programObject != mProgramMap.end()) + { + if (programObject->second->getRefCount() == 0) + { + mProgramShaderHandleAllocator.release(programObject->first); + delete programObject->second; + mProgramMap.erase(programObject); + } + else + { + programObject->second->flagForDeletion(); + } + } +} + +void ResourceManager::deleteTexture(GLuint texture) +{ + TextureMap::iterator textureObject = mTextureMap.find(texture); + + if (textureObject != mTextureMap.end()) + { + mTextureHandleAllocator.release(textureObject->first); + if (textureObject->second) textureObject->second->release(); + mTextureMap.erase(textureObject); + } +} + +void ResourceManager::deleteRenderbuffer(GLuint renderbuffer) +{ + RenderbufferMap::iterator renderbufferObject = mRenderbufferMap.find(renderbuffer); + + if (renderbufferObject != mRenderbufferMap.end()) + { + mRenderbufferHandleAllocator.release(renderbufferObject->first); + if (renderbufferObject->second) renderbufferObject->second->release(); + mRenderbufferMap.erase(renderbufferObject); + } +} + +void ResourceManager::deleteSampler(GLuint sampler) +{ + auto samplerObject = mSamplerMap.find(sampler); + + if (samplerObject != mSamplerMap.end()) + { + mSamplerHandleAllocator.release(samplerObject->first); + if (samplerObject->second) samplerObject->second->release(); + mSamplerMap.erase(samplerObject); + } +} + +void ResourceManager::deleteFenceSync(GLuint fenceSync) +{ + auto fenceObjectIt = mFenceSyncMap.find(fenceSync); + + if (fenceObjectIt != mFenceSyncMap.end()) + { + mFenceSyncHandleAllocator.release(fenceObjectIt->first); + if (fenceObjectIt->second) fenceObjectIt->second->release(); + mFenceSyncMap.erase(fenceObjectIt); + } +} + +Buffer *ResourceManager::getBuffer(unsigned int handle) +{ + BufferMap::iterator buffer = mBufferMap.find(handle); + + if (buffer == mBufferMap.end()) + { + return NULL; + } + else + { + return buffer->second; + } +} + +Shader *ResourceManager::getShader(unsigned int handle) +{ + ShaderMap::iterator shader = mShaderMap.find(handle); + + if (shader == mShaderMap.end()) + { + return NULL; + } + else + { + return shader->second; + } +} + +Texture *ResourceManager::getTexture(unsigned int handle) +{ + if (handle == 0) return NULL; + + TextureMap::iterator texture = mTextureMap.find(handle); + + if (texture == mTextureMap.end()) + { + return NULL; + } + else + { + return texture->second; + } +} + +Program *ResourceManager::getProgram(unsigned int handle) const +{ + ProgramMap::const_iterator program = mProgramMap.find(handle); + + if (program == mProgramMap.end()) + { + return NULL; + } + else + { + return program->second; + } +} + +Renderbuffer *ResourceManager::getRenderbuffer(unsigned int handle) +{ + RenderbufferMap::iterator renderbuffer = mRenderbufferMap.find(handle); + + if (renderbuffer == mRenderbufferMap.end()) + { + return NULL; + } + else + { + return renderbuffer->second; + } +} + +Sampler *ResourceManager::getSampler(unsigned int handle) +{ + auto sampler = mSamplerMap.find(handle); + + if (sampler == mSamplerMap.end()) + { + return NULL; + } + else + { + return sampler->second; + } +} + +FenceSync *ResourceManager::getFenceSync(unsigned int handle) +{ + auto fenceObjectIt = mFenceSyncMap.find(handle); + + if (fenceObjectIt == mFenceSyncMap.end()) + { + return NULL; + } + else + { + return fenceObjectIt->second; + } +} + +void ResourceManager::setRenderbuffer(GLuint handle, Renderbuffer *buffer) +{ + mRenderbufferMap[handle] = buffer; +} + +void ResourceManager::checkBufferAllocation(GLuint handle) +{ + if (handle != 0) + { + auto bufferMapIt = mBufferMap.find(handle); + bool handleAllocated = (bufferMapIt != mBufferMap.end()); + + if (handleAllocated && bufferMapIt->second != nullptr) + { + return; + } + + Buffer *buffer = new Buffer(mFactory->createBuffer(), handle); + buffer->addRef(); + + if (handleAllocated) + { + bufferMapIt->second = buffer; + } + else + { + mBufferHandleAllocator.reserve(handle); + mBufferMap[handle] = buffer; + } + } +} + +void ResourceManager::checkTextureAllocation(GLuint handle, GLenum type) +{ + if (handle != 0) + { + auto textureMapIt = mTextureMap.find(handle); + bool handleAllocated = (textureMapIt != mTextureMap.end()); + + if (handleAllocated && textureMapIt->second != nullptr) + { + return; + } + + Texture *texture = new Texture(mFactory->createTexture(type), handle, type); + texture->addRef(); + + if (handleAllocated) + { + textureMapIt->second = texture; + } + else + { + mTextureHandleAllocator.reserve(handle); + mTextureMap[handle] = texture; + } + } +} + +void ResourceManager::checkRenderbufferAllocation(GLuint handle) +{ + if (handle != 0) + { + auto renderbufferMapIt = mRenderbufferMap.find(handle); + bool handleAllocated = (renderbufferMapIt != mRenderbufferMap.end()); + + if (handleAllocated && renderbufferMapIt->second != nullptr) + { + return; + } + + Renderbuffer *renderbuffer = new Renderbuffer(mFactory->createRenderbuffer(), handle); + renderbuffer->addRef(); + + if (handleAllocated) + { + renderbufferMapIt->second = renderbuffer; + } + else + { + mRenderbufferHandleAllocator.reserve(handle); + mRenderbufferMap[handle] = renderbuffer; + } + } +} + +void ResourceManager::checkSamplerAllocation(GLuint sampler) +{ + if (sampler != 0 && !getSampler(sampler)) + { + Sampler *samplerObject = new Sampler(sampler); + mSamplerMap[sampler] = samplerObject; + samplerObject->addRef(); + // Samplers cannot be created via Bind + } +} + +bool ResourceManager::isSampler(GLuint sampler) +{ + return mSamplerMap.find(sampler) != mSamplerMap.end(); +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/ResourceManager.h b/src/3rdparty/angle/src/libANGLE/ResourceManager.h new file mode 100644 index 0000000000..8e95e8840a --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/ResourceManager.h @@ -0,0 +1,114 @@ +// +// 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. +// + +// ResourceManager.h : Defines the ResourceManager class, which tracks objects +// shared by multiple GL contexts. + +#ifndef LIBANGLE_RESOURCEMANAGER_H_ +#define LIBANGLE_RESOURCEMANAGER_H_ + +#include "angle_gl.h" +#include "common/angleutils.h" +#include "libANGLE/angletypes.h" +#include "libANGLE/HandleAllocator.h" + +#include + +namespace rx +{ +class ImplFactory; +} + +namespace gl +{ +class Buffer; +class Shader; +class Program; +class Texture; +class Renderbuffer; +class Sampler; +class FenceSync; +struct Data; + +class ResourceManager : angle::NonCopyable +{ + public: + explicit ResourceManager(rx::ImplFactory *factory); + ~ResourceManager(); + + void addRef(); + void release(); + + GLuint createBuffer(); + GLuint createShader(const gl::Data &data, GLenum type); + GLuint createProgram(); + GLuint createTexture(); + GLuint createRenderbuffer(); + GLuint createSampler(); + GLuint createFenceSync(); + + void deleteBuffer(GLuint buffer); + void deleteShader(GLuint shader); + void deleteProgram(GLuint program); + void deleteTexture(GLuint texture); + void deleteRenderbuffer(GLuint renderbuffer); + void deleteSampler(GLuint sampler); + void deleteFenceSync(GLuint fenceSync); + + Buffer *getBuffer(GLuint handle); + Shader *getShader(GLuint handle); + Program *getProgram(GLuint handle) const; + Texture *getTexture(GLuint handle); + Renderbuffer *getRenderbuffer(GLuint handle); + Sampler *getSampler(GLuint handle); + FenceSync *getFenceSync(GLuint handle); + + void setRenderbuffer(GLuint handle, Renderbuffer *renderbuffer); + + void checkBufferAllocation(GLuint handle); + void checkTextureAllocation(GLuint handle, GLenum type); + void checkRenderbufferAllocation(GLuint handle); + void checkSamplerAllocation(GLuint sampler); + + bool isSampler(GLuint sampler); + + private: + void createTextureInternal(GLuint handle); + + rx::ImplFactory *mFactory; + std::size_t mRefCount; + + typedef std::map BufferMap; + BufferMap mBufferMap; + HandleAllocator mBufferHandleAllocator; + + typedef std::map ShaderMap; + ShaderMap mShaderMap; + + typedef std::map ProgramMap; + ProgramMap mProgramMap; + HandleAllocator mProgramShaderHandleAllocator; + + typedef std::map TextureMap; + TextureMap mTextureMap; + HandleAllocator mTextureHandleAllocator; + + typedef std::map RenderbufferMap; + RenderbufferMap mRenderbufferMap; + HandleAllocator mRenderbufferHandleAllocator; + + typedef std::map SamplerMap; + SamplerMap mSamplerMap; + HandleAllocator mSamplerHandleAllocator; + + typedef std::map FenceMap; + FenceMap mFenceSyncMap; + HandleAllocator mFenceSyncHandleAllocator; +}; + +} + +#endif // LIBANGLE_RESOURCEMANAGER_H_ diff --git a/src/3rdparty/angle/src/libANGLE/Sampler.cpp b/src/3rdparty/angle/src/libANGLE/Sampler.cpp new file mode 100644 index 0000000000..d58bd5a862 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/Sampler.cpp @@ -0,0 +1,43 @@ +// +// 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. +// + +// Sampler.cpp : Implements the Sampler class, which represents a GLES 3 +// sampler object. Sampler objects store some state needed to sample textures. + +#include "libANGLE/Sampler.h" +#include "libANGLE/angletypes.h" + +namespace gl +{ + +Sampler::Sampler(GLuint id) + : RefCountObject(id), + mMinFilter(GL_NEAREST_MIPMAP_LINEAR), + mMagFilter(GL_LINEAR), + mWrapS(GL_REPEAT), + mWrapT(GL_REPEAT), + mWrapR(GL_REPEAT), + mMinLod(-1000.0f), + mMaxLod(1000.0f), + mComparisonMode(GL_NONE), + mComparisonFunc(GL_LEQUAL) +{ +} + +void Sampler::getState(SamplerState *samplerState) const +{ + samplerState->minFilter = mMinFilter; + samplerState->magFilter = mMagFilter; + samplerState->wrapS = mWrapS; + samplerState->wrapT = mWrapT; + samplerState->wrapR = mWrapR; + samplerState->minLod = mMinLod; + samplerState->maxLod = mMaxLod; + samplerState->compareMode = mComparisonMode; + samplerState->compareFunc = mComparisonFunc; +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/Sampler.h b/src/3rdparty/angle/src/libANGLE/Sampler.h new file mode 100644 index 0000000000..d33798ff15 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/Sampler.h @@ -0,0 +1,60 @@ +// +// 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. +// + +// Sampler.h : Defines the Sampler class, which represents a GLES 3 +// sampler object. Sampler objects store some state needed to sample textures. + +#ifndef LIBANGLE_SAMPLER_H_ +#define LIBANGLE_SAMPLER_H_ + +#include "libANGLE/RefCountObject.h" + +namespace gl +{ +struct SamplerState; + +class Sampler : public RefCountObject +{ + public: + Sampler(GLuint id); + + void setMinFilter(GLenum minFilter) { mMinFilter = minFilter; } + void setMagFilter(GLenum magFilter) { mMagFilter = magFilter; } + void setWrapS(GLenum wrapS) { mWrapS = wrapS; } + void setWrapT(GLenum wrapT) { mWrapT = wrapT; } + void setWrapR(GLenum wrapR) { mWrapR = wrapR; } + void setMinLod(GLfloat minLod) { mMinLod = minLod; } + void setMaxLod(GLfloat maxLod) { mMaxLod = maxLod; } + void setComparisonMode(GLenum comparisonMode) { mComparisonMode = comparisonMode; } + void setComparisonFunc(GLenum comparisonFunc) { mComparisonFunc = comparisonFunc; } + + GLenum getMinFilter() const { return mMinFilter; } + GLenum getMagFilter() const { return mMagFilter; } + GLenum getWrapS() const { return mWrapS; } + GLenum getWrapT() const { return mWrapT; } + GLenum getWrapR() const { return mWrapR; } + GLfloat getMinLod() const { return mMinLod; } + GLfloat getMaxLod() const { return mMaxLod; } + GLenum getComparisonMode() const { return mComparisonMode; } + GLenum getComparisonFunc() const { return mComparisonFunc; } + + void getState(SamplerState *samplerState) const; + + private: + GLenum mMinFilter; + GLenum mMagFilter; + GLenum mWrapS; + GLenum mWrapT; + GLenum mWrapR; + GLfloat mMinLod; + GLfloat mMaxLod; + GLenum mComparisonMode; + GLenum mComparisonFunc; +}; + +} + +#endif // LIBANGLE_SAMPLER_H_ diff --git a/src/3rdparty/angle/src/libANGLE/Shader.cpp b/src/3rdparty/angle/src/libANGLE/Shader.cpp new file mode 100644 index 0000000000..7af4ff358d --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/Shader.cpp @@ -0,0 +1,243 @@ +// +// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Shader.cpp: Implements the gl::Shader class and its derived classes +// VertexShader and FragmentShader. Implements GL shader objects and related +// functionality. [OpenGL ES 2.0.24] section 2.10 page 24 and section 3.8 page 84. + +#include "libANGLE/Shader.h" +#include "libANGLE/renderer/Renderer.h" +#include "libANGLE/renderer/ShaderImpl.h" +#include "libANGLE/Constants.h" +#include "libANGLE/ResourceManager.h" + +#include "common/utilities.h" + +#include "GLSLANG/ShaderLang.h" + +#include + +namespace gl +{ + +Shader::Shader(ResourceManager *manager, rx::ShaderImpl *impl, GLenum type, GLuint handle) + : mShader(impl), + mType(type), + mHandle(handle), + mResourceManager(manager), + mRefCount(0), + mDeleteStatus(false), + mCompiled(false) +{ + ASSERT(impl); +} + +Shader::~Shader() +{ + SafeDelete(mShader); +} + +GLuint Shader::getHandle() const +{ + return mHandle; +} + +void Shader::setSource(GLsizei count, const char *const *string, const GLint *length) +{ + std::ostringstream stream; + + for (int i = 0; i < count; i++) + { + if (length == nullptr || length[i] < 0) + { + stream.write(string[i], strlen(string[i])); + } + else + { + stream.write(string[i], length[i]); + } + } + + mSource = stream.str(); +} + +int Shader::getInfoLogLength() const +{ + return mShader->getInfoLog().empty() ? 0 : (mShader->getInfoLog().length() + 1); +} + +void Shader::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) const +{ + int index = 0; + + if (bufSize > 0) + { + index = std::min(bufSize - 1, static_cast(mShader->getInfoLog().length())); + memcpy(infoLog, mShader->getInfoLog().c_str(), index); + + infoLog[index] = '\0'; + } + + if (length) + { + *length = index; + } +} + +int Shader::getSourceLength() const +{ + return mSource.empty() ? 0 : (mSource.length() + 1); +} + +int Shader::getTranslatedSourceLength() const +{ + return mShader->getTranslatedSource().empty() ? 0 : (mShader->getTranslatedSource().length() + 1); +} + +void Shader::getSourceImpl(const std::string &source, GLsizei bufSize, GLsizei *length, char *buffer) +{ + int index = 0; + + if (bufSize > 0) + { + index = std::min(bufSize - 1, static_cast(source.length())); + memcpy(buffer, source.c_str(), index); + + buffer[index] = '\0'; + } + + if (length) + { + *length = index; + } +} + +void Shader::getSource(GLsizei bufSize, GLsizei *length, char *buffer) const +{ + getSourceImpl(mSource, bufSize, length, buffer); +} + +void Shader::getTranslatedSource(GLsizei bufSize, GLsizei *length, char *buffer) const +{ + getSourceImpl(mShader->getTranslatedSource(), bufSize, length, buffer); +} + +void Shader::getTranslatedSourceWithDebugInfo(GLsizei bufSize, GLsizei *length, char *buffer) const +{ + std::string debugInfo(mShader->getDebugInfo()); + getSourceImpl(debugInfo, bufSize, length, buffer); +} + +void Shader::compile(Compiler *compiler) +{ + mCompiled = mShader->compile(compiler, mSource); +} + +void Shader::addRef() +{ + mRefCount++; +} + +void Shader::release() +{ + mRefCount--; + + if (mRefCount == 0 && mDeleteStatus) + { + mResourceManager->deleteShader(mHandle); + } +} + +unsigned int Shader::getRefCount() const +{ + return mRefCount; +} + +bool Shader::isFlaggedForDeletion() const +{ + return mDeleteStatus; +} + +void Shader::flagForDeletion() +{ + mDeleteStatus = true; +} + +const std::vector &Shader::getVaryings() const +{ + return mShader->getVaryings(); +} + +const std::vector &Shader::getUniforms() const +{ + return mShader->getUniforms(); +} + +const std::vector &Shader::getInterfaceBlocks() const +{ + return mShader->getInterfaceBlocks(); +} + +const std::vector &Shader::getActiveAttributes() const +{ + return mShader->getActiveAttributes(); +} + +const std::vector &Shader::getActiveOutputVariables() const +{ + return mShader->getActiveOutputVariables(); +} + +std::vector &Shader::getVaryings() +{ + return mShader->getVaryings(); +} + +std::vector &Shader::getUniforms() +{ + return mShader->getUniforms(); +} + +std::vector &Shader::getInterfaceBlocks() +{ + return mShader->getInterfaceBlocks(); +} + +std::vector &Shader::getActiveAttributes() +{ + return mShader->getActiveAttributes(); +} + +std::vector &Shader::getActiveOutputVariables() +{ + return mShader->getActiveOutputVariables(); +} + + +int Shader::getSemanticIndex(const std::string &attributeName) const +{ + if (!attributeName.empty()) + { + const auto &activeAttributes = mShader->getActiveAttributes(); + + int semanticIndex = 0; + for (size_t attributeIndex = 0; attributeIndex < activeAttributes.size(); attributeIndex++) + { + const sh::ShaderVariable &attribute = activeAttributes[attributeIndex]; + + if (attribute.name == attributeName) + { + return semanticIndex; + } + + semanticIndex += gl::VariableRegisterCount(attribute.type); + } + } + + return -1; +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/Shader.h b/src/3rdparty/angle/src/libANGLE/Shader.h new file mode 100644 index 0000000000..10e79c7499 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/Shader.h @@ -0,0 +1,118 @@ +// +// 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. +// + +// Shader.h: Defines the abstract gl::Shader class and its concrete derived +// classes VertexShader and FragmentShader. Implements GL shader objects and +// related functionality. [OpenGL ES 2.0.24] section 2.10 page 24 and section +// 3.8 page 84. + +#ifndef LIBANGLE_SHADER_H_ +#define LIBANGLE_SHADER_H_ + +#include +#include +#include + +#include "angle_gl.h" +#include + +#include "common/angleutils.h" +#include "libANGLE/angletypes.h" + +namespace rx +{ +class ShaderImpl; +} + +namespace gl +{ +class Compiler; +class ResourceManager; +struct Data; + +struct PackedVarying : public sh::Varying +{ + unsigned int registerIndex; // Assigned during link + unsigned int columnIndex; // Assigned during link, defaults to 0 + + PackedVarying(const sh::Varying &varying) + : sh::Varying(varying), + registerIndex(GL_INVALID_INDEX), + columnIndex(0) + {} + + bool registerAssigned() const { return registerIndex != GL_INVALID_INDEX; } + bool isBuiltIn() const { return name.compare(0, 3, "gl_") == 0; } + + void resetRegisterAssignment() + { + registerIndex = GL_INVALID_INDEX; + } +}; + +class Shader : angle::NonCopyable +{ + public: + Shader(ResourceManager *manager, rx::ShaderImpl *impl, GLenum type, GLuint handle); + + virtual ~Shader(); + + GLenum getType() const { return mType; } + GLuint getHandle() const; + + rx::ShaderImpl *getImplementation() { return mShader; } + const rx::ShaderImpl *getImplementation() const { return mShader; } + + void deleteSource(); + void setSource(GLsizei count, const char *const *string, const GLint *length); + int getInfoLogLength() const; + void getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) const; + int getSourceLength() const; + void getSource(GLsizei bufSize, GLsizei *length, char *buffer) const; + int getTranslatedSourceLength() const; + void getTranslatedSource(GLsizei bufSize, GLsizei *length, char *buffer) const; + void getTranslatedSourceWithDebugInfo(GLsizei bufSize, GLsizei *length, char *buffer) const; + + void compile(Compiler *compiler); + bool isCompiled() const { return mCompiled; } + + void addRef(); + void release(); + unsigned int getRefCount() const; + bool isFlaggedForDeletion() const; + void flagForDeletion(); + + const std::vector &getVaryings() const; + const std::vector &getUniforms() const; + const std::vector &getInterfaceBlocks() const; + const std::vector &getActiveAttributes() const; + const std::vector &getActiveOutputVariables() const; + + std::vector &getVaryings(); + std::vector &getUniforms(); + std::vector &getInterfaceBlocks(); + std::vector &getActiveAttributes(); + std::vector &getActiveOutputVariables(); + + int getSemanticIndex(const std::string &attributeName) const; + + private: + static void getSourceImpl(const std::string &source, GLsizei bufSize, GLsizei *length, char *buffer); + + rx::ShaderImpl *mShader; + const GLuint mHandle; + const GLenum mType; + std::string mSource; + unsigned int mRefCount; // Number of program objects this shader is attached to + bool mDeleteStatus; // Flag to indicate that the shader can be deleted when no longer in use + bool mCompiled; // Indicates if this shader has been successfully compiled + + ResourceManager *mResourceManager; +}; + +} + +#endif // LIBANGLE_SHADER_H_ diff --git a/src/3rdparty/angle/src/libANGLE/State.cpp b/src/3rdparty/angle/src/libANGLE/State.cpp new file mode 100644 index 0000000000..4c044d2950 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/State.cpp @@ -0,0 +1,1470 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// State.cpp: Implements the State class, encapsulating raw GL state. + +#include "libANGLE/State.h" + +#include "libANGLE/Context.h" +#include "libANGLE/Caps.h" +#include "libANGLE/Framebuffer.h" +#include "libANGLE/FramebufferAttachment.h" +#include "libANGLE/Query.h" +#include "libANGLE/VertexArray.h" +#include "libANGLE/formatutils.h" + +namespace gl +{ + +State::State() +{ + mMaxDrawBuffers = 0; + mMaxCombinedTextureImageUnits = 0; +} + +State::~State() +{ + reset(); +} + +void State::initialize(const Caps& caps, GLuint clientVersion) +{ + mMaxDrawBuffers = caps.maxDrawBuffers; + mMaxCombinedTextureImageUnits = caps.maxCombinedTextureImageUnits; + + setColorClearValue(0.0f, 0.0f, 0.0f, 0.0f); + + mDepthClearValue = 1.0f; + mStencilClearValue = 0; + + mRasterizer.rasterizerDiscard = false; + mRasterizer.cullFace = false; + mRasterizer.cullMode = GL_BACK; + mRasterizer.frontFace = GL_CCW; + mRasterizer.polygonOffsetFill = false; + mRasterizer.polygonOffsetFactor = 0.0f; + mRasterizer.polygonOffsetUnits = 0.0f; + mRasterizer.pointDrawMode = false; + mRasterizer.multiSample = false; + mScissorTest = false; + mScissor.x = 0; + mScissor.y = 0; + mScissor.width = 0; + mScissor.height = 0; + + mBlend.blend = false; + mBlend.sourceBlendRGB = GL_ONE; + mBlend.sourceBlendAlpha = GL_ONE; + mBlend.destBlendRGB = GL_ZERO; + mBlend.destBlendAlpha = GL_ZERO; + mBlend.blendEquationRGB = GL_FUNC_ADD; + mBlend.blendEquationAlpha = GL_FUNC_ADD; + mBlend.sampleAlphaToCoverage = false; + mBlend.dither = true; + + mBlendColor.red = 0; + mBlendColor.green = 0; + mBlendColor.blue = 0; + mBlendColor.alpha = 0; + + mDepthStencil.depthTest = false; + mDepthStencil.depthFunc = GL_LESS; + mDepthStencil.depthMask = true; + mDepthStencil.stencilTest = false; + mDepthStencil.stencilFunc = GL_ALWAYS; + mDepthStencil.stencilMask = static_cast(-1); + mDepthStencil.stencilWritemask = static_cast(-1); + mDepthStencil.stencilBackFunc = GL_ALWAYS; + mDepthStencil.stencilBackMask = static_cast(-1); + mDepthStencil.stencilBackWritemask = static_cast(-1); + mDepthStencil.stencilFail = GL_KEEP; + mDepthStencil.stencilPassDepthFail = GL_KEEP; + mDepthStencil.stencilPassDepthPass = GL_KEEP; + mDepthStencil.stencilBackFail = GL_KEEP; + mDepthStencil.stencilBackPassDepthFail = GL_KEEP; + mDepthStencil.stencilBackPassDepthPass = GL_KEEP; + + mStencilRef = 0; + mStencilBackRef = 0; + + mSampleCoverage = false; + mSampleCoverageValue = 1.0f; + mSampleCoverageInvert = false; + mGenerateMipmapHint = GL_DONT_CARE; + mFragmentShaderDerivativeHint = GL_DONT_CARE; + + mLineWidth = 1.0f; + + mViewport.x = 0; + mViewport.y = 0; + mViewport.width = 0; + mViewport.height = 0; + mNearZ = 0.0f; + mFarZ = 1.0f; + + mBlend.colorMaskRed = true; + mBlend.colorMaskGreen = true; + mBlend.colorMaskBlue = true; + mBlend.colorMaskAlpha = true; + + mActiveSampler = 0; + + const GLfloat defaultFloatValues[] = { 0.0f, 0.0f, 0.0f, 1.0f }; + mVertexAttribCurrentValues.resize(caps.maxVertexAttributes); + for (size_t attribIndex = 0; attribIndex < mVertexAttribCurrentValues.size(); ++attribIndex) + { + mVertexAttribCurrentValues[attribIndex].setFloatValues(defaultFloatValues); + } + + mUniformBuffers.resize(caps.maxCombinedUniformBlocks); + mTransformFeedbackBuffers.resize(caps.maxTransformFeedbackSeparateAttributes); + + mSamplerTextures[GL_TEXTURE_2D].resize(caps.maxCombinedTextureImageUnits); + mSamplerTextures[GL_TEXTURE_CUBE_MAP].resize(caps.maxCombinedTextureImageUnits); + if (clientVersion >= 3) + { + // TODO: These could also be enabled via extension + mSamplerTextures[GL_TEXTURE_2D_ARRAY].resize(caps.maxCombinedTextureImageUnits); + mSamplerTextures[GL_TEXTURE_3D].resize(caps.maxCombinedTextureImageUnits); + } + + mSamplers.resize(caps.maxCombinedTextureImageUnits); + + mActiveQueries[GL_ANY_SAMPLES_PASSED].set(NULL); + mActiveQueries[GL_ANY_SAMPLES_PASSED_CONSERVATIVE].set(NULL); + mActiveQueries[GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN].set(NULL); + + mProgram = NULL; + + mReadFramebuffer = NULL; + mDrawFramebuffer = NULL; + + mPrimitiveRestart = false; +} + +void State::reset() +{ + for (TextureBindingMap::iterator bindingVec = mSamplerTextures.begin(); bindingVec != mSamplerTextures.end(); bindingVec++) + { + TextureBindingVector &textureVector = bindingVec->second; + for (size_t textureIdx = 0; textureIdx < textureVector.size(); textureIdx++) + { + textureVector[textureIdx].set(NULL); + } + } + for (size_t samplerIdx = 0; samplerIdx < mSamplers.size(); samplerIdx++) + { + mSamplers[samplerIdx].set(NULL); + } + + mArrayBuffer.set(NULL); + mRenderbuffer.set(NULL); + + if (mProgram) + { + mProgram->release(); + } + mProgram = NULL; + + mTransformFeedback.set(NULL); + + for (State::ActiveQueryMap::iterator i = mActiveQueries.begin(); i != mActiveQueries.end(); i++) + { + i->second.set(NULL); + } + + mGenericUniformBuffer.set(NULL); + mGenericTransformFeedbackBuffer.set(NULL); + for (BufferVector::iterator bufItr = mUniformBuffers.begin(); bufItr != mUniformBuffers.end(); ++bufItr) + { + bufItr->set(NULL); + } + + for (BufferVector::iterator bufItr = mTransformFeedbackBuffers.begin(); bufItr != mTransformFeedbackBuffers.end(); ++bufItr) + { + bufItr->set(NULL); + } + + mCopyReadBuffer.set(NULL); + mCopyWriteBuffer.set(NULL); + + mPack.pixelBuffer.set(NULL); + mUnpack.pixelBuffer.set(NULL); + + mProgram = NULL; +} + +const RasterizerState &State::getRasterizerState() const +{ + return mRasterizer; +} + +const BlendState &State::getBlendState() const +{ + return mBlend; +} + +const DepthStencilState &State::getDepthStencilState() const +{ + return mDepthStencil; +} + +void State::setColorClearValue(float red, float green, float blue, float alpha) +{ + mColorClearValue.red = red; + mColorClearValue.green = green; + mColorClearValue.blue = blue; + mColorClearValue.alpha = alpha; +} + +void State::setDepthClearValue(float depth) +{ + mDepthClearValue = depth; +} + +void State::setStencilClearValue(int stencil) +{ + mStencilClearValue = stencil; +} + +void State::setColorMask(bool red, bool green, bool blue, bool alpha) +{ + mBlend.colorMaskRed = red; + mBlend.colorMaskGreen = green; + mBlend.colorMaskBlue = blue; + mBlend.colorMaskAlpha = alpha; +} + +void State::setDepthMask(bool mask) +{ + mDepthStencil.depthMask = mask; +} + +bool State::isRasterizerDiscardEnabled() const +{ + return mRasterizer.rasterizerDiscard; +} + +void State::setRasterizerDiscard(bool enabled) +{ + mRasterizer.rasterizerDiscard = enabled; +} + +bool State::isCullFaceEnabled() const +{ + return mRasterizer.cullFace; +} + +void State::setCullFace(bool enabled) +{ + mRasterizer.cullFace = enabled; +} + +void State::setCullMode(GLenum mode) +{ + mRasterizer.cullMode = mode; +} + +void State::setFrontFace(GLenum front) +{ + mRasterizer.frontFace = front; +} + +bool State::isDepthTestEnabled() const +{ + return mDepthStencil.depthTest; +} + +void State::setDepthTest(bool enabled) +{ + mDepthStencil.depthTest = enabled; +} + +void State::setDepthFunc(GLenum depthFunc) +{ + mDepthStencil.depthFunc = depthFunc; +} + +void State::setDepthRange(float zNear, float zFar) +{ + mNearZ = zNear; + mFarZ = zFar; +} + +void State::getDepthRange(float *zNear, float *zFar) const +{ + *zNear = mNearZ; + *zFar = mFarZ; +} + +bool State::isBlendEnabled() const +{ + return mBlend.blend; +} + +void State::setBlend(bool enabled) +{ + mBlend.blend = enabled; +} + +void State::setBlendFactors(GLenum sourceRGB, GLenum destRGB, GLenum sourceAlpha, GLenum destAlpha) +{ + mBlend.sourceBlendRGB = sourceRGB; + mBlend.destBlendRGB = destRGB; + mBlend.sourceBlendAlpha = sourceAlpha; + mBlend.destBlendAlpha = destAlpha; +} + +void State::setBlendColor(float red, float green, float blue, float alpha) +{ + mBlendColor.red = red; + mBlendColor.green = green; + mBlendColor.blue = blue; + mBlendColor.alpha = alpha; +} + +void State::setBlendEquation(GLenum rgbEquation, GLenum alphaEquation) +{ + mBlend.blendEquationRGB = rgbEquation; + mBlend.blendEquationAlpha = alphaEquation; +} + +const ColorF &State::getBlendColor() const +{ + return mBlendColor; +} + +bool State::isStencilTestEnabled() const +{ + return mDepthStencil.stencilTest; +} + +void State::setStencilTest(bool enabled) +{ + mDepthStencil.stencilTest = enabled; +} + +void State::setStencilParams(GLenum stencilFunc, GLint stencilRef, GLuint stencilMask) +{ + mDepthStencil.stencilFunc = stencilFunc; + mStencilRef = (stencilRef > 0) ? stencilRef : 0; + mDepthStencil.stencilMask = stencilMask; +} + +void State::setStencilBackParams(GLenum stencilBackFunc, GLint stencilBackRef, GLuint stencilBackMask) +{ + mDepthStencil.stencilBackFunc = stencilBackFunc; + mStencilBackRef = (stencilBackRef > 0) ? stencilBackRef : 0; + mDepthStencil.stencilBackMask = stencilBackMask; +} + +void State::setStencilWritemask(GLuint stencilWritemask) +{ + mDepthStencil.stencilWritemask = stencilWritemask; +} + +void State::setStencilBackWritemask(GLuint stencilBackWritemask) +{ + mDepthStencil.stencilBackWritemask = stencilBackWritemask; +} + +void State::setStencilOperations(GLenum stencilFail, GLenum stencilPassDepthFail, GLenum stencilPassDepthPass) +{ + mDepthStencil.stencilFail = stencilFail; + mDepthStencil.stencilPassDepthFail = stencilPassDepthFail; + mDepthStencil.stencilPassDepthPass = stencilPassDepthPass; +} + +void State::setStencilBackOperations(GLenum stencilBackFail, GLenum stencilBackPassDepthFail, GLenum stencilBackPassDepthPass) +{ + mDepthStencil.stencilBackFail = stencilBackFail; + mDepthStencil.stencilBackPassDepthFail = stencilBackPassDepthFail; + mDepthStencil.stencilBackPassDepthPass = stencilBackPassDepthPass; +} + +GLint State::getStencilRef() const +{ + return mStencilRef; +} + +GLint State::getStencilBackRef() const +{ + return mStencilBackRef; +} + +bool State::isPolygonOffsetFillEnabled() const +{ + return mRasterizer.polygonOffsetFill; +} + +void State::setPolygonOffsetFill(bool enabled) +{ + mRasterizer.polygonOffsetFill = enabled; +} + +void State::setPolygonOffsetParams(GLfloat factor, GLfloat units) +{ + // An application can pass NaN values here, so handle this gracefully + mRasterizer.polygonOffsetFactor = factor != factor ? 0.0f : factor; + mRasterizer.polygonOffsetUnits = units != units ? 0.0f : units; +} + +bool State::isSampleAlphaToCoverageEnabled() const +{ + return mBlend.sampleAlphaToCoverage; +} + +void State::setSampleAlphaToCoverage(bool enabled) +{ + mBlend.sampleAlphaToCoverage = enabled; +} + +bool State::isSampleCoverageEnabled() const +{ + return mSampleCoverage; +} + +void State::setSampleCoverage(bool enabled) +{ + mSampleCoverage = enabled; +} + +void State::setSampleCoverageParams(GLclampf value, bool invert) +{ + mSampleCoverageValue = value; + mSampleCoverageInvert = invert; +} + +void State::getSampleCoverageParams(GLclampf *value, bool *invert) const +{ + ASSERT(value != NULL && invert != NULL); + + *value = mSampleCoverageValue; + *invert = mSampleCoverageInvert; +} + +bool State::isScissorTestEnabled() const +{ + return mScissorTest; +} + +void State::setScissorTest(bool enabled) +{ + mScissorTest = enabled; +} + +void State::setScissorParams(GLint x, GLint y, GLsizei width, GLsizei height) +{ + mScissor.x = x; + mScissor.y = y; + mScissor.width = width; + mScissor.height = height; +} + +const Rectangle &State::getScissor() const +{ + return mScissor; +} + +bool State::isDitherEnabled() const +{ + return mBlend.dither; +} + +void State::setDither(bool enabled) +{ + mBlend.dither = enabled; +} + +bool State::isPrimitiveRestartEnabled() const +{ + return mPrimitiveRestart; +} + +void State::setPrimitiveRestart(bool enabled) +{ + mPrimitiveRestart = enabled; +} + +void State::setEnableFeature(GLenum feature, bool enabled) +{ + switch (feature) + { + case GL_CULL_FACE: setCullFace(enabled); break; + case GL_POLYGON_OFFSET_FILL: setPolygonOffsetFill(enabled); break; + case GL_SAMPLE_ALPHA_TO_COVERAGE: setSampleAlphaToCoverage(enabled); break; + case GL_SAMPLE_COVERAGE: setSampleCoverage(enabled); break; + case GL_SCISSOR_TEST: setScissorTest(enabled); break; + case GL_STENCIL_TEST: setStencilTest(enabled); break; + case GL_DEPTH_TEST: setDepthTest(enabled); break; + case GL_BLEND: setBlend(enabled); break; + case GL_DITHER: setDither(enabled); break; + case GL_PRIMITIVE_RESTART_FIXED_INDEX: setPrimitiveRestart(enabled); break; + case GL_RASTERIZER_DISCARD: setRasterizerDiscard(enabled); break; + default: UNREACHABLE(); + } +} + +bool State::getEnableFeature(GLenum feature) +{ + switch (feature) + { + case GL_CULL_FACE: return isCullFaceEnabled(); + case GL_POLYGON_OFFSET_FILL: return isPolygonOffsetFillEnabled(); + case GL_SAMPLE_ALPHA_TO_COVERAGE: return isSampleAlphaToCoverageEnabled(); + case GL_SAMPLE_COVERAGE: return isSampleCoverageEnabled(); + case GL_SCISSOR_TEST: return isScissorTestEnabled(); + case GL_STENCIL_TEST: return isStencilTestEnabled(); + case GL_DEPTH_TEST: return isDepthTestEnabled(); + case GL_BLEND: return isBlendEnabled(); + case GL_DITHER: return isDitherEnabled(); + case GL_PRIMITIVE_RESTART_FIXED_INDEX: return isPrimitiveRestartEnabled(); + case GL_RASTERIZER_DISCARD: return isRasterizerDiscardEnabled(); + default: UNREACHABLE(); return false; + } +} + +void State::setLineWidth(GLfloat width) +{ + mLineWidth = width; +} + +void State::setGenerateMipmapHint(GLenum hint) +{ + mGenerateMipmapHint = hint; +} + +void State::setFragmentShaderDerivativeHint(GLenum hint) +{ + mFragmentShaderDerivativeHint = hint; + // TODO: Propagate the hint to shader translator so we can write + // ddx, ddx_coarse, or ddx_fine depending on the hint. + // Ignore for now. It is valid for implementations to ignore hint. +} + +void State::setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height) +{ + mViewport.x = x; + mViewport.y = y; + mViewport.width = width; + mViewport.height = height; +} + +const Rectangle &State::getViewport() const +{ + return mViewport; +} + +void State::setActiveSampler(unsigned int active) +{ + mActiveSampler = active; +} + +unsigned int State::getActiveSampler() const +{ + return mActiveSampler; +} + +void State::setSamplerTexture(GLenum type, Texture *texture) +{ + mSamplerTextures[type][mActiveSampler].set(texture); +} + +Texture *State::getSamplerTexture(unsigned int sampler, GLenum type) const +{ + const auto it = mSamplerTextures.find(type); + ASSERT(it != mSamplerTextures.end()); + return it->second[sampler].get(); +} + +GLuint State::getSamplerTextureId(unsigned int sampler, GLenum type) const +{ + const auto it = mSamplerTextures.find(type); + ASSERT(it != mSamplerTextures.end()); + return it->second[sampler].id(); +} + +void State::detachTexture(const TextureMap &zeroTextures, GLuint texture) +{ + // Textures have a detach method on State rather than a simple + // removeBinding, because the zero/null texture objects are managed + // separately, and don't have to go through the Context's maps or + // the ResourceManager. + + // [OpenGL ES 2.0.24] section 3.8 page 84: + // If a texture object is deleted, it is as if all texture units which are bound to that texture object are + // rebound to texture object zero + + for (TextureBindingMap::iterator bindingVec = mSamplerTextures.begin(); bindingVec != mSamplerTextures.end(); bindingVec++) + { + GLenum textureType = bindingVec->first; + TextureBindingVector &textureVector = bindingVec->second; + for (size_t textureIdx = 0; textureIdx < textureVector.size(); textureIdx++) + { + BindingPointer &binding = textureVector[textureIdx]; + if (binding.id() == texture) + { + auto it = zeroTextures.find(textureType); + ASSERT(it != zeroTextures.end()); + // Zero textures are the "default" textures instead of NULL + binding.set(it->second.get()); + } + } + } + + // [OpenGL ES 2.0.24] section 4.4 page 112: + // If a texture object is deleted while its image is attached to the currently bound framebuffer, then it is + // as if Texture2DAttachment had been called, with a texture of 0, for each attachment point to which this + // image was attached in the currently bound framebuffer. + + if (mReadFramebuffer) + { + mReadFramebuffer->detachTexture(texture); + } + + if (mDrawFramebuffer) + { + mDrawFramebuffer->detachTexture(texture); + } +} + +void State::initializeZeroTextures(const TextureMap &zeroTextures) +{ + for (auto it = zeroTextures.cbegin(); it != zeroTextures.cend(); ++it) + { + const auto &zeroTexture = *it; + auto &samplerTextureArray = mSamplerTextures[zeroTexture.first]; + + for (size_t textureUnit = 0; textureUnit < samplerTextureArray.size(); ++textureUnit) + { + samplerTextureArray[textureUnit].set(zeroTexture.second.get()); + } + } +} + +void State::setSamplerBinding(GLuint textureUnit, Sampler *sampler) +{ + mSamplers[textureUnit].set(sampler); +} + +GLuint State::getSamplerId(GLuint textureUnit) const +{ + ASSERT(textureUnit < mSamplers.size()); + return mSamplers[textureUnit].id(); +} + +Sampler *State::getSampler(GLuint textureUnit) const +{ + return mSamplers[textureUnit].get(); +} + +void State::detachSampler(GLuint sampler) +{ + // [OpenGL ES 3.0.2] section 3.8.2 pages 123-124: + // If a sampler object that is currently bound to one or more texture units is + // deleted, it is as though BindSampler is called once for each texture unit to + // which the sampler is bound, with unit set to the texture unit and sampler set to zero. + for (size_t textureUnit = 0; textureUnit < mSamplers.size(); textureUnit++) + { + BindingPointer &samplerBinding = mSamplers[textureUnit]; + if (samplerBinding.id() == sampler) + { + samplerBinding.set(NULL); + } + } +} + +void State::setRenderbufferBinding(Renderbuffer *renderbuffer) +{ + mRenderbuffer.set(renderbuffer); +} + +GLuint State::getRenderbufferId() const +{ + return mRenderbuffer.id(); +} + +Renderbuffer *State::getCurrentRenderbuffer() +{ + return mRenderbuffer.get(); +} + +void State::detachRenderbuffer(GLuint renderbuffer) +{ + // [OpenGL ES 2.0.24] section 4.4 page 109: + // If a renderbuffer that is currently bound to RENDERBUFFER is deleted, it is as though BindRenderbuffer + // had been executed with the target RENDERBUFFER and name of zero. + + if (mRenderbuffer.id() == renderbuffer) + { + mRenderbuffer.set(NULL); + } + + // [OpenGL ES 2.0.24] section 4.4 page 111: + // If a renderbuffer object is deleted while its image is attached to the currently bound framebuffer, + // then it is as if FramebufferRenderbuffer had been called, with a renderbuffer of 0, for each attachment + // point to which this image was attached in the currently bound framebuffer. + + Framebuffer *readFramebuffer = mReadFramebuffer; + Framebuffer *drawFramebuffer = mDrawFramebuffer; + + if (readFramebuffer) + { + readFramebuffer->detachRenderbuffer(renderbuffer); + } + + if (drawFramebuffer && drawFramebuffer != readFramebuffer) + { + drawFramebuffer->detachRenderbuffer(renderbuffer); + } + +} + +void State::setReadFramebufferBinding(Framebuffer *framebuffer) +{ + mReadFramebuffer = framebuffer; +} + +void State::setDrawFramebufferBinding(Framebuffer *framebuffer) +{ + mDrawFramebuffer = framebuffer; +} + +Framebuffer *State::getTargetFramebuffer(GLenum target) const +{ + switch (target) + { + case GL_READ_FRAMEBUFFER_ANGLE: return mReadFramebuffer; + case GL_DRAW_FRAMEBUFFER_ANGLE: + case GL_FRAMEBUFFER: return mDrawFramebuffer; + default: UNREACHABLE(); return NULL; + } +} + +Framebuffer *State::getReadFramebuffer() +{ + return mReadFramebuffer; +} + +Framebuffer *State::getDrawFramebuffer() +{ + return mDrawFramebuffer; +} + +const Framebuffer *State::getReadFramebuffer() const +{ + return mReadFramebuffer; +} + +const Framebuffer *State::getDrawFramebuffer() const +{ + return mDrawFramebuffer; +} + +bool State::removeReadFramebufferBinding(GLuint framebuffer) +{ + if (mReadFramebuffer->id() == framebuffer) + { + mReadFramebuffer = NULL; + return true; + } + + return false; +} + +bool State::removeDrawFramebufferBinding(GLuint framebuffer) +{ + if (mDrawFramebuffer->id() == framebuffer) + { + mDrawFramebuffer = NULL; + return true; + } + + return false; +} + +void State::setVertexArrayBinding(VertexArray *vertexArray) +{ + mVertexArray = vertexArray; +} + +GLuint State::getVertexArrayId() const +{ + ASSERT(mVertexArray != NULL); + return mVertexArray->id(); +} + +VertexArray *State::getVertexArray() const +{ + ASSERT(mVertexArray != NULL); + return mVertexArray; +} + +bool State::removeVertexArrayBinding(GLuint vertexArray) +{ + if (mVertexArray->id() == vertexArray) + { + mVertexArray = NULL; + return true; + } + + return false; +} + +void State::setProgram(Program *newProgram) +{ + if (mProgram != newProgram) + { + if (mProgram) + { + mProgram->release(); + } + + mProgram = newProgram; + + if (mProgram) + { + newProgram->addRef(); + } + } +} + +Program *State::getProgram() const +{ + return mProgram; +} + +void State::setTransformFeedbackBinding(TransformFeedback *transformFeedback) +{ + mTransformFeedback.set(transformFeedback); +} + +TransformFeedback *State::getCurrentTransformFeedback() const +{ + return mTransformFeedback.get(); +} + +bool State::isTransformFeedbackActiveUnpaused() const +{ + gl::TransformFeedback *curTransformFeedback = getCurrentTransformFeedback(); + return curTransformFeedback && curTransformFeedback->isStarted() && !curTransformFeedback->isPaused(); +} + +void State::detachTransformFeedback(GLuint transformFeedback) +{ + if (mTransformFeedback.id() == transformFeedback) + { + mTransformFeedback.set(NULL); + } +} + +bool State::isQueryActive() const +{ + for (State::ActiveQueryMap::const_iterator i = mActiveQueries.begin(); + i != mActiveQueries.end(); i++) + { + if (i->second.get() != NULL) + { + return true; + } + } + + return false; +} + +void State::setActiveQuery(GLenum target, Query *query) +{ + mActiveQueries[target].set(query); +} + +GLuint State::getActiveQueryId(GLenum target) const +{ + const Query *query = getActiveQuery(target); + return (query ? query->id() : 0u); +} + +Query *State::getActiveQuery(GLenum target) const +{ + const auto it = mActiveQueries.find(target); + + // All query types should already exist in the activeQueries map + ASSERT(it != mActiveQueries.end()); + + return it->second.get(); +} + +void State::setArrayBufferBinding(Buffer *buffer) +{ + mArrayBuffer.set(buffer); +} + +GLuint State::getArrayBufferId() const +{ + return mArrayBuffer.id(); +} + +bool State::removeArrayBufferBinding(GLuint buffer) +{ + if (mArrayBuffer.id() == buffer) + { + mArrayBuffer.set(NULL); + return true; + } + + return false; +} + +void State::setGenericUniformBufferBinding(Buffer *buffer) +{ + mGenericUniformBuffer.set(buffer); +} + +void State::setIndexedUniformBufferBinding(GLuint index, Buffer *buffer, GLintptr offset, GLsizeiptr size) +{ + mUniformBuffers[index].set(buffer, offset, size); +} + +GLuint State::getIndexedUniformBufferId(GLuint index) const +{ + ASSERT(static_cast(index) < mUniformBuffers.size()); + + return mUniformBuffers[index].id(); +} + +Buffer *State::getIndexedUniformBuffer(GLuint index) const +{ + ASSERT(static_cast(index) < mUniformBuffers.size()); + + return mUniformBuffers[index].get(); +} + +GLintptr State::getIndexedUniformBufferOffset(GLuint index) const +{ + ASSERT(static_cast(index) < mUniformBuffers.size()); + + return mUniformBuffers[index].getOffset(); +} + +GLsizeiptr State::getIndexedUniformBufferSize(GLuint index) const +{ + ASSERT(static_cast(index) < mUniformBuffers.size()); + + return mUniformBuffers[index].getSize(); +} + +void State::setGenericTransformFeedbackBufferBinding(Buffer *buffer) +{ + mGenericTransformFeedbackBuffer.set(buffer); +} + +void State::setIndexedTransformFeedbackBufferBinding(GLuint index, Buffer *buffer, GLintptr offset, GLsizeiptr size) +{ + mTransformFeedbackBuffers[index].set(buffer, offset, size); +} + +GLuint State::getIndexedTransformFeedbackBufferId(GLuint index) const +{ + ASSERT(static_cast(index) < mTransformFeedbackBuffers.size()); + + return mTransformFeedbackBuffers[index].id(); +} + +Buffer *State::getIndexedTransformFeedbackBuffer(GLuint index) const +{ + ASSERT(static_cast(index) < mTransformFeedbackBuffers.size()); + + return mTransformFeedbackBuffers[index].get(); +} + +GLuint State::getIndexedTransformFeedbackBufferOffset(GLuint index) const +{ + ASSERT(static_cast(index) < mTransformFeedbackBuffers.size()); + + return mTransformFeedbackBuffers[index].getOffset(); +} + +size_t State::getTransformFeedbackBufferIndexRange() const +{ + return mTransformFeedbackBuffers.size(); +} + +void State::setCopyReadBufferBinding(Buffer *buffer) +{ + mCopyReadBuffer.set(buffer); +} + +void State::setCopyWriteBufferBinding(Buffer *buffer) +{ + mCopyWriteBuffer.set(buffer); +} + +void State::setPixelPackBufferBinding(Buffer *buffer) +{ + mPack.pixelBuffer.set(buffer); +} + +void State::setPixelUnpackBufferBinding(Buffer *buffer) +{ + mUnpack.pixelBuffer.set(buffer); +} + +Buffer *State::getTargetBuffer(GLenum target) const +{ + switch (target) + { + case GL_ARRAY_BUFFER: return mArrayBuffer.get(); + case GL_COPY_READ_BUFFER: return mCopyReadBuffer.get(); + case GL_COPY_WRITE_BUFFER: return mCopyWriteBuffer.get(); + case GL_ELEMENT_ARRAY_BUFFER: return getVertexArray()->getElementArrayBuffer(); + case GL_PIXEL_PACK_BUFFER: return mPack.pixelBuffer.get(); + case GL_PIXEL_UNPACK_BUFFER: return mUnpack.pixelBuffer.get(); + case GL_TRANSFORM_FEEDBACK_BUFFER: return mGenericTransformFeedbackBuffer.get(); + case GL_UNIFORM_BUFFER: return mGenericUniformBuffer.get(); + default: UNREACHABLE(); return NULL; + } +} + +void State::setEnableVertexAttribArray(unsigned int attribNum, bool enabled) +{ + getVertexArray()->enableAttribute(attribNum, enabled); +} + +void State::setVertexAttribf(GLuint index, const GLfloat values[4]) +{ + ASSERT(static_cast(index) < mVertexAttribCurrentValues.size()); + mVertexAttribCurrentValues[index].setFloatValues(values); +} + +void State::setVertexAttribu(GLuint index, const GLuint values[4]) +{ + ASSERT(static_cast(index) < mVertexAttribCurrentValues.size()); + mVertexAttribCurrentValues[index].setUnsignedIntValues(values); +} + +void State::setVertexAttribi(GLuint index, const GLint values[4]) +{ + ASSERT(static_cast(index) < mVertexAttribCurrentValues.size()); + mVertexAttribCurrentValues[index].setIntValues(values); +} + +void State::setVertexAttribState(unsigned int attribNum, Buffer *boundBuffer, GLint size, GLenum type, bool normalized, + bool pureInteger, GLsizei stride, const void *pointer) +{ + getVertexArray()->setAttributeState(attribNum, boundBuffer, size, type, normalized, pureInteger, stride, pointer); +} + +const VertexAttribCurrentValueData &State::getVertexAttribCurrentValue(unsigned int attribNum) const +{ + ASSERT(static_cast(attribNum) < mVertexAttribCurrentValues.size()); + return mVertexAttribCurrentValues[attribNum]; +} + +const void *State::getVertexAttribPointer(unsigned int attribNum) const +{ + return getVertexArray()->getVertexAttribute(attribNum).pointer; +} + +void State::setPackAlignment(GLint alignment) +{ + mPack.alignment = alignment; +} + +GLint State::getPackAlignment() const +{ + return mPack.alignment; +} + +void State::setPackReverseRowOrder(bool reverseRowOrder) +{ + mPack.reverseRowOrder = reverseRowOrder; +} + +bool State::getPackReverseRowOrder() const +{ + return mPack.reverseRowOrder; +} + +const PixelPackState &State::getPackState() const +{ + return mPack; +} + +PixelPackState &State::getPackState() +{ + return mPack; +} + +void State::setUnpackAlignment(GLint alignment) +{ + mUnpack.alignment = alignment; +} + +GLint State::getUnpackAlignment() const +{ + return mUnpack.alignment; +} + +void State::setUnpackRowLength(GLint rowLength) +{ + mUnpack.rowLength = rowLength; +} + +GLint State::getUnpackRowLength() const +{ + return mUnpack.rowLength; +} + +const PixelUnpackState &State::getUnpackState() const +{ + return mUnpack; +} + +PixelUnpackState &State::getUnpackState() +{ + return mUnpack; +} + +void State::getBooleanv(GLenum pname, GLboolean *params) +{ + switch (pname) + { + case GL_SAMPLE_COVERAGE_INVERT: *params = mSampleCoverageInvert; break; + case GL_DEPTH_WRITEMASK: *params = mDepthStencil.depthMask; break; + case GL_COLOR_WRITEMASK: + params[0] = mBlend.colorMaskRed; + params[1] = mBlend.colorMaskGreen; + params[2] = mBlend.colorMaskBlue; + params[3] = mBlend.colorMaskAlpha; + break; + case GL_CULL_FACE: *params = mRasterizer.cullFace; break; + case GL_POLYGON_OFFSET_FILL: *params = mRasterizer.polygonOffsetFill; break; + case GL_SAMPLE_ALPHA_TO_COVERAGE: *params = mBlend.sampleAlphaToCoverage; break; + case GL_SAMPLE_COVERAGE: *params = mSampleCoverage; break; + case GL_SCISSOR_TEST: *params = mScissorTest; break; + case GL_STENCIL_TEST: *params = mDepthStencil.stencilTest; break; + case GL_DEPTH_TEST: *params = mDepthStencil.depthTest; break; + case GL_BLEND: *params = mBlend.blend; break; + case GL_DITHER: *params = mBlend.dither; break; + case GL_TRANSFORM_FEEDBACK_ACTIVE: *params = getCurrentTransformFeedback()->isStarted(); break; + case GL_TRANSFORM_FEEDBACK_PAUSED: *params = getCurrentTransformFeedback()->isPaused(); break; + default: + UNREACHABLE(); + break; + } +} + +void State::getFloatv(GLenum pname, GLfloat *params) +{ + // Please note: DEPTH_CLEAR_VALUE is included in our internal getFloatv implementation + // because it is stored as a float, despite the fact that the GL ES 2.0 spec names + // GetIntegerv as its native query function. As it would require conversion in any + // case, this should make no difference to the calling application. + switch (pname) + { + case GL_LINE_WIDTH: *params = mLineWidth; break; + case GL_SAMPLE_COVERAGE_VALUE: *params = mSampleCoverageValue; break; + case GL_DEPTH_CLEAR_VALUE: *params = mDepthClearValue; break; + case GL_POLYGON_OFFSET_FACTOR: *params = mRasterizer.polygonOffsetFactor; break; + case GL_POLYGON_OFFSET_UNITS: *params = mRasterizer.polygonOffsetUnits; break; + case GL_DEPTH_RANGE: + params[0] = mNearZ; + params[1] = mFarZ; + break; + case GL_COLOR_CLEAR_VALUE: + params[0] = mColorClearValue.red; + params[1] = mColorClearValue.green; + params[2] = mColorClearValue.blue; + params[3] = mColorClearValue.alpha; + break; + case GL_BLEND_COLOR: + params[0] = mBlendColor.red; + params[1] = mBlendColor.green; + params[2] = mBlendColor.blue; + params[3] = mBlendColor.alpha; + break; + default: + UNREACHABLE(); + break; + } +} + +void State::getIntegerv(const gl::Data &data, GLenum pname, GLint *params) +{ + if (pname >= GL_DRAW_BUFFER0_EXT && pname <= GL_DRAW_BUFFER15_EXT) + { + unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0_EXT); + ASSERT(colorAttachment < mMaxDrawBuffers); + Framebuffer *framebuffer = mDrawFramebuffer; + *params = framebuffer->getDrawBufferState(colorAttachment); + return; + } + + // Please note: DEPTH_CLEAR_VALUE is not included in our internal getIntegerv implementation + // because it is stored as a float, despite the fact that the GL ES 2.0 spec names + // GetIntegerv as its native query function. As it would require conversion in any + // case, this should make no difference to the calling application. You may find it in + // State::getFloatv. + switch (pname) + { + case GL_ARRAY_BUFFER_BINDING: *params = mArrayBuffer.id(); break; + case GL_ELEMENT_ARRAY_BUFFER_BINDING: *params = getVertexArray()->getElementArrayBufferId(); break; + //case GL_FRAMEBUFFER_BINDING: // now equivalent to GL_DRAW_FRAMEBUFFER_BINDING_ANGLE + case GL_DRAW_FRAMEBUFFER_BINDING_ANGLE: *params = mDrawFramebuffer->id(); break; + case GL_READ_FRAMEBUFFER_BINDING_ANGLE: *params = mReadFramebuffer->id(); break; + case GL_RENDERBUFFER_BINDING: *params = mRenderbuffer.id(); break; + case GL_VERTEX_ARRAY_BINDING: *params = mVertexArray->id(); break; + case GL_CURRENT_PROGRAM: *params = mProgram ? mProgram->id() : 0; break; + case GL_PACK_ALIGNMENT: *params = mPack.alignment; break; + case GL_PACK_REVERSE_ROW_ORDER_ANGLE: *params = mPack.reverseRowOrder; break; + case GL_UNPACK_ALIGNMENT: *params = mUnpack.alignment; break; + case GL_UNPACK_ROW_LENGTH: *params = mUnpack.rowLength; break; + case GL_GENERATE_MIPMAP_HINT: *params = mGenerateMipmapHint; break; + case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES: *params = mFragmentShaderDerivativeHint; break; + case GL_ACTIVE_TEXTURE: *params = (mActiveSampler + GL_TEXTURE0); break; + case GL_STENCIL_FUNC: *params = mDepthStencil.stencilFunc; break; + case GL_STENCIL_REF: *params = mStencilRef; break; + case GL_STENCIL_VALUE_MASK: *params = clampToInt(mDepthStencil.stencilMask); break; + case GL_STENCIL_BACK_FUNC: *params = mDepthStencil.stencilBackFunc; break; + case GL_STENCIL_BACK_REF: *params = mStencilBackRef; break; + case GL_STENCIL_BACK_VALUE_MASK: *params = clampToInt(mDepthStencil.stencilBackMask); break; + case GL_STENCIL_FAIL: *params = mDepthStencil.stencilFail; break; + case GL_STENCIL_PASS_DEPTH_FAIL: *params = mDepthStencil.stencilPassDepthFail; break; + case GL_STENCIL_PASS_DEPTH_PASS: *params = mDepthStencil.stencilPassDepthPass; break; + case GL_STENCIL_BACK_FAIL: *params = mDepthStencil.stencilBackFail; break; + case GL_STENCIL_BACK_PASS_DEPTH_FAIL: *params = mDepthStencil.stencilBackPassDepthFail; break; + case GL_STENCIL_BACK_PASS_DEPTH_PASS: *params = mDepthStencil.stencilBackPassDepthPass; break; + case GL_DEPTH_FUNC: *params = mDepthStencil.depthFunc; break; + case GL_BLEND_SRC_RGB: *params = mBlend.sourceBlendRGB; break; + case GL_BLEND_SRC_ALPHA: *params = mBlend.sourceBlendAlpha; break; + case GL_BLEND_DST_RGB: *params = mBlend.destBlendRGB; break; + case GL_BLEND_DST_ALPHA: *params = mBlend.destBlendAlpha; break; + case GL_BLEND_EQUATION_RGB: *params = mBlend.blendEquationRGB; break; + case GL_BLEND_EQUATION_ALPHA: *params = mBlend.blendEquationAlpha; break; + case GL_STENCIL_WRITEMASK: *params = clampToInt(mDepthStencil.stencilWritemask); break; + case GL_STENCIL_BACK_WRITEMASK: *params = clampToInt(mDepthStencil.stencilBackWritemask); break; + case GL_STENCIL_CLEAR_VALUE: *params = mStencilClearValue; break; + case GL_IMPLEMENTATION_COLOR_READ_TYPE: *params = mReadFramebuffer->getImplementationColorReadType(); break; + case GL_IMPLEMENTATION_COLOR_READ_FORMAT: *params = mReadFramebuffer->getImplementationColorReadFormat(); break; + case GL_SAMPLE_BUFFERS: + case GL_SAMPLES: + { + gl::Framebuffer *framebuffer = mDrawFramebuffer; + if (framebuffer->checkStatus(data) == GL_FRAMEBUFFER_COMPLETE) + { + switch (pname) + { + case GL_SAMPLE_BUFFERS: + if (framebuffer->getSamples(data) != 0) + { + *params = 1; + } + else + { + *params = 0; + } + break; + case GL_SAMPLES: + *params = framebuffer->getSamples(data); + break; + } + } + else + { + *params = 0; + } + } + break; + case GL_VIEWPORT: + params[0] = mViewport.x; + params[1] = mViewport.y; + params[2] = mViewport.width; + params[3] = mViewport.height; + break; + case GL_SCISSOR_BOX: + params[0] = mScissor.x; + params[1] = mScissor.y; + params[2] = mScissor.width; + params[3] = mScissor.height; + break; + case GL_CULL_FACE_MODE: *params = mRasterizer.cullMode; break; + case GL_FRONT_FACE: *params = mRasterizer.frontFace; break; + case GL_RED_BITS: + case GL_GREEN_BITS: + case GL_BLUE_BITS: + case GL_ALPHA_BITS: + { + gl::Framebuffer *framebuffer = getDrawFramebuffer(); + gl::FramebufferAttachment *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; + } + } + else + { + *params = 0; + } + } + break; + case GL_DEPTH_BITS: + { + gl::Framebuffer *framebuffer = getDrawFramebuffer(); + gl::FramebufferAttachment *depthbuffer = framebuffer->getDepthbuffer(); + + if (depthbuffer) + { + *params = depthbuffer->getDepthSize(); + } + else + { + *params = 0; + } + } + break; + case GL_STENCIL_BITS: + { + gl::Framebuffer *framebuffer = getDrawFramebuffer(); + gl::FramebufferAttachment *stencilbuffer = framebuffer->getStencilbuffer(); + + if (stencilbuffer) + { + *params = stencilbuffer->getStencilSize(); + } + else + { + *params = 0; + } + } + break; + case GL_TEXTURE_BINDING_2D: + ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits); + *params = getSamplerTextureId(mActiveSampler, GL_TEXTURE_2D) ; + break; + case GL_TEXTURE_BINDING_CUBE_MAP: + ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits); + *params = getSamplerTextureId(mActiveSampler, GL_TEXTURE_CUBE_MAP); + break; + case GL_TEXTURE_BINDING_3D: + ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits); + *params = getSamplerTextureId(mActiveSampler, GL_TEXTURE_3D); + break; + case GL_TEXTURE_BINDING_2D_ARRAY: + ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits); + *params = getSamplerTextureId(mActiveSampler, GL_TEXTURE_2D_ARRAY); + break; + case GL_UNIFORM_BUFFER_BINDING: + *params = mGenericUniformBuffer.id(); + break; + case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: + *params = mGenericTransformFeedbackBuffer.id(); + break; + case GL_COPY_READ_BUFFER_BINDING: + *params = mCopyReadBuffer.id(); + break; + case GL_COPY_WRITE_BUFFER_BINDING: + *params = mCopyWriteBuffer.id(); + break; + case GL_PIXEL_PACK_BUFFER_BINDING: + *params = mPack.pixelBuffer.id(); + break; + case GL_PIXEL_UNPACK_BUFFER_BINDING: + *params = mUnpack.pixelBuffer.id(); + break; + default: + UNREACHABLE(); + break; + } +} + +bool State::getIndexedIntegerv(GLenum target, GLuint index, GLint *data) +{ + switch (target) + { + case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: + if (static_cast(index) < mTransformFeedbackBuffers.size()) + { + *data = mTransformFeedbackBuffers[index].id(); + } + break; + case GL_UNIFORM_BUFFER_BINDING: + if (static_cast(index) < mUniformBuffers.size()) + { + *data = mUniformBuffers[index].id(); + } + break; + default: + return false; + } + + return true; +} + +bool State::getIndexedInteger64v(GLenum target, GLuint index, GLint64 *data) +{ + switch (target) + { + case GL_TRANSFORM_FEEDBACK_BUFFER_START: + if (static_cast(index) < mTransformFeedbackBuffers.size()) + { + *data = mTransformFeedbackBuffers[index].getOffset(); + } + break; + case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE: + if (static_cast(index) < mTransformFeedbackBuffers.size()) + { + *data = mTransformFeedbackBuffers[index].getSize(); + } + break; + case GL_UNIFORM_BUFFER_START: + if (static_cast(index) < mUniformBuffers.size()) + { + *data = mUniformBuffers[index].getOffset(); + } + break; + case GL_UNIFORM_BUFFER_SIZE: + if (static_cast(index) < mUniformBuffers.size()) + { + *data = mUniformBuffers[index].getSize(); + } + break; + default: + return false; + } + + return true; +} + +bool State::hasMappedBuffer(GLenum target) const +{ + if (target == GL_ARRAY_BUFFER) + { + const VertexArray *vao = getVertexArray(); + for (size_t attribIndex = 0; attribIndex < mVertexAttribCurrentValues.size(); attribIndex++) + { + const gl::VertexAttribute &vertexAttrib = vao->getVertexAttribute(attribIndex); + gl::Buffer *boundBuffer = vertexAttrib.buffer.get(); + if (vertexAttrib.enabled && boundBuffer && boundBuffer->isMapped()) + { + return true; + } + } + + return false; + } + else + { + Buffer *buffer = getTargetBuffer(target); + return (buffer && buffer->isMapped()); + } +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/State.h b/src/3rdparty/angle/src/libANGLE/State.h new file mode 100644 index 0000000000..4370a2f16f --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/State.h @@ -0,0 +1,335 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// State.h: Defines the State class, encapsulating raw GL state + +#ifndef LIBANGLE_STATE_H_ +#define LIBANGLE_STATE_H_ + +#include "common/angleutils.h" +#include "libANGLE/RefCountObject.h" +#include "libANGLE/angletypes.h" +#include "libANGLE/VertexAttribute.h" +#include "libANGLE/Renderbuffer.h" +#include "libANGLE/Texture.h" +#include "libANGLE/TransformFeedback.h" +#include "libANGLE/Program.h" +#include "libANGLE/Sampler.h" + +namespace gl +{ +class Query; +class VertexArray; +class Context; +struct Caps; +struct Data; + +typedef std::map< GLenum, BindingPointer > TextureMap; + +class State : angle::NonCopyable +{ + public: + State(); + ~State(); + + void initialize(const Caps& caps, GLuint clientVersion); + void reset(); + + // State chunk getters + const RasterizerState &getRasterizerState() const; + const BlendState &getBlendState() const; + const DepthStencilState &getDepthStencilState() const; + + // Clear behavior setters & state parameter block generation function + void setColorClearValue(float red, float green, float blue, float alpha); + void setDepthClearValue(float depth); + void setStencilClearValue(int stencil); + + const ColorF &getColorClearValue() const { return mColorClearValue; } + float getDepthClearValue() const { return mDepthClearValue; } + int getStencilClearValue() const { return mStencilClearValue; } + + // Write mask manipulation + void setColorMask(bool red, bool green, bool blue, bool alpha); + void setDepthMask(bool mask); + + // Discard toggle & query + bool isRasterizerDiscardEnabled() const; + void setRasterizerDiscard(bool enabled); + + // Primitive restart + bool isPrimitiveRestartEnabled() const; + void setPrimitiveRestart(bool enabled); + + // Face culling state manipulation + bool isCullFaceEnabled() const; + void setCullFace(bool enabled); + void setCullMode(GLenum mode); + void setFrontFace(GLenum front); + + // Depth test state manipulation + bool isDepthTestEnabled() const; + void setDepthTest(bool enabled); + void setDepthFunc(GLenum depthFunc); + void setDepthRange(float zNear, float zFar); + void getDepthRange(float *zNear, float *zFar) const; + + // Blend state manipulation + bool isBlendEnabled() const; + void setBlend(bool enabled); + void setBlendFactors(GLenum sourceRGB, GLenum destRGB, GLenum sourceAlpha, GLenum destAlpha); + void setBlendColor(float red, float green, float blue, float alpha); + void setBlendEquation(GLenum rgbEquation, GLenum alphaEquation); + const ColorF &getBlendColor() const; + + // Stencil state maniupulation + bool isStencilTestEnabled() const; + void setStencilTest(bool enabled); + void setStencilParams(GLenum stencilFunc, GLint stencilRef, GLuint stencilMask); + void setStencilBackParams(GLenum stencilBackFunc, GLint stencilBackRef, GLuint stencilBackMask); + void setStencilWritemask(GLuint stencilWritemask); + void setStencilBackWritemask(GLuint stencilBackWritemask); + void setStencilOperations(GLenum stencilFail, GLenum stencilPassDepthFail, GLenum stencilPassDepthPass); + void setStencilBackOperations(GLenum stencilBackFail, GLenum stencilBackPassDepthFail, GLenum stencilBackPassDepthPass); + GLint getStencilRef() const; + GLint getStencilBackRef() const; + + // Depth bias/polygon offset state manipulation + bool isPolygonOffsetFillEnabled() const; + void setPolygonOffsetFill(bool enabled); + void setPolygonOffsetParams(GLfloat factor, GLfloat units); + + // Multisample coverage state manipulation + bool isSampleAlphaToCoverageEnabled() const; + void setSampleAlphaToCoverage(bool enabled); + bool isSampleCoverageEnabled() const; + void setSampleCoverage(bool enabled); + void setSampleCoverageParams(GLclampf value, bool invert); + void getSampleCoverageParams(GLclampf *value, bool *invert) const; + + // Scissor test state toggle & query + bool isScissorTestEnabled() const; + void setScissorTest(bool enabled); + void setScissorParams(GLint x, GLint y, GLsizei width, GLsizei height); + const Rectangle &getScissor() const; + + // Dither state toggle & query + bool isDitherEnabled() const; + void setDither(bool enabled); + + // Generic state toggle & query + void setEnableFeature(GLenum feature, bool enabled); + bool getEnableFeature(GLenum feature); + + // Line width state setter + void setLineWidth(GLfloat width); + + // Hint setters + void setGenerateMipmapHint(GLenum hint); + void setFragmentShaderDerivativeHint(GLenum hint); + + // Viewport state setter/getter + void setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height); + const Rectangle &getViewport() const; + + // Texture binding & active texture unit manipulation + void setActiveSampler(unsigned int active); + unsigned int getActiveSampler() const; + void setSamplerTexture(GLenum type, Texture *texture); + Texture *getSamplerTexture(unsigned int sampler, GLenum type) const; + GLuint getSamplerTextureId(unsigned int sampler, GLenum type) const; + void detachTexture(const TextureMap &zeroTextures, GLuint texture); + void initializeZeroTextures(const TextureMap &zeroTextures); + + // Sampler object binding manipulation + void setSamplerBinding(GLuint textureUnit, Sampler *sampler); + GLuint getSamplerId(GLuint textureUnit) const; + Sampler *getSampler(GLuint textureUnit) const; + void detachSampler(GLuint sampler); + + // Renderbuffer binding manipulation + void setRenderbufferBinding(Renderbuffer *renderbuffer); + GLuint getRenderbufferId() const; + Renderbuffer *getCurrentRenderbuffer(); + void detachRenderbuffer(GLuint renderbuffer); + + // Framebuffer binding manipulation + void setReadFramebufferBinding(Framebuffer *framebuffer); + void setDrawFramebufferBinding(Framebuffer *framebuffer); + Framebuffer *getTargetFramebuffer(GLenum target) const; + Framebuffer *getReadFramebuffer(); + Framebuffer *getDrawFramebuffer(); + const Framebuffer *getReadFramebuffer() const; + const Framebuffer *getDrawFramebuffer() const; + bool removeReadFramebufferBinding(GLuint framebuffer); + bool removeDrawFramebufferBinding(GLuint framebuffer); + + // Vertex array object binding manipulation + void setVertexArrayBinding(VertexArray *vertexArray); + GLuint getVertexArrayId() const; + VertexArray *getVertexArray() const; + bool removeVertexArrayBinding(GLuint vertexArray); + + // Program binding manipulation + void setProgram(Program *newProgram); + Program *getProgram() const; + + // Transform feedback object (not buffer) binding manipulation + void setTransformFeedbackBinding(TransformFeedback *transformFeedback); + TransformFeedback *getCurrentTransformFeedback() const; + bool isTransformFeedbackActiveUnpaused() const; + void detachTransformFeedback(GLuint transformFeedback); + + // Query binding manipulation + bool isQueryActive() const; + void setActiveQuery(GLenum target, Query *query); + GLuint getActiveQueryId(GLenum target) const; + Query *getActiveQuery(GLenum target) const; + + //// Typed buffer binding point manipulation //// + // GL_ARRAY_BUFFER + void setArrayBufferBinding(Buffer *buffer); + GLuint getArrayBufferId() const; + bool removeArrayBufferBinding(GLuint buffer); + + // GL_UNIFORM_BUFFER - Both indexed and generic targets + void setGenericUniformBufferBinding(Buffer *buffer); + void setIndexedUniformBufferBinding(GLuint index, Buffer *buffer, GLintptr offset, GLsizeiptr size); + GLuint getIndexedUniformBufferId(GLuint index) const; + Buffer *getIndexedUniformBuffer(GLuint index) const; + GLintptr getIndexedUniformBufferOffset(GLuint index) const; + GLsizeiptr getIndexedUniformBufferSize(GLuint index) const; + + // GL_TRANSFORM_FEEDBACK_BUFFER - Both indexed and generic targets + void setGenericTransformFeedbackBufferBinding(Buffer *buffer); + void setIndexedTransformFeedbackBufferBinding(GLuint index, Buffer *buffer, GLintptr offset, GLsizeiptr size); + GLuint getIndexedTransformFeedbackBufferId(GLuint index) const; + Buffer *getIndexedTransformFeedbackBuffer(GLuint index) const; + GLuint getIndexedTransformFeedbackBufferOffset(GLuint index) const; + size_t getTransformFeedbackBufferIndexRange() const; + + // GL_COPY_[READ/WRITE]_BUFFER + void setCopyReadBufferBinding(Buffer *buffer); + void setCopyWriteBufferBinding(Buffer *buffer); + + // GL_PIXEL[PACK/UNPACK]_BUFFER + void setPixelPackBufferBinding(Buffer *buffer); + void setPixelUnpackBufferBinding(Buffer *buffer); + + // Retrieve typed buffer by target (non-indexed) + Buffer *getTargetBuffer(GLenum target) const; + + // Vertex attrib manipulation + void setEnableVertexAttribArray(unsigned int attribNum, bool enabled); + void setVertexAttribf(GLuint index, const GLfloat values[4]); + void setVertexAttribu(GLuint index, const GLuint values[4]); + void setVertexAttribi(GLuint index, const GLint values[4]); + void setVertexAttribState(unsigned int attribNum, Buffer *boundBuffer, GLint size, GLenum type, + bool normalized, bool pureInteger, GLsizei stride, const void *pointer); + const VertexAttribCurrentValueData &getVertexAttribCurrentValue(unsigned int attribNum) const; + const void *getVertexAttribPointer(unsigned int attribNum) const; + + // Pixel pack state manipulation + void setPackAlignment(GLint alignment); + GLint getPackAlignment() const; + void setPackReverseRowOrder(bool reverseRowOrder); + bool getPackReverseRowOrder() const; + const PixelPackState &getPackState() const; + PixelPackState &getPackState(); + + // Pixel unpack state manipulation + void setUnpackAlignment(GLint alignment); + GLint getUnpackAlignment() const; + void setUnpackRowLength(GLint rowLength); + GLint getUnpackRowLength() const; + const PixelUnpackState &getUnpackState() const; + PixelUnpackState &getUnpackState(); + + // State query functions + void getBooleanv(GLenum pname, GLboolean *params); + void getFloatv(GLenum pname, GLfloat *params); + void getIntegerv(const gl::Data &data, GLenum pname, GLint *params); + bool getIndexedIntegerv(GLenum target, GLuint index, GLint *data); + bool getIndexedInteger64v(GLenum target, GLuint index, GLint64 *data); + + bool hasMappedBuffer(GLenum target) const; + + private: + // Cached values from Context's caps + GLuint mMaxDrawBuffers; + GLuint mMaxCombinedTextureImageUnits; + + ColorF mColorClearValue; + GLclampf mDepthClearValue; + int mStencilClearValue; + + RasterizerState mRasterizer; + bool mScissorTest; + Rectangle mScissor; + + BlendState mBlend; + ColorF mBlendColor; + bool mSampleCoverage; + GLclampf mSampleCoverageValue; + bool mSampleCoverageInvert; + + DepthStencilState mDepthStencil; + GLint mStencilRef; + GLint mStencilBackRef; + + GLfloat mLineWidth; + + GLenum mGenerateMipmapHint; + GLenum mFragmentShaderDerivativeHint; + + Rectangle mViewport; + float mNearZ; + float mFarZ; + + BindingPointer mArrayBuffer; + Framebuffer *mReadFramebuffer; + Framebuffer *mDrawFramebuffer; + BindingPointer mRenderbuffer; + Program *mProgram; + + typedef std::vector VertexAttribVector; + VertexAttribVector mVertexAttribCurrentValues; // From glVertexAttrib + VertexArray *mVertexArray; + + // Texture and sampler bindings + size_t mActiveSampler; // Active texture unit selector - GL_TEXTURE0 + + typedef std::vector< BindingPointer > TextureBindingVector; + typedef std::map TextureBindingMap; + TextureBindingMap mSamplerTextures; + + typedef std::vector< BindingPointer > SamplerBindingVector; + SamplerBindingVector mSamplers; + + typedef std::map< GLenum, BindingPointer > ActiveQueryMap; + ActiveQueryMap mActiveQueries; + + BindingPointer mGenericUniformBuffer; + typedef std::vector< OffsetBindingPointer > BufferVector; + BufferVector mUniformBuffers; + + BindingPointer mTransformFeedback; + BindingPointer mGenericTransformFeedbackBuffer; + BufferVector mTransformFeedbackBuffers; + + BindingPointer mCopyReadBuffer; + BindingPointer mCopyWriteBuffer; + + PixelUnpackState mUnpack; + PixelPackState mPack; + + bool mPrimitiveRestart; +}; + +} + +#endif // LIBANGLE_STATE_H_ + diff --git a/src/3rdparty/angle/src/libANGLE/Surface.cpp b/src/3rdparty/angle/src/libANGLE/Surface.cpp new file mode 100644 index 0000000000..ac455f3905 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/Surface.cpp @@ -0,0 +1,166 @@ +// +// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Surface.cpp: Implements the egl::Surface class, representing a drawing surface +// such as the client area of a window, including any back buffers. +// Implements EGLSurface and related functionality. [EGL 1.4] section 2.2 page 3. + +#include "libANGLE/Surface.h" + +#include "libANGLE/Config.h" +#include "libANGLE/Texture.h" +#include "libANGLE/renderer/SurfaceImpl.h" + +#include + +namespace egl +{ + +Surface::Surface(rx::SurfaceImpl *impl, EGLint surfaceType, const egl::Config *config, const AttributeMap &attributes) + : RefCountObject(0), // id unused + mImplementation(impl), + mType(surfaceType), + mConfig(config), + mPostSubBufferRequested(false), + mFixedSize(false), + mFixedWidth(0), + mFixedHeight(0), + mTextureFormat(EGL_NO_TEXTURE), + mTextureTarget(EGL_NO_TEXTURE), + // FIXME: Determine actual pixel aspect ratio + mPixelAspectRatio(static_cast(1.0 * EGL_DISPLAY_SCALING)), + mRenderBuffer(EGL_BACK_BUFFER), + mSwapBehavior(EGL_BUFFER_PRESERVED), + mTexture(NULL) +{ + addRef(); + + mPostSubBufferRequested = (attributes.get(EGL_POST_SUB_BUFFER_SUPPORTED_NV, EGL_FALSE) == EGL_TRUE); + + mFixedSize = (attributes.get(EGL_FIXED_SIZE_ANGLE, EGL_FALSE) == EGL_TRUE); + if (mFixedSize) + { + mFixedWidth = attributes.get(EGL_WIDTH, 0); + mFixedHeight = attributes.get(EGL_HEIGHT, 0); + } + + if (mType != EGL_WINDOW_BIT) + { + mTextureFormat = attributes.get(EGL_TEXTURE_FORMAT, EGL_NO_TEXTURE); + mTextureTarget = attributes.get(EGL_TEXTURE_TARGET, EGL_NO_TEXTURE); + } +} + +Surface::~Surface() +{ + if (mTexture) + { + if (mImplementation) + { + mImplementation->releaseTexImage(mTexture->id()); + } + mTexture->releaseTexImage(); + mTexture = NULL; + } + + SafeDelete(mImplementation); +} + +EGLint Surface::getType() const +{ + return mType; +} + +Error Surface::swap() +{ + return mImplementation->swap(); +} + +Error Surface::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) +{ + return mImplementation->postSubBuffer(x, y, width, height); +} + +Error Surface::querySurfacePointerANGLE(EGLint attribute, void **value) +{ + return mImplementation->querySurfacePointerANGLE(attribute, value); +} + +EGLint Surface::isPostSubBufferSupported() const +{ + return mPostSubBufferRequested && mImplementation->isPostSubBufferSupported(); +} + +void Surface::setSwapInterval(EGLint interval) +{ + mImplementation->setSwapInterval(interval); +} + +const Config *Surface::getConfig() const +{ + return mConfig; +} + +EGLint Surface::getPixelAspectRatio() const +{ + return mPixelAspectRatio; +} + +EGLenum Surface::getRenderBuffer() const +{ + return mRenderBuffer; +} + +EGLenum Surface::getSwapBehavior() const +{ + return mSwapBehavior; +} + +EGLenum Surface::getTextureFormat() const +{ + return mTextureFormat; +} + +EGLenum Surface::getTextureTarget() const +{ + return mTextureTarget; +} + +EGLint Surface::isFixedSize() const +{ + return mFixedSize; +} + +EGLint Surface::getWidth() const +{ + return mFixedSize ? mFixedWidth : mImplementation->getWidth(); +} + +EGLint Surface::getHeight() const +{ + return mFixedSize ? mFixedHeight : mImplementation->getHeight(); +} + +Error Surface::bindTexImage(gl::Texture *texture, EGLint buffer) +{ + ASSERT(!mTexture); + + texture->bindTexImage(this); + mTexture = texture; + return mImplementation->bindTexImage(buffer); +} + +Error Surface::releaseTexImage(EGLint buffer) +{ + ASSERT(mTexture); + gl::Texture *boundTexture = mTexture; + mTexture = NULL; + + boundTexture->releaseTexImage(); + return mImplementation->releaseTexImage(buffer); +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/Surface.h b/src/3rdparty/angle/src/libANGLE/Surface.h new file mode 100644 index 0000000000..430bf0195d --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/Surface.h @@ -0,0 +1,98 @@ +// +// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Surface.h: Defines the egl::Surface class, representing a drawing surface +// such as the client area of a window, including any back buffers. +// Implements EGLSurface and related functionality. [EGL 1.4] section 2.2 page 3. + +#ifndef LIBANGLE_SURFACE_H_ +#define LIBANGLE_SURFACE_H_ + +#include + +#include "common/angleutils.h" +#include "libANGLE/Error.h" +#include "libANGLE/RefCountObject.h" + +namespace gl +{ +class Texture; +} + +namespace rx +{ +class SurfaceImpl; +} + +namespace egl +{ +class AttributeMap; +class Display; +struct Config; + +class Surface final : public RefCountObject +{ + public: + Surface(rx::SurfaceImpl *impl, EGLint surfaceType, const egl::Config *config, const AttributeMap &attributes); + + rx::SurfaceImpl *getImplementation() { return mImplementation; } + const rx::SurfaceImpl *getImplementation() const { return mImplementation; } + + EGLint getType() const; + + Error swap(); + Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height); + Error querySurfacePointerANGLE(EGLint attribute, void **value); + Error bindTexImage(gl::Texture *texture, EGLint buffer); + Error releaseTexImage(EGLint buffer); + + EGLint isPostSubBufferSupported() const; + + void setSwapInterval(EGLint interval); + + const Config *getConfig() const; + + // width and height can change with client window resizing + EGLint getWidth() const; + EGLint getHeight() const; + EGLint getPixelAspectRatio() const; + EGLenum getRenderBuffer() const; + EGLenum getSwapBehavior() const; + EGLenum getTextureFormat() const; + EGLenum getTextureTarget() const; + + gl::Texture *getBoundTexture() const { return mTexture; } + + EGLint isFixedSize() const; + + private: + virtual ~Surface(); + + rx::SurfaceImpl *mImplementation; + + EGLint mType; + + const egl::Config *mConfig; + + bool mPostSubBufferRequested; + + bool mFixedSize; + size_t mFixedWidth; + size_t mFixedHeight; + + EGLenum mTextureFormat; + EGLenum mTextureTarget; + + EGLint mPixelAspectRatio; // Display aspect ratio + EGLenum mRenderBuffer; // Render buffer + EGLenum mSwapBehavior; // Buffer swap behavior + + gl::Texture *mTexture; +}; + +} + +#endif // LIBANGLE_SURFACE_H_ diff --git a/src/3rdparty/angle/src/libANGLE/Texture.cpp b/src/3rdparty/angle/src/libANGLE/Texture.cpp new file mode 100644 index 0000000000..cd4584f694 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/Texture.cpp @@ -0,0 +1,573 @@ +// +// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Texture.cpp: Implements the gl::Texture class. [OpenGL ES 2.0.24] section 3.7 page 63. + +#include "libANGLE/Texture.h" +#include "libANGLE/Data.h" +#include "libANGLE/formatutils.h" + +#include "libANGLE/Config.h" +#include "libANGLE/Surface.h" + +#include "common/mathutil.h" +#include "common/utilities.h" + +namespace gl +{ + +bool IsMipmapFiltered(const gl::SamplerState &samplerState) +{ + switch (samplerState.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; + } +} + +bool IsPointSampled(const gl::SamplerState &samplerState) +{ + return (samplerState.magFilter == GL_NEAREST && (samplerState.minFilter == GL_NEAREST || samplerState.minFilter == GL_NEAREST_MIPMAP_NEAREST)); +} + +static size_t GetImageDescIndex(GLenum target, size_t level) +{ + return IsCubeMapTextureTarget(target) ? ((level * 6) + CubeMapTextureTargetToLayerIndex(target)) : level; +} + +unsigned int Texture::mCurrentTextureSerial = 1; + +Texture::Texture(rx::TextureImpl *impl, GLuint id, GLenum target) + : RefCountObject(id), + mTexture(impl), + mTextureSerial(issueTextureSerial()), + mUsage(GL_NONE), + mImmutableLevelCount(0), + mTarget(target), + mImageDescs(IMPLEMENTATION_MAX_TEXTURE_LEVELS * (target == GL_TEXTURE_CUBE_MAP ? 6 : 1)), + mCompletenessCache(), + mBoundSurface(NULL) +{ +} + +Texture::~Texture() +{ + if (mBoundSurface) + { + mBoundSurface->releaseTexImage(EGL_BACK_BUFFER); + mBoundSurface = NULL; + } + SafeDelete(mTexture); +} + +GLenum Texture::getTarget() const +{ + return mTarget; +} + +void Texture::setUsage(GLenum usage) +{ + mUsage = usage; + getImplementation()->setUsage(usage); +} + +GLenum Texture::getUsage() const +{ + return mUsage; +} + +size_t Texture::getWidth(GLenum target, size_t level) const +{ + ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target))); + return getImageDesc(target, level).size.width; +} + +size_t Texture::getHeight(GLenum target, size_t level) const +{ + ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target))); + return getImageDesc(target, level).size.height; +} + +size_t Texture::getDepth(GLenum target, size_t level) const +{ + ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target))); + return getImageDesc(target, level).size.depth; +} + +GLenum Texture::getInternalFormat(GLenum target, size_t level) const +{ + ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target))); + return getImageDesc(target, level).internalFormat; +} + +bool Texture::isSamplerComplete(const SamplerState &samplerState, const Data &data) const +{ + const ImageDesc &baseImageDesc = getImageDesc(getBaseImageTarget(), samplerState.baseLevel); + const TextureCaps &textureCaps = data.textureCaps->get(baseImageDesc.internalFormat); + if (!mCompletenessCache.cacheValid || + mCompletenessCache.samplerState != samplerState || + mCompletenessCache.filterable != textureCaps.filterable || + mCompletenessCache.clientVersion != data.clientVersion || + mCompletenessCache.supportsNPOT != data.extensions->textureNPOT) + { + mCompletenessCache.cacheValid = true; + mCompletenessCache.samplerState = samplerState; + mCompletenessCache.filterable = textureCaps.filterable; + mCompletenessCache.clientVersion = data.clientVersion; + mCompletenessCache.supportsNPOT = data.extensions->textureNPOT; + mCompletenessCache.samplerComplete = computeSamplerCompleteness(samplerState, data); + } + return mCompletenessCache.samplerComplete; +} + +// Tests for cube texture completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81. +bool Texture::isCubeComplete() const +{ + ASSERT(mTarget == GL_TEXTURE_CUBE_MAP); + + const ImageDesc &baseImageDesc = getImageDesc(FirstCubeMapTextureTarget, 0); + if (baseImageDesc.size.width == 0 || baseImageDesc.size.width != baseImageDesc.size.height) + { + return false; + } + + for (GLenum face = FirstCubeMapTextureTarget + 1; face <= LastCubeMapTextureTarget; face++) + { + const ImageDesc &faceImageDesc = getImageDesc(face, 0); + if (faceImageDesc.size.width != baseImageDesc.size.width || + faceImageDesc.size.height != baseImageDesc.size.height || + faceImageDesc.internalFormat != baseImageDesc.internalFormat) + { + return false; + } + } + + return true; +} + +unsigned int Texture::getTextureSerial() const +{ + return mTextureSerial; +} + +unsigned int Texture::issueTextureSerial() +{ + return mCurrentTextureSerial++; +} + +bool Texture::isImmutable() const +{ + return (mImmutableLevelCount > 0); +} + +int Texture::immutableLevelCount() +{ + return mImmutableLevelCount; +} + +Error Texture::setImage(GLenum target, size_t level, GLenum internalFormat, const Extents &size, GLenum format, GLenum type, + const PixelUnpackState &unpack, const uint8_t *pixels) +{ + ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target))); + + Error error = mTexture->setImage(target, level, internalFormat, size, format, type, unpack, pixels); + if (error.isError()) + { + return error; + } + + releaseTexImage(); + + setImageDesc(target, level, ImageDesc(size, GetSizedInternalFormat(internalFormat, type))); + + return Error(GL_NO_ERROR); +} + +Error Texture::setSubImage(GLenum target, size_t level, const Box &area, GLenum format, GLenum type, + const PixelUnpackState &unpack, const uint8_t *pixels) +{ + ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target))); + + return mTexture->setSubImage(target, level, area, format, type, unpack, pixels); +} + +Error Texture::setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const Extents &size, + const PixelUnpackState &unpack, const uint8_t *pixels) +{ + ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target))); + + Error error = mTexture->setCompressedImage(target, level, internalFormat, size, unpack, pixels); + if (error.isError()) + { + return error; + } + + releaseTexImage(); + + setImageDesc(target, level, ImageDesc(size, GetSizedInternalFormat(internalFormat, GL_UNSIGNED_BYTE))); + + return Error(GL_NO_ERROR); +} + +Error Texture::setCompressedSubImage(GLenum target, size_t level, const Box &area, GLenum format, + const PixelUnpackState &unpack, const uint8_t *pixels) +{ + ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target))); + + return mTexture->setCompressedSubImage(target, level, area, format, unpack, pixels); +} + +Error Texture::copyImage(GLenum target, size_t level, const Rectangle &sourceArea, GLenum internalFormat, + const Framebuffer *source) +{ + ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target))); + + Error error = mTexture->copyImage(target, level, sourceArea, internalFormat, source); + if (error.isError()) + { + return error; + } + + releaseTexImage(); + + setImageDesc(target, level, ImageDesc(Extents(sourceArea.width, sourceArea.height, 1), + GetSizedInternalFormat(internalFormat, GL_UNSIGNED_BYTE))); + + return Error(GL_NO_ERROR); +} + +Error Texture::copySubImage(GLenum target, size_t level, const Offset &destOffset, const Rectangle &sourceArea, + const Framebuffer *source) +{ + ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target))); + + return mTexture->copySubImage(target, level, destOffset, sourceArea, source); +} + +Error Texture::setStorage(GLenum target, size_t levels, GLenum internalFormat, const Extents &size) +{ + ASSERT(target == mTarget); + + Error error = mTexture->setStorage(target, levels, internalFormat, size); + if (error.isError()) + { + return error; + } + + releaseTexImage(); + + mImmutableLevelCount = levels; + clearImageDescs(); + setImageDescChain(levels, size, internalFormat); + + return Error(GL_NO_ERROR); +} + + +Error Texture::generateMipmaps() +{ + Error error = mTexture->generateMipmaps(); + if (error.isError()) + { + return error; + } + + releaseTexImage(); + + const ImageDesc &baseImageInfo = getImageDesc(getBaseImageTarget(), 0); + size_t mipLevels = log2(std::max(std::max(baseImageInfo.size.width, baseImageInfo.size.height), baseImageInfo.size.depth)) + 1; + setImageDescChain(mipLevels, baseImageInfo.size, baseImageInfo.internalFormat); + + return Error(GL_NO_ERROR); +} + +void Texture::setImageDescChain(size_t levels, Extents baseSize, GLenum sizedInternalFormat) +{ + for (size_t level = 0; level < levels; level++) + { + Extents levelSize(std::max(baseSize.width >> level, 1), + std::max(baseSize.height >> level, 1), + (mTarget == GL_TEXTURE_2D_ARRAY) ? baseSize.depth : std::max(baseSize.depth >> level, 1)); + ImageDesc levelInfo(levelSize, sizedInternalFormat); + + if (mTarget == GL_TEXTURE_CUBE_MAP) + { + for (size_t face = FirstCubeMapTextureTarget; face <= LastCubeMapTextureTarget; face++) + { + setImageDesc(face, level, levelInfo); + } + } + else + { + setImageDesc(mTarget, level, levelInfo); + } + } +} + +Texture::ImageDesc::ImageDesc() + : size(0, 0, 0), internalFormat(GL_NONE) +{ +} + +Texture::ImageDesc::ImageDesc(const Extents &size, GLenum internalFormat) + : size(size), + internalFormat(internalFormat) +{ +} + +const Texture::ImageDesc &Texture::getImageDesc(GLenum target, size_t level) const +{ + size_t descIndex = GetImageDescIndex(target, level); + ASSERT(descIndex < mImageDescs.size()); + return mImageDescs[descIndex]; +} + +void Texture::setImageDesc(GLenum target, size_t level, const ImageDesc &desc) +{ + size_t descIndex = GetImageDescIndex(target, level); + ASSERT(descIndex < mImageDescs.size()); + mImageDescs[descIndex] = desc; + mCompletenessCache.cacheValid = false; +} + +void Texture::clearImageDesc(GLenum target, size_t level) +{ + setImageDesc(target, level, ImageDesc()); +} + +void Texture::clearImageDescs() +{ + for (size_t descIndex = 0; descIndex < mImageDescs.size(); descIndex++) + { + mImageDescs[descIndex] = ImageDesc(); + } + mCompletenessCache.cacheValid = false; +} + +void Texture::bindTexImage(egl::Surface *surface) +{ + ASSERT(surface); + + releaseTexImage(); + mTexture->bindTexImage(surface); + mBoundSurface = surface; + + // Set the image info to the size and format of the surface + ASSERT(mTarget == GL_TEXTURE_2D); + Extents size(surface->getWidth(), surface->getHeight(), 1); + ImageDesc desc(size, surface->getConfig()->renderTargetFormat); + setImageDesc(mTarget, 0, desc); +} + +void Texture::releaseTexImage() +{ + if (mBoundSurface) + { + mBoundSurface = NULL; + mTexture->releaseTexImage(); + + // Erase the image info for level 0 + ASSERT(mTarget == GL_TEXTURE_2D); + clearImageDesc(mTarget, 0); + } +} + +GLenum Texture::getBaseImageTarget() const +{ + return mTarget == GL_TEXTURE_CUBE_MAP ? FirstCubeMapTextureTarget : mTarget; +} + +size_t Texture::getExpectedMipLevels() const +{ + const ImageDesc &baseImageDesc = getImageDesc(getBaseImageTarget(), 0); + if (mTarget == GL_TEXTURE_3D) + { + return log2(std::max(std::max(baseImageDesc.size.width, baseImageDesc.size.height), baseImageDesc.size.depth)) + 1; + } + else + { + return log2(std::max(baseImageDesc.size.width, baseImageDesc.size.height)) + 1; + } +} + +bool Texture::computeSamplerCompleteness(const SamplerState &samplerState, const Data &data) const +{ + const ImageDesc &baseImageDesc = getImageDesc(getBaseImageTarget(), samplerState.baseLevel); + if (baseImageDesc.size.width == 0 || baseImageDesc.size.height == 0 || baseImageDesc.size.depth == 0) + { + return false; + } + + if (mTarget == GL_TEXTURE_CUBE_MAP && baseImageDesc.size.width != baseImageDesc.size.height) + { + return false; + } + + const TextureCaps &textureCaps = data.textureCaps->get(baseImageDesc.internalFormat); + if (!textureCaps.filterable && !IsPointSampled(samplerState)) + { + return false; + } + + bool npotSupport = data.extensions->textureNPOT || data.clientVersion >= 3; + if (!npotSupport) + { + if ((samplerState.wrapS != GL_CLAMP_TO_EDGE && !gl::isPow2(baseImageDesc.size.width)) || + (samplerState.wrapT != GL_CLAMP_TO_EDGE && !gl::isPow2(baseImageDesc.size.height))) + { + return false; + } + } + + if (IsMipmapFiltered(samplerState)) + { + if (!npotSupport) + { + if (!gl::isPow2(baseImageDesc.size.width) || !gl::isPow2(baseImageDesc.size.height)) + { + return false; + } + } + + if (!computeMipmapCompleteness(samplerState)) + { + return false; + } + } + else + { + if (mTarget == GL_TEXTURE_CUBE_MAP && !isCubeComplete()) + { + return false; + } + } + + // OpenGLES 3.0.2 spec section 3.8.13 states that a texture is not mipmap complete if: + // The internalformat specified for the texture arrays is a sized internal depth or + // depth and stencil format (see table 3.13), the value of TEXTURE_COMPARE_- + // MODE is NONE, and either the magnification filter is not NEAREST or the mini- + // fication filter is neither NEAREST nor NEAREST_MIPMAP_NEAREST. + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(baseImageDesc.internalFormat); + if (formatInfo.depthBits > 0 && data.clientVersion > 2) + { + if (samplerState.compareMode == GL_NONE) + { + if ((samplerState.minFilter != GL_NEAREST && samplerState.minFilter != GL_NEAREST_MIPMAP_NEAREST) || + samplerState.magFilter != GL_NEAREST) + { + return false; + } + } + } + + return true; +} + +bool Texture::computeMipmapCompleteness(const gl::SamplerState &samplerState) const +{ + size_t expectedMipLevels = getExpectedMipLevels(); + + size_t maxLevel = std::min(expectedMipLevels, samplerState.maxLevel + 1); + + for (size_t level = samplerState.baseLevel; level < maxLevel; level++) + { + if (mTarget == GL_TEXTURE_CUBE_MAP) + { + for (GLenum face = FirstCubeMapTextureTarget; face <= LastCubeMapTextureTarget; face++) + { + if (!computeLevelCompleteness(face, level, samplerState)) + { + return false; + } + } + } + else + { + if (!computeLevelCompleteness(mTarget, level, samplerState)) + { + return false; + } + } + } + + return true; +} + + +bool Texture::computeLevelCompleteness(GLenum target, size_t level, const gl::SamplerState &samplerState) const +{ + ASSERT(level < IMPLEMENTATION_MAX_TEXTURE_LEVELS); + + if (isImmutable()) + { + return true; + } + + const ImageDesc &baseImageDesc = getImageDesc(getBaseImageTarget(), samplerState.baseLevel); + if (baseImageDesc.size.width == 0 || baseImageDesc.size.height == 0 || baseImageDesc.size.depth == 0) + { + return false; + } + + // The base image level is complete if the width and height are positive + if (level == 0) + { + return true; + } + + const ImageDesc &levelImageDesc = getImageDesc(target, level); + if (levelImageDesc.internalFormat != baseImageDesc.internalFormat) + { + return false; + } + + if (levelImageDesc.size.width != std::max(1, baseImageDesc.size.width >> level)) + { + return false; + } + + if (levelImageDesc.size.height != std::max(1, baseImageDesc.size.height >> level)) + { + return false; + } + + if (mTarget == GL_TEXTURE_3D) + { + if (levelImageDesc.size.depth != std::max(1, baseImageDesc.size.depth >> level)) + { + return false; + } + } + else if (mTarget == GL_TEXTURE_2D_ARRAY) + { + if (levelImageDesc.size.depth != baseImageDesc.size.depth) + { + return false; + } + } + + return true; +} + +Texture::SamplerCompletenessCache::SamplerCompletenessCache() + : cacheValid(false), + samplerState(), + filterable(false), + clientVersion(0), + supportsNPOT(false), + samplerComplete(false) +{ +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/Texture.h b/src/3rdparty/angle/src/libANGLE/Texture.h new file mode 100644 index 0000000000..b5a0717713 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/Texture.h @@ -0,0 +1,156 @@ +// +// 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. +// + +// Texture.h: Defines the gl::Texture class [OpenGL ES 2.0.24] section 3.7 page 63. + +#ifndef LIBANGLE_TEXTURE_H_ +#define LIBANGLE_TEXTURE_H_ + +#include "common/debug.h" +#include "libANGLE/RefCountObject.h" +#include "libANGLE/angletypes.h" +#include "libANGLE/Constants.h" +#include "libANGLE/renderer/TextureImpl.h" +#include "libANGLE/Caps.h" + +#include "angle_gl.h" + +#include +#include + +namespace egl +{ +class Surface; +} + +namespace gl +{ +class Framebuffer; +struct Data; + +bool IsMipmapFiltered(const gl::SamplerState &samplerState); + +class Texture final : public RefCountObject +{ + public: + Texture(rx::TextureImpl *impl, GLuint id, GLenum target); + + virtual ~Texture(); + + GLenum getTarget() const; + + const SamplerState &getSamplerState() const { return mSamplerState; } + SamplerState &getSamplerState() { return mSamplerState; } + + void setUsage(GLenum usage); + GLenum getUsage() const; + + size_t getWidth(GLenum target, size_t level) const; + size_t getHeight(GLenum target, size_t level) const; + size_t getDepth(GLenum target, size_t level) const; + GLenum getInternalFormat(GLenum target, size_t level) const; + + bool isSamplerComplete(const SamplerState &samplerState, const Data &data) const; + bool isCubeComplete() const; + + virtual Error setImage(GLenum target, size_t level, GLenum internalFormat, const Extents &size, GLenum format, GLenum type, + const PixelUnpackState &unpack, const uint8_t *pixels); + virtual Error setSubImage(GLenum target, size_t level, const Box &area, GLenum format, GLenum type, + const PixelUnpackState &unpack, const uint8_t *pixels); + + virtual Error setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const Extents &size, + const PixelUnpackState &unpack, const uint8_t *pixels); + virtual Error setCompressedSubImage(GLenum target, size_t level, const Box &area, GLenum format, + const PixelUnpackState &unpack, const uint8_t *pixels); + + virtual Error copyImage(GLenum target, size_t level, const Rectangle &sourceArea, GLenum internalFormat, + const Framebuffer *source); + virtual Error copySubImage(GLenum target, size_t level, const Offset &destOffset, const Rectangle &sourceArea, + const Framebuffer *source); + + virtual Error setStorage(GLenum target, size_t levels, GLenum internalFormat, const Extents &size); + + virtual Error generateMipmaps(); + + // Texture serials provide a unique way of identifying a Texture that isn't a raw pointer. + // "id" is not good enough, as Textures can be deleted, then re-allocated with the same id. + unsigned int getTextureSerial() const; + + bool isImmutable() const; + GLsizei immutableLevelCount(); + + void bindTexImage(egl::Surface *surface); + void releaseTexImage(); + + rx::TextureImpl *getImplementation() { return mTexture; } + const rx::TextureImpl *getImplementation() const { return mTexture; } + + 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. + + private: + static unsigned int issueTextureSerial(); + + rx::TextureImpl *mTexture; + + SamplerState mSamplerState; + GLenum mUsage; + + GLsizei mImmutableLevelCount; + + GLenum mTarget; + + + struct ImageDesc + { + Extents size; + GLenum internalFormat; + + ImageDesc(); + ImageDesc(const Extents &size, GLenum internalFormat); + }; + + const unsigned int mTextureSerial; + static unsigned int mCurrentTextureSerial; + + GLenum getBaseImageTarget() const; + size_t getExpectedMipLevels() const; + + bool computeSamplerCompleteness(const SamplerState &samplerState, const Data &data) const; + bool computeMipmapCompleteness(const gl::SamplerState &samplerState) const; + bool computeLevelCompleteness(GLenum target, size_t level, const gl::SamplerState &samplerState) const; + + const ImageDesc &getImageDesc(GLenum target, size_t level) const; + void setImageDesc(GLenum target, size_t level, const ImageDesc &desc); + void setImageDescChain(size_t levels, Extents baseSize, GLenum sizedInternalFormat); + void clearImageDesc(GLenum target, size_t level); + void clearImageDescs(); + + std::vector mImageDescs; + + struct SamplerCompletenessCache + { + SamplerCompletenessCache(); + + bool cacheValid; + + // All values that affect sampler completeness that are not stored within + // the texture itself + SamplerState samplerState; + bool filterable; + GLint clientVersion; + bool supportsNPOT; + + // Result of the sampler completeness with the above parameters + bool samplerComplete; + }; + mutable SamplerCompletenessCache mCompletenessCache; + + egl::Surface *mBoundSurface; +}; + +} + +#endif // LIBANGLE_TEXTURE_H_ diff --git a/src/3rdparty/angle/src/libANGLE/TransformFeedback.cpp b/src/3rdparty/angle/src/libANGLE/TransformFeedback.cpp new file mode 100644 index 0000000000..6effaca976 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/TransformFeedback.cpp @@ -0,0 +1,71 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "libANGLE/TransformFeedback.h" +#include "libANGLE/renderer/TransformFeedbackImpl.h" + +namespace gl +{ + +TransformFeedback::TransformFeedback(rx::TransformFeedbackImpl* impl, GLuint id) + : RefCountObject(id), + mTransformFeedback(impl), + mStarted(GL_FALSE), + mPrimitiveMode(GL_NONE), + mPaused(GL_FALSE) +{ + ASSERT(impl != NULL); +} + +TransformFeedback::~TransformFeedback() +{ + SafeDelete(mTransformFeedback); +} + +void TransformFeedback::start(GLenum primitiveMode) +{ + mStarted = GL_TRUE; + mPrimitiveMode = primitiveMode; + mPaused = GL_FALSE; + mTransformFeedback->begin(primitiveMode); +} + +void TransformFeedback::stop() +{ + mStarted = GL_FALSE; + mPrimitiveMode = GL_NONE; + mPaused = GL_FALSE; + mTransformFeedback->end(); +} + +GLboolean TransformFeedback::isStarted() const +{ + return mStarted; +} + +GLenum TransformFeedback::getDrawMode() const +{ + return mPrimitiveMode; +} + +void TransformFeedback::pause() +{ + mPaused = GL_TRUE; + mTransformFeedback->pause(); +} + +void TransformFeedback::resume() +{ + mPaused = GL_FALSE; + mTransformFeedback->resume(); +} + +GLboolean TransformFeedback::isPaused() const +{ + return mPaused; +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/TransformFeedback.h b/src/3rdparty/angle/src/libANGLE/TransformFeedback.h new file mode 100644 index 0000000000..7673db93ff --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/TransformFeedback.h @@ -0,0 +1,50 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef LIBANGLE_TRANSFORM_FEEDBACK_H_ +#define LIBANGLE_TRANSFORM_FEEDBACK_H_ + +#include "libANGLE/RefCountObject.h" + +#include "common/angleutils.h" + +#include "angle_gl.h" + +namespace rx +{ +class TransformFeedbackImpl; +} + +namespace gl +{ + +class TransformFeedback : public RefCountObject +{ + public: + TransformFeedback(rx::TransformFeedbackImpl* impl, GLuint id); + virtual ~TransformFeedback(); + + void start(GLenum primitiveMode); + void stop(); + GLboolean isStarted() const; + + GLenum getDrawMode() const; + + void pause(); + void resume(); + GLboolean isPaused() const; + + private: + rx::TransformFeedbackImpl* mTransformFeedback; + + GLboolean mStarted; + GLenum mPrimitiveMode; + GLboolean mPaused; +}; + +} + +#endif // LIBANGLE_TRANSFORM_FEEDBACK_H_ diff --git a/src/3rdparty/angle/src/libANGLE/Uniform.cpp b/src/3rdparty/angle/src/libANGLE/Uniform.cpp new file mode 100644 index 0000000000..f161b9d6bd --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/Uniform.cpp @@ -0,0 +1,107 @@ +// +// 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 "libANGLE/Uniform.h" + +#include "common/utilities.h" + +#include + +namespace gl +{ + +LinkedUniform::LinkedUniform(GLenum type, GLenum precision, const std::string &name, unsigned int arraySize, + const int blockIndex, const sh::BlockMemberInfo &blockInfo) + : type(type), + precision(precision), + name(name), + arraySize(arraySize), + blockIndex(blockIndex), + blockInfo(blockInfo), + data(NULL), + dirty(true), + psRegisterIndex(GL_INVALID_INDEX), + vsRegisterIndex(GL_INVALID_INDEX), + registerCount(0), + registerElement(0) +{ + // We use data storage for default block uniforms to cache values that are sent to D3D during rendering + // Uniform blocks/buffers are treated separately by the Renderer (ES3 path only) + if (isInDefaultBlock()) + { + size_t bytes = dataSize(); + data = new unsigned char[bytes]; + memset(data, 0, bytes); + registerCount = VariableRowCount(type) * elementCount(); + } +} + +LinkedUniform::~LinkedUniform() +{ + delete[] data; +} + +bool LinkedUniform::isArray() const +{ + return arraySize > 0; +} + +unsigned int LinkedUniform::elementCount() const +{ + return arraySize > 0 ? arraySize : 1; +} + +bool LinkedUniform::isReferencedByVertexShader() const +{ + return vsRegisterIndex != GL_INVALID_INDEX; +} + +bool LinkedUniform::isReferencedByFragmentShader() const +{ + return psRegisterIndex != GL_INVALID_INDEX; +} + +bool LinkedUniform::isInDefaultBlock() const +{ + return blockIndex == -1; +} + +size_t LinkedUniform::dataSize() const +{ + ASSERT(type != GL_STRUCT_ANGLEX); + return VariableInternalSize(type) * elementCount(); +} + +bool LinkedUniform::isSampler() const +{ + return IsSamplerType(type); +} + +UniformBlock::UniformBlock(const std::string &name, unsigned int elementIndex, unsigned int dataSize) + : name(name), + elementIndex(elementIndex), + dataSize(dataSize), + psRegisterIndex(GL_INVALID_INDEX), + vsRegisterIndex(GL_INVALID_INDEX) +{ +} + +bool UniformBlock::isArrayElement() const +{ + return elementIndex != GL_INVALID_INDEX; +} + +bool UniformBlock::isReferencedByVertexShader() const +{ + return vsRegisterIndex != GL_INVALID_INDEX; +} + +bool UniformBlock::isReferencedByFragmentShader() const +{ + return psRegisterIndex != GL_INVALID_INDEX; +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/Uniform.h b/src/3rdparty/angle/src/libANGLE/Uniform.h new file mode 100644 index 0000000000..dcf30f23cc --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/Uniform.h @@ -0,0 +1,77 @@ +// +// 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 LIBANGLE_UNIFORM_H_ +#define LIBANGLE_UNIFORM_H_ + +#include +#include + +#include "angle_gl.h" +#include "common/debug.h" +#include "compiler/translator/blocklayout.h" +#include "libANGLE/angletypes.h" + +namespace gl +{ + +// Helper struct representing a single shader uniform +struct LinkedUniform : angle::NonCopyable +{ + LinkedUniform(GLenum type, GLenum precision, const std::string &name, unsigned int arraySize, const int blockIndex, const sh::BlockMemberInfo &blockInfo); + + ~LinkedUniform(); + + bool isArray() const; + unsigned int elementCount() const; + bool isReferencedByVertexShader() const; + bool isReferencedByFragmentShader() const; + bool isInDefaultBlock() const; + size_t dataSize() const; + bool isSampler() const; + + const GLenum type; + const GLenum precision; + const std::string name; + const unsigned int arraySize; + const int blockIndex; + const sh::BlockMemberInfo blockInfo; + + unsigned char *data; + bool dirty; + + unsigned int psRegisterIndex; + unsigned int vsRegisterIndex; + unsigned int registerCount; + + // Register "elements" are used for uniform structs in ES3, to appropriately identify single uniforms + // inside aggregate types, which are packed according C-like structure rules. + unsigned int registerElement; +}; + +// Helper struct representing a single shader uniform block +struct UniformBlock : angle::NonCopyable +{ + // use GL_INVALID_INDEX for non-array elements + UniformBlock(const std::string &name, unsigned int elementIndex, unsigned int dataSize); + + bool isArrayElement() const; + bool isReferencedByVertexShader() const; + bool isReferencedByFragmentShader() const; + + const std::string name; + const unsigned int elementIndex; + const unsigned int dataSize; + + std::vector memberUniformIndexes; + + unsigned int psRegisterIndex; + unsigned int vsRegisterIndex; +}; + +} + +#endif // LIBANGLE_UNIFORM_H_ diff --git a/src/3rdparty/angle/src/libANGLE/VertexArray.cpp b/src/3rdparty/angle/src/libANGLE/VertexArray.cpp new file mode 100644 index 0000000000..f0aded905d --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/VertexArray.cpp @@ -0,0 +1,101 @@ +// +// 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. +// +// Implementation of the state class for mananging GLES 3 Vertex Array Objects. +// + +#include "libANGLE/VertexArray.h" +#include "libANGLE/Buffer.h" +#include "libANGLE/renderer/VertexArrayImpl.h" + +namespace gl +{ + +VertexArray::VertexArray(rx::VertexArrayImpl *impl, GLuint id, size_t maxAttribs) + : mId(id), + mVertexArray(impl), + mVertexAttributes(maxAttribs) +{ + ASSERT(impl != NULL); +} + +VertexArray::~VertexArray() +{ + SafeDelete(mVertexArray); + + for (size_t i = 0; i < getMaxAttribs(); i++) + { + mVertexAttributes[i].buffer.set(NULL); + } + mElementArrayBuffer.set(NULL); +} + +GLuint VertexArray::id() const +{ + return mId; +} + +void VertexArray::detachBuffer(GLuint bufferName) +{ + for (size_t attribute = 0; attribute < getMaxAttribs(); attribute++) + { + if (mVertexAttributes[attribute].buffer.id() == bufferName) + { + mVertexAttributes[attribute].buffer.set(NULL); + } + } + + if (mElementArrayBuffer.id() == bufferName) + { + mElementArrayBuffer.set(NULL); + } +} + +const VertexAttribute& VertexArray::getVertexAttribute(size_t attributeIndex) const +{ + ASSERT(attributeIndex < getMaxAttribs()); + return mVertexAttributes[attributeIndex]; +} + +const std::vector &VertexArray::getVertexAttributes() const +{ + return mVertexAttributes; +} + +void VertexArray::setVertexAttribDivisor(GLuint index, GLuint divisor) +{ + ASSERT(index < getMaxAttribs()); + mVertexAttributes[index].divisor = divisor; + mVertexArray->setAttributeDivisor(index, divisor); +} + +void VertexArray::enableAttribute(unsigned int attributeIndex, bool enabledState) +{ + ASSERT(attributeIndex < getMaxAttribs()); + mVertexAttributes[attributeIndex].enabled = enabledState; + mVertexArray->enableAttribute(attributeIndex, enabledState); +} + +void VertexArray::setAttributeState(unsigned int attributeIndex, gl::Buffer *boundBuffer, GLint size, GLenum type, + bool normalized, bool pureInteger, GLsizei stride, const void *pointer) +{ + ASSERT(attributeIndex < getMaxAttribs()); + mVertexAttributes[attributeIndex].buffer.set(boundBuffer); + mVertexAttributes[attributeIndex].size = size; + mVertexAttributes[attributeIndex].type = type; + mVertexAttributes[attributeIndex].normalized = normalized; + mVertexAttributes[attributeIndex].pureInteger = pureInteger; + mVertexAttributes[attributeIndex].stride = stride; + mVertexAttributes[attributeIndex].pointer = pointer; + mVertexArray->setAttribute(attributeIndex, mVertexAttributes[attributeIndex]); +} + +void VertexArray::setElementArrayBuffer(Buffer *buffer) +{ + mElementArrayBuffer.set(buffer); + mVertexArray->setElementArrayBuffer(buffer); +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/VertexArray.h b/src/3rdparty/angle/src/libANGLE/VertexArray.h new file mode 100644 index 0000000000..5c79b9953d --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/VertexArray.h @@ -0,0 +1,66 @@ +// +// 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. +// +// This class contains prototypes for representing GLES 3 Vertex Array Objects: +// +// The buffer objects that are to be used by the vertex stage of the GL are collected +// together to form a vertex array object. All state related to the definition of data used +// by the vertex processor is encapsulated in a vertex array object. +// + +#ifndef LIBANGLE_VERTEXARRAY_H_ +#define LIBANGLE_VERTEXARRAY_H_ + +#include "libANGLE/RefCountObject.h" +#include "libANGLE/Constants.h" +#include "libANGLE/VertexAttribute.h" + +#include + +namespace rx +{ +class VertexArrayImpl; +} + +namespace gl +{ +class Buffer; + +class VertexArray +{ + public: + VertexArray(rx::VertexArrayImpl *impl, GLuint id, size_t maxAttribs); + ~VertexArray(); + + GLuint id() const; + + const VertexAttribute& getVertexAttribute(size_t attributeIndex) const; + const std::vector &getVertexAttributes() const; + + void detachBuffer(GLuint bufferName); + void setVertexAttribDivisor(GLuint index, GLuint divisor); + void enableAttribute(unsigned int attributeIndex, bool enabledState); + void setAttributeState(unsigned int attributeIndex, gl::Buffer *boundBuffer, GLint size, GLenum type, + bool normalized, bool pureInteger, GLsizei stride, const void *pointer); + + Buffer *getElementArrayBuffer() const { return mElementArrayBuffer.get(); } + void setElementArrayBuffer(Buffer *buffer); + GLuint getElementArrayBufferId() const { return mElementArrayBuffer.id(); } + size_t getMaxAttribs() const { return mVertexAttributes.size(); } + + rx::VertexArrayImpl *getImplementation() { return mVertexArray; } + const rx::VertexArrayImpl *getImplementation() const { return mVertexArray; } + + private: + GLuint mId; + + rx::VertexArrayImpl *mVertexArray; + std::vector mVertexAttributes; + BindingPointer mElementArrayBuffer; +}; + +} + +#endif // LIBANGLE_VERTEXARRAY_H_ diff --git a/src/3rdparty/angle/src/libANGLE/VertexAttribute.cpp b/src/3rdparty/angle/src/libANGLE/VertexAttribute.cpp new file mode 100644 index 0000000000..19934e7fac --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/VertexAttribute.cpp @@ -0,0 +1,73 @@ +// +// Copyright 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// Implementation of the state class for mananging GLES 3 Vertex Array Objects. +// + +#include "libANGLE/VertexAttribute.h" + +namespace gl +{ + +VertexAttribute::VertexAttribute() + : enabled(false), + type(GL_FLOAT), + size(4), + normalized(false), + pureInteger(false), + stride(0), + pointer(NULL), + divisor(0) +{ +} + +bool operator==(const VertexAttribute &a, const VertexAttribute &b) +{ + return a.enabled == b.enabled && + a.type == b.type && + a.size == b.size && + a.normalized == b.normalized && + a.pureInteger == b.pureInteger && + a.stride == b.stride && + a.pointer == b.pointer && + a.buffer.get() == b.buffer.get() && + a.divisor == b.divisor; +} + +bool operator!=(const VertexAttribute &a, const VertexAttribute &b) +{ + return !(a == b); +} + +size_t ComputeVertexAttributeTypeSize(const VertexAttribute& attrib) +{ + GLuint size = attrib.size; + switch (attrib.type) + { + case GL_BYTE: return size * sizeof(GLbyte); + case GL_UNSIGNED_BYTE: return size * sizeof(GLubyte); + case GL_SHORT: return size * sizeof(GLshort); + case GL_UNSIGNED_SHORT: return size * sizeof(GLushort); + case GL_INT: return size * sizeof(GLint); + case GL_UNSIGNED_INT: return size * sizeof(GLuint); + case GL_INT_2_10_10_10_REV: return 4; + case GL_UNSIGNED_INT_2_10_10_10_REV: return 4; + case GL_FIXED: return size * sizeof(GLfixed); + case GL_HALF_FLOAT: return size * sizeof(GLhalf); + case GL_FLOAT: return size * sizeof(GLfloat); + default: UNREACHABLE(); return size * sizeof(GLfloat); + } +} + +size_t ComputeVertexAttributeStride(const VertexAttribute& attrib) +{ + if (!attrib.enabled) + { + return 16; + } + return attrib.stride ? attrib.stride : ComputeVertexAttributeTypeSize(attrib); +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/VertexAttribute.h b/src/3rdparty/angle/src/libANGLE/VertexAttribute.h new file mode 100644 index 0000000000..bdffe97466 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/VertexAttribute.h @@ -0,0 +1,122 @@ +// +// 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. +// +// Helper structure describing a single vertex attribute +// + +#ifndef LIBANGLE_VERTEXATTRIBUTE_H_ +#define LIBANGLE_VERTEXATTRIBUTE_H_ + +#include "libANGLE/Buffer.h" + +namespace gl +{ + +struct VertexAttribute +{ + bool enabled; // From glEnable/DisableVertexAttribArray + + GLenum type; + GLuint size; + bool normalized; + bool pureInteger; + GLuint stride; // 0 means natural stride + + union + { + const GLvoid *pointer; + GLintptr offset; + }; + BindingPointer buffer; // Captured when glVertexAttribPointer is called. + + GLuint divisor; + + VertexAttribute(); +}; + +bool operator==(const VertexAttribute &a, const VertexAttribute &b); +bool operator!=(const VertexAttribute &a, const VertexAttribute &b); + +template +T QuerySingleVertexAttributeParameter(const VertexAttribute& attrib, GLenum pname) +{ + switch (pname) + { + case GL_VERTEX_ATTRIB_ARRAY_ENABLED: + return static_cast(attrib.enabled ? GL_TRUE : GL_FALSE); + case GL_VERTEX_ATTRIB_ARRAY_SIZE: + return static_cast(attrib.size); + case GL_VERTEX_ATTRIB_ARRAY_STRIDE: + return static_cast(attrib.stride); + case GL_VERTEX_ATTRIB_ARRAY_TYPE: + return static_cast(attrib.type); + case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED: + return static_cast(attrib.normalized ? GL_TRUE : GL_FALSE); + case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: + return static_cast(attrib.buffer.id()); + case GL_VERTEX_ATTRIB_ARRAY_DIVISOR: + return static_cast(attrib.divisor); + case GL_VERTEX_ATTRIB_ARRAY_INTEGER: + return static_cast(attrib.pureInteger ? GL_TRUE : GL_FALSE); + default: + UNREACHABLE(); + return static_cast(0); + } +} + +size_t ComputeVertexAttributeTypeSize(const VertexAttribute& attrib); +size_t ComputeVertexAttributeStride(const VertexAttribute& attrib); + +struct VertexAttribCurrentValueData +{ + union + { + GLfloat FloatValues[4]; + GLint IntValues[4]; + GLuint UnsignedIntValues[4]; + }; + GLenum Type; + + void setFloatValues(const GLfloat floatValues[4]) + { + for (unsigned int valueIndex = 0; valueIndex < 4; valueIndex++) + { + FloatValues[valueIndex] = floatValues[valueIndex]; + } + Type = GL_FLOAT; + } + + void setIntValues(const GLint intValues[4]) + { + for (unsigned int valueIndex = 0; valueIndex < 4; valueIndex++) + { + IntValues[valueIndex] = intValues[valueIndex]; + } + Type = GL_INT; + } + + void setUnsignedIntValues(const GLuint unsignedIntValues[4]) + { + for (unsigned int valueIndex = 0; valueIndex < 4; valueIndex++) + { + UnsignedIntValues[valueIndex] = unsignedIntValues[valueIndex]; + } + Type = GL_UNSIGNED_INT; + } + + bool operator==(const VertexAttribCurrentValueData &other) + { + return (Type == other.Type && memcmp(FloatValues, other.FloatValues, sizeof(float) * 4) == 0); + } + + bool operator!=(const VertexAttribCurrentValueData &other) + { + return !(*this == other); + } +}; + +} + +#endif // LIBANGLE_VERTEXATTRIBUTE_H_ diff --git a/src/3rdparty/angle/src/libANGLE/angletypes.cpp b/src/3rdparty/angle/src/libANGLE/angletypes.cpp new file mode 100644 index 0000000000..16879f8041 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/angletypes.cpp @@ -0,0 +1,246 @@ +// +// 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. +// + +// angletypes.h : Defines a variety of structures and enum types that are used throughout libGLESv2 + +#include "libANGLE/angletypes.h" +#include "libANGLE/Program.h" +#include "libANGLE/VertexAttribute.h" +#include "libANGLE/State.h" +#include "libANGLE/VertexArray.h" + +namespace gl +{ + +bool operator==(const Rectangle &a, const Rectangle &b) +{ + return a.x == b.x && + a.y == b.y && + a.width == b.width && + a.height == b.height; +} + +bool operator!=(const Rectangle &a, const Rectangle &b) +{ + return !(a == b); +} + +SamplerState::SamplerState() + : minFilter(GL_NEAREST_MIPMAP_LINEAR), + magFilter(GL_LINEAR), + wrapS(GL_REPEAT), + wrapT(GL_REPEAT), + wrapR(GL_REPEAT), + maxAnisotropy(1.0f), + baseLevel(0), + maxLevel(1000), + minLod(-1000.0f), + maxLod(1000.0f), + compareMode(GL_NONE), + compareFunc(GL_LEQUAL), + swizzleRed(GL_RED), + swizzleGreen(GL_GREEN), + swizzleBlue(GL_BLUE), + swizzleAlpha(GL_ALPHA) +{} + +bool SamplerState::swizzleRequired() const +{ + return swizzleRed != GL_RED || swizzleGreen != GL_GREEN || + swizzleBlue != GL_BLUE || swizzleAlpha != GL_ALPHA; +} + +bool SamplerState::operator==(const SamplerState &other) const +{ + return minFilter == other.minFilter && + magFilter == other.magFilter && + wrapS == other.wrapS && + wrapT == other.wrapT && + wrapR == other.wrapR && + maxAnisotropy == other.maxAnisotropy && + baseLevel == other.baseLevel && + maxLevel == other.maxLevel && + minLod == other.minLod && + maxLod == other.maxLod && + compareMode == other.compareMode && + compareFunc == other.compareFunc && + swizzleRed == other.swizzleRed && + swizzleGreen == other.swizzleGreen && + swizzleBlue == other.swizzleBlue && + swizzleAlpha == other.swizzleAlpha; +} + +bool SamplerState::operator!=(const SamplerState &other) const +{ + return !(*this == other); +} + +static void MinMax(int a, int b, int *minimum, int *maximum) +{ + if (a < b) + { + *minimum = a; + *maximum = b; + } + else + { + *minimum = b; + *maximum = a; + } +} + +bool ClipRectangle(const Rectangle &source, const Rectangle &clip, Rectangle *intersection) +{ + int minSourceX, maxSourceX, minSourceY, maxSourceY; + MinMax(source.x, source.x + source.width, &minSourceX, &maxSourceX); + MinMax(source.y, source.y + source.height, &minSourceY, &maxSourceY); + + int minClipX, maxClipX, minClipY, maxClipY; + MinMax(clip.x, clip.x + clip.width, &minClipX, &maxClipX); + MinMax(clip.y, clip.y + clip.height, &minClipY, &maxClipY); + + if (minSourceX >= maxClipX || maxSourceX <= minClipX || minSourceY >= maxClipY || maxSourceY <= minClipY) + { + if (intersection) + { + intersection->x = minSourceX; + intersection->y = maxSourceY; + intersection->width = maxSourceX - minSourceX; + intersection->height = maxSourceY - minSourceY; + } + + return false; + } + else + { + if (intersection) + { + intersection->x = std::max(minSourceX, minClipX); + intersection->y = std::max(minSourceY, minClipY); + intersection->width = std::min(maxSourceX, maxClipX) - std::max(minSourceX, minClipX); + intersection->height = std::min(maxSourceY, maxClipY) - std::max(minSourceY, minClipY); + } + + return true; + } +} + +VertexFormat::VertexFormat() + : mType(GL_NONE), + mNormalized(GL_FALSE), + mComponents(0), + mPureInteger(false) +{} + +VertexFormat::VertexFormat(GLenum type, GLboolean normalized, GLuint components, bool pureInteger) + : mType(type), + mNormalized(normalized), + mComponents(components), + mPureInteger(pureInteger) +{ + // Float data can not be normalized, so ignore the user setting + if (mType == GL_FLOAT || mType == GL_HALF_FLOAT || mType == GL_FIXED) + { + mNormalized = GL_FALSE; + } +} + +VertexFormat::VertexFormat(const VertexAttribute &attrib) + : mType(attrib.type), + mNormalized(attrib.normalized ? GL_TRUE : GL_FALSE), + mComponents(attrib.size), + mPureInteger(attrib.pureInteger) +{ + // Ensure we aren't initializing a vertex format which should be using + // the current-value type + ASSERT(attrib.enabled); + + // Float data can not be normalized, so ignore the user setting + if (mType == GL_FLOAT || mType == GL_HALF_FLOAT || mType == GL_FIXED) + { + mNormalized = GL_FALSE; + } +} + +VertexFormat::VertexFormat(const VertexAttribute &attrib, GLenum currentValueType) + : mType(attrib.type), + mNormalized(attrib.normalized ? GL_TRUE : GL_FALSE), + mComponents(attrib.size), + mPureInteger(attrib.pureInteger) +{ + if (!attrib.enabled) + { + mType = currentValueType; + mNormalized = GL_FALSE; + mComponents = 4; + mPureInteger = (currentValueType != GL_FLOAT); + } + + // Float data can not be normalized, so ignore the user setting + if (mType == GL_FLOAT || mType == GL_HALF_FLOAT || mType == GL_FIXED) + { + mNormalized = GL_FALSE; + } +} + +void VertexFormat::GetInputLayout(VertexFormat *inputLayout, + Program *program, + const State &state) +{ + const std::vector &vertexAttributes = state.getVertexArray()->getVertexAttributes(); + for (unsigned int attributeIndex = 0; attributeIndex < vertexAttributes.size(); attributeIndex++) + { + int semanticIndex = program->getSemanticIndex(attributeIndex); + + if (semanticIndex != -1) + { + inputLayout[semanticIndex] = VertexFormat(vertexAttributes[attributeIndex], state.getVertexAttribCurrentValue(attributeIndex).Type); + } + } +} + +bool VertexFormat::operator==(const VertexFormat &other) const +{ + return (mType == other.mType && + mComponents == other.mComponents && + mNormalized == other.mNormalized && + mPureInteger == other.mPureInteger ); +} + +bool VertexFormat::operator!=(const VertexFormat &other) const +{ + return !(*this == other); +} + +bool VertexFormat::operator<(const VertexFormat& other) const +{ + if (mType != other.mType) + { + return mType < other.mType; + } + if (mNormalized != other.mNormalized) + { + return mNormalized < other.mNormalized; + } + if (mComponents != other.mComponents) + { + return mComponents < other.mComponents; + } + return mPureInteger < other.mPureInteger; +} + +bool Box::operator==(const Box &other) const +{ + return (x == other.x && y == other.y && z == other.z && + width == other.width && height == other.height && depth == other.depth); +} + +bool Box::operator!=(const Box &other) const +{ + return !(*this == other); +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/angletypes.h b/src/3rdparty/angle/src/libANGLE/angletypes.h new file mode 100644 index 0000000000..e4e08b5512 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/angletypes.h @@ -0,0 +1,323 @@ +// +// 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. +// + +// angletypes.h : Defines a variety of structures and enum types that are used throughout libGLESv2 + +#ifndef LIBANGLE_ANGLETYPES_H_ +#define LIBANGLE_ANGLETYPES_H_ + +#include "libANGLE/Constants.h" +#include "libANGLE/RefCountObject.h" + +#include +#include + +namespace gl +{ +class Buffer; +class State; +class Program; +struct VertexAttribute; +struct VertexAttribCurrentValueData; + +enum SamplerType +{ + SAMPLER_PIXEL, + SAMPLER_VERTEX +}; + +template +struct Color +{ + T red; + T green; + T blue; + T alpha; + + Color() : red(0), green(0), blue(0), alpha(0) { } + Color(T r, T g, T b, T a) : red(r), green(g), blue(b), alpha(a) { } +}; + +template +bool operator==(const Color &a, const Color &b) +{ + return a.red == b.red && + a.green == b.green && + a.blue == b.blue && + a.alpha == b.alpha; +} + +template +bool operator!=(const Color &a, const Color &b) +{ + return !(a == b); +} + +typedef Color ColorF; +typedef Color ColorI; +typedef Color ColorUI; + +struct Rectangle +{ + int x; + int y; + int width; + int height; + + Rectangle() : x(0), y(0), width(0), height(0) { } + Rectangle(int x_in, int y_in, int width_in, int height_in) : x(x_in), y(y_in), width(width_in), height(height_in) { } +}; + +bool operator==(const Rectangle &a, const Rectangle &b); +bool operator!=(const Rectangle &a, const Rectangle &b); + +bool ClipRectangle(const Rectangle &source, const Rectangle &clip, Rectangle *intersection); + +struct Offset +{ + int x; + int y; + int z; + + Offset() : x(0), y(0), z(0) { } + Offset(int x_in, int y_in, int z_in) : x(x_in), y(y_in), z(z_in) { } +}; + +struct Extents +{ + int width; + int height; + int depth; + + Extents() : width(0), height(0), depth(0) { } + Extents(int width_, int height_, int depth_) : width(width_), height(height_), depth(depth_) { } + + bool empty() const { return (width * height * depth) == 0; } +}; + +struct Box +{ + int x; + int y; + int z; + int width; + int height; + int depth; + + Box() : x(0), y(0), z(0), width(0), height(0), depth(0) { } + Box(int x_in, int y_in, int z_in, int width_in, int height_in, int depth_in) : x(x_in), y(y_in), z(z_in), width(width_in), height(height_in), depth(depth_in) { } + Box(const Offset &offset, const Extents &size) : x(offset.x), y(offset.y), z(offset.z), width(size.width), height(size.height), depth(size.depth) { } + bool operator==(const Box &other) const; + bool operator!=(const Box &other) const; +}; + + +struct RasterizerState +{ + bool cullFace; + GLenum cullMode; + GLenum frontFace; + + bool polygonOffsetFill; + GLfloat polygonOffsetFactor; + GLfloat polygonOffsetUnits; + + bool pointDrawMode; + bool multiSample; + + bool rasterizerDiscard; +}; + +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 +{ + SamplerState(); + + GLenum minFilter; + GLenum magFilter; + GLenum wrapS; + GLenum wrapT; + GLenum wrapR; + float maxAnisotropy; + + GLint baseLevel; + GLint maxLevel; + GLfloat minLod; + GLfloat maxLod; + + GLenum compareMode; + GLenum compareFunc; + + GLenum swizzleRed; + GLenum swizzleGreen; + GLenum swizzleBlue; + GLenum swizzleAlpha; + + bool swizzleRequired() const; + + bool operator==(const SamplerState &other) const; + bool operator!=(const SamplerState &other) const; +}; + +struct PixelUnpackState +{ + BindingPointer pixelBuffer; + GLint alignment; + GLint rowLength; + GLint skipRows; + GLint skipPixels; + GLint imageHeight; + GLint skipImages; + + PixelUnpackState() + : alignment(4), + rowLength(0), + skipRows(0), + skipPixels(0), + imageHeight(0), + skipImages(0) + {} + + PixelUnpackState(GLint alignmentIn, GLint rowLengthIn) + : alignment(alignmentIn), + rowLength(rowLengthIn), + skipRows(0), + skipPixels(0), + imageHeight(0), + skipImages(0) + {} +}; + +struct PixelPackState +{ + BindingPointer pixelBuffer; + GLint alignment; + bool reverseRowOrder; + GLint rowLength; + GLint skipRows; + GLint skipPixels; + + PixelPackState() + : alignment(4), + reverseRowOrder(false), + rowLength(0), + skipRows(0), + skipPixels(0) + {} + + explicit PixelPackState(GLint alignmentIn, bool reverseRowOrderIn) + : alignment(alignmentIn), + reverseRowOrder(reverseRowOrderIn), + rowLength(0), + skipRows(0), + skipPixels(0) + {} +}; + +struct VertexFormat +{ + GLenum mType; + GLboolean mNormalized; + GLuint mComponents; + bool mPureInteger; + + VertexFormat(); + VertexFormat(GLenum type, GLboolean normalized, GLuint components, bool pureInteger); + explicit VertexFormat(const VertexAttribute &attribute); + VertexFormat(const VertexAttribute &attribute, GLenum currentValueType); + + static void GetInputLayout(VertexFormat *inputLayout, + Program *program, + const State& currentValues); + + bool operator==(const VertexFormat &other) const; + bool operator!=(const VertexFormat &other) const; + bool operator<(const VertexFormat& other) const; +}; + +} + +namespace rx +{ + +enum VendorID : uint32_t +{ + VENDOR_ID_AMD = 0x1002, + VENDOR_ID_INTEL = 0x8086, + VENDOR_ID_NVIDIA = 0x10DE, +}; + +// Downcast a base implementation object (EG TextureImpl to TextureD3D) +template +inline DestT *GetAs(SrcT *src) +{ + ASSERT(HAS_DYNAMIC_TYPE(DestT*, src)); + return static_cast(src); +} + +template +inline const DestT *GetAs(const SrcT *src) +{ + ASSERT(HAS_DYNAMIC_TYPE(const DestT*, src)); + return static_cast(src); +} + +// Downcast a GL object to an Impl (EG gl::Texture to rx::TextureD3D) +template +inline DestT *GetImplAs(SrcT *src) +{ + return GetAs(src->getImplementation()); +} + +template +inline const DestT *GetImplAs(const SrcT *src) +{ + return GetAs(src->getImplementation()); +} + +} + +#endif // LIBANGLE_ANGLETYPES_H_ diff --git a/src/3rdparty/angle/src/libANGLE/features.h b/src/3rdparty/angle/src/libANGLE/features.h new file mode 100644 index 0000000000..fbe013f47d --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/features.h @@ -0,0 +1,40 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef LIBANGLE_FEATURES_H_ +#define LIBANGLE_FEATURES_H_ + +#define ANGLE_DISABLED 0 +#define ANGLE_ENABLED 1 + +// Feature defaults + +// Direct3D9EX +// 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_D3D9EX=0" in your project file. +#if !defined(ANGLE_D3D9EX) +#define ANGLE_D3D9EX ANGLE_ENABLED +#endif + +// Vsync +// ENABLED allows Vsync to be configured at runtime +// DISABLED disallows Vsync +#if !defined(ANGLE_VSYNC) +#define ANGLE_VSYNC ANGLE_ENABLED +#endif + +// Program binary loading +#if !defined(ANGLE_PROGRAM_BINARY_LOAD) +#define ANGLE_PROGRAM_BINARY_LOAD ANGLE_ENABLED +#endif + +// Shader debug info +#if !defined(ANGLE_SHADER_DEBUG_INFO) +#define ANGLE_SHADER_DEBUG_INFO ANGLE_DISABLED +#endif + +#endif // LIBANGLE_FEATURES_H_ diff --git a/src/3rdparty/angle/src/libANGLE/formatutils.cpp b/src/3rdparty/angle/src/libANGLE/formatutils.cpp new file mode 100644 index 0000000000..51e6a5a65d --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/formatutils.cpp @@ -0,0 +1,650 @@ +// +// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// formatutils.cpp: Queries for GL image formats. + +#include "common/mathutil.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/Context.h" +#include "libANGLE/Framebuffer.h" +#include "libANGLE/renderer/Renderer.h" + +namespace gl +{ + +// ES2 requires that format is equal to internal format at all glTex*Image2D entry points and the implementation +// can decide the true, sized, internal format. The ES2FormatMap determines the internal format for all valid +// format and type combinations. + +typedef std::pair FormatTypePair; +typedef std::pair FormatPair; +typedef std::map FormatMap; + +// A helper function to insert data into the format map with fewer characters. +static inline void InsertFormatMapping(FormatMap *map, GLenum format, GLenum type, GLenum internalFormat) +{ + map->insert(FormatPair(FormatTypePair(format, type), internalFormat)); +} + +FormatMap BuildFormatMap() +{ + FormatMap map; + + // | Format | Type | Internal format | + InsertFormatMapping(&map, GL_RGBA, GL_UNSIGNED_BYTE, GL_RGBA8); + InsertFormatMapping(&map, GL_RGBA, GL_BYTE, GL_RGBA8_SNORM); + InsertFormatMapping(&map, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, GL_RGBA4); + InsertFormatMapping(&map, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, GL_RGB5_A1); + InsertFormatMapping(&map, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, GL_RGB10_A2); + InsertFormatMapping(&map, GL_RGBA, GL_FLOAT, GL_RGBA32F); + InsertFormatMapping(&map, GL_RGBA, GL_HALF_FLOAT, GL_RGBA16F); + InsertFormatMapping(&map, GL_RGBA, GL_HALF_FLOAT_OES, GL_RGBA16F); + + InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, GL_RGBA8UI); + InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_BYTE, GL_RGBA8I); + InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT, GL_RGBA16UI); + InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_SHORT, GL_RGBA16I); + InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_INT, GL_RGBA32UI); + InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_INT, GL_RGBA32I); + InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV, GL_RGB10_A2UI); + + InsertFormatMapping(&map, GL_RGB, GL_UNSIGNED_BYTE, GL_RGB8); + InsertFormatMapping(&map, GL_RGB, GL_BYTE, GL_RGB8_SNORM); + InsertFormatMapping(&map, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, GL_RGB565); + InsertFormatMapping(&map, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV, GL_R11F_G11F_B10F); + InsertFormatMapping(&map, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV, GL_RGB9_E5); + InsertFormatMapping(&map, GL_RGB, GL_FLOAT, GL_RGB32F); + InsertFormatMapping(&map, GL_RGB, GL_HALF_FLOAT, GL_RGB16F); + InsertFormatMapping(&map, GL_RGB, GL_HALF_FLOAT_OES, GL_RGB16F); + + InsertFormatMapping(&map, GL_RGB_INTEGER, GL_UNSIGNED_BYTE, GL_RGB8UI); + InsertFormatMapping(&map, GL_RGB_INTEGER, GL_BYTE, GL_RGB8I); + InsertFormatMapping(&map, GL_RGB_INTEGER, GL_UNSIGNED_SHORT, GL_RGB16UI); + InsertFormatMapping(&map, GL_RGB_INTEGER, GL_SHORT, GL_RGB16I); + InsertFormatMapping(&map, GL_RGB_INTEGER, GL_UNSIGNED_INT, GL_RGB32UI); + InsertFormatMapping(&map, GL_RGB_INTEGER, GL_INT, GL_RGB32I); + + InsertFormatMapping(&map, GL_RG, GL_UNSIGNED_BYTE, GL_RG8); + InsertFormatMapping(&map, GL_RG, GL_BYTE, GL_RG8_SNORM); + InsertFormatMapping(&map, GL_RG, GL_FLOAT, GL_RG32F); + InsertFormatMapping(&map, GL_RG, GL_HALF_FLOAT, GL_RG16F); + InsertFormatMapping(&map, GL_RG, GL_HALF_FLOAT_OES, GL_RG16F); + + InsertFormatMapping(&map, GL_RG_INTEGER, GL_UNSIGNED_BYTE, GL_RG8UI); + InsertFormatMapping(&map, GL_RG_INTEGER, GL_BYTE, GL_RG8I); + InsertFormatMapping(&map, GL_RG_INTEGER, GL_UNSIGNED_SHORT, GL_RG16UI); + InsertFormatMapping(&map, GL_RG_INTEGER, GL_SHORT, GL_RG16I); + InsertFormatMapping(&map, GL_RG_INTEGER, GL_UNSIGNED_INT, GL_RG32UI); + InsertFormatMapping(&map, GL_RG_INTEGER, GL_INT, GL_RG32I); + + InsertFormatMapping(&map, GL_RED, GL_UNSIGNED_BYTE, GL_R8); + InsertFormatMapping(&map, GL_RED, GL_BYTE, GL_R8_SNORM); + InsertFormatMapping(&map, GL_RED, GL_FLOAT, GL_R32F); + InsertFormatMapping(&map, GL_RED, GL_HALF_FLOAT, GL_R16F); + InsertFormatMapping(&map, GL_RED, GL_HALF_FLOAT_OES, GL_R16F); + + InsertFormatMapping(&map, GL_RED_INTEGER, GL_UNSIGNED_BYTE, GL_R8UI); + InsertFormatMapping(&map, GL_RED_INTEGER, GL_BYTE, GL_R8I); + InsertFormatMapping(&map, GL_RED_INTEGER, GL_UNSIGNED_SHORT, GL_R16UI); + InsertFormatMapping(&map, GL_RED_INTEGER, GL_SHORT, GL_R16I); + InsertFormatMapping(&map, GL_RED_INTEGER, GL_UNSIGNED_INT, GL_R32UI); + InsertFormatMapping(&map, GL_RED_INTEGER, GL_INT, GL_R32I); + + InsertFormatMapping(&map, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, GL_LUMINANCE8_ALPHA8_EXT); + InsertFormatMapping(&map, GL_LUMINANCE, GL_UNSIGNED_BYTE, GL_LUMINANCE8_EXT); + InsertFormatMapping(&map, GL_ALPHA, GL_UNSIGNED_BYTE, GL_ALPHA8_EXT); + InsertFormatMapping(&map, GL_LUMINANCE_ALPHA, GL_FLOAT, GL_LUMINANCE_ALPHA32F_EXT); + InsertFormatMapping(&map, GL_LUMINANCE, GL_FLOAT, GL_LUMINANCE32F_EXT); + InsertFormatMapping(&map, GL_ALPHA, GL_FLOAT, GL_ALPHA32F_EXT); + InsertFormatMapping(&map, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT, GL_LUMINANCE_ALPHA16F_EXT); + InsertFormatMapping(&map, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES, GL_LUMINANCE_ALPHA16F_EXT); + InsertFormatMapping(&map, GL_LUMINANCE, GL_HALF_FLOAT, GL_LUMINANCE16F_EXT); + InsertFormatMapping(&map, GL_LUMINANCE, GL_HALF_FLOAT_OES, GL_LUMINANCE16F_EXT); + InsertFormatMapping(&map, GL_ALPHA, GL_HALF_FLOAT, GL_ALPHA16F_EXT); + InsertFormatMapping(&map, GL_ALPHA, GL_HALF_FLOAT_OES, GL_ALPHA16F_EXT); + + InsertFormatMapping(&map, GL_BGRA_EXT, GL_UNSIGNED_BYTE, GL_BGRA8_EXT); + InsertFormatMapping(&map, GL_BGRA_EXT, GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT, GL_BGRA4_ANGLEX); + InsertFormatMapping(&map, GL_BGRA_EXT, GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT, GL_BGR5_A1_ANGLEX); + + InsertFormatMapping(&map, GL_SRGB_EXT, GL_UNSIGNED_BYTE, GL_SRGB8); + InsertFormatMapping(&map, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE, GL_SRGB8_ALPHA8); + + InsertFormatMapping(&map, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, GL_COMPRESSED_RGB_S3TC_DXT1_EXT); + InsertFormatMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT); + InsertFormatMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, GL_UNSIGNED_BYTE, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE); + InsertFormatMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, GL_UNSIGNED_BYTE, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE); + + InsertFormatMapping(&map, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, GL_DEPTH_COMPONENT16); + InsertFormatMapping(&map, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, GL_DEPTH_COMPONENT32_OES); + InsertFormatMapping(&map, GL_DEPTH_COMPONENT, GL_FLOAT, GL_DEPTH_COMPONENT32F); + + InsertFormatMapping(&map, GL_STENCIL, GL_UNSIGNED_BYTE, GL_STENCIL_INDEX8); + + InsertFormatMapping(&map, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, GL_DEPTH24_STENCIL8); + InsertFormatMapping(&map, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, GL_DEPTH32F_STENCIL8); + + return map; +} + +Type::Type() + : bytes(0), + bytesShift(0), + specialInterpretation(false) +{ +} + +static Type GenTypeInfo(GLuint bytes, bool specialInterpretation) +{ + Type info; + info.bytes = bytes; + GLuint i = 0; + while ((1u << i) < bytes) + { + ++i; + } + info.bytesShift = i; + ASSERT((1u << info.bytesShift) == bytes); + info.specialInterpretation = specialInterpretation; + return info; +} + +bool operator<(const Type& a, const Type& b) +{ + return memcmp(&a, &b, sizeof(Type)) < 0; +} + +// Information about internal formats +static bool AlwaysSupported(GLuint, const Extensions &) +{ + return true; +} + +static bool UnimplementedSupport(GLuint, const Extensions &) +{ + return false; +} + +static bool NeverSupported(GLuint, const Extensions &) +{ + return false; +} + +template +static bool RequireES(GLuint clientVersion, const Extensions &) +{ + return clientVersion >= minCoreGLVersion; +} + +// Pointer to a boolean memeber of the Extensions struct +typedef bool(Extensions::*ExtensionBool); + +// Check support for a single extension +template +static bool RequireExt(GLuint, const Extensions & extensions) +{ + return extensions.*bool1; +} + +// Check for a minimum client version or a single extension +template +static bool RequireESOrExt(GLuint clientVersion, const Extensions &extensions) +{ + return clientVersion >= minCoreGLVersion || extensions.*bool1; +} + +// Check for a minimum client version or two extensions +template +static bool RequireESOrExtAndExt(GLuint clientVersion, const Extensions &extensions) +{ + return clientVersion >= minCoreGLVersion || (extensions.*bool1 && extensions.*bool2); +} + +// Check for a minimum client version or at least one of two extensions +template +static bool RequireESOrExtOrExt(GLuint clientVersion, const Extensions &extensions) +{ + return clientVersion >= minCoreGLVersion || extensions.*bool1 || extensions.*bool2; +} + +// Check support for two extensions +template +static bool RequireExtAndExt(GLuint, const Extensions &extensions) +{ + return extensions.*bool1 && extensions.*bool2; +} + +InternalFormat::InternalFormat() + : redBits(0), + greenBits(0), + blueBits(0), + luminanceBits(0), + alphaBits(0), + sharedBits(0), + depthBits(0), + stencilBits(0), + pixelBytes(0), + componentCount(0), + compressedBlockWidth(0), + compressedBlockHeight(0), + format(GL_NONE), + type(GL_NONE), + componentType(GL_NONE), + colorEncoding(GL_NONE), + compressed(false), + textureSupport(NeverSupported), + renderSupport(NeverSupported), + filterSupport(NeverSupported) +{ +} + +static InternalFormat UnsizedFormat(GLenum format, InternalFormat::SupportCheckFunction textureSupport, + InternalFormat::SupportCheckFunction renderSupport, + InternalFormat::SupportCheckFunction filterSupport) +{ + InternalFormat formatInfo; + formatInfo.format = format; + formatInfo.textureSupport = textureSupport; + formatInfo.renderSupport = renderSupport; + formatInfo.filterSupport = filterSupport; + return formatInfo; +} + +static InternalFormat RGBAFormat(GLuint red, GLuint green, GLuint blue, GLuint alpha, GLuint shared, + GLenum format, GLenum type, GLenum componentType, bool srgb, + InternalFormat::SupportCheckFunction textureSupport, + InternalFormat::SupportCheckFunction renderSupport, + InternalFormat::SupportCheckFunction filterSupport) +{ + InternalFormat formatInfo; + formatInfo.redBits = red; + formatInfo.greenBits = green; + formatInfo.blueBits = blue; + formatInfo.alphaBits = alpha; + formatInfo.sharedBits = shared; + formatInfo.pixelBytes = (red + green + blue + alpha + shared) / 8; + formatInfo.componentCount = ((red > 0) ? 1 : 0) + ((green > 0) ? 1 : 0) + ((blue > 0) ? 1 : 0) + ((alpha > 0) ? 1 : 0); + formatInfo.format = format; + formatInfo.type = type; + formatInfo.componentType = componentType; + formatInfo.colorEncoding = (srgb ? GL_SRGB : GL_LINEAR); + formatInfo.textureSupport = textureSupport; + formatInfo.renderSupport = renderSupport; + formatInfo.filterSupport = filterSupport; + return formatInfo; +} + +static InternalFormat LUMAFormat(GLuint luminance, GLuint alpha, GLenum format, GLenum type, GLenum componentType, + InternalFormat::SupportCheckFunction textureSupport, + InternalFormat::SupportCheckFunction renderSupport, + InternalFormat::SupportCheckFunction filterSupport) +{ + InternalFormat formatInfo; + formatInfo.luminanceBits = luminance; + formatInfo.alphaBits = alpha; + formatInfo.pixelBytes = (luminance + alpha) / 8; + formatInfo.componentCount = ((luminance > 0) ? 1 : 0) + ((alpha > 0) ? 1 : 0); + formatInfo.format = format; + formatInfo.type = type; + formatInfo.componentType = componentType; + formatInfo.colorEncoding = GL_LINEAR; + formatInfo.textureSupport = textureSupport; + formatInfo.renderSupport = renderSupport; + formatInfo.filterSupport = filterSupport; + return formatInfo; +} + +static InternalFormat DepthStencilFormat(GLuint depthBits, GLuint stencilBits, GLuint unusedBits, GLenum format, + GLenum type, GLenum componentType, InternalFormat::SupportCheckFunction textureSupport, + InternalFormat::SupportCheckFunction renderSupport, + InternalFormat::SupportCheckFunction filterSupport) +{ + InternalFormat formatInfo; + formatInfo.depthBits = depthBits; + formatInfo.stencilBits = stencilBits; + formatInfo.pixelBytes = (depthBits + stencilBits + unusedBits) / 8; + formatInfo.componentCount = ((depthBits > 0) ? 1 : 0) + ((stencilBits > 0) ? 1 : 0); + formatInfo.format = format; + formatInfo.type = type; + formatInfo.componentType = componentType; + formatInfo.colorEncoding = GL_LINEAR; + formatInfo.textureSupport = textureSupport; + formatInfo.renderSupport = renderSupport; + formatInfo.filterSupport = filterSupport; + return formatInfo; +} + +static InternalFormat CompressedFormat(GLuint compressedBlockWidth, GLuint compressedBlockHeight, GLuint compressedBlockSize, + GLuint componentCount, GLenum format, GLenum type, bool srgb, + InternalFormat::SupportCheckFunction textureSupport, + InternalFormat::SupportCheckFunction renderSupport, + InternalFormat::SupportCheckFunction filterSupport) +{ + InternalFormat formatInfo; + formatInfo.compressedBlockWidth = compressedBlockWidth; + formatInfo.compressedBlockHeight = compressedBlockHeight; + formatInfo.pixelBytes = compressedBlockSize / 8; + formatInfo.componentCount = componentCount; + formatInfo.format = format; + formatInfo.type = type; + formatInfo.componentType = GL_UNSIGNED_NORMALIZED; + formatInfo.colorEncoding = (srgb ? GL_SRGB : GL_LINEAR); + formatInfo.compressed = true; + formatInfo.textureSupport = textureSupport; + formatInfo.renderSupport = renderSupport; + formatInfo.filterSupport = filterSupport; + return formatInfo; +} + +typedef std::pair InternalFormatInfoPair; +typedef std::map InternalFormatInfoMap; + +static InternalFormatInfoMap BuildInternalFormatInfoMap() +{ + InternalFormatInfoMap map; + + // From ES 3.0.1 spec, table 3.12 + map.insert(InternalFormatInfoPair(GL_NONE, InternalFormat())); + + // | Internal format | | R | G | B | A |S | Format | Type | Component type | SRGB | Texture supported | Renderable | Filterable | + map.insert(InternalFormatInfoPair(GL_R8, RGBAFormat( 8, 0, 0, 0, 0, GL_RED, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, RequireESOrExt<3, &Extensions::textureRG>, RequireESOrExt<3, &Extensions::textureRG>, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_R8_SNORM, RGBAFormat( 8, 0, 0, 0, 0, GL_RED, GL_BYTE, GL_SIGNED_NORMALIZED, false, RequireES<3>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_RG8, RGBAFormat( 8, 8, 0, 0, 0, GL_RG, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, RequireESOrExt<3, &Extensions::textureRG>, RequireESOrExt<3, &Extensions::textureRG>, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_RG8_SNORM, RGBAFormat( 8, 8, 0, 0, 0, GL_RG, GL_BYTE, GL_SIGNED_NORMALIZED, false, RequireES<3>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_RGB8, RGBAFormat( 8, 8, 8, 0, 0, GL_RGB, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, RequireESOrExt<3, &Extensions::rgb8rgba8>, RequireESOrExt<3, &Extensions::rgb8rgba8>, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_RGB8_SNORM, RGBAFormat( 8, 8, 8, 0, 0, GL_RGB, GL_BYTE, GL_SIGNED_NORMALIZED, false, RequireES<3>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_RGB565, RGBAFormat( 5, 6, 5, 0, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_NORMALIZED, false, RequireES<2>, RequireES<2>, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_RGBA4, RGBAFormat( 4, 4, 4, 4, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_NORMALIZED, false, RequireES<2>, RequireES<2>, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_RGB5_A1, RGBAFormat( 5, 5, 5, 1, 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, GL_UNSIGNED_NORMALIZED, false, RequireES<2>, RequireES<2>, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_RGBA8, RGBAFormat( 8, 8, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, RequireESOrExt<3, &Extensions::rgb8rgba8>, RequireESOrExt<3, &Extensions::rgb8rgba8>, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_RGBA8_SNORM, RGBAFormat( 8, 8, 8, 8, 0, GL_RGBA, GL_BYTE, GL_SIGNED_NORMALIZED, false, RequireES<3>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_RGB10_A2, RGBAFormat(10, 10, 10, 2, 0, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, GL_UNSIGNED_NORMALIZED, false, RequireES<3>, RequireES<3>, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_RGB10_A2UI, RGBAFormat(10, 10, 10, 2, 0, GL_RGBA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV, GL_UNSIGNED_INT, false, RequireES<3>, NeverSupported, NeverSupported))); + map.insert(InternalFormatInfoPair(GL_SRGB8, RGBAFormat( 8, 8, 8, 0, 0, GL_RGB, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, true, RequireESOrExt<3, &Extensions::sRGB>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_SRGB8_ALPHA8, RGBAFormat( 8, 8, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, true, RequireESOrExt<3, &Extensions::sRGB>, RequireESOrExt<3, &Extensions::sRGB>, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_R11F_G11F_B10F, RGBAFormat(11, 11, 10, 0, 0, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV, GL_FLOAT, false, RequireES<3>, RequireExt<&Extensions::colorBufferFloat>, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_RGB9_E5, RGBAFormat( 9, 9, 9, 0, 5, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV, GL_FLOAT, false, RequireES<3>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_R8I, RGBAFormat( 8, 0, 0, 0, 0, GL_RED_INTEGER, GL_BYTE, GL_INT, false, RequireES<3>, RequireES<3>, NeverSupported))); + map.insert(InternalFormatInfoPair(GL_R8UI, RGBAFormat( 8, 0, 0, 0, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, GL_UNSIGNED_INT, false, RequireES<3>, RequireES<3>, NeverSupported))); + map.insert(InternalFormatInfoPair(GL_R16I, RGBAFormat(16, 0, 0, 0, 0, GL_RED_INTEGER, GL_SHORT, GL_INT, false, RequireES<3>, RequireES<3>, NeverSupported))); + map.insert(InternalFormatInfoPair(GL_R16UI, RGBAFormat(16, 0, 0, 0, 0, GL_RED_INTEGER, GL_UNSIGNED_SHORT, GL_UNSIGNED_INT, false, RequireES<3>, RequireES<3>, NeverSupported))); + map.insert(InternalFormatInfoPair(GL_R32I, RGBAFormat(32, 0, 0, 0, 0, GL_RED_INTEGER, GL_INT, GL_INT, false, RequireES<3>, RequireES<3>, NeverSupported))); + map.insert(InternalFormatInfoPair(GL_R32UI, RGBAFormat(32, 0, 0, 0, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, GL_UNSIGNED_INT, false, RequireES<3>, RequireES<3>, NeverSupported))); + map.insert(InternalFormatInfoPair(GL_RG8I, RGBAFormat( 8, 8, 0, 0, 0, GL_RG_INTEGER, GL_BYTE, GL_INT, false, RequireES<3>, RequireES<3>, NeverSupported))); + map.insert(InternalFormatInfoPair(GL_RG8UI, RGBAFormat( 8, 8, 0, 0, 0, GL_RG_INTEGER, GL_UNSIGNED_BYTE, GL_UNSIGNED_INT, false, RequireES<3>, RequireES<3>, NeverSupported))); + map.insert(InternalFormatInfoPair(GL_RG16I, RGBAFormat(16, 16, 0, 0, 0, GL_RG_INTEGER, GL_SHORT, GL_INT, false, RequireES<3>, RequireES<3>, NeverSupported))); + map.insert(InternalFormatInfoPair(GL_RG16UI, RGBAFormat(16, 16, 0, 0, 0, GL_RG_INTEGER, GL_UNSIGNED_SHORT, GL_UNSIGNED_INT, false, RequireES<3>, RequireES<3>, NeverSupported))); + map.insert(InternalFormatInfoPair(GL_RG32I, RGBAFormat(32, 32, 0, 0, 0, GL_RG_INTEGER, GL_INT, GL_INT, false, RequireES<3>, RequireES<3>, NeverSupported))); + map.insert(InternalFormatInfoPair(GL_RG32UI, RGBAFormat(32, 32, 0, 0, 0, GL_RG_INTEGER, GL_UNSIGNED_INT, GL_UNSIGNED_INT, false, RequireES<3>, RequireES<3>, NeverSupported))); + map.insert(InternalFormatInfoPair(GL_RGB8I, RGBAFormat( 8, 8, 8, 0, 0, GL_RGB_INTEGER, GL_BYTE, GL_INT, false, RequireES<3>, NeverSupported, NeverSupported))); + map.insert(InternalFormatInfoPair(GL_RGB8UI, RGBAFormat( 8, 8, 8, 0, 0, GL_RGB_INTEGER, GL_UNSIGNED_BYTE, GL_UNSIGNED_INT, false, RequireES<3>, NeverSupported, NeverSupported))); + map.insert(InternalFormatInfoPair(GL_RGB16I, RGBAFormat(16, 16, 16, 0, 0, GL_RGB_INTEGER, GL_SHORT, GL_INT, false, RequireES<3>, NeverSupported, NeverSupported))); + map.insert(InternalFormatInfoPair(GL_RGB16UI, RGBAFormat(16, 16, 16, 0, 0, GL_RGB_INTEGER, GL_UNSIGNED_SHORT, GL_UNSIGNED_INT, false, RequireES<3>, NeverSupported, NeverSupported))); + map.insert(InternalFormatInfoPair(GL_RGB32I, RGBAFormat(32, 32, 32, 0, 0, GL_RGB_INTEGER, GL_INT, GL_INT, false, RequireES<3>, NeverSupported, NeverSupported))); + map.insert(InternalFormatInfoPair(GL_RGB32UI, RGBAFormat(32, 32, 32, 0, 0, GL_RGB_INTEGER, GL_UNSIGNED_INT, GL_UNSIGNED_INT, false, RequireES<3>, NeverSupported, NeverSupported))); + map.insert(InternalFormatInfoPair(GL_RGBA8I, RGBAFormat( 8, 8, 8, 8, 0, GL_RGBA_INTEGER, GL_BYTE, GL_INT, false, RequireES<3>, RequireES<3>, NeverSupported))); + map.insert(InternalFormatInfoPair(GL_RGBA8UI, RGBAFormat( 8, 8, 8, 8, 0, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, GL_UNSIGNED_INT, false, RequireES<3>, RequireES<3>, NeverSupported))); + map.insert(InternalFormatInfoPair(GL_RGBA16I, RGBAFormat(16, 16, 16, 16, 0, GL_RGBA_INTEGER, GL_SHORT, GL_INT, false, RequireES<3>, RequireES<3>, NeverSupported))); + map.insert(InternalFormatInfoPair(GL_RGBA16UI, RGBAFormat(16, 16, 16, 16, 0, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT, GL_UNSIGNED_INT, false, RequireES<3>, RequireES<3>, NeverSupported))); + map.insert(InternalFormatInfoPair(GL_RGBA32I, RGBAFormat(32, 32, 32, 32, 0, GL_RGBA_INTEGER, GL_INT, GL_INT, false, RequireES<3>, RequireES<3>, NeverSupported))); + map.insert(InternalFormatInfoPair(GL_RGBA32UI, RGBAFormat(32, 32, 32, 32, 0, GL_RGBA_INTEGER, GL_UNSIGNED_INT, GL_UNSIGNED_INT, false, RequireES<3>, RequireES<3>, NeverSupported))); + + map.insert(InternalFormatInfoPair(GL_BGRA8_EXT, RGBAFormat( 8, 8, 8, 8, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, RequireExt<&Extensions::textureFormatBGRA8888>, RequireExt<&Extensions::textureFormatBGRA8888>, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_BGRA4_ANGLEX, RGBAFormat( 4, 4, 4, 4, 0, GL_BGRA_EXT, GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT, GL_UNSIGNED_NORMALIZED, false, RequireExt<&Extensions::textureFormatBGRA8888>, RequireExt<&Extensions::textureFormatBGRA8888>, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_BGR5_A1_ANGLEX, RGBAFormat( 5, 5, 5, 1, 0, GL_BGRA_EXT, GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT, GL_UNSIGNED_NORMALIZED, false, RequireExt<&Extensions::textureFormatBGRA8888>, RequireExt<&Extensions::textureFormatBGRA8888>, AlwaysSupported))); + + // Floating point renderability and filtering is provided by OES_texture_float and OES_texture_half_float + // | Internal format | | D |S | Format | Type | Comp | SRGB | Texture supported | Renderable | Filterable | + // | | | | | | | type | | | | | + map.insert(InternalFormatInfoPair(GL_R16F, RGBAFormat(16, 0, 0, 0, 0, GL_RED, GL_HALF_FLOAT, GL_FLOAT, false, RequireESOrExtAndExt<3, &Extensions::textureHalfFloat, &Extensions::textureRG>, RequireESOrExtAndExt<3, &Extensions::textureHalfFloat, &Extensions::textureRG>, RequireExt<&Extensions::textureHalfFloatLinear>))); + map.insert(InternalFormatInfoPair(GL_RG16F, RGBAFormat(16, 16, 0, 0, 0, GL_RG, GL_HALF_FLOAT, GL_FLOAT, false, RequireESOrExtAndExt<3, &Extensions::textureHalfFloat, &Extensions::textureRG>, RequireESOrExtAndExt<3, &Extensions::textureHalfFloat, &Extensions::textureRG>, RequireExt<&Extensions::textureHalfFloatLinear>))); + map.insert(InternalFormatInfoPair(GL_RGB16F, RGBAFormat(16, 16, 16, 0, 0, GL_RGB, GL_HALF_FLOAT, GL_FLOAT, false, RequireESOrExt<3, &Extensions::textureHalfFloat>, RequireESOrExt<3, &Extensions::textureHalfFloat>, RequireExt<&Extensions::textureHalfFloatLinear>))); + map.insert(InternalFormatInfoPair(GL_RGBA16F, RGBAFormat(16, 16, 16, 16, 0, GL_RGBA, GL_HALF_FLOAT, GL_FLOAT, false, RequireESOrExt<3, &Extensions::textureHalfFloat>, RequireESOrExt<3, &Extensions::textureHalfFloat>, RequireExt<&Extensions::textureHalfFloatLinear>))); + map.insert(InternalFormatInfoPair(GL_R32F, RGBAFormat(32, 0, 0, 0, 0, GL_RED, GL_FLOAT, GL_FLOAT, false, RequireESOrExtAndExt<3, &Extensions::textureFloat, &Extensions::textureRG>, RequireESOrExtAndExt<3, &Extensions::textureFloat, &Extensions::textureRG>, RequireExt<&Extensions::textureFloatLinear> ))); + map.insert(InternalFormatInfoPair(GL_RG32F, RGBAFormat(32, 32, 0, 0, 0, GL_RG, GL_FLOAT, GL_FLOAT, false, RequireESOrExtAndExt<3, &Extensions::textureFloat, &Extensions::textureRG>, RequireESOrExtAndExt<3, &Extensions::textureFloat, &Extensions::textureRG>, RequireExt<&Extensions::textureFloatLinear> ))); + map.insert(InternalFormatInfoPair(GL_RGB32F, RGBAFormat(32, 32, 32, 0, 0, GL_RGB, GL_FLOAT, GL_FLOAT, false, RequireESOrExt<3, &Extensions::textureFloat>, RequireESOrExt<3, &Extensions::textureFloat>, RequireExt<&Extensions::textureFloatLinear> ))); + map.insert(InternalFormatInfoPair(GL_RGBA32F, RGBAFormat(32, 32, 32, 32, 0, GL_RGBA, GL_FLOAT, GL_FLOAT, false, RequireESOrExt<3, &Extensions::textureFloat>, RequireESOrExt<3, &Extensions::textureFloat>, RequireExt<&Extensions::textureFloatLinear> ))); + + // Depth stencil formats + // | Internal format | | D |S | X | Format | Type | Component type | Supported | Renderable | Filterable | + map.insert(InternalFormatInfoPair(GL_DEPTH_COMPONENT16, DepthStencilFormat(16, 0, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, GL_UNSIGNED_NORMALIZED, RequireES<2>, RequireES<2>, RequireESOrExt<3, &Extensions::depthTextures>))); + map.insert(InternalFormatInfoPair(GL_DEPTH_COMPONENT24, DepthStencilFormat(24, 0, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, GL_UNSIGNED_NORMALIZED, RequireES<3>, RequireES<3>, RequireESOrExt<3, &Extensions::depthTextures>))); + map.insert(InternalFormatInfoPair(GL_DEPTH_COMPONENT32F, DepthStencilFormat(32, 0, 0, GL_DEPTH_COMPONENT, GL_FLOAT, GL_FLOAT, RequireES<3>, RequireES<3>, RequireESOrExt<3, &Extensions::depthTextures>))); + map.insert(InternalFormatInfoPair(GL_DEPTH_COMPONENT32_OES, DepthStencilFormat(32, 0, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, GL_UNSIGNED_NORMALIZED, RequireExt<&Extensions::depthTextures>, RequireExt<&Extensions::depthTextures>, AlwaysSupported ))); + map.insert(InternalFormatInfoPair(GL_DEPTH24_STENCIL8, DepthStencilFormat(24, 8, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, GL_UNSIGNED_NORMALIZED, RequireESOrExt<3, &Extensions::depthTextures>, RequireESOrExtOrExt<3, &Extensions::depthTextures, &Extensions::packedDepthStencil>, AlwaysSupported ))); + map.insert(InternalFormatInfoPair(GL_DEPTH32F_STENCIL8, DepthStencilFormat(32, 8, 24, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, GL_FLOAT, RequireES<3>, RequireES<3>, AlwaysSupported ))); + // STENCIL_INDEX8 is special-cased, see around the bottom of the list. + + // Luminance alpha formats + // | Internal format | | L | A | Format | Type | Component type | Supported | Renderable | Filterable | + map.insert(InternalFormatInfoPair(GL_ALPHA8_EXT, LUMAFormat( 0, 8, GL_ALPHA, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, RequireExt<&Extensions::textureStorage>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_LUMINANCE8_EXT, LUMAFormat( 8, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, RequireExt<&Extensions::textureStorage>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_ALPHA32F_EXT, LUMAFormat( 0, 32, GL_ALPHA, GL_FLOAT, GL_FLOAT, RequireExtAndExt<&Extensions::textureStorage, &Extensions::textureFloat>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_LUMINANCE32F_EXT, LUMAFormat(32, 0, GL_LUMINANCE, GL_FLOAT, GL_FLOAT, RequireExtAndExt<&Extensions::textureStorage, &Extensions::textureFloat>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_ALPHA16F_EXT, LUMAFormat( 0, 16, GL_ALPHA, GL_HALF_FLOAT, GL_FLOAT, RequireExtAndExt<&Extensions::textureStorage, &Extensions::textureHalfFloat>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_LUMINANCE16F_EXT, LUMAFormat(16, 0, GL_LUMINANCE, GL_HALF_FLOAT, GL_FLOAT, RequireExtAndExt<&Extensions::textureStorage, &Extensions::textureHalfFloat>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_LUMINANCE8_ALPHA8_EXT, LUMAFormat( 8, 8, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, RequireExt<&Extensions::textureStorage>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_LUMINANCE_ALPHA32F_EXT, LUMAFormat(32, 32, GL_LUMINANCE_ALPHA, GL_FLOAT, GL_FLOAT, RequireExtAndExt<&Extensions::textureStorage, &Extensions::textureFloat>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_LUMINANCE_ALPHA16F_EXT, LUMAFormat(16, 16, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT, GL_FLOAT, RequireExtAndExt<&Extensions::textureStorage, &Extensions::textureHalfFloat>, NeverSupported, AlwaysSupported))); + + // Unsized formats + // | Internal format | | Format | Supported | Renderable | Filterable | + map.insert(InternalFormatInfoPair(GL_ALPHA, UnsizedFormat(GL_ALPHA, RequireES<2>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_LUMINANCE, UnsizedFormat(GL_LUMINANCE, RequireES<2>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_LUMINANCE_ALPHA, UnsizedFormat(GL_LUMINANCE_ALPHA, RequireES<2>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_RED, UnsizedFormat(GL_RED, RequireESOrExt<3, &Extensions::textureRG>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_RG, UnsizedFormat(GL_RG, RequireESOrExt<3, &Extensions::textureRG>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_RGB, UnsizedFormat(GL_RGB, RequireES<2>, RequireES<2>, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_RGBA, UnsizedFormat(GL_RGBA, RequireES<2>, RequireES<2>, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_RED_INTEGER, UnsizedFormat(GL_RED_INTEGER, RequireES<3>, NeverSupported, NeverSupported ))); + map.insert(InternalFormatInfoPair(GL_RG_INTEGER, UnsizedFormat(GL_RG_INTEGER, RequireES<3>, NeverSupported, NeverSupported ))); + map.insert(InternalFormatInfoPair(GL_RGB_INTEGER, UnsizedFormat(GL_RGB_INTEGER, RequireES<3>, NeverSupported, NeverSupported ))); + map.insert(InternalFormatInfoPair(GL_RGBA_INTEGER, UnsizedFormat(GL_RGBA_INTEGER, RequireES<3>, NeverSupported, NeverSupported ))); + map.insert(InternalFormatInfoPair(GL_BGRA_EXT, UnsizedFormat(GL_BGRA_EXT, RequireExt<&Extensions::textureFormatBGRA8888>, RequireExt<&Extensions::textureFormatBGRA8888>, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_DEPTH_COMPONENT, UnsizedFormat(GL_DEPTH_COMPONENT, RequireES<2>, RequireES<2>, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_DEPTH_STENCIL, UnsizedFormat(GL_DEPTH_STENCIL, RequireESOrExt<3, &Extensions::packedDepthStencil>, RequireESOrExt<3, &Extensions::packedDepthStencil>, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_SRGB_EXT, UnsizedFormat(GL_RGB, RequireESOrExt<3, &Extensions::sRGB>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_SRGB_ALPHA_EXT, UnsizedFormat(GL_RGBA, RequireESOrExt<3, &Extensions::sRGB>, RequireESOrExt<3, &Extensions::sRGB>, AlwaysSupported))); + + // Compressed formats, From ES 3.0.1 spec, table 3.16 + // | Internal format | |W |H | BS |CC| Format | Type | SRGB | Supported | Renderable | Filterable | + map.insert(InternalFormatInfoPair(GL_COMPRESSED_R11_EAC, CompressedFormat(4, 4, 64, 1, GL_COMPRESSED_R11_EAC, GL_UNSIGNED_BYTE, false, UnimplementedSupport, UnimplementedSupport, UnimplementedSupport))); + map.insert(InternalFormatInfoPair(GL_COMPRESSED_SIGNED_R11_EAC, CompressedFormat(4, 4, 64, 1, GL_COMPRESSED_SIGNED_R11_EAC, GL_UNSIGNED_BYTE, false, UnimplementedSupport, UnimplementedSupport, UnimplementedSupport))); + map.insert(InternalFormatInfoPair(GL_COMPRESSED_RG11_EAC, CompressedFormat(4, 4, 128, 2, GL_COMPRESSED_RG11_EAC, GL_UNSIGNED_BYTE, false, UnimplementedSupport, UnimplementedSupport, UnimplementedSupport))); + map.insert(InternalFormatInfoPair(GL_COMPRESSED_SIGNED_RG11_EAC, CompressedFormat(4, 4, 128, 2, GL_COMPRESSED_SIGNED_RG11_EAC, GL_UNSIGNED_BYTE, false, UnimplementedSupport, UnimplementedSupport, UnimplementedSupport))); + map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGB8_ETC2, CompressedFormat(4, 4, 64, 3, GL_COMPRESSED_RGB8_ETC2, GL_UNSIGNED_BYTE, false, UnimplementedSupport, UnimplementedSupport, UnimplementedSupport))); + map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_ETC2, CompressedFormat(4, 4, 64, 3, GL_COMPRESSED_SRGB8_ETC2, GL_UNSIGNED_BYTE, true, UnimplementedSupport, UnimplementedSupport, UnimplementedSupport))); + map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, CompressedFormat(4, 4, 64, 3, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_UNSIGNED_BYTE, false, UnimplementedSupport, UnimplementedSupport, UnimplementedSupport))); + map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, CompressedFormat(4, 4, 64, 3, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_UNSIGNED_BYTE, true, UnimplementedSupport, UnimplementedSupport, UnimplementedSupport))); + map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA8_ETC2_EAC, CompressedFormat(4, 4, 128, 4, GL_COMPRESSED_RGBA8_ETC2_EAC, GL_UNSIGNED_BYTE, false, UnimplementedSupport, UnimplementedSupport, UnimplementedSupport))); + map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, CompressedFormat(4, 4, 128, 4, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, GL_UNSIGNED_BYTE, true, UnimplementedSupport, UnimplementedSupport, UnimplementedSupport))); + + // From GL_EXT_texture_compression_dxt1 + // | Internal format | |W |H | BS |CC| Format | Type | SRGB | Supported | Renderable | Filterable | + map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGB_S3TC_DXT1_EXT, CompressedFormat(4, 4, 64, 3, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, false, RequireExt<&Extensions::textureCompressionDXT1>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, CompressedFormat(4, 4, 64, 4, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, false, RequireExt<&Extensions::textureCompressionDXT1>, NeverSupported, AlwaysSupported))); + + // From GL_ANGLE_texture_compression_dxt3 + map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, CompressedFormat(4, 4, 128, 4, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, GL_UNSIGNED_BYTE, false, RequireExt<&Extensions::textureCompressionDXT5>, NeverSupported, AlwaysSupported))); + + // From GL_ANGLE_texture_compression_dxt5 + map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, CompressedFormat(4, 4, 128, 4, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, GL_UNSIGNED_BYTE, false, RequireExt<&Extensions::textureCompressionDXT5>, NeverSupported, AlwaysSupported))); + + // For STENCIL_INDEX8 we chose a normalized component type for the following reasons: + // - Multisampled buffer are disallowed for non-normalized integer component types and we want to support it for STENCIL_INDEX8 + // - All other stencil formats (all depth-stencil) are either float or normalized + // - It affects only validation of internalformat in RenderbufferStorageMultisample. + // | Internal format | |D |S |X | Format | Type | Component type | Supported | Renderable | Filterable | + map.insert(InternalFormatInfoPair(GL_STENCIL_INDEX8, DepthStencilFormat(0, 8, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, RequireES<2>, RequireES<2>, NeverSupported))); + + return map; +} + +static const InternalFormatInfoMap &GetInternalFormatMap() +{ + static const InternalFormatInfoMap formatMap = BuildInternalFormatInfoMap(); + return formatMap; +} + +static FormatSet BuildAllSizedInternalFormatSet() +{ + FormatSet result; + + const InternalFormatInfoMap &formats = GetInternalFormatMap(); + for (InternalFormatInfoMap::const_iterator i = formats.begin(); i != formats.end(); i++) + { + if (i->second.pixelBytes > 0) + { + result.insert(i->first); + } + } + + return result; +} + +const Type &GetTypeInfo(GLenum type) +{ + switch (type) + { + case GL_UNSIGNED_BYTE: + case GL_BYTE: + { + static const Type info = GenTypeInfo(1, false); + return info; + } + case GL_UNSIGNED_SHORT: + case GL_SHORT: + case GL_HALF_FLOAT: + case GL_HALF_FLOAT_OES: + { + static const Type info = GenTypeInfo(2, false); + return info; + } + case GL_UNSIGNED_INT: + case GL_INT: + case GL_FLOAT: + { + static const Type info = GenTypeInfo(4, false); + return info; + } + case GL_UNSIGNED_SHORT_5_6_5: + case GL_UNSIGNED_SHORT_4_4_4_4: + case GL_UNSIGNED_SHORT_5_5_5_1: + case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT: + case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT: + { + static const Type info = GenTypeInfo(2, true); + return info; + } + case GL_UNSIGNED_INT_2_10_10_10_REV: + case GL_UNSIGNED_INT_24_8: + case GL_UNSIGNED_INT_10F_11F_11F_REV: + case GL_UNSIGNED_INT_5_9_9_9_REV: + { + ASSERT(GL_UNSIGNED_INT_24_8_OES == GL_UNSIGNED_INT_24_8); + static const Type info = GenTypeInfo(4, true); + return info; + } + case GL_FLOAT_32_UNSIGNED_INT_24_8_REV: + { + static const Type info = GenTypeInfo(8, true); + return info; + } + default: + { + static const Type defaultInfo; + return defaultInfo; + } + } +} + +const InternalFormat &GetInternalFormatInfo(GLenum internalFormat) +{ + const InternalFormatInfoMap &formatMap = GetInternalFormatMap(); + InternalFormatInfoMap::const_iterator iter = formatMap.find(internalFormat); + if (iter != formatMap.end()) + { + return iter->second; + } + else + { + static const InternalFormat defaultInternalFormat; + return defaultInternalFormat; + } +} + +GLuint InternalFormat::computeRowPitch(GLenum formatType, GLsizei width, GLint alignment, GLint rowLength) const +{ + ASSERT(alignment > 0 && isPow2(alignment)); + GLuint rowBytes; + if (rowLength > 0) + { + ASSERT(!compressed); + rowBytes = pixelBytes * rowLength; + } + else + { + rowBytes = computeBlockSize(formatType, width, 1); + } + return rx::roundUp(rowBytes, static_cast(alignment)); +} + +GLuint InternalFormat::computeDepthPitch(GLenum formatType, GLsizei width, GLsizei height, GLint alignment, GLint rowLength) const +{ + return computeRowPitch(formatType, width, alignment, rowLength) * height; +} + +GLuint InternalFormat::computeBlockSize(GLenum formatType, GLsizei width, GLsizei height) const +{ + if (compressed) + { + GLsizei numBlocksWide = (width + compressedBlockWidth - 1) / compressedBlockWidth; + GLsizei numBlocksHight = (height + compressedBlockHeight - 1) / compressedBlockHeight; + return (pixelBytes * numBlocksWide * numBlocksHight); + } + else + { + const Type &typeInfo = GetTypeInfo(formatType); + if (typeInfo.specialInterpretation) + { + return typeInfo.bytes * width * height; + } + else + { + return componentCount * typeInfo.bytes * width * height; + } + } +} + +GLenum GetSizedInternalFormat(GLenum internalFormat, GLenum type) +{ + const InternalFormat& formatInfo = GetInternalFormatInfo(internalFormat); + if (formatInfo.pixelBytes > 0) + { + return internalFormat; + } + else + { + static const FormatMap formatMap = BuildFormatMap(); + FormatMap::const_iterator iter = formatMap.find(FormatTypePair(internalFormat, type)); + if (iter != formatMap.end()) + { + return iter->second; + } + else + { + return GL_NONE; + } + } +} + +const FormatSet &GetAllSizedInternalFormats() +{ + static FormatSet formatSet = BuildAllSizedInternalFormatSet(); + return formatSet; +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/formatutils.h b/src/3rdparty/angle/src/libANGLE/formatutils.h new file mode 100644 index 0000000000..37d4a8f8ef --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/formatutils.h @@ -0,0 +1,81 @@ +// +// 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. +// + +// formatutils.h: Queries for GL image formats. + +#ifndef LIBANGLE_FORMATUTILS_H_ +#define LIBANGLE_FORMATUTILS_H_ + +#include "libANGLE/Caps.h" +#include "libANGLE/angletypes.h" + +#include "angle_gl.h" + +#include +#include + +namespace gl +{ + +struct Type +{ + Type(); + + GLuint bytes; + GLuint bytesShift; // Bit shift by this value to effectively divide/multiply by "bytes" in a more optimal way + bool specialInterpretation; +}; +const Type &GetTypeInfo(GLenum type); + +struct InternalFormat +{ + InternalFormat(); + + GLuint redBits; + GLuint greenBits; + GLuint blueBits; + + GLuint luminanceBits; + + GLuint alphaBits; + GLuint sharedBits; + + GLuint depthBits; + GLuint stencilBits; + + GLuint pixelBytes; + + GLuint componentCount; + + bool compressed; + GLuint compressedBlockWidth; + GLuint compressedBlockHeight; + + GLenum format; + GLenum type; + + GLenum componentType; + GLenum colorEncoding; + + typedef bool (*SupportCheckFunction)(GLuint, const Extensions &); + SupportCheckFunction textureSupport; + SupportCheckFunction renderSupport; + SupportCheckFunction filterSupport; + + GLuint computeRowPitch(GLenum formatType, GLsizei width, GLint alignment, GLint rowLength) const; + GLuint computeDepthPitch(GLenum formatType, GLsizei width, GLsizei height, GLint alignment, GLint rowLength) const; + GLuint computeBlockSize(GLenum formatType, GLsizei width, GLsizei height) const; +}; +const InternalFormat &GetInternalFormatInfo(GLenum internalFormat); + +GLenum GetSizedInternalFormat(GLenum internalFormat, GLenum type); + +typedef std::set FormatSet; +const FormatSet &GetAllSizedInternalFormats(); + +} + +#endif // LIBANGLE_FORMATUTILS_H_ diff --git a/src/3rdparty/angle/src/libANGLE/queryconversions.cpp b/src/3rdparty/angle/src/libANGLE/queryconversions.cpp new file mode 100644 index 0000000000..460e346eac --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/queryconversions.cpp @@ -0,0 +1,147 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// queryconversions.cpp: Implementation of state query cast conversions + +#include "libANGLE/Context.h" +#include "common/utilities.h" + +namespace gl +{ + +// Helper class for converting a GL type to a GLenum: +// We can't use CastStateValueEnum generally, because of GLboolean + GLubyte overlap. +// We restrict our use to CastStateValue, where it eliminates duplicate parameters. + +template +struct CastStateValueEnum { static GLenum mEnumForType; }; + +template <> GLenum CastStateValueEnum::mEnumForType = GL_INT; +template <> GLenum CastStateValueEnum::mEnumForType = GL_UNSIGNED_INT; +template <> GLenum CastStateValueEnum::mEnumForType = GL_BOOL; +template <> GLenum CastStateValueEnum::mEnumForType = GL_INT_64_ANGLEX; +template <> GLenum CastStateValueEnum::mEnumForType = GL_FLOAT; + +template +QueryT CastStateValueToInt(GLenum pname, NativeT value) +{ + GLenum queryType = CastStateValueEnum::mEnumForType; + GLenum nativeType = CastStateValueEnum::mEnumForType; + + if (nativeType == GL_FLOAT) + { + // RGBA color values and DepthRangeF values are converted to integer using Equation 2.4 from Table 4.5 + if (pname == GL_DEPTH_RANGE || pname == GL_COLOR_CLEAR_VALUE || pname == GL_DEPTH_CLEAR_VALUE || pname == GL_BLEND_COLOR) + { + return static_cast((static_cast(0xFFFFFFFF) * value - 1.0f) / 2.0f); + } + else + { + return gl::iround(value); + } + } + + // Clamp 64-bit int values when casting to int + if (nativeType == GL_INT_64_ANGLEX && queryType == GL_INT) + { + GLint64 minIntValue = static_cast(std::numeric_limits::min()); + GLint64 maxIntValue = static_cast(std::numeric_limits::max()); + GLint64 clampedValue = std::max(std::min(static_cast(value), maxIntValue), minIntValue); + return static_cast(clampedValue); + } + + return static_cast(value); +} + +template +QueryT CastStateValue(GLenum pname, NativeT value) +{ + GLenum queryType = CastStateValueEnum::mEnumForType; + + switch (queryType) + { + case GL_INT: return CastStateValueToInt(pname, value); + case GL_INT_64_ANGLEX: return CastStateValueToInt(pname, value); + case GL_FLOAT: return static_cast(value); + case GL_BOOL: return (value == static_cast(0) ? GL_FALSE : GL_TRUE); + default: UNREACHABLE(); return 0; + } +} + +template +void CastStateValues(Context *context, GLenum nativeType, GLenum pname, + unsigned int numParams, QueryT *outParams) +{ + if (nativeType == GL_INT) + { + GLint *intParams = NULL; + intParams = new GLint[numParams]; + + context->getIntegerv(pname, intParams); + + for (unsigned int i = 0; i < numParams; ++i) + { + outParams[i] = CastStateValue(pname, intParams[i]); + } + + delete [] intParams; + } + else if (nativeType == GL_BOOL) + { + GLboolean *boolParams = NULL; + boolParams = new GLboolean[numParams]; + + context->getBooleanv(pname, boolParams); + + for (unsigned int i = 0; i < numParams; ++i) + { + outParams[i] = (boolParams[i] == GL_FALSE ? static_cast(0) : static_cast(1)); + } + + delete [] boolParams; + } + else if (nativeType == GL_FLOAT) + { + GLfloat *floatParams = NULL; + floatParams = new GLfloat[numParams]; + + context->getFloatv(pname, floatParams); + + for (unsigned int i = 0; i < numParams; ++i) + { + outParams[i] = CastStateValue(pname, floatParams[i]); + } + + delete [] floatParams; + } + else if (nativeType == GL_INT_64_ANGLEX) + { + GLint64 *int64Params = NULL; + int64Params = new GLint64[numParams]; + + context->getInteger64v(pname, int64Params); + + for (unsigned int i = 0; i < numParams; ++i) + { + outParams[i] = CastStateValue(pname, int64Params[i]); + } + + delete [] int64Params; + } + else UNREACHABLE(); +} + +// Explicit template instantiation (how we export template functions in different files) +// The calls below will make CastStateValues successfully link with the GL state query types +// The GL state query API types are: bool, int, uint, float, int64 + +template void CastStateValues(Context *, GLenum, GLenum, unsigned int, GLboolean *); +template void CastStateValues(Context *, GLenum, GLenum, unsigned int, GLint *); +template void CastStateValues(Context *, GLenum, GLenum, unsigned int, GLuint *); +template void CastStateValues(Context *, GLenum, GLenum, unsigned int, GLfloat *); +template void CastStateValues(Context *, GLenum, GLenum, unsigned int, GLint64 *); + +} diff --git a/src/3rdparty/angle/src/libANGLE/queryconversions.h b/src/3rdparty/angle/src/libANGLE/queryconversions.h new file mode 100644 index 0000000000..da7047f730 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/queryconversions.h @@ -0,0 +1,17 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// queryconversions.h: Declaration of state query cast conversions + +namespace gl +{ + +// The GL state query API types are: bool, int, uint, float, int64 +template +void CastStateValues(Context *context, GLenum nativeType, GLenum pname, + unsigned int numParams, QueryT *outParams); + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/BufferImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/BufferImpl.h new file mode 100644 index 0000000000..9bc5eaff58 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/BufferImpl.h @@ -0,0 +1,38 @@ +// +// Copyright 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// BufferImpl.h: Defines the abstract rx::BufferImpl class. + +#ifndef LIBANGLE_RENDERER_BUFFERIMPL_H_ +#define LIBANGLE_RENDERER_BUFFERIMPL_H_ + +#include "common/angleutils.h" +#include "libANGLE/Buffer.h" + +#include + +namespace rx +{ + +class BufferImpl : angle::NonCopyable +{ + public: + virtual ~BufferImpl() { } + + virtual gl::Error setData(const void* data, size_t size, GLenum usage) = 0; + virtual gl::Error setSubData(const void* data, size_t size, size_t offset) = 0; + virtual gl::Error copySubData(BufferImpl* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size) = 0; + virtual gl::Error map(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr) = 0; + virtual gl::Error unmap() = 0; + + // This method may not have a corresponding GL-backed function. It is necessary + // for validation, for certain indexed draw calls. + virtual gl::Error getData(const uint8_t **outData) = 0; +}; + +} + +#endif // LIBANGLE_RENDERER_BUFFERIMPL_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/CompilerImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/CompilerImpl.h new file mode 100644 index 0000000000..ccc78d8c2a --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/CompilerImpl.h @@ -0,0 +1,30 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// CompilerImpl.h: Defines the rx::CompilerImpl class, an implementation interface +// for the gl::Compiler object. + +#include "common/angleutils.h" +#include "libANGLE/Error.h" + +#ifndef LIBANGLE_RENDERER_COMPILERIMPL_H_ +#define LIBANGLE_RENDERER_COMPILERIMPL_H_ + +namespace rx +{ + +class CompilerImpl : angle::NonCopyable +{ + public: + CompilerImpl() {} + virtual ~CompilerImpl() {} + + virtual gl::Error release() = 0; +}; + +} + +#endif // LIBANGLE_RENDERER_COMPILERIMPL_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/DisplayImpl.cpp b/src/3rdparty/angle/src/libANGLE/renderer/DisplayImpl.cpp new file mode 100644 index 0000000000..7713ee2d6d --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/DisplayImpl.cpp @@ -0,0 +1,58 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// DisplayImpl.cpp: Implementation methods of egl::Display + +#include "libANGLE/renderer/DisplayImpl.h" + +#include "libANGLE/Surface.h" + +namespace rx +{ + +DisplayImpl::DisplayImpl() + : mExtensionsInitialized(false), + mCapsInitialized(false) +{ +} + +DisplayImpl::~DisplayImpl() +{ + while (!mSurfaceSet.empty()) + { + destroySurface(*mSurfaceSet.begin()); + } +} + +void DisplayImpl::destroySurface(egl::Surface *surface) +{ + mSurfaceSet.erase(surface); + surface->release(); +} + +const egl::DisplayExtensions &DisplayImpl::getExtensions() const +{ + if (!mExtensionsInitialized) + { + generateExtensions(&mExtensions); + mExtensionsInitialized = true; + } + + return mExtensions; +} + +const egl::Caps &DisplayImpl::getCaps() const +{ + if (!mCapsInitialized) + { + generateCaps(&mCaps); + mCapsInitialized = true; + } + + return mCaps; +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/DisplayImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/DisplayImpl.h new file mode 100644 index 0000000000..381fa67f71 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/DisplayImpl.h @@ -0,0 +1,99 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// DisplayImpl.h: Implementation methods of egl::Display + +#ifndef LIBANGLE_RENDERER_DISPLAYIMPL_H_ +#define LIBANGLE_RENDERER_DISPLAYIMPL_H_ + +#include "common/angleutils.h" +#include "libANGLE/Caps.h" +#include "libANGLE/Config.h" +#include "libANGLE/Error.h" +#include "libANGLE/renderer/Renderer.h" + +#include +#include + +namespace egl +{ +class AttributeMap; +class Display; +struct Config; +class Surface; +} + +namespace gl +{ +class Context; +} + +namespace rx +{ +class SurfaceImpl; +struct ConfigDesc; + +class DisplayImpl : angle::NonCopyable +{ + public: + DisplayImpl(); + virtual ~DisplayImpl(); + + virtual egl::Error initialize(egl::Display *display) = 0; + virtual void terminate() = 0; + + virtual egl::Error createWindowSurface(const egl::Config *configuration, EGLNativeWindowType window, const egl::AttributeMap &attribs, + SurfaceImpl **outSurface) = 0; + virtual egl::Error createPbufferSurface(const egl::Config *configuration, const egl::AttributeMap &attribs, + SurfaceImpl **outSurface) = 0; + virtual egl::Error createPbufferFromClientBuffer(const egl::Config *configuration, EGLClientBuffer shareHandle, + const egl::AttributeMap &attribs, SurfaceImpl **outSurface) = 0; + virtual egl::Error createPixmapSurface(const egl::Config *configuration, NativePixmapType nativePixmap, + const egl::AttributeMap &attribs, SurfaceImpl **outSurface) = 0; + virtual egl::Error createContext(const egl::Config *config, const gl::Context *shareContext, const egl::AttributeMap &attribs, + gl::Context **outContext) = 0; + + virtual egl::Error makeCurrent(egl::Surface *drawSurface, egl::Surface *readSurface, gl::Context *context) = 0; + + virtual egl::ConfigSet generateConfigs() const = 0; + + virtual bool isDeviceLost() const = 0; + virtual bool testDeviceLost() = 0; + virtual egl::Error restoreLostDevice() = 0; + + virtual bool isValidNativeWindow(EGLNativeWindowType window) const = 0; + + virtual std::string getVendorString() const = 0; + + const egl::Caps &getCaps() const; + + typedef std::set SurfaceSet; + const SurfaceSet &getSurfaceSet() const { return mSurfaceSet; } + SurfaceSet &getSurfaceSet() { return mSurfaceSet; } + + void destroySurface(egl::Surface *surface); + + const egl::DisplayExtensions &getExtensions() const; + + protected: + // Place the surface set here so it can be accessible for handling + // context loss events. (It is shared between the Display and Impl.) + SurfaceSet mSurfaceSet; + + private: + virtual void generateExtensions(egl::DisplayExtensions *outExtensions) const = 0; + virtual void generateCaps(egl::Caps *outCaps) const = 0; + + mutable bool mExtensionsInitialized; + mutable egl::DisplayExtensions mExtensions; + + mutable bool mCapsInitialized; + mutable egl::Caps mCaps; +}; + +} + +#endif // LIBANGLE_RENDERER_DISPLAYIMPL_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/FenceNVImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/FenceNVImpl.h new file mode 100644 index 0000000000..3463921d6e --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/FenceNVImpl.h @@ -0,0 +1,34 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// FenceNVImpl.h: Defines the rx::FenceNVImpl class. + +#ifndef LIBANGLE_RENDERER_FENCENVIMPL_H_ +#define LIBANGLE_RENDERER_FENCENVIMPL_H_ + +#include "libANGLE/Error.h" + +#include "common/angleutils.h" + +#include "angle_gl.h" + +namespace rx +{ + +class FenceNVImpl : angle::NonCopyable +{ + public: + FenceNVImpl() { }; + virtual ~FenceNVImpl() { }; + + virtual gl::Error set() = 0; + virtual gl::Error test(bool flushCommandBuffer, GLboolean *outFinished) = 0; + virtual gl::Error finishFence(GLboolean *outFinished) = 0; +}; + +} + +#endif // LIBANGLE_RENDERER_FENCENVIMPL_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/FenceSyncImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/FenceSyncImpl.h new file mode 100644 index 0000000000..321964113f --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/FenceSyncImpl.h @@ -0,0 +1,35 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// FenceSyncImpl.h: Defines the rx::FenceSyncImpl class. + +#ifndef LIBANGLE_RENDERER_FENCESYNCIMPL_H_ +#define LIBANGLE_RENDERER_FENCESYNCIMPL_H_ + +#include "libANGLE/Error.h" + +#include "common/angleutils.h" + +#include "angle_gl.h" + +namespace rx +{ + +class FenceSyncImpl : angle::NonCopyable +{ + public: + FenceSyncImpl() { }; + virtual ~FenceSyncImpl() { }; + + virtual gl::Error set() = 0; + virtual gl::Error clientWait(GLbitfield flags, GLuint64 timeout, GLenum *outResult) = 0; + virtual gl::Error serverWait(GLbitfield flags, GLuint64 timeout) = 0; + virtual gl::Error getStatus(GLint *outResult) = 0; +}; + +} + +#endif // LIBANGLE_RENDERER_FENCESYNCIMPL_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/FramebufferImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/FramebufferImpl.h new file mode 100644 index 0000000000..728f949a0f --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/FramebufferImpl.h @@ -0,0 +1,68 @@ +// +// Copyright 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// FramebufferImpl.h: Defines the abstract rx::FramebufferImpl class. + +#ifndef LIBANGLE_RENDERER_FRAMEBUFFERIMPL_H_ +#define LIBANGLE_RENDERER_FRAMEBUFFERIMPL_H_ + +#include "angle_gl.h" +#include "common/angleutils.h" +#include "libANGLE/Error.h" +#include "libANGLE/Framebuffer.h" + +namespace gl +{ +class State; +class Framebuffer; +class FramebufferAttachment; +struct Rectangle; +} + +namespace rx +{ + +class FramebufferImpl : angle::NonCopyable +{ + public: + explicit FramebufferImpl(const gl::Framebuffer::Data &data) : mData(data) { } + virtual ~FramebufferImpl() { } + + virtual void setColorAttachment(size_t index, const gl::FramebufferAttachment *attachment) = 0; + virtual void setDepthAttachment(const gl::FramebufferAttachment *attachment) = 0; + virtual void setStencilAttachment(const gl::FramebufferAttachment *attachment) = 0; + virtual void setDepthStencilAttachment(const gl::FramebufferAttachment *attachment) = 0; + + virtual void setDrawBuffers(size_t count, const GLenum *buffers) = 0; + virtual void setReadBuffer(GLenum buffer) = 0; + + virtual gl::Error invalidate(size_t count, const GLenum *attachments) = 0; + virtual gl::Error invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area) = 0; + + virtual gl::Error clear(const gl::Data &data, GLbitfield mask) = 0; + virtual gl::Error clearBufferfv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLfloat *values) = 0; + virtual gl::Error clearBufferuiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLuint *values) = 0; + virtual gl::Error clearBufferiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLint *values) = 0; + virtual gl::Error clearBufferfi(const gl::State &state, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) = 0; + + virtual GLenum getImplementationColorReadFormat() const = 0; + virtual GLenum getImplementationColorReadType() const = 0; + virtual gl::Error readPixels(const gl::State &state, const gl::Rectangle &area, GLenum format, GLenum type, GLvoid *pixels) const = 0; + + virtual gl::Error blit(const gl::State &state, const gl::Rectangle &sourceArea, const gl::Rectangle &destArea, + GLbitfield mask, GLenum filter, const gl::Framebuffer *sourceFramebuffer) = 0; + + virtual GLenum checkStatus() const = 0; + + const gl::Framebuffer::Data &getData() const { return mData; } + + protected: + const gl::Framebuffer::Data &mData; +}; + +} + +#endif // LIBANGLE_RENDERER_FRAMEBUFFERIMPL_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/Image.h b/src/3rdparty/angle/src/libANGLE/renderer/Image.h new file mode 100644 index 0000000000..62d854c9b6 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/Image.h @@ -0,0 +1,77 @@ +// +// 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 LIBANGLE_RENDERER_IMAGE_H_ +#define LIBANGLE_RENDERER_IMAGE_H_ + +#include "common/debug.h" +#include "libANGLE/Error.h" + +#include + +namespace gl +{ +class Framebuffer; +struct Rectangle; +struct Extents; +struct Box; +struct Offset; +struct ImageIndex; +} + +namespace rx +{ +class RendererD3D; +class RenderTarget; +class TextureStorage; + +class Image +{ + public: + Image(); + virtual ~Image() {}; + + GLsizei getWidth() const { return mWidth; } + GLsizei getHeight() const { return mHeight; } + GLsizei getDepth() const { return mDepth; } + GLenum getInternalFormat() const { return mInternalFormat; } + GLenum getTarget() const { return mTarget; } + bool isRenderableFormat() const { return mRenderable; } + + void markDirty() {mDirty = true;} + void markClean() {mDirty = false;} + virtual bool isDirty() const = 0; + + virtual bool redefine(GLenum target, GLenum internalformat, const gl::Extents &size, bool forceRelease) = 0; + + virtual gl::Error loadData(const gl::Box &area, GLint unpackAlignment, GLenum type, const void *input) = 0; + virtual gl::Error loadCompressedData(const gl::Box &area, const void *input) = 0; + + virtual gl::Error copy(const gl::Offset &destOffset, const gl::Rectangle &sourceArea, const gl::Framebuffer *source) = 0; + virtual gl::Error copy(const gl::Offset &destOffset, const gl::Box &sourceArea, + const gl::ImageIndex &sourceIndex, TextureStorage *source) = 0; + + protected: + GLsizei mWidth; + GLsizei mHeight; + GLsizei mDepth; + GLenum mInternalFormat; + bool mRenderable; + GLenum mTarget; + + bool mDirty; + + private: + DISALLOW_COPY_AND_ASSIGN(Image); +}; + +} + +#endif // LIBANGLE_RENDERER_IMAGE_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/ImplFactory.h b/src/3rdparty/angle/src/libANGLE/renderer/ImplFactory.h new file mode 100644 index 0000000000..d77e59f7df --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/ImplFactory.h @@ -0,0 +1,68 @@ +// +// Copyright 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// ImplFactory.h: +// Factory interface for Impl objects. +// + +#ifndef LIBANGLE_RENDERER_IMPLFACTORY_H_ +#define LIBANGLE_RENDERER_IMPLFACTORY_H_ + +#include "libANGLE/Framebuffer.h" + +namespace rx +{ +class BufferImpl; +class CompilerImpl; +class FenceNVImpl; +class FenceSyncImpl; +class FramebufferImpl; +class ProgramImpl; +class QueryImpl; +class RenderbufferImpl; +class ShaderImpl; +class TextureImpl; +class TransformFeedbackImpl; +class VertexArrayImpl; + +class ImplFactory : angle::NonCopyable +{ + public: + ImplFactory() {} + virtual ~ImplFactory() {} + + // Shader creation + virtual CompilerImpl *createCompiler(const gl::Data &data) = 0; + virtual ShaderImpl *createShader(GLenum type) = 0; + virtual ProgramImpl *createProgram() = 0; + + // Framebuffer creation + virtual FramebufferImpl *createDefaultFramebuffer(const gl::Framebuffer::Data &data) = 0; + virtual FramebufferImpl *createFramebuffer(const gl::Framebuffer::Data &data) = 0; + + // Texture creation + virtual TextureImpl *createTexture(GLenum target) = 0; + + // Renderbuffer creation + virtual RenderbufferImpl *createRenderbuffer() = 0; + + // Buffer creation + virtual BufferImpl *createBuffer() = 0; + + // Vertex Array creation + virtual VertexArrayImpl *createVertexArray() = 0; + + // Query and Fence creation + virtual QueryImpl *createQuery(GLenum type) = 0; + virtual FenceNVImpl *createFenceNV() = 0; + virtual FenceSyncImpl *createFenceSync() = 0; + + // Transform Feedback creation + virtual TransformFeedbackImpl *createTransformFeedback() = 0; +}; + +} + +#endif // LIBANGLE_RENDERER_IMPLFACTORY_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/IndexRangeCache.cpp b/src/3rdparty/angle/src/libANGLE/renderer/IndexRangeCache.cpp new file mode 100644 index 0000000000..4a71cf4b45 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/IndexRangeCache.cpp @@ -0,0 +1,114 @@ +// +// 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. +// + +// IndexRangeCache.cpp: Defines the rx::IndexRangeCache class which stores information about +// ranges of indices. + +#include "libANGLE/renderer/IndexRangeCache.h" +#include "libANGLE/formatutils.h" + +#include "common/debug.h" + +namespace rx +{ + +template +static RangeUI ComputeTypedRange(const IndexType *indices, GLsizei count) +{ + unsigned int minIndex = indices[0]; + unsigned int maxIndex = indices[0]; + + for (GLsizei i = 1; i < count; i++) + { + if (minIndex > indices[i]) minIndex = indices[i]; + if (maxIndex < indices[i]) maxIndex = indices[i]; + } + + return RangeUI(minIndex, maxIndex); +} + +RangeUI IndexRangeCache::ComputeRange(GLenum type, const GLvoid *indices, GLsizei count) +{ + switch (type) + { + case GL_UNSIGNED_BYTE: + return ComputeTypedRange(static_cast(indices), count); + case GL_UNSIGNED_INT: + return ComputeTypedRange(static_cast(indices), count); + case GL_UNSIGNED_SHORT: + return ComputeTypedRange(static_cast(indices), count); + default: + UNREACHABLE(); + return RangeUI(); + } +} + +void IndexRangeCache::addRange(GLenum type, unsigned int offset, GLsizei count, const RangeUI &range) +{ + mIndexRangeCache[IndexRange(type, offset, count)] = range; +} + +void IndexRangeCache::invalidateRange(unsigned int offset, unsigned int size) +{ + unsigned int invalidateStart = offset; + unsigned int invalidateEnd = offset + size; + + IndexRangeMap::iterator i = mIndexRangeCache.begin(); + while (i != mIndexRangeCache.end()) + { + unsigned int rangeStart = i->first.offset; + unsigned int rangeEnd = i->first.offset + (gl::GetTypeInfo(i->first.type).bytes * i->first.count); + + if (invalidateEnd < rangeStart || invalidateStart > rangeEnd) + { + ++i; + } + else + { + mIndexRangeCache.erase(i++); + } + } +} + +bool IndexRangeCache::findRange(GLenum type, unsigned int offset, GLsizei count, + RangeUI *outRange) const +{ + IndexRangeMap::const_iterator i = mIndexRangeCache.find(IndexRange(type, offset, count)); + if (i != mIndexRangeCache.end()) + { + if (outRange) *outRange = i->second; + return true; + } + else + { + if (outRange) *outRange = RangeUI(0, 0); + return false; + } +} + +void IndexRangeCache::clear() +{ + mIndexRangeCache.clear(); +} + +IndexRangeCache::IndexRange::IndexRange() + : type(GL_NONE), offset(0), count(0) +{ +} + +IndexRangeCache::IndexRange::IndexRange(GLenum typ, intptr_t off, GLsizei c) + : type(typ), offset(off), count(c) +{ +} + +bool IndexRangeCache::IndexRange::operator<(const IndexRange& rhs) const +{ + if (type != rhs.type) return type < rhs.type; + if (offset != rhs.offset) return offset < rhs.offset; + return count < rhs.count; +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/IndexRangeCache.h b/src/3rdparty/angle/src/libANGLE/renderer/IndexRangeCache.h new file mode 100644 index 0000000000..77249f5ff6 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/IndexRangeCache.h @@ -0,0 +1,53 @@ +// +// 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. +// + +// IndexRangeCache.h: Defines the rx::IndexRangeCache class which stores information about +// ranges of indices. + +#ifndef LIBANGLE_RENDERER_INDEXRANGECACHE_H_ +#define LIBANGLE_RENDERER_INDEXRANGECACHE_H_ + +#include "common/angleutils.h" +#include "common/mathutil.h" + +#include "angle_gl.h" + +#include + +namespace rx +{ + +class IndexRangeCache +{ + public: + void addRange(GLenum type, unsigned int offset, GLsizei count, const RangeUI &range); + bool findRange(GLenum type, unsigned int offset, GLsizei count, RangeUI *rangeOut) const; + + void invalidateRange(unsigned int offset, unsigned int size); + void clear(); + + static RangeUI ComputeRange(GLenum type, const GLvoid *indices, GLsizei count); + + private: + struct IndexRange + { + GLenum type; + unsigned int offset; + GLsizei count; + + IndexRange(); + IndexRange(GLenum type, intptr_t offset, GLsizei count); + + bool operator<(const IndexRange& rhs) const; + }; + + typedef std::map IndexRangeMap; + IndexRangeMap mIndexRangeCache; +}; + +} + +#endif // LIBANGLE_RENDERER_INDEXRANGECACHE_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/ProgramImpl.cpp b/src/3rdparty/angle/src/libANGLE/renderer/ProgramImpl.cpp new file mode 100644 index 0000000000..8fbc53768f --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/ProgramImpl.cpp @@ -0,0 +1,152 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// ProgramD3D.cpp: Defines the rx::ProgramD3D class which implements rx::ProgramImpl. + +#include "libANGLE/renderer/ProgramImpl.h" + +#include "common/utilities.h" + +namespace rx +{ + +namespace +{ + +unsigned int ParseAndStripArrayIndex(std::string* name) +{ + unsigned int subscript = GL_INVALID_INDEX; + + // Strip any trailing array operator and retrieve the subscript + size_t open = name->find_last_of('['); + size_t close = name->find_last_of(']'); + if (open != std::string::npos && close == name->length() - 1) + { + subscript = atoi(name->substr(open + 1).c_str()); + name->erase(open); + } + + return subscript; +} + +} + +LinkResult::LinkResult(bool linkSuccess, const gl::Error &error) + : linkSuccess(linkSuccess), + error(error) +{ +} + +ProgramImpl::~ProgramImpl() +{ + // Ensure that reset was called by the inherited class during destruction + ASSERT(mUniformIndex.size() == 0); +} + +gl::LinkedUniform *ProgramImpl::getUniformByLocation(GLint location) const +{ + ASSERT(location >= 0 && static_cast(location) < mUniformIndex.size()); + return mUniforms[mUniformIndex[location].index]; +} + +gl::LinkedUniform *ProgramImpl::getUniformByName(const std::string &name) const +{ + for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++) + { + if (mUniforms[uniformIndex]->name == name) + { + return mUniforms[uniformIndex]; + } + } + + return NULL; +} + +gl::UniformBlock *ProgramImpl::getUniformBlockByIndex(GLuint blockIndex) const +{ + ASSERT(blockIndex < mUniformBlocks.size()); + return mUniformBlocks[blockIndex]; +} + +GLint ProgramImpl::getUniformLocation(std::string name) +{ + unsigned int subscript = ParseAndStripArrayIndex(&name); + + unsigned int numUniforms = mUniformIndex.size(); + for (unsigned int location = 0; location < numUniforms; location++) + { + if (mUniformIndex[location].name == name) + { + const int index = mUniformIndex[location].index; + const bool isArray = mUniforms[index]->isArray(); + + if ((isArray && mUniformIndex[location].element == subscript) || + (subscript == GL_INVALID_INDEX)) + { + return location; + } + } + } + + return -1; +} + +GLuint ProgramImpl::getUniformIndex(std::string name) +{ + unsigned int subscript = ParseAndStripArrayIndex(&name); + + // The app is not allowed to specify array indices other than 0 for arrays of basic types + if (subscript != 0 && subscript != GL_INVALID_INDEX) + { + return GL_INVALID_INDEX; + } + + unsigned int numUniforms = mUniforms.size(); + for (unsigned int index = 0; index < numUniforms; index++) + { + if (mUniforms[index]->name == name) + { + if (mUniforms[index]->isArray() || subscript == GL_INVALID_INDEX) + { + return index; + } + } + } + + return GL_INVALID_INDEX; +} + +GLuint ProgramImpl::getUniformBlockIndex(std::string name) const +{ + unsigned int subscript = ParseAndStripArrayIndex(&name); + + unsigned int numUniformBlocks = mUniformBlocks.size(); + for (unsigned int blockIndex = 0; blockIndex < numUniformBlocks; blockIndex++) + { + const gl::UniformBlock &uniformBlock = *mUniformBlocks[blockIndex]; + if (uniformBlock.name == name) + { + const bool arrayElementZero = (subscript == GL_INVALID_INDEX && uniformBlock.elementIndex == 0); + if (subscript == uniformBlock.elementIndex || arrayElementZero) + { + return blockIndex; + } + } + } + + return GL_INVALID_INDEX; +} + +void ProgramImpl::reset() +{ + std::fill(mSemanticIndex, mSemanticIndex + ArraySize(mSemanticIndex), -1); + SafeDeleteContainer(mUniforms); + mUniformIndex.clear(); + SafeDeleteContainer(mUniformBlocks); + mTransformFeedbackLinkedVaryings.clear(); +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/ProgramImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/ProgramImpl.h new file mode 100644 index 0000000000..1128ab6741 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/ProgramImpl.h @@ -0,0 +1,137 @@ +// +// Copyright 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// ProgramImpl.h: Defines the abstract rx::ProgramImpl class. + +#ifndef LIBANGLE_RENDERER_PROGRAMIMPL_H_ +#define LIBANGLE_RENDERER_PROGRAMIMPL_H_ + +#include "common/angleutils.h" +#include "libANGLE/BinaryStream.h" +#include "libANGLE/Constants.h" +#include "libANGLE/Program.h" +#include "libANGLE/Shader.h" +#include "libANGLE/renderer/Renderer.h" + +#include + +namespace rx +{ + +struct LinkResult +{ + bool linkSuccess; + gl::Error error; + LinkResult(bool linkSuccess, const gl::Error &error); +}; + +class ProgramImpl : angle::NonCopyable +{ + public: + typedef int SemanticIndexArray[gl::MAX_VERTEX_ATTRIBS]; + + ProgramImpl() { } + virtual ~ProgramImpl(); + + virtual bool usesPointSize() const = 0; + virtual int getShaderVersion() const = 0; + virtual GLenum getTransformFeedbackBufferMode() const = 0; + + virtual GLenum getBinaryFormat() = 0; + virtual LinkResult load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) = 0; + virtual gl::Error save(gl::BinaryOutputStream *stream) = 0; + + virtual LinkResult link(const gl::Data &data, gl::InfoLog &infoLog, + gl::Shader *fragmentShader, gl::Shader *vertexShader, + const std::vector &transformFeedbackVaryings, + GLenum transformFeedbackBufferMode, + int *registers, std::vector *linkedVaryings, + std::map *outputVariables) = 0; + + virtual void setUniform1fv(GLint location, GLsizei count, const GLfloat *v) = 0; + virtual void setUniform2fv(GLint location, GLsizei count, const GLfloat *v) = 0; + virtual void setUniform3fv(GLint location, GLsizei count, const GLfloat *v) = 0; + virtual void setUniform4fv(GLint location, GLsizei count, const GLfloat *v) = 0; + virtual void setUniform1iv(GLint location, GLsizei count, const GLint *v) = 0; + virtual void setUniform2iv(GLint location, GLsizei count, const GLint *v) = 0; + virtual void setUniform3iv(GLint location, GLsizei count, const GLint *v) = 0; + virtual void setUniform4iv(GLint location, GLsizei count, const GLint *v) = 0; + virtual void setUniform1uiv(GLint location, GLsizei count, const GLuint *v) = 0; + virtual void setUniform2uiv(GLint location, GLsizei count, const GLuint *v) = 0; + virtual void setUniform3uiv(GLint location, GLsizei count, const GLuint *v) = 0; + virtual void setUniform4uiv(GLint location, GLsizei count, const GLuint *v) = 0; + virtual void setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) = 0; + virtual void setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) = 0; + virtual void setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) = 0; + virtual void setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) = 0; + virtual void setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) = 0; + virtual void setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) = 0; + virtual void setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) = 0; + virtual void setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) = 0; + virtual void setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) = 0; + + virtual void getUniformfv(GLint location, GLfloat *params) = 0; + virtual void getUniformiv(GLint location, GLint *params) = 0; + virtual void getUniformuiv(GLint location, GLuint *params) = 0; + + // TODO: The following functions are possibly only applicable to D3D backends. The should be carefully evaluated to + // determine if they can be removed from this interface. + virtual GLint getSamplerMapping(gl::SamplerType type, unsigned int samplerIndex, const gl::Caps &caps) const = 0; + virtual GLenum getSamplerTextureType(gl::SamplerType type, unsigned int samplerIndex) const = 0; + virtual GLint getUsedSamplerRange(gl::SamplerType type) const = 0; + virtual void updateSamplerMapping() = 0; + virtual bool validateSamplers(gl::InfoLog *infoLog, const gl::Caps &caps) = 0; + + virtual LinkResult compileProgramExecutables(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader, + int registers) = 0; + + virtual bool linkUniforms(gl::InfoLog &infoLog, const gl::Shader &vertexShader, const gl::Shader &fragmentShader, + const gl::Caps &caps) = 0; + virtual bool defineUniformBlock(gl::InfoLog &infoLog, const gl::Shader &shader, const sh::InterfaceBlock &interfaceBlock, + const gl::Caps &caps) = 0; + + virtual gl::Error applyUniforms() = 0; + virtual gl::Error applyUniformBuffers(const gl::Data &data, GLuint uniformBlockBindings[]) = 0; + virtual bool assignUniformBlockRegister(gl::InfoLog &infoLog, gl::UniformBlock *uniformBlock, GLenum shader, + unsigned int registerIndex, const gl::Caps &caps) = 0; + + const std::vector &getUniforms() const { return mUniforms; } + const std::vector &getUniformIndices() const { return mUniformIndex; } + const std::vector &getUniformBlocks() const { return mUniformBlocks; } + const std::vector &getTransformFeedbackLinkedVaryings() const { return mTransformFeedbackLinkedVaryings; } + const sh::Attribute *getShaderAttributes() const { return mShaderAttributes; } + const SemanticIndexArray &getSemanticIndexes() const { return mSemanticIndex; } + + std::vector &getUniforms() { return mUniforms; } + std::vector &getUniformIndices() { return mUniformIndex; } + std::vector &getUniformBlocks() { return mUniformBlocks; } + std::vector &getTransformFeedbackLinkedVaryings() { return mTransformFeedbackLinkedVaryings; } + sh::Attribute *getShaderAttributes() { return mShaderAttributes; } + SemanticIndexArray &getSemanticIndexes() { return mSemanticIndex; } + + gl::LinkedUniform *getUniformByLocation(GLint location) const; + gl::LinkedUniform *getUniformByName(const std::string &name) const; + gl::UniformBlock *getUniformBlockByIndex(GLuint blockIndex) const; + + GLint getUniformLocation(std::string name); + GLuint getUniformIndex(std::string name); + GLuint getUniformBlockIndex(std::string name) const; + + virtual void reset(); + + protected: + std::vector mUniforms; + std::vector mUniformIndex; + std::vector mUniformBlocks; + std::vector mTransformFeedbackLinkedVaryings; + + SemanticIndexArray mSemanticIndex; + sh::Attribute mShaderAttributes[gl::MAX_VERTEX_ATTRIBS]; +}; + +} + +#endif // LIBANGLE_RENDERER_PROGRAMIMPL_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/QueryImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/QueryImpl.h new file mode 100644 index 0000000000..bed63ea1b0 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/QueryImpl.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. +// + +// QueryImpl.h: Defines the abstract rx::QueryImpl class. + +#ifndef LIBANGLE_RENDERER_QUERYIMPL_H_ +#define LIBANGLE_RENDERER_QUERYIMPL_H_ + +#include "libANGLE/Error.h" + +#include "common/angleutils.h" + +#include + +namespace rx +{ + +class QueryImpl : angle::NonCopyable +{ + public: + explicit QueryImpl(GLenum type) { mType = type; } + virtual ~QueryImpl() { } + + virtual gl::Error begin() = 0; + virtual gl::Error end() = 0; + virtual gl::Error getResult(GLuint *params) = 0; + virtual gl::Error isResultAvailable(GLuint *available) = 0; + + GLenum getType() const { return mType; } + + private: + GLenum mType; +}; + +} + +#endif // LIBANGLE_RENDERER_QUERYIMPL_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/RenderbufferImpl.cpp b/src/3rdparty/angle/src/libANGLE/renderer/RenderbufferImpl.cpp new file mode 100644 index 0000000000..ea5a40a21a --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/RenderbufferImpl.cpp @@ -0,0 +1,21 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// RenderbufferImpl.h: Implements the shared methods of the abstract class gl::RenderbufferImpl + +#include "libANGLE/renderer/RenderbufferImpl.h" + +namespace rx +{ +RenderbufferImpl::RenderbufferImpl() +{ +} + +RenderbufferImpl::~RenderbufferImpl() +{ +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/RenderbufferImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/RenderbufferImpl.h new file mode 100644 index 0000000000..8ce257c833 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/RenderbufferImpl.h @@ -0,0 +1,33 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// RenderbufferImpl.h: Defines the abstract class gl::RenderbufferImpl + +#ifndef LIBANGLE_RENDERER_RENDERBUFFERIMPL_H_ +#define LIBANGLE_RENDERER_RENDERBUFFERIMPL_H_ + +#include "angle_gl.h" + +#include "libANGLE/Error.h" + +#include "common/angleutils.h" + +namespace rx +{ + +class RenderbufferImpl : angle::NonCopyable +{ + public: + RenderbufferImpl(); + virtual ~RenderbufferImpl() = 0; + + virtual gl::Error setStorage(GLenum internalformat, size_t width, size_t height) = 0; + virtual gl::Error setStorageMultisample(size_t samples, GLenum internalformat, size_t width, size_t height) = 0; +}; + +} + +#endif // LIBANGLE_RENDERER_RENDERBUFFERIMPL_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/Renderer.cpp b/src/3rdparty/angle/src/libANGLE/renderer/Renderer.cpp new file mode 100644 index 0000000000..fbc2ad5d1c --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/Renderer.cpp @@ -0,0 +1,72 @@ +// +// Copyright (c) 2012-2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Renderer.cpp: Implements EGL dependencies for creating and destroying Renderer instances. + +#include "common/utilities.h" +#include "libANGLE/AttributeMap.h" +#include "libANGLE/renderer/Renderer.h" + +#include + +namespace rx +{ + +Renderer::Renderer() + : mCapsInitialized(false), + mWorkaroundsInitialized(false) +{ +} + +Renderer::~Renderer() +{ +} + +const gl::Caps &Renderer::getRendererCaps() const +{ + if (!mCapsInitialized) + { + generateCaps(&mCaps, &mTextureCaps, &mExtensions); + mCapsInitialized = true; + } + + return mCaps; +} + +const gl::TextureCapsMap &Renderer::getRendererTextureCaps() const +{ + if (!mCapsInitialized) + { + generateCaps(&mCaps, &mTextureCaps, &mExtensions); + mCapsInitialized = true; + } + + return mTextureCaps; +} + +const gl::Extensions &Renderer::getRendererExtensions() const +{ + if (!mCapsInitialized) + { + generateCaps(&mCaps, &mTextureCaps, &mExtensions); + mCapsInitialized = true; + } + + return mExtensions; +} + +const Workarounds &Renderer::getWorkarounds() const +{ + if (!mWorkaroundsInitialized) + { + mWorkarounds = generateWorkarounds(); + mWorkaroundsInitialized = true; + } + + return mWorkarounds; +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/Renderer.h b/src/3rdparty/angle/src/libANGLE/renderer/Renderer.h new file mode 100644 index 0000000000..b607fe5613 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/Renderer.h @@ -0,0 +1,91 @@ +// +// Copyright (c) 2012-2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Renderer.h: Defines a back-end specific class that hides the details of the +// implementation-specific renderer. + +#ifndef LIBANGLE_RENDERER_RENDERER_H_ +#define LIBANGLE_RENDERER_RENDERER_H_ + +#include "libANGLE/Caps.h" +#include "libANGLE/Error.h" +#include "libANGLE/Framebuffer.h" +#include "libANGLE/Uniform.h" +#include "libANGLE/angletypes.h" +#include "libANGLE/renderer/ImplFactory.h" +#include "libANGLE/renderer/Workarounds.h" +#include "common/mathutil.h" + +#include + +#include + +namespace egl +{ +class AttributeMap; +class Display; +class Surface; +} + +namespace gl +{ +class Buffer; +struct Data; +} + +namespace rx +{ +struct TranslatedIndexData; +struct Workarounds; +class DisplayImpl; + +class Renderer : public ImplFactory +{ + public: + Renderer(); + virtual ~Renderer(); + + virtual gl::Error flush() = 0; + virtual gl::Error finish() = 0; + + virtual gl::Error drawArrays(const gl::Data &data, GLenum mode, + GLint first, GLsizei count, GLsizei instances) = 0; + virtual gl::Error drawElements(const gl::Data &data, GLenum mode, GLsizei count, GLenum type, + const GLvoid *indices, GLsizei instances, + const RangeUI &indexRange) = 0; + + // lost device + //TODO(jmadill): investigate if this stuff is necessary in GL + virtual void notifyDeviceLost() = 0; + virtual bool isDeviceLost() const = 0; + virtual bool testDeviceLost() = 0; + virtual bool testDeviceResettable() = 0; + + virtual VendorID getVendorId() const = 0; + virtual std::string getVendorString() const = 0; + virtual std::string getRendererDescription() const = 0; + + // Renderer capabilities + const gl::Caps &getRendererCaps() const; + const gl::TextureCapsMap &getRendererTextureCaps() const; + const gl::Extensions &getRendererExtensions() const; + const Workarounds &getWorkarounds() const; + + private: + virtual void generateCaps(gl::Caps *outCaps, gl::TextureCapsMap* outTextureCaps, gl::Extensions *outExtensions) const = 0; + virtual Workarounds generateWorkarounds() const = 0; + + mutable bool mCapsInitialized; + mutable gl::Caps mCaps; + mutable gl::TextureCapsMap mTextureCaps; + mutable gl::Extensions mExtensions; + + mutable bool mWorkaroundsInitialized; + mutable Workarounds mWorkarounds; +}; + +} +#endif // LIBANGLE_RENDERER_RENDERER_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/ShaderImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/ShaderImpl.h new file mode 100644 index 0000000000..3011bc57f8 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/ShaderImpl.h @@ -0,0 +1,57 @@ +// +// Copyright 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// ShaderImpl.h: Defines the abstract rx::ShaderImpl class. + +#ifndef LIBANGLE_RENDERER_SHADERIMPL_H_ +#define LIBANGLE_RENDERER_SHADERIMPL_H_ + +#include + +#include "common/angleutils.h" +#include "libANGLE/Shader.h" + +namespace rx +{ + +class ShaderImpl : angle::NonCopyable +{ + public: + ShaderImpl() { } + virtual ~ShaderImpl() { } + + virtual bool compile(gl::Compiler *compiler, const std::string &source) = 0; + virtual std::string getDebugInfo() const = 0; + + virtual const std::string &getInfoLog() const { return mInfoLog; } + virtual const std::string &getTranslatedSource() const { return mTranslatedSource; } + + const std::vector &getVaryings() const { return mVaryings; } + const std::vector &getUniforms() const { return mUniforms; } + const std::vector &getInterfaceBlocks() const { return mInterfaceBlocks; } + const std::vector &getActiveAttributes() const { return mActiveAttributes; } + const std::vector &getActiveOutputVariables() const { return mActiveOutputVariables; } + + std::vector &getVaryings() { return mVaryings; } + std::vector &getUniforms() { return mUniforms; } + std::vector &getInterfaceBlocks() { return mInterfaceBlocks; } + std::vector &getActiveAttributes() { return mActiveAttributes; } + std::vector &getActiveOutputVariables() { return mActiveOutputVariables; } + + protected: + std::string mInfoLog; + std::string mTranslatedSource; + + std::vector mVaryings; + std::vector mUniforms; + std::vector mInterfaceBlocks; + std::vector mActiveAttributes; + std::vector mActiveOutputVariables; +}; + +} + +#endif // LIBANGLE_RENDERER_SHADERIMPL_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/SurfaceImpl.cpp b/src/3rdparty/angle/src/libANGLE/renderer/SurfaceImpl.cpp new file mode 100644 index 0000000000..36f5fdca3f --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/SurfaceImpl.cpp @@ -0,0 +1,22 @@ +// +// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// SurfaceImpl.cpp: Implementation of Surface stub method class + +#include "libANGLE/renderer/SurfaceImpl.h" + +namespace rx +{ + +SurfaceImpl::SurfaceImpl() +{ +} + +SurfaceImpl::~SurfaceImpl() +{ +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/SurfaceImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/SurfaceImpl.h new file mode 100644 index 0000000000..ca04a42bd1 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/SurfaceImpl.h @@ -0,0 +1,48 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// SurfaceImpl.h: Implementation methods of egl::Surface + +#ifndef LIBANGLE_RENDERER_SURFACEIMPL_H_ +#define LIBANGLE_RENDERER_SURFACEIMPL_H_ + +#include "common/angleutils.h" +#include "libANGLE/Error.h" + +namespace egl +{ +class Display; +struct Config; +} + +namespace rx +{ + +class SurfaceImpl : angle::NonCopyable +{ + public: + SurfaceImpl(); + virtual ~SurfaceImpl(); + + virtual egl::Error initialize() = 0; + virtual egl::Error swap() = 0; + virtual egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) = 0; + virtual egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) = 0; + virtual egl::Error bindTexImage(EGLint buffer) = 0; + virtual egl::Error releaseTexImage(EGLint buffer) = 0; + virtual void setSwapInterval(EGLint interval) = 0; + + // width and height can change with client window resizing + virtual EGLint getWidth() const = 0; + virtual EGLint getHeight() const = 0; + + virtual EGLint isPostSubBufferSupported() const = 0; +}; + +} + +#endif // LIBANGLE_RENDERER_SURFACEIMPL_H_ + diff --git a/src/3rdparty/angle/src/libANGLE/renderer/TextureImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/TextureImpl.h new file mode 100644 index 0000000000..d628906116 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/TextureImpl.h @@ -0,0 +1,72 @@ +// +// Copyright 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// TextureImpl.h: Defines the abstract rx::TextureImpl classes. + +#ifndef LIBANGLE_RENDERER_TEXTUREIMPL_H_ +#define LIBANGLE_RENDERER_TEXTUREIMPL_H_ + +#include "libANGLE/Error.h" +#include "libANGLE/ImageIndex.h" + +#include "common/angleutils.h" + +#include "angle_gl.h" + +#include + +namespace egl +{ +class Surface; +} + +namespace gl +{ +struct Box; +struct Extents; +struct Offset; +struct Rectangle; +class Framebuffer; +struct PixelUnpackState; +struct SamplerState; +} + +namespace rx +{ + +class TextureImpl : angle::NonCopyable +{ + public: + virtual ~TextureImpl() {}; + + virtual void setUsage(GLenum usage) = 0; + + virtual gl::Error setImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, GLenum format, GLenum type, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) = 0; + virtual gl::Error setSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, GLenum type, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) = 0; + + virtual gl::Error setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) = 0; + virtual gl::Error setCompressedSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) = 0; + + virtual gl::Error copyImage(GLenum target, size_t level, const gl::Rectangle &sourceArea, GLenum internalFormat, + const gl::Framebuffer *source) = 0; + virtual gl::Error copySubImage(GLenum target, size_t level, const gl::Offset &destOffset, const gl::Rectangle &sourceArea, + const gl::Framebuffer *source) = 0; + + virtual gl::Error setStorage(GLenum target, size_t levels, GLenum internalFormat, const gl::Extents &size) = 0; + + virtual gl::Error generateMipmaps() = 0; + + virtual void bindTexImage(egl::Surface *surface) = 0; + virtual void releaseTexImage() = 0; +}; + +} + +#endif // LIBANGLE_RENDERER_TEXTUREIMPL_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/TransformFeedbackImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/TransformFeedbackImpl.h new file mode 100644 index 0000000000..8f9133cfe5 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/TransformFeedbackImpl.h @@ -0,0 +1,31 @@ +// +// Copyright 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// TransformFeedbackImpl.h: Defines the abstract rx::TransformFeedbackImpl class. + +#ifndef LIBANGLE_RENDERER_TRANSFORMFEEDBACKIMPL_H_ +#define LIBANGLE_RENDERER_TRANSFORMFEEDBACKIMPL_H_ + +#include "common/angleutils.h" +#include "libANGLE/TransformFeedback.h" + +namespace rx +{ + +class TransformFeedbackImpl : angle::NonCopyable +{ + public: + virtual ~TransformFeedbackImpl() { } + + virtual void begin(GLenum primitiveMode) = 0; + virtual void end() = 0; + virtual void pause() = 0; + virtual void resume() = 0; +}; + +} + +#endif // LIBANGLE_RENDERER_TRANSFORMFEEDBACKIMPL_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/VertexArrayImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/VertexArrayImpl.h new file mode 100644 index 0000000000..0e25f952c2 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/VertexArrayImpl.h @@ -0,0 +1,32 @@ +// +// Copyright 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// VertexAttribImpl.h: Defines the abstract rx::VertexAttribImpl class. + +#ifndef LIBANGLE_RENDERER_VERTEXARRAYIMPL_H_ +#define LIBANGLE_RENDERER_VERTEXARRAYIMPL_H_ + +#include "common/angleutils.h" +#include "libANGLE/Buffer.h" +#include "libANGLE/VertexAttribute.h" + +namespace rx +{ + +class VertexArrayImpl : angle::NonCopyable +{ + public: + virtual ~VertexArrayImpl() { } + + virtual void setElementArrayBuffer(const gl::Buffer *buffer) = 0; + virtual void setAttribute(size_t idx, const gl::VertexAttribute &attr) = 0; + virtual void setAttributeDivisor(size_t idx, GLuint divisor) = 0; + virtual void enableAttribute(size_t idx, bool enabledState) = 0; +}; + +} + +#endif // LIBANGLE_RENDERER_VERTEXARRAYIMPL_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/Workarounds.h b/src/3rdparty/angle/src/libANGLE/renderer/Workarounds.h new file mode 100644 index 0000000000..b73f4a5472 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/Workarounds.h @@ -0,0 +1,74 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// angletypes.h: Workarounds for driver bugs and other issues. + +#ifndef LIBANGLE_RENDERER_WORKAROUNDS_H_ +#define LIBANGLE_RENDERER_WORKAROUNDS_H_ + +// TODO(jmadill,zmo,geofflang): make a workarounds library that can operate +// independent of ANGLE's renderer. Workarounds should also be accessible +// outside of the Renderer. + +namespace rx +{ + +struct D3DCompilerWorkarounds : angle::NonCopyable +{ + D3DCompilerWorkarounds() + : skipOptimization(false), + useMaxOptimization(false), + enableIEEEStrictness(false) + {} + + void reset() + { + skipOptimization = false; + useMaxOptimization = false; + enableIEEEStrictness = false; + } + + bool skipOptimization; + bool useMaxOptimization; + + // IEEE strictness needs to be enabled for NANs to work. + bool enableIEEEStrictness; +}; + +struct Workarounds +{ + Workarounds() + : mrtPerfWorkaround(false), + setDataFasterThanImageUpload(false), + zeroMaxLodWorkaround(false), + useInstancedPointSpriteEmulation(false) + {} + + // On some systems, having extra rendertargets than necessary slows down the shader. + // We can fix this by optimizing those out of the shader. At the same time, we can + // work around a bug on some nVidia drivers that they ignore "null" render targets + // in D3D11, by compacting the active color attachments list to omit null entries. + bool mrtPerfWorkaround; + + bool setDataFasterThanImageUpload; + + // Some renderers can't disable mipmaps on a mipmapped texture (i.e. solely sample from level zero, and ignore the other levels). + // D3D11 Feature Level 10+ does this by setting MaxLOD to 0.0f in the Sampler state. D3D9 sets D3DSAMP_MIPFILTER to D3DTEXF_NONE. + // There is no equivalent to this in D3D11 Feature Level 9_3. + // This causes problems when (for example) an application creates a mipmapped texture2D, but sets GL_TEXTURE_MIN_FILTER to GL_NEAREST (i.e disables mipmaps). + // To work around this, D3D11 FL9_3 has to create two copies of the texture. The textures' level zeros are identical, but only one texture has mips. + bool zeroMaxLodWorkaround; + + // Some renderers do not support Geometry Shaders so the Geometry Shader-based + // PointSprite emulation will not work. + // To work around this, D3D11 FL9_3 has to use a different pointsprite + // emulation that is implemented using instanced quads. + bool useInstancedPointSpriteEmulation; +}; + +} + +#endif // LIBANGLE_RENDERER_WORKAROUNDS_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/BufferD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/BufferD3D.cpp new file mode 100644 index 0000000000..1af8794356 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/BufferD3D.cpp @@ -0,0 +1,80 @@ +// +// Copyright 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// BufferD3D.cpp Defines common functionality between the Buffer9 and Buffer11 classes. + +#include "libANGLE/renderer/d3d/BufferD3D.h" + +#include "libANGLE/renderer/d3d/IndexBuffer.h" +#include "libANGLE/renderer/d3d/VertexBuffer.h" + +namespace rx +{ + +unsigned int BufferD3D::mNextSerial = 1; + +BufferD3D::BufferD3D(BufferFactoryD3D *factory) + : BufferImpl(), + mFactory(factory), + mStaticVertexBuffer(nullptr), + mStaticIndexBuffer(nullptr), + mUnmodifiedDataUse(0) +{ + updateSerial(); +} + +BufferD3D::~BufferD3D() +{ + SafeDelete(mStaticVertexBuffer); + SafeDelete(mStaticIndexBuffer); +} + +void BufferD3D::updateSerial() +{ + mSerial = mNextSerial++; +} + +void BufferD3D::initializeStaticData() +{ + if (!mStaticVertexBuffer) + { + mStaticVertexBuffer = new StaticVertexBufferInterface(mFactory); + } + if (!mStaticIndexBuffer) + { + mStaticIndexBuffer = new StaticIndexBufferInterface(mFactory); + } +} + +void BufferD3D::invalidateStaticData() +{ + if ((mStaticVertexBuffer && mStaticVertexBuffer->getBufferSize() != 0) || (mStaticIndexBuffer && mStaticIndexBuffer->getBufferSize() != 0)) + { + SafeDelete(mStaticVertexBuffer); + SafeDelete(mStaticIndexBuffer); + + // Re-init static data to track that we're in a static buffer + initializeStaticData(); + } + + mUnmodifiedDataUse = 0; +} + +// Creates static buffers if sufficient used data has been left unmodified +void BufferD3D::promoteStaticUsage(int dataSize) +{ + if (!mStaticVertexBuffer && !mStaticIndexBuffer) + { + mUnmodifiedDataUse += dataSize; + + if (mUnmodifiedDataUse > 3 * getSize()) + { + initializeStaticData(); + } + } +} + +} \ No newline at end of file diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/BufferD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/BufferD3D.h new file mode 100644 index 0000000000..a46398f911 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/BufferD3D.h @@ -0,0 +1,56 @@ +// +// Copyright 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// BufferD3D.h: Defines the rx::BufferD3D class, an implementation of BufferImpl. + +#ifndef LIBANGLE_RENDERER_D3D_BUFFERD3D_H_ +#define LIBANGLE_RENDERER_D3D_BUFFERD3D_H_ + +#include "libANGLE/renderer/BufferImpl.h" +#include "libANGLE/angletypes.h" + +#include + +namespace rx +{ +class BufferFactoryD3D; +class StaticIndexBufferInterface; +class StaticVertexBufferInterface; + +class BufferD3D : public BufferImpl +{ + public: + BufferD3D(BufferFactoryD3D *factory); + virtual ~BufferD3D(); + + unsigned int getSerial() const { return mSerial; } + + virtual size_t getSize() const = 0; + virtual bool supportsDirectBinding() const = 0; + virtual void markTransformFeedbackUsage() = 0; + + StaticVertexBufferInterface *getStaticVertexBuffer() { return mStaticVertexBuffer; } + StaticIndexBufferInterface *getStaticIndexBuffer() { return mStaticIndexBuffer; } + + void initializeStaticData(); + void invalidateStaticData(); + void promoteStaticUsage(int dataSize); + + protected: + void updateSerial(); + + BufferFactoryD3D *mFactory; + unsigned int mSerial; + static unsigned int mNextSerial; + + StaticVertexBufferInterface *mStaticVertexBuffer; + StaticIndexBufferInterface *mStaticIndexBuffer; + unsigned int mUnmodifiedDataUse; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_BUFFERD3D_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/CompilerD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/CompilerD3D.cpp new file mode 100644 index 0000000000..a22757cf9f --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/CompilerD3D.cpp @@ -0,0 +1,128 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// CompilerD3D.cpp: Implementation of the rx::CompilerD3D class. + +#include "libANGLE/renderer/d3d/CompilerD3D.h" + +#include "libANGLE/Caps.h" +#include "libANGLE/Data.h" + +#include "common/debug.h" + +namespace rx +{ + +// Global count of active shader compiler handles. Needed to know when to call ShInitialize and ShFinalize. +static size_t activeCompilerHandles = 0; + +CompilerD3D::CompilerD3D(const gl::Data &data, ShShaderOutput outputType) + : mSpec(data.clientVersion > 2 ? SH_GLES3_SPEC : SH_GLES2_SPEC), + mOutputType(outputType), + mResources(), + mFragmentCompiler(NULL), + mVertexCompiler(NULL) +{ + ASSERT(data.clientVersion == 2 || data.clientVersion == 3); + + const gl::Caps &caps = *data.caps; + const gl::Extensions &extensions = *data.extensions; + + ShInitBuiltInResources(&mResources); + mResources.MaxVertexAttribs = caps.maxVertexAttributes; + mResources.MaxVertexUniformVectors = caps.maxVertexUniformVectors; + mResources.MaxVaryingVectors = caps.maxVaryingVectors; + mResources.MaxVertexTextureImageUnits = caps.maxVertexTextureImageUnits; + mResources.MaxCombinedTextureImageUnits = caps.maxCombinedTextureImageUnits; + mResources.MaxTextureImageUnits = caps.maxTextureImageUnits; + mResources.MaxFragmentUniformVectors = caps.maxFragmentUniformVectors; + mResources.MaxDrawBuffers = caps.maxDrawBuffers; + mResources.OES_standard_derivatives = extensions.standardDerivatives; + mResources.EXT_draw_buffers = extensions.drawBuffers; + mResources.EXT_shader_texture_lod = 1; + // resources.OES_EGL_image_external = mRenderer->getShareHandleSupport() ? 1 : 0; // TODO: commented out until the extension is actually supported. + mResources.FragmentPrecisionHigh = 1; // Shader Model 2+ always supports FP24 (s16e7) which corresponds to highp + mResources.EXT_frag_depth = 1; // Shader Model 2+ always supports explicit depth output + + // GLSL ES 3.0 constants + mResources.MaxVertexOutputVectors = caps.maxVertexOutputComponents / 4; + mResources.MaxFragmentInputVectors = caps.maxFragmentInputComponents / 4; + mResources.MinProgramTexelOffset = caps.minProgramTexelOffset; + mResources.MaxProgramTexelOffset = caps.maxProgramTexelOffset; +} + +CompilerD3D::~CompilerD3D() +{ + release(); +} + +CompilerD3D *CompilerD3D::makeCompilerD3D(CompilerImpl *compiler) +{ + ASSERT(HAS_DYNAMIC_TYPE(CompilerD3D*, compiler)); + return static_cast(compiler); +} + +gl::Error CompilerD3D::release() +{ + if (mFragmentCompiler) + { + ShDestruct(mFragmentCompiler); + mFragmentCompiler = NULL; + + ASSERT(activeCompilerHandles > 0); + activeCompilerHandles--; + } + + if (mVertexCompiler) + { + ShDestruct(mVertexCompiler); + mVertexCompiler = NULL; + + ASSERT(activeCompilerHandles > 0); + activeCompilerHandles--; + } + + if (activeCompilerHandles == 0) + { + ShFinalize(); + } + + return gl::Error(GL_NO_ERROR); +} + +ShHandle CompilerD3D::getCompilerHandle(GLenum type) +{ + ShHandle *compiler = NULL; + switch (type) + { + case GL_VERTEX_SHADER: + compiler = &mVertexCompiler; + break; + + case GL_FRAGMENT_SHADER: + compiler = &mFragmentCompiler; + break; + + default: + UNREACHABLE(); + return NULL; + } + + if (!(*compiler)) + { + if (activeCompilerHandles == 0) + { + ShInitialize(); + } + + *compiler = ShConstructCompiler(type, mSpec, mOutputType, &mResources); + activeCompilerHandles++; + } + + return *compiler; +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/CompilerD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/CompilerD3D.h new file mode 100644 index 0000000000..0f83e4f8c8 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/CompilerD3D.h @@ -0,0 +1,48 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// CompilerD3D.h: Defines the rx::CompilerD3D class, an implementation of rx::CompilerImpl. + +#ifndef LIBANGLE_RENDERER_COMPILERD3D_H_ +#define LIBANGLE_RENDERER_COMPILERD3D_H_ + +#include "libANGLE/renderer/CompilerImpl.h" +#include "libANGLE/Caps.h" + +#include "GLSLANG/ShaderLang.h" + +namespace gl +{ +struct Data; +} + +namespace rx +{ + +class CompilerD3D : public CompilerImpl +{ + public: + CompilerD3D(const gl::Data &data, ShShaderOutput outputType); + virtual ~CompilerD3D(); + + static CompilerD3D *makeCompilerD3D(CompilerImpl *compiler); + + gl::Error release() override; + + ShHandle getCompilerHandle(GLenum type); + + private: + ShShaderSpec mSpec; + ShShaderOutput mOutputType; + ShBuiltInResources mResources; + + ShHandle mFragmentCompiler; + ShHandle mVertexCompiler; +}; + +} + +#endif // LIBANGLE_RENDERER_COMPILERD3D_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/DisplayD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/DisplayD3D.cpp new file mode 100644 index 0000000000..add5d62fae --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/DisplayD3D.cpp @@ -0,0 +1,357 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// DisplayD3D.cpp: D3D implementation of egl::Display + +#include "libANGLE/renderer/d3d/DisplayD3D.h" + +#include "libANGLE/Context.h" +#include "libANGLE/Config.h" +#include "libANGLE/Display.h" +#include "libANGLE/Surface.h" +#include "libANGLE/renderer/d3d/RendererD3D.h" +#include "libANGLE/renderer/d3d/SurfaceD3D.h" +#include "libANGLE/renderer/d3d/SwapChainD3D.h" +#include "platform/Platform.h" + +#include + +#if defined (ANGLE_ENABLE_D3D9) +# include "libANGLE/renderer/d3d/d3d9/Renderer9.h" +#endif // ANGLE_ENABLE_D3D9 + +#if defined (ANGLE_ENABLE_D3D11) +# include "libANGLE/renderer/d3d/d3d11/Renderer11.h" +#endif // ANGLE_ENABLE_D3D11 + +#if defined (ANGLE_TEST_CONFIG) +# define ANGLE_DEFAULT_D3D11 1 +#endif + +#if !defined(ANGLE_DEFAULT_D3D11) +// Enables use of the Direct3D 11 API for a default display, when available +# define ANGLE_DEFAULT_D3D11 0 +#endif + +namespace rx +{ + +typedef RendererD3D *(*CreateRendererD3DFunction)(egl::Display*); + +template +static RendererD3D *CreateTypedRendererD3D(egl::Display *display) +{ + return new RendererType(display); +} + +egl::Error CreateRendererD3D(egl::Display *display, RendererD3D **outRenderer) +{ + ASSERT(outRenderer != nullptr); + + std::vector rendererCreationFunctions; + + const auto &attribMap = display->getAttributeMap(); + EGLNativeDisplayType nativeDisplay = display->getNativeDisplayId(); + + EGLint requestedDisplayType = attribMap.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE); + +# if defined(ANGLE_ENABLE_D3D11) + if (nativeDisplay == EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE || + nativeDisplay == EGL_D3D11_ONLY_DISPLAY_ANGLE || + requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE) + { + rendererCreationFunctions.push_back(CreateTypedRendererD3D); + } +# endif + +# if defined(ANGLE_ENABLE_D3D9) + if (nativeDisplay == EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE || + requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE) + { + rendererCreationFunctions.push_back(CreateTypedRendererD3D); + } +# endif + + if (nativeDisplay != EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE && + nativeDisplay != EGL_D3D11_ONLY_DISPLAY_ANGLE && + requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE) + { + // The default display is requested, try the D3D9 and D3D11 renderers, order them using + // the definition of ANGLE_DEFAULT_D3D11 +# if ANGLE_DEFAULT_D3D11 +# if defined(ANGLE_ENABLE_D3D11) + rendererCreationFunctions.push_back(CreateTypedRendererD3D); +# endif +# if defined(ANGLE_ENABLE_D3D9) + rendererCreationFunctions.push_back(CreateTypedRendererD3D); +# endif +# else +# if defined(ANGLE_ENABLE_D3D9) + rendererCreationFunctions.push_back(CreateTypedRendererD3D); +# endif +# if defined(ANGLE_ENABLE_D3D11) + rendererCreationFunctions.push_back(CreateTypedRendererD3D); +# endif +# endif + } + + egl::Error result(EGL_NOT_INITIALIZED, "No available renderers."); + for (size_t i = 0; i < rendererCreationFunctions.size(); i++) + { + RendererD3D *renderer = rendererCreationFunctions[i](display); + result = renderer->initialize(); + +# if defined(ANGLE_ENABLE_D3D11) + if (renderer->getRendererClass() == RENDERER_D3D11) + { + ASSERT(result.getID() >= 0 && result.getID() < NUM_D3D11_INIT_ERRORS); + + angle::Platform *platform = ANGLEPlatformCurrent(); + platform->histogramEnumeration("GPU.ANGLE.D3D11InitializeResult", + result.getID(), NUM_D3D11_INIT_ERRORS); + } +# endif + +# if defined(ANGLE_ENABLE_D3D9) + if (renderer->getRendererClass() == RENDERER_D3D9) + { + ASSERT(result.getID() >= 0 && result.getID() < NUM_D3D9_INIT_ERRORS); + + angle::Platform *platform = ANGLEPlatformCurrent(); + platform->histogramEnumeration("GPU.ANGLE.D3D9InitializeResult", + result.getID(), NUM_D3D9_INIT_ERRORS); + } +# endif + + if (!result.isError()) + { + *outRenderer = renderer; + break; + } + else + { + // Failed to create the renderer, try the next + SafeDelete(renderer); + } + } + + return result; +} + +DisplayD3D::DisplayD3D() + : mRenderer(nullptr) +{ +} + +egl::Error DisplayD3D::createWindowSurface(const egl::Config *configuration, EGLNativeWindowType window, + const egl::AttributeMap &attribs, SurfaceImpl **outSurface) +{ + ASSERT(mRenderer != nullptr); + + EGLint width = attribs.get(EGL_WIDTH, 0); + EGLint height = attribs.get(EGL_HEIGHT, 0); + EGLint fixedSize = attribs.get(EGL_FIXED_SIZE_ANGLE, EGL_FALSE); + + if (!fixedSize) + { + width = -1; + height = -1; + } + + SurfaceD3D *surface = SurfaceD3D::createFromWindow(mRenderer, mDisplay, configuration, window, fixedSize, + width, height); + egl::Error error = surface->initialize(); + if (error.isError()) + { + SafeDelete(surface); + return error; + } + + *outSurface = surface; + return egl::Error(EGL_SUCCESS); +} + +egl::Error DisplayD3D::createPbufferSurface(const egl::Config *configuration, const egl::AttributeMap &attribs, + SurfaceImpl **outSurface) +{ + ASSERT(mRenderer != nullptr); + + EGLint width = attribs.get(EGL_WIDTH, 0); + EGLint height = attribs.get(EGL_HEIGHT, 0); + + SurfaceD3D *surface = SurfaceD3D::createOffscreen(mRenderer, mDisplay, configuration, NULL, width, height); + egl::Error error = surface->initialize(); + if (error.isError()) + { + SafeDelete(surface); + return error; + } + + *outSurface = surface; + return egl::Error(EGL_SUCCESS); +} + +egl::Error DisplayD3D::createPbufferFromClientBuffer(const egl::Config *configuration, EGLClientBuffer shareHandle, + const egl::AttributeMap &attribs, SurfaceImpl **outSurface) +{ + ASSERT(mRenderer != nullptr); + + EGLint width = attribs.get(EGL_WIDTH, 0); + EGLint height = attribs.get(EGL_HEIGHT, 0); + + SurfaceD3D *surface = SurfaceD3D::createOffscreen(mRenderer, mDisplay, configuration, shareHandle, + width, height); + egl::Error error = surface->initialize(); + if (error.isError()) + { + SafeDelete(surface); + return error; + } + + *outSurface = surface; + return egl::Error(EGL_SUCCESS); +} + +egl::Error DisplayD3D::createPixmapSurface(const egl::Config *configuration, NativePixmapType nativePixmap, + const egl::AttributeMap &attribs, SurfaceImpl **outSurface) +{ + ASSERT(mRenderer != nullptr); + + UNIMPLEMENTED(); + *outSurface = nullptr; + return egl::Error(EGL_BAD_DISPLAY); +} + +egl::Error DisplayD3D::createContext(const egl::Config *config, const gl::Context *shareContext, const egl::AttributeMap &attribs, + gl::Context **outContext) +{ + ASSERT(mRenderer != nullptr); + + EGLint clientVersion = attribs.get(EGL_CONTEXT_CLIENT_VERSION, 1); + bool notifyResets = (attribs.get(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT, EGL_NO_RESET_NOTIFICATION_EXT) == EGL_LOSE_CONTEXT_ON_RESET_EXT); + bool robustAccess = (attribs.get(EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT, EGL_FALSE) == EGL_TRUE); + + *outContext = new gl::Context(config, clientVersion, shareContext, mRenderer, notifyResets, robustAccess); + return egl::Error(EGL_SUCCESS); +} + +egl::Error DisplayD3D::makeCurrent(egl::Surface *drawSurface, egl::Surface *readSurface, gl::Context *context) +{ + return egl::Error(EGL_SUCCESS); +} + +egl::Error DisplayD3D::initialize(egl::Display *display) +{ + ASSERT(mRenderer == nullptr && display != nullptr); + mDisplay = display; + return CreateRendererD3D(display, &mRenderer); +} + +void DisplayD3D::terminate() +{ + SafeDelete(mRenderer); +} + +egl::ConfigSet DisplayD3D::generateConfigs() const +{ + ASSERT(mRenderer != nullptr); + return mRenderer->generateConfigs(); +} + +bool DisplayD3D::isDeviceLost() const +{ + ASSERT(mRenderer != nullptr); + return mRenderer->isDeviceLost(); +} + +bool DisplayD3D::testDeviceLost() +{ + ASSERT(mRenderer != nullptr); + return mRenderer->testDeviceLost(); +} + +egl::Error DisplayD3D::restoreLostDevice() +{ + // Release surface resources to make the Reset() succeed + for (auto it = mSurfaceSet.cbegin(); it != mSurfaceSet.cend(); ++it) + { + const auto &surface = *it; + if (surface->getBoundTexture()) + { + surface->releaseTexImage(EGL_BACK_BUFFER); + } + SurfaceD3D *surfaceD3D = GetImplAs(surface); + surfaceD3D->releaseSwapChain(); + } + + if (!mRenderer->resetDevice()) + { + return egl::Error(EGL_BAD_ALLOC); + } + + // Restore any surfaces that may have been lost + for (auto it = mSurfaceSet.cbegin(); it != mSurfaceSet.cend(); ++it) + { + const auto &surface = *it; + SurfaceD3D *surfaceD3D = GetImplAs(surface); + + egl::Error error = surfaceD3D->resetSwapChain(); + if (error.isError()) + { + return error; + } + } + + return egl::Error(EGL_SUCCESS); +} + +bool DisplayD3D::isValidNativeWindow(EGLNativeWindowType window) const +{ + return NativeWindow::isValidNativeWindow(window); +} + +void DisplayD3D::generateExtensions(egl::DisplayExtensions *outExtensions) const +{ + outExtensions->createContextRobustness = true; + + // ANGLE-specific extensions + if (mRenderer->getShareHandleSupport()) + { + outExtensions->d3dShareHandleClientBuffer = true; + outExtensions->surfaceD3DTexture2DShareHandle = true; + } + + outExtensions->querySurfacePointer = true; + outExtensions->windowFixedSize = true; + + if (mRenderer->getPostSubBufferSupport()) + { + outExtensions->postSubBuffer = true; + } + + outExtensions->createContext = true; +} + +std::string DisplayD3D::getVendorString() const +{ + std::string vendorString = "Google Inc."; + if (mRenderer) + { + vendorString += " " + mRenderer->getVendorString(); + } + + return vendorString; +} + +void DisplayD3D::generateCaps(egl::Caps *outCaps) const +{ + // Display must be initialized to generate caps + ASSERT(mRenderer != nullptr); + + outCaps->textureNPOT = mRenderer->getRendererExtensions().textureNPOT; +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/DisplayD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/DisplayD3D.h new file mode 100644 index 0000000000..f007ba9a19 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/DisplayD3D.h @@ -0,0 +1,61 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// DisplayD3D.h: D3D implementation of egl::Display + +#ifndef LIBANGLE_RENDERER_D3D_DISPLAYD3D_H_ +#define LIBANGLE_RENDERER_D3D_DISPLAYD3D_H_ + +#include "libANGLE/renderer/DisplayImpl.h" + +namespace rx +{ +class RendererD3D; + +class DisplayD3D : public DisplayImpl +{ + public: + DisplayD3D(); + + egl::Error initialize(egl::Display *display) override; + virtual void terminate() override; + + egl::Error createWindowSurface(const egl::Config *configuration, EGLNativeWindowType window, const egl::AttributeMap &attribs, + SurfaceImpl **outSurface) override; + egl::Error createPbufferSurface(const egl::Config *configuration, const egl::AttributeMap &attribs, + SurfaceImpl **outSurface) override; + egl::Error createPbufferFromClientBuffer(const egl::Config *configuration, EGLClientBuffer shareHandle, + const egl::AttributeMap &attribs, SurfaceImpl **outSurface) override; + egl::Error createPixmapSurface(const egl::Config *configuration, NativePixmapType nativePixmap, + const egl::AttributeMap &attribs, SurfaceImpl **outSurface) override; + + egl::Error createContext(const egl::Config *config, const gl::Context *shareContext, const egl::AttributeMap &attribs, + gl::Context **outContext) override; + + egl::Error makeCurrent(egl::Surface *drawSurface, egl::Surface *readSurface, gl::Context *context) override; + + egl::ConfigSet generateConfigs() const override; + + bool isDeviceLost() const override; + bool testDeviceLost() override; + egl::Error restoreLostDevice() override; + + bool isValidNativeWindow(EGLNativeWindowType window) const override; + + std::string getVendorString() const override; + + private: + void generateExtensions(egl::DisplayExtensions *outExtensions) const override; + void generateCaps(egl::Caps *outCaps) const override; + + egl::Display *mDisplay; + + rx::RendererD3D *mRenderer; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_DISPLAYD3D_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/DynamicHLSL.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/DynamicHLSL.cpp new file mode 100644 index 0000000000..0dbc30ae36 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/DynamicHLSL.cpp @@ -0,0 +1,1265 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// DynamicHLSL.cpp: Implementation for link and run-time HLSL generation +// + +#include "libANGLE/renderer/d3d/DynamicHLSL.h" + +#include "common/utilities.h" +#include "compiler/translator/blocklayoutHLSL.h" +#include "libANGLE/renderer/d3d/ShaderD3D.h" +#include "libANGLE/renderer/d3d/RendererD3D.h" +#include "libANGLE/Program.h" +#include "libANGLE/Shader.h" +#include "libANGLE/formatutils.h" + +// For use with ArrayString, see angleutils.h +static_assert(GL_INVALID_INDEX == UINT_MAX, "GL_INVALID_INDEX must be equal to the max unsigned int."); + +using namespace gl; + +namespace rx +{ + +namespace +{ + +std::string HLSLComponentTypeString(GLenum componentType) +{ + switch (componentType) + { + case GL_UNSIGNED_INT: return "uint"; + case GL_INT: return "int"; + case GL_UNSIGNED_NORMALIZED: + case GL_SIGNED_NORMALIZED: + case GL_FLOAT: return "float"; + default: UNREACHABLE(); return "not-component-type"; + } +} + +std::string HLSLComponentTypeString(GLenum componentType, int componentCount) +{ + return HLSLComponentTypeString(componentType) + (componentCount > 1 ? Str(componentCount) : ""); +} + +std::string HLSLMatrixTypeString(GLenum type) +{ + switch (type) + { + case GL_FLOAT_MAT2: return "float2x2"; + case GL_FLOAT_MAT3: return "float3x3"; + case GL_FLOAT_MAT4: return "float4x4"; + case GL_FLOAT_MAT2x3: return "float2x3"; + case GL_FLOAT_MAT3x2: return "float3x2"; + case GL_FLOAT_MAT2x4: return "float2x4"; + case GL_FLOAT_MAT4x2: return "float4x2"; + case GL_FLOAT_MAT3x4: return "float3x4"; + case GL_FLOAT_MAT4x3: return "float4x3"; + default: UNREACHABLE(); return "not-matrix-type"; + } +} + +std::string HLSLTypeString(GLenum type) +{ + if (gl::IsMatrixType(type)) + { + return HLSLMatrixTypeString(type); + } + + return HLSLComponentTypeString(gl::VariableComponentType(type), gl::VariableComponentCount(type)); +} + +const PixelShaderOutputVariable *FindOutputAtLocation(const std::vector &outputVariables, + unsigned int location) +{ + for (size_t variableIndex = 0; variableIndex < outputVariables.size(); ++variableIndex) + { + if (outputVariables[variableIndex].outputIndex == location) + { + return &outputVariables[variableIndex]; + } + } + + return NULL; +} + +const std::string VERTEX_ATTRIBUTE_STUB_STRING = "@@ VERTEX ATTRIBUTES @@"; +const std::string PIXEL_OUTPUT_STUB_STRING = "@@ PIXEL OUTPUT @@"; + +} + +DynamicHLSL::DynamicHLSL(RendererD3D *const renderer) + : mRenderer(renderer) +{ +} + +static bool packVarying(PackedVarying *varying, const int maxVaryingVectors, VaryingPacking packing) +{ + // Make sure we use transposed matrix types to count registers correctly. + int registers = 0; + int elements = 0; + + if (varying->isStruct()) + { + registers = HLSLVariableRegisterCount(*varying, true) * varying->elementCount(); + elements = 4; + } + else + { + GLenum transposedType = TransposeMatrixType(varying->type); + registers = VariableRowCount(transposedType) * varying->elementCount(); + elements = VariableColumnCount(transposedType); + } + + if (elements >= 2 && elements <= 4) + { + for (int r = 0; r <= maxVaryingVectors - registers; r++) + { + bool available = true; + + for (int y = 0; y < registers && available; y++) + { + for (int x = 0; x < elements && available; x++) + { + if (packing[r + y][x]) + { + available = false; + } + } + } + + if (available) + { + varying->registerIndex = r; + varying->columnIndex = 0; + + for (int y = 0; y < registers; y++) + { + for (int x = 0; x < elements; x++) + { + packing[r + y][x] = &*varying; + } + } + + return true; + } + } + + if (elements == 2) + { + for (int r = maxVaryingVectors - registers; r >= 0; r--) + { + bool available = true; + + for (int y = 0; y < registers && available; y++) + { + for (int x = 2; x < 4 && available; x++) + { + if (packing[r + y][x]) + { + available = false; + } + } + } + + if (available) + { + varying->registerIndex = r; + varying->columnIndex = 2; + + for (int y = 0; y < registers; y++) + { + for (int x = 2; x < 4; x++) + { + packing[r + y][x] = &*varying; + } + } + + return true; + } + } + } + } + else if (elements == 1) + { + int space[4] = { 0 }; + + for (int y = 0; y < maxVaryingVectors; y++) + { + for (int x = 0; x < 4; x++) + { + space[x] += packing[y][x] ? 0 : 1; + } + } + + int column = 0; + + for (int x = 0; x < 4; x++) + { + if (space[x] >= registers && (space[column] < registers || space[x] < space[column])) + { + column = x; + } + } + + if (space[column] >= registers) + { + for (int r = 0; r < maxVaryingVectors; r++) + { + if (!packing[r][column]) + { + varying->registerIndex = r; + varying->columnIndex = column; + + for (int y = r; y < r + registers; y++) + { + packing[y][column] = &*varying; + } + + break; + } + } + + return true; + } + } + else UNREACHABLE(); + + return false; +} + +// 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 DynamicHLSL::packVaryings(InfoLog &infoLog, VaryingPacking packing, ShaderD3D *fragmentShader, + ShaderD3D *vertexShader, const std::vector &transformFeedbackVaryings) +{ + // TODO (geofflang): Use context's caps + const int maxVaryingVectors = mRenderer->getRendererCaps().maxVaryingVectors; + + vertexShader->resetVaryingsRegisterAssignment(); + fragmentShader->resetVaryingsRegisterAssignment(); + + std::set packedVaryings; + + std::vector &fragmentVaryings = fragmentShader->getVaryings(); + std::vector &vertexVaryings = vertexShader->getVaryings(); + for (unsigned int varyingIndex = 0; varyingIndex < fragmentVaryings.size(); varyingIndex++) + { + PackedVarying *varying = &fragmentVaryings[varyingIndex]; + + // Do not assign registers to built-in or unreferenced varyings + if (varying->isBuiltIn() || !varying->staticUse) + { + continue; + } + + if (packVarying(varying, maxVaryingVectors, packing)) + { + packedVaryings.insert(varying->name); + } + else + { + infoLog.append("Could not pack varying %s", varying->name.c_str()); + return -1; + } + } + + for (unsigned int feedbackVaryingIndex = 0; feedbackVaryingIndex < transformFeedbackVaryings.size(); feedbackVaryingIndex++) + { + const std::string &transformFeedbackVarying = transformFeedbackVaryings[feedbackVaryingIndex]; + + if (transformFeedbackVarying == "gl_Position" || transformFeedbackVarying == "gl_PointSize") + { + // do not pack builtin XFB varyings + continue; + } + + if (packedVaryings.find(transformFeedbackVarying) == packedVaryings.end()) + { + bool found = false; + for (unsigned int varyingIndex = 0; varyingIndex < vertexVaryings.size(); varyingIndex++) + { + PackedVarying *varying = &vertexVaryings[varyingIndex]; + if (transformFeedbackVarying == varying->name) + { + if (!packVarying(varying, maxVaryingVectors, packing)) + { + infoLog.append("Could not pack varying %s", varying->name.c_str()); + return -1; + } + + found = true; + break; + } + } + + if (!found) + { + infoLog.append("Transform feedback varying %s does not exist in the vertex shader.", transformFeedbackVarying.c_str()); + return -1; + } + } + } + + // Return the number of used registers + int registers = 0; + + for (int r = 0; r < maxVaryingVectors; r++) + { + if (packing[r][0] || packing[r][1] || packing[r][2] || packing[r][3]) + { + registers++; + } + } + + return registers; +} + +std::string DynamicHLSL::generateVaryingHLSL(const ShaderD3D *shader) const +{ + std::string varyingSemantic = getVaryingSemantic(shader->mUsesPointSize); + std::string varyingHLSL; + + const std::vector &varyings = shader->getVaryings(); + + for (unsigned int varyingIndex = 0; varyingIndex < varyings.size(); varyingIndex++) + { + const PackedVarying &varying = varyings[varyingIndex]; + if (varying.registerAssigned()) + { + ASSERT(!varying.isBuiltIn()); + GLenum transposedType = TransposeMatrixType(varying.type); + int variableRows = (varying.isStruct() ? 1 : VariableRowCount(transposedType)); + + for (unsigned int elementIndex = 0; elementIndex < varying.elementCount(); elementIndex++) + { + for (int row = 0; row < variableRows; row++) + { + // TODO: Add checks to ensure D3D interpolation modifiers don't result in too many registers being used. + // For example, if there are N registers, and we have N vec3 varyings and 1 float varying, then D3D will pack them into N registers. + // If the float varying has the 'nointerpolation' modifier on it then we would need N + 1 registers, and D3D compilation will fail. + + switch (varying.interpolation) + { + case sh::INTERPOLATION_SMOOTH: varyingHLSL += " "; break; + case sh::INTERPOLATION_FLAT: varyingHLSL += " nointerpolation "; break; + case sh::INTERPOLATION_CENTROID: varyingHLSL += " centroid "; break; + default: UNREACHABLE(); + } + + unsigned int semanticIndex = elementIndex * variableRows + + varying.columnIndex * mRenderer->getRendererCaps().maxVaryingVectors + + varying.registerIndex + row; + std::string n = Str(semanticIndex); + + std::string typeString; + + if (varying.isStruct()) + { + // TODO(jmadill): pass back translated name from the shader translator + typeString = decorateVariable(varying.structName); + } + else + { + GLenum componentType = VariableComponentType(transposedType); + int columnCount = VariableColumnCount(transposedType); + typeString = HLSLComponentTypeString(componentType, columnCount); + } + varyingHLSL += typeString + " v" + n + " : " + varyingSemantic + n + ";\n"; + } + } + } + } + + return varyingHLSL; +} + +std::string DynamicHLSL::generateVertexShaderForInputLayout(const std::string &sourceShader, + const VertexFormat inputLayout[], + const sh::Attribute shaderAttributes[]) const +{ + std::string structHLSL, initHLSL; + + int semanticIndex = 0; + unsigned int inputIndex = 0; + + // If gl_PointSize is used in the shader then pointsprites rendering is expected. + // If the renderer does not support Geometry shaders then Instanced PointSprite emulation + // must be used. + bool usesPointSize = sourceShader.find("GL_USES_POINT_SIZE") != std::string::npos; + bool useInstancedPointSpriteEmulation = usesPointSize && mRenderer->getWorkarounds().useInstancedPointSpriteEmulation; + + // Instanced PointSprite emulation requires additional entries in the + // VS_INPUT structure to support the vertices that make up the quad vertices. + // These values must be in sync with the cooresponding values added during inputlayout creation + // in InputLayoutCache::applyVertexBuffers(). + // + // The additional entries must appear first in the VS_INPUT layout because + // Windows Phone 8 era devices require per vertex data to physically come + // before per instance data in the shader. + if (useInstancedPointSpriteEmulation) + { + structHLSL += " float3 spriteVertexPos : SPRITEPOSITION0;\n"; + structHLSL += " float2 spriteTexCoord : SPRITETEXCOORD0;\n"; + } + + for (unsigned int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++) + { + const sh::Attribute &shaderAttribute = shaderAttributes[attributeIndex]; + if (!shaderAttribute.name.empty()) + { + ASSERT(inputIndex < MAX_VERTEX_ATTRIBS); + const VertexFormat &vertexFormat = inputLayout[inputIndex]; + + // HLSL code for input structure + if (IsMatrixType(shaderAttribute.type)) + { + // Matrix types are always transposed + structHLSL += " " + HLSLMatrixTypeString(TransposeMatrixType(shaderAttribute.type)); + } + else + { + GLenum componentType = mRenderer->getVertexComponentType(vertexFormat); + + if (shaderAttribute.name == "gl_InstanceID") + { + // The input type of the instance ID in HLSL (uint) differs from the one in ESSL (int). + structHLSL += " uint"; + } + else + { + structHLSL += " " + HLSLComponentTypeString(componentType, VariableComponentCount(shaderAttribute.type)); + } + } + + structHLSL += " " + decorateVariable(shaderAttribute.name) + " : "; + + if (shaderAttribute.name == "gl_InstanceID") + { + structHLSL += "SV_InstanceID"; + } + else + { + structHLSL += "TEXCOORD" + Str(semanticIndex); + semanticIndex += VariableRegisterCount(shaderAttribute.type); + } + + structHLSL += ";\n"; + + // HLSL code for initialization + initHLSL += " " + decorateVariable(shaderAttribute.name) + " = "; + + // Mismatched vertex attribute to vertex input may result in an undefined + // data reinterpretation (eg for pure integer->float, float->pure integer) + // TODO: issue warning with gl debug info extension, when supported + if (IsMatrixType(shaderAttribute.type) || + (mRenderer->getVertexConversionType(vertexFormat) & VERTEX_CONVERT_GPU) != 0) + { + initHLSL += generateAttributeConversionHLSL(vertexFormat, shaderAttribute); + } + else + { + initHLSL += "input." + decorateVariable(shaderAttribute.name); + } + + initHLSL += ";\n"; + + inputIndex += VariableRowCount(TransposeMatrixType(shaderAttribute.type)); + } + } + + std::string replacementHLSL = "struct VS_INPUT\n" + "{\n" + + structHLSL + + "};\n" + "\n" + "void initAttributes(VS_INPUT input)\n" + "{\n" + + initHLSL + + "}\n"; + + std::string vertexHLSL(sourceShader); + + size_t copyInsertionPos = vertexHLSL.find(VERTEX_ATTRIBUTE_STUB_STRING); + vertexHLSL.replace(copyInsertionPos, VERTEX_ATTRIBUTE_STUB_STRING.length(), replacementHLSL); + + return vertexHLSL; +} + +std::string DynamicHLSL::generatePixelShaderForOutputSignature(const std::string &sourceShader, const std::vector &outputVariables, + bool usesFragDepth, const std::vector &outputLayout) const +{ + const int shaderModel = mRenderer->getMajorShaderModel(); + std::string targetSemantic = (shaderModel >= 4) ? "SV_TARGET" : "COLOR"; + std::string depthSemantic = (shaderModel >= 4) ? "SV_Depth" : "DEPTH"; + + std::string declarationHLSL; + std::string copyHLSL; + + for (size_t layoutIndex = 0; layoutIndex < outputLayout.size(); ++layoutIndex) + { + GLenum binding = outputLayout[layoutIndex]; + + if (binding != GL_NONE) + { + unsigned int location = (binding - GL_COLOR_ATTACHMENT0); + + const PixelShaderOutputVariable *outputVariable = FindOutputAtLocation(outputVariables, location); + + // OpenGL ES 3.0 spec $4.2.1 + // If [...] not all user-defined output variables are written, the values of fragment colors + // corresponding to unwritten variables are similarly undefined. + if (outputVariable) + { + declarationHLSL += " " + HLSLTypeString(outputVariable->type) + " " + outputVariable->name + + " : " + targetSemantic + Str(layoutIndex) + ";\n"; + + copyHLSL += " output." + outputVariable->name + " = " + outputVariable->source + ";\n"; + } + } + } + + if (usesFragDepth) + { + declarationHLSL += " float gl_Depth : " + depthSemantic + ";\n"; + copyHLSL += " output.gl_Depth = gl_Depth; \n"; + } + + std::string replacementHLSL = "struct PS_OUTPUT\n" + "{\n" + + declarationHLSL + + "};\n" + "\n" + "PS_OUTPUT generateOutput()\n" + "{\n" + " PS_OUTPUT output;\n" + + copyHLSL + + " return output;\n" + "}\n"; + + std::string pixelHLSL(sourceShader); + + size_t outputInsertionPos = pixelHLSL.find(PIXEL_OUTPUT_STUB_STRING); + pixelHLSL.replace(outputInsertionPos, PIXEL_OUTPUT_STUB_STRING.length(), replacementHLSL); + + return pixelHLSL; +} + +std::string DynamicHLSL::getVaryingSemantic(bool pointSize) const +{ + // SM3 reserves the TEXCOORD semantic for point sprite texcoords (gl_PointCoord) + // In D3D11 we manually compute gl_PointCoord in the GS. + int shaderModel = mRenderer->getMajorShaderModel(); + return ((pointSize && shaderModel < 4) ? "COLOR" : "TEXCOORD"); +} + +struct DynamicHLSL::SemanticInfo +{ + struct BuiltinInfo + { + BuiltinInfo() + : enabled(false), + index(0), + systemValue(false) + {} + + bool enabled; + std::string semantic; + unsigned int index; + bool systemValue; + + std::string str() const + { + return (systemValue ? semantic : (semantic + Str(index))); + } + + void enableSystem(const std::string &systemValueSemantic) + { + enabled = true; + semantic = systemValueSemantic; + systemValue = true; + } + + void enable(const std::string &semanticVal, unsigned int indexVal) + { + enabled = true; + semantic = semanticVal; + index = indexVal; + } + }; + + BuiltinInfo dxPosition; + BuiltinInfo glPosition; + BuiltinInfo glFragCoord; + BuiltinInfo glPointCoord; + BuiltinInfo glPointSize; +}; + +DynamicHLSL::SemanticInfo DynamicHLSL::getSemanticInfo(int startRegisters, bool position, bool fragCoord, + bool pointCoord, bool pointSize, bool pixelShader) const +{ + SemanticInfo info; + bool hlsl4 = (mRenderer->getMajorShaderModel() >= 4); + const std::string &varyingSemantic = getVaryingSemantic(pointSize); + + int reservedRegisterIndex = startRegisters; + + if (hlsl4) + { + info.dxPosition.enableSystem("SV_Position"); + } + else if (pixelShader) + { + info.dxPosition.enableSystem("VPOS"); + } + else + { + info.dxPosition.enableSystem("POSITION"); + } + + if (position) + { + info.glPosition.enable(varyingSemantic, reservedRegisterIndex++); + } + + if (fragCoord) + { + info.glFragCoord.enable(varyingSemantic, reservedRegisterIndex++); + } + + if (pointCoord) + { + // SM3 reserves the TEXCOORD semantic for point sprite texcoords (gl_PointCoord) + // In D3D11 we manually compute gl_PointCoord in the GS. + if (hlsl4) + { + info.glPointCoord.enable(varyingSemantic, reservedRegisterIndex++); + } + else + { + info.glPointCoord.enable("TEXCOORD", 0); + } + } + + // Special case: do not include PSIZE semantic in HLSL 3 pixel shaders + if (pointSize && (!pixelShader || hlsl4)) + { + info.glPointSize.enableSystem("PSIZE"); + } + + return info; +} + +std::string DynamicHLSL::generateVaryingLinkHLSL(const SemanticInfo &info, const std::string &varyingHLSL) const +{ + std::string linkHLSL = "{\n"; + + ASSERT(info.dxPosition.enabled); + linkHLSL += " float4 dx_Position : " + info.dxPosition.str() + ";\n"; + + if (info.glPosition.enabled) + { + linkHLSL += " float4 gl_Position : " + info.glPosition.str() + ";\n"; + } + + if (info.glFragCoord.enabled) + { + linkHLSL += " float4 gl_FragCoord : " + info.glFragCoord.str() + ";\n"; + } + + if (info.glPointCoord.enabled) + { + linkHLSL += " float2 gl_PointCoord : " + info.glPointCoord.str() + ";\n"; + } + + if (info.glPointSize.enabled) + { + linkHLSL += " float gl_PointSize : " + info.glPointSize.str() + ";\n"; + } + + // Do this after glPointSize, to potentially combine gl_PointCoord and gl_PointSize into the same register. + linkHLSL += varyingHLSL; + + linkHLSL += "};\n"; + + return linkHLSL; +} + +void DynamicHLSL::storeBuiltinLinkedVaryings(const SemanticInfo &info, + std::vector *linkedVaryings) const +{ + if (info.glPosition.enabled) + { + linkedVaryings->push_back(LinkedVarying("gl_Position", GL_FLOAT_VEC4, 1, info.glPosition.semantic, + info.glPosition.index, 1)); + } + + if (info.glFragCoord.enabled) + { + linkedVaryings->push_back(LinkedVarying("gl_FragCoord", GL_FLOAT_VEC4, 1, info.glFragCoord.semantic, + info.glFragCoord.index, 1)); + } + + if (info.glPointSize.enabled) + { + linkedVaryings->push_back(LinkedVarying("gl_PointSize", GL_FLOAT, 1, "PSIZE", 0, 1)); + } +} + +void DynamicHLSL::storeUserLinkedVaryings(const ShaderD3D *vertexShader, + std::vector *linkedVaryings) const +{ + const std::string &varyingSemantic = getVaryingSemantic(vertexShader->mUsesPointSize); + const std::vector &varyings = vertexShader->getVaryings(); + + for (unsigned int varyingIndex = 0; varyingIndex < varyings.size(); varyingIndex++) + { + const PackedVarying &varying = varyings[varyingIndex]; + + if (varying.registerAssigned()) + { + ASSERT(!varying.isBuiltIn()); + GLenum transposedType = TransposeMatrixType(varying.type); + int variableRows = (varying.isStruct() ? 1 : VariableRowCount(transposedType)); + + linkedVaryings->push_back(LinkedVarying(varying.name, varying.type, varying.elementCount(), + varyingSemantic, varying.registerIndex, + variableRows * varying.elementCount())); + } + } +} + +bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data, InfoLog &infoLog, int registers, + const VaryingPacking packing, + std::string &pixelHLSL, std::string &vertexHLSL, + ShaderD3D *fragmentShader, ShaderD3D *vertexShader, + const std::vector &transformFeedbackVaryings, + std::vector *linkedVaryings, + std::map *programOutputVars, + std::vector *outPixelShaderKey, + bool *outUsesFragDepth) const +{ + if (pixelHLSL.empty() || vertexHLSL.empty()) + { + return false; + } + + bool usesMRT = fragmentShader->mUsesMultipleRenderTargets; + bool usesFragColor = fragmentShader->mUsesFragColor; + bool usesFragData = fragmentShader->mUsesFragData; + bool usesFragCoord = fragmentShader->mUsesFragCoord; + bool usesPointCoord = fragmentShader->mUsesPointCoord; + bool usesPointSize = vertexShader->mUsesPointSize; + bool useInstancedPointSpriteEmulation = usesPointSize && mRenderer->getWorkarounds().useInstancedPointSpriteEmulation; + + if (usesFragColor && usesFragData) + { + infoLog.append("Cannot use both gl_FragColor and gl_FragData in the same fragment shader."); + return false; + } + + // Write the HLSL input/output declarations + const int shaderModel = mRenderer->getMajorShaderModel(); + const int registersNeeded = registers + (usesFragCoord ? 1 : 0) + (usesPointCoord ? 1 : 0); + + // Two cases when writing to gl_FragColor and using ESSL 1.0: + // - with a 3.0 context, the output color is copied to channel 0 + // - with a 2.0 context, the output color is broadcast to all channels + const bool broadcast = (fragmentShader->mUsesFragColor && data.clientVersion < 3); + const unsigned int numRenderTargets = (broadcast || usesMRT ? data.caps->maxDrawBuffers : 1); + + // gl_Position only needs to be outputted from the vertex shader if transform feedback is active. + // This isn't supported on D3D11 Feature Level 9_3, so we don't output gl_Position from the vertex shader in this case. + // This saves us 1 output vector. + bool outputPositionFromVS = !(shaderModel >= 4 && mRenderer->getShaderModelSuffix() != ""); + + int shaderVersion = vertexShader->getShaderVersion(); + + if (static_cast(registersNeeded) > data.caps->maxVaryingVectors) + { + infoLog.append("No varying registers left to support gl_FragCoord/gl_PointCoord"); + return false; + } + + const std::string &varyingHLSL = generateVaryingHLSL(vertexShader); + + // Instanced PointSprite emulation requires that gl_PointCoord is present in the vertex shader VS_OUTPUT + // structure to ensure compatibility with the generated PS_INPUT of the pixel shader. + // GeometryShader PointSprite emulation does not require this additional entry because the + // GS_OUTPUT of the Geometry shader contains the pointCoord value and already matches the PS_INPUT of the + // generated pixel shader. + // The Geometry Shader point sprite implementation needs gl_PointSize to be in VS_OUTPUT and GS_INPUT. + // Instanced point sprites doesn't need gl_PointSize in VS_OUTPUT. + const SemanticInfo &vertexSemantics = getSemanticInfo(registers, outputPositionFromVS, + usesFragCoord, (useInstancedPointSpriteEmulation && usesPointCoord), + (!useInstancedPointSpriteEmulation && usesPointSize), false); + + storeUserLinkedVaryings(vertexShader, linkedVaryings); + storeBuiltinLinkedVaryings(vertexSemantics, linkedVaryings); + + // Instanced PointSprite emulation requires additional entries originally generated in the + // GeometryShader HLSL. These include pointsize clamp values. + if (useInstancedPointSpriteEmulation) + { + vertexHLSL += "static float minPointSize = " + Str((int)mRenderer->getRendererCaps().minAliasedPointSize) + ".0f;\n" + "static float maxPointSize = " + Str((int)mRenderer->getRendererCaps().maxAliasedPointSize) + ".0f;\n"; + } + + // Add stub string to be replaced when shader is dynamically defined by its layout + vertexHLSL += "\n" + VERTEX_ATTRIBUTE_STUB_STRING + "\n" + "struct VS_OUTPUT\n" + generateVaryingLinkHLSL(vertexSemantics, varyingHLSL) + "\n" + "VS_OUTPUT main(VS_INPUT input)\n" + "{\n" + " initAttributes(input);\n"; + + if (vertexShader->usesDeferredInit()) + { + vertexHLSL += "\n" + " initializeDeferredGlobals();\n"; + } + + vertexHLSL += "\n" + " gl_main();\n" + "\n" + " VS_OUTPUT output;\n"; + + if (outputPositionFromVS) + { + vertexHLSL += " output.gl_Position = gl_Position;\n"; + } + + // On D3D9 or D3D11 Feature Level 9, we need to emulate large viewports using dx_ViewAdjust. + if (shaderModel >= 4 && mRenderer->getShaderModelSuffix() == "") + { + vertexHLSL += " output.dx_Position.x = gl_Position.x;\n" + " output.dx_Position.y = -gl_Position.y;\n" + " output.dx_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n" + " output.dx_Position.w = gl_Position.w;\n"; + } + else + { + vertexHLSL += " output.dx_Position.x = gl_Position.x * dx_ViewAdjust.z + dx_ViewAdjust.x * gl_Position.w;\n" + " output.dx_Position.y = -(gl_Position.y * dx_ViewAdjust.w + dx_ViewAdjust.y * gl_Position.w);\n" + " output.dx_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n" + " output.dx_Position.w = gl_Position.w;\n"; + } + + // We don't need to output gl_PointSize if we use are emulating point sprites via instancing. + if (usesPointSize && shaderModel >= 3 && !useInstancedPointSpriteEmulation) + { + vertexHLSL += " output.gl_PointSize = gl_PointSize;\n"; + } + + if (usesFragCoord) + { + vertexHLSL += " output.gl_FragCoord = gl_Position;\n"; + } + + const std::vector &vertexVaryings = vertexShader->getVaryings(); + for (unsigned int vertVaryingIndex = 0; vertVaryingIndex < vertexVaryings.size(); vertVaryingIndex++) + { + const PackedVarying &varying = vertexVaryings[vertVaryingIndex]; + if (varying.registerAssigned()) + { + for (unsigned int elementIndex = 0; elementIndex < varying.elementCount(); elementIndex++) + { + int variableRows = (varying.isStruct() ? 1 : VariableRowCount(TransposeMatrixType(varying.type))); + + for (int row = 0; row < variableRows; row++) + { + int r = varying.registerIndex + varying.columnIndex * data.caps->maxVaryingVectors + elementIndex * variableRows + row; + vertexHLSL += " output.v" + Str(r); + + vertexHLSL += " = _" + varying.name; + + if (varying.isArray()) + { + vertexHLSL += ArrayString(elementIndex); + } + + if (variableRows > 1) + { + vertexHLSL += ArrayString(row); + } + + vertexHLSL += ";\n"; + } + } + } + } + + // Instanced PointSprite emulation requires additional entries to calculate + // the final output vertex positions of the quad that represents each sprite. + if (useInstancedPointSpriteEmulation) + { + vertexHLSL += "\n" + " gl_PointSize = clamp(gl_PointSize, minPointSize, maxPointSize);\n" + " output.dx_Position.xyz += float3(input.spriteVertexPos.x * gl_PointSize / (dx_ViewCoords.x*2), input.spriteVertexPos.y * gl_PointSize / (dx_ViewCoords.y*2), input.spriteVertexPos.z) * output.dx_Position.w;\n"; + + if (usesPointCoord) + { + vertexHLSL += "\n" + " output.gl_PointCoord = input.spriteTexCoord;\n"; + } + } + + vertexHLSL += "\n" + " return output;\n" + "}\n"; + + const SemanticInfo &pixelSemantics = getSemanticInfo(registers, outputPositionFromVS, usesFragCoord, usesPointCoord, + (!useInstancedPointSpriteEmulation && usesPointSize), true); + + pixelHLSL += "struct PS_INPUT\n" + generateVaryingLinkHLSL(pixelSemantics, varyingHLSL) + "\n"; + + if (shaderVersion < 300) + { + for (unsigned int renderTargetIndex = 0; renderTargetIndex < numRenderTargets; renderTargetIndex++) + { + PixelShaderOutputVariable outputKeyVariable; + outputKeyVariable.type = GL_FLOAT_VEC4; + outputKeyVariable.name = "gl_Color" + Str(renderTargetIndex); + outputKeyVariable.source = broadcast ? "gl_Color[0]" : "gl_Color[" + Str(renderTargetIndex) + "]"; + outputKeyVariable.outputIndex = renderTargetIndex; + + outPixelShaderKey->push_back(outputKeyVariable); + } + + *outUsesFragDepth = fragmentShader->mUsesFragDepth; + } + else + { + defineOutputVariables(fragmentShader, programOutputVars); + + const std::vector &shaderOutputVars = fragmentShader->getActiveOutputVariables(); + for (auto locationIt = programOutputVars->begin(); locationIt != programOutputVars->end(); locationIt++) + { + const VariableLocation &outputLocation = locationIt->second; + const sh::ShaderVariable &outputVariable = shaderOutputVars[outputLocation.index]; + const std::string &variableName = "out_" + outputLocation.name; + const std::string &elementString = (outputLocation.element == GL_INVALID_INDEX ? "" : Str(outputLocation.element)); + + ASSERT(outputVariable.staticUse); + + PixelShaderOutputVariable outputKeyVariable; + outputKeyVariable.type = outputVariable.type; + outputKeyVariable.name = variableName + elementString; + outputKeyVariable.source = variableName + ArrayString(outputLocation.element); + outputKeyVariable.outputIndex = locationIt->first; + + outPixelShaderKey->push_back(outputKeyVariable); + } + + *outUsesFragDepth = false; + } + + pixelHLSL += PIXEL_OUTPUT_STUB_STRING + "\n"; + + if (fragmentShader->mUsesFrontFacing) + { + 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"; + } + + if (usesFragCoord) + { + pixelHLSL += " float rhw = 1.0 / input.gl_FragCoord.w;\n"; + + // Certain Shader Models (4_0+ and 3_0) allow reading from dx_Position in the pixel shader. + // Other Shader Models (4_0_level_9_3 and 2_x) don't support this, so we emulate it using dx_ViewCoords. + if (shaderModel >= 4 && mRenderer->getShaderModelSuffix() == "") + { + pixelHLSL += " gl_FragCoord.x = input.dx_Position.x;\n" + " gl_FragCoord.y = input.dx_Position.y;\n"; + } + else if (shaderModel == 3) + { + pixelHLSL += " gl_FragCoord.x = input.dx_Position.x + 0.5;\n" + " gl_FragCoord.y = input.dx_Position.y + 0.5;\n"; + } + else + { + // 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_DepthFront.x + dx_DepthFront.y;\n" + " gl_FragCoord.w = rhw;\n"; + } + + if (usesPointCoord && shaderModel >= 3) + { + pixelHLSL += " gl_PointCoord.x = input.gl_PointCoord.x;\n"; + pixelHLSL += " gl_PointCoord.y = 1.0 - input.gl_PointCoord.y;\n"; + } + + if (fragmentShader->mUsesFrontFacing) + { + if (shaderModel <= 3) + { + pixelHLSL += " gl_FrontFacing = (vFace * dx_DepthFront.z >= 0.0);\n"; + } + else + { + pixelHLSL += " gl_FrontFacing = isFrontFace;\n"; + } + } + + const std::vector &fragmentVaryings = fragmentShader->getVaryings(); + for (unsigned int varyingIndex = 0; varyingIndex < fragmentVaryings.size(); varyingIndex++) + { + const PackedVarying &varying = fragmentVaryings[varyingIndex]; + if (varying.registerAssigned()) + { + ASSERT(!varying.isBuiltIn()); + for (unsigned int elementIndex = 0; elementIndex < varying.elementCount(); elementIndex++) + { + GLenum transposedType = TransposeMatrixType(varying.type); + int variableRows = (varying.isStruct() ? 1 : VariableRowCount(transposedType)); + for (int row = 0; row < variableRows; row++) + { + std::string n = Str(varying.registerIndex + varying.columnIndex * data.caps->maxVaryingVectors + elementIndex * variableRows + row); + pixelHLSL += " _" + varying.name; + + if (varying.isArray()) + { + pixelHLSL += ArrayString(elementIndex); + } + + if (variableRows > 1) + { + pixelHLSL += ArrayString(row); + } + + if (varying.isStruct()) + { + pixelHLSL += " = input.v" + n + ";\n"; break; + } + else + { + switch (VariableColumnCount(transposedType)) + { + 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(); + } + } + } + } + } + else + { + ASSERT(varying.isBuiltIn() || !varying.staticUse); + } + } + + if (fragmentShader->usesDeferredInit()) + { + pixelHLSL += "\n" + " initializeDeferredGlobals();\n"; + } + + pixelHLSL += "\n" + " gl_main();\n" + "\n" + " return generateOutput();\n" + "}\n"; + + return true; +} + +void DynamicHLSL::defineOutputVariables(ShaderD3D *fragmentShader, std::map *programOutputVars) const +{ + const std::vector &shaderOutputVars = fragmentShader->getActiveOutputVariables(); + + for (unsigned int outputVariableIndex = 0; outputVariableIndex < shaderOutputVars.size(); outputVariableIndex++) + { + const sh::Attribute &outputVariable = shaderOutputVars[outputVariableIndex]; + const int baseLocation = outputVariable.location == -1 ? 0 : outputVariable.location; + + ASSERT(outputVariable.staticUse); + + if (outputVariable.arraySize > 0) + { + for (unsigned int elementIndex = 0; elementIndex < outputVariable.arraySize; elementIndex++) + { + const int location = baseLocation + elementIndex; + ASSERT(programOutputVars->count(location) == 0); + (*programOutputVars)[location] = VariableLocation(outputVariable.name, elementIndex, outputVariableIndex); + } + } + else + { + ASSERT(programOutputVars->count(baseLocation) == 0); + (*programOutputVars)[baseLocation] = VariableLocation(outputVariable.name, GL_INVALID_INDEX, outputVariableIndex); + } + } +} + +std::string DynamicHLSL::generateGeometryShaderHLSL(int registers, ShaderD3D *fragmentShader, ShaderD3D *vertexShader) const +{ + // for now we only handle point sprite emulation + ASSERT(vertexShader->mUsesPointSize && mRenderer->getMajorShaderModel() >= 4); + return generatePointSpriteHLSL(registers, fragmentShader, vertexShader); +} + +std::string DynamicHLSL::generatePointSpriteHLSL(int registers, ShaderD3D *fragmentShader, ShaderD3D *vertexShader) const +{ + ASSERT(registers >= 0); + ASSERT(vertexShader->mUsesPointSize); + ASSERT(mRenderer->getMajorShaderModel() >= 4); + + std::string geomHLSL; + + const SemanticInfo &inSemantics = getSemanticInfo(registers, true, fragmentShader->mUsesFragCoord, + false, true, false); + const SemanticInfo &outSemantics = getSemanticInfo(registers, true, fragmentShader->mUsesFragCoord, + fragmentShader->mUsesPointCoord, true, false); + + std::string varyingHLSL = generateVaryingHLSL(vertexShader); + std::string inLinkHLSL = generateVaryingLinkHLSL(inSemantics, varyingHLSL); + std::string outLinkHLSL = generateVaryingLinkHLSL(outSemantics, varyingHLSL); + + // TODO(geofflang): use context's caps + geomHLSL += "uniform float4 dx_ViewCoords : register(c1);\n" + "\n" + "struct GS_INPUT\n" + inLinkHLSL + "\n" + + "struct GS_OUTPUT\n" + outLinkHLSL + "\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(mRenderer->getRendererCaps().minAliasedPointSize) + ".0f;\n" + "static float maxPointSize = " + Str(mRenderer->getRendererCaps().maxAliasedPointSize) + ".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_Position = input[0].gl_Position;\n" + " output.gl_PointSize = input[0].gl_PointSize;\n"; + + for (int r = 0; r < registers; r++) + { + geomHLSL += " output.v" + Str(r) + " = input[0].v" + Str(r) + ";\n"; + } + + if (fragmentShader->mUsesFragCoord) + { + geomHLSL += " output.gl_FragCoord = input[0].gl_FragCoord;\n"; + } + + geomHLSL += " \n" + " float gl_PointSize = clamp(input[0].gl_PointSize, minPointSize, maxPointSize);\n" + " float4 dx_Position = input[0].dx_Position;\n" + " float2 viewportScale = float2(1.0f / dx_ViewCoords.x, 1.0f / dx_ViewCoords.y) * dx_Position.w;\n"; + + for (int corner = 0; corner < 4; corner++) + { + geomHLSL += " \n" + " output.dx_Position = dx_Position + float4(pointSpriteCorners[" + Str(corner) + "] * viewportScale * gl_PointSize, 0.0f, 0.0f);\n"; + + if (fragmentShader->mUsesPointCoord) + { + geomHLSL += " output.gl_PointCoord = pointSpriteTexcoords[" + Str(corner) + "];\n"; + } + + geomHLSL += " outStream.Append(output);\n"; + } + + geomHLSL += " \n" + " outStream.RestartStrip();\n" + "}\n"; + + return geomHLSL; +} + +// This method needs to match OutputHLSL::decorate +std::string DynamicHLSL::decorateVariable(const std::string &name) +{ + if (name.compare(0, 3, "gl_") != 0) + { + return "_" + name; + } + + return name; +} + +std::string DynamicHLSL::generateAttributeConversionHLSL(const VertexFormat &vertexFormat, const sh::ShaderVariable &shaderAttrib) const +{ + std::string attribString = "input." + decorateVariable(shaderAttrib.name); + + // Matrix + if (IsMatrixType(shaderAttrib.type)) + { + return "transpose(" + attribString + ")"; + } + + GLenum shaderComponentType = VariableComponentType(shaderAttrib.type); + int shaderComponentCount = VariableComponentCount(shaderAttrib.type); + + // Perform integer to float conversion (if necessary) + bool requiresTypeConversion = (shaderComponentType == GL_FLOAT && vertexFormat.mType != GL_FLOAT); + + if (requiresTypeConversion) + { + // TODO: normalization for 32-bit integer formats + ASSERT(!vertexFormat.mNormalized && !vertexFormat.mPureInteger); + return "float" + Str(shaderComponentCount) + "(" + attribString + ")"; + } + + // No conversion necessary + return attribString; +} + +void DynamicHLSL::getInputLayoutSignature(const VertexFormat inputLayout[], GLenum signature[]) const +{ + for (size_t inputIndex = 0; inputIndex < MAX_VERTEX_ATTRIBS; inputIndex++) + { + const VertexFormat &vertexFormat = inputLayout[inputIndex]; + + if (vertexFormat.mType == GL_NONE) + { + signature[inputIndex] = GL_NONE; + } + else + { + bool gpuConverted = ((mRenderer->getVertexConversionType(vertexFormat) & VERTEX_CONVERT_GPU) != 0); + signature[inputIndex] = (gpuConverted ? GL_TRUE : GL_FALSE); + } + } +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/DynamicHLSL.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/DynamicHLSL.h new file mode 100644 index 0000000000..26ae13b342 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/DynamicHLSL.h @@ -0,0 +1,99 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// DynamicHLSL.h: Interface for link and run-time HLSL generation +// + +#ifndef LIBANGLE_RENDERER_D3D_DYNAMICHLSL_H_ +#define LIBANGLE_RENDERER_D3D_DYNAMICHLSL_H_ + +#include "common/angleutils.h" +#include "libANGLE/Constants.h" + +#include "angle_gl.h" + +#include +#include + +namespace sh +{ +struct Attribute; +struct ShaderVariable; +} + +namespace gl +{ +class InfoLog; +struct VariableLocation; +struct LinkedVarying; +struct VertexAttribute; +struct VertexFormat; +struct PackedVarying; +struct Data; +} + +namespace rx +{ +class RendererD3D; +class ShaderD3D; + +typedef const gl::PackedVarying *VaryingPacking[gl::IMPLEMENTATION_MAX_VARYING_VECTORS][4]; + +struct PixelShaderOutputVariable +{ + GLenum type; + std::string name; + std::string source; + size_t outputIndex; +}; + +class DynamicHLSL : angle::NonCopyable +{ + public: + explicit DynamicHLSL(RendererD3D *const renderer); + + int packVaryings(gl::InfoLog &infoLog, VaryingPacking packing, ShaderD3D *fragmentShader, + ShaderD3D *vertexShader, const std::vector& transformFeedbackVaryings); + std::string generateVertexShaderForInputLayout(const std::string &sourceShader, const gl::VertexFormat inputLayout[], + const sh::Attribute shaderAttributes[]) const; + std::string generatePixelShaderForOutputSignature(const std::string &sourceShader, const std::vector &outputVariables, + bool usesFragDepth, const std::vector &outputLayout) const; + bool generateShaderLinkHLSL(const gl::Data &data, gl::InfoLog &infoLog, int registers, + const VaryingPacking packing, + std::string &pixelHLSL, std::string &vertexHLSL, + ShaderD3D *fragmentShader, ShaderD3D *vertexShader, + const std::vector &transformFeedbackVaryings, + std::vector *linkedVaryings, + std::map *programOutputVars, + std::vector *outPixelShaderKey, + bool *outUsesFragDepth) const; + + std::string generateGeometryShaderHLSL(int registers, ShaderD3D *fragmentShader, ShaderD3D *vertexShader) const; + void getInputLayoutSignature(const gl::VertexFormat inputLayout[], GLenum signature[]) const; + + private: + RendererD3D *const mRenderer; + + struct SemanticInfo; + + std::string getVaryingSemantic(bool pointSize) const; + SemanticInfo getSemanticInfo(int startRegisters, bool position, bool fragCoord, bool pointCoord, + bool pointSize, bool pixelShader) const; + std::string generateVaryingLinkHLSL(const SemanticInfo &info, const std::string &varyingHLSL) const; + std::string generateVaryingHLSL(const ShaderD3D *shader) const; + void storeUserLinkedVaryings(const ShaderD3D *vertexShader, std::vector *linkedVaryings) const; + void storeBuiltinLinkedVaryings(const SemanticInfo &info, std::vector *linkedVaryings) const; + void defineOutputVariables(ShaderD3D *fragmentShader, std::map *programOutputVars) const; + std::string generatePointSpriteHLSL(int registers, ShaderD3D *fragmentShader, ShaderD3D *vertexShader) const; + + // Prepend an underscore + static std::string decorateVariable(const std::string &name); + + std::string generateAttributeConversionHLSL(const gl::VertexFormat &vertexFormat, const sh::ShaderVariable &shaderAttrib) const; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_DYNAMICHLSL_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/FramebufferD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/FramebufferD3D.cpp new file mode 100644 index 0000000000..1a4734b269 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/FramebufferD3D.cpp @@ -0,0 +1,463 @@ +// +// Copyright 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// FramebufferD3D.cpp: Implements the DefaultAttachmentD3D and FramebufferD3D classes. + +#include "libANGLE/renderer/d3d/FramebufferD3D.h" + +#include "libANGLE/formatutils.h" +#include "libANGLE/Framebuffer.h" +#include "libANGLE/FramebufferAttachment.h" +#include "libANGLE/Surface.h" +#include "libANGLE/renderer/d3d/RendererD3D.h" +#include "libANGLE/renderer/d3d/RenderbufferD3D.h" +#include "libANGLE/renderer/d3d/RenderTargetD3D.h" +#include "libANGLE/renderer/d3d/SurfaceD3D.h" +#include "libANGLE/renderer/d3d/SwapChainD3D.h" +#include "libANGLE/renderer/d3d/TextureD3D.h" + +namespace rx +{ + +namespace +{ + +ClearParameters GetClearParameters(const gl::State &state, GLbitfield mask) +{ + ClearParameters clearParams; + memset(&clearParams, 0, sizeof(ClearParameters)); + + const auto &blendState = state.getBlendState(); + + for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++) + { + clearParams.clearColor[i] = false; + } + clearParams.colorFClearValue = state.getColorClearValue(); + clearParams.colorClearType = GL_FLOAT; + clearParams.colorMaskRed = blendState.colorMaskRed; + clearParams.colorMaskGreen = blendState.colorMaskGreen; + clearParams.colorMaskBlue = blendState.colorMaskBlue; + clearParams.colorMaskAlpha = blendState.colorMaskAlpha; + clearParams.clearDepth = false; + clearParams.depthClearValue = state.getDepthClearValue(); + clearParams.clearStencil = false; + clearParams.stencilClearValue = state.getStencilClearValue(); + clearParams.stencilWriteMask = state.getDepthStencilState().stencilWritemask; + clearParams.scissorEnabled = state.isScissorTestEnabled(); + clearParams.scissor = state.getScissor(); + + const gl::Framebuffer *framebufferObject = state.getDrawFramebuffer(); + if (mask & GL_COLOR_BUFFER_BIT) + { + if (framebufferObject->hasEnabledColorAttachment()) + { + for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++) + { + clearParams.clearColor[i] = true; + } + } + } + + if (mask & GL_DEPTH_BUFFER_BIT) + { + if (state.getDepthStencilState().depthMask && framebufferObject->getDepthbuffer() != NULL) + { + clearParams.clearDepth = true; + } + } + + if (mask & GL_STENCIL_BUFFER_BIT) + { + if (framebufferObject->getStencilbuffer() != NULL && + framebufferObject->getStencilbuffer()->getStencilSize() > 0) + { + clearParams.clearStencil = true; + } + } + + return clearParams; +} + +} + +FramebufferD3D::FramebufferD3D(const gl::Framebuffer::Data &data, RendererD3D *renderer) + : FramebufferImpl(data), + mRenderer(renderer), + mColorAttachmentsForRender(mData.mColorAttachments.size(), nullptr), + mInvalidateColorAttachmentCache(true) +{ + ASSERT(mRenderer != nullptr); +} + +FramebufferD3D::~FramebufferD3D() +{ +} + +void FramebufferD3D::setColorAttachment(size_t, const gl::FramebufferAttachment *) +{ + mInvalidateColorAttachmentCache = true; +} + +void FramebufferD3D::setDepthAttachment(const gl::FramebufferAttachment *) +{ +} + +void FramebufferD3D::setStencilAttachment(const gl::FramebufferAttachment *) +{ +} + +void FramebufferD3D::setDepthStencilAttachment(const gl::FramebufferAttachment *) +{ +} + +void FramebufferD3D::setDrawBuffers(size_t, const GLenum *) +{ + mInvalidateColorAttachmentCache = true; +} + +void FramebufferD3D::setReadBuffer(GLenum) +{ +} + +gl::Error FramebufferD3D::invalidate(size_t, const GLenum *) +{ + // No-op in D3D + return gl::Error(GL_NO_ERROR); +} + +gl::Error FramebufferD3D::invalidateSub(size_t, const GLenum *, const gl::Rectangle &) +{ + // No-op in D3D + return gl::Error(GL_NO_ERROR); +} + +gl::Error FramebufferD3D::clear(const gl::Data &data, GLbitfield mask) +{ + const gl::State &state = *data.state; + ClearParameters clearParams = GetClearParameters(state, mask); + return clear(state, clearParams); +} + +gl::Error FramebufferD3D::clearBufferfv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLfloat *values) +{ + // glClearBufferfv can be called to clear the color buffer or depth buffer + ClearParameters clearParams = GetClearParameters(state, 0); + + if (buffer == GL_COLOR) + { + for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++) + { + clearParams.clearColor[i] = (drawbuffer == static_cast(i)); + } + clearParams.colorFClearValue = gl::ColorF(values[0], values[1], values[2], values[3]); + clearParams.colorClearType = GL_FLOAT; + } + + if (buffer == GL_DEPTH) + { + clearParams.clearDepth = true; + clearParams.depthClearValue = values[0]; + } + + return clear(state, clearParams); +} + +gl::Error FramebufferD3D::clearBufferuiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLuint *values) +{ + // glClearBufferuiv can only be called to clear a color buffer + ClearParameters clearParams = GetClearParameters(state, 0); + for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++) + { + clearParams.clearColor[i] = (drawbuffer == static_cast(i)); + } + clearParams.colorUIClearValue = gl::ColorUI(values[0], values[1], values[2], values[3]); + clearParams.colorClearType = GL_UNSIGNED_INT; + + return clear(state, clearParams); +} + +gl::Error FramebufferD3D::clearBufferiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLint *values) +{ + // glClearBufferiv can be called to clear the color buffer or stencil buffer + ClearParameters clearParams = GetClearParameters(state, 0); + + if (buffer == GL_COLOR) + { + for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++) + { + clearParams.clearColor[i] = (drawbuffer == static_cast(i)); + } + clearParams.colorIClearValue = gl::ColorI(values[0], values[1], values[2], values[3]); + clearParams.colorClearType = GL_INT; + } + + if (buffer == GL_STENCIL) + { + clearParams.clearStencil = true; + clearParams.stencilClearValue = values[1]; + } + + return clear(state, clearParams); +} + +gl::Error FramebufferD3D::clearBufferfi(const gl::State &state, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) +{ + // glClearBufferfi can only be called to clear a depth stencil buffer + ClearParameters clearParams = GetClearParameters(state, 0); + clearParams.clearDepth = true; + clearParams.depthClearValue = depth; + clearParams.clearStencil = true; + clearParams.stencilClearValue = stencil; + + return clear(state, clearParams); +} + +GLenum FramebufferD3D::getImplementationColorReadFormat() const +{ + const gl::FramebufferAttachment *readAttachment = mData.getReadAttachment(); + + if (readAttachment == nullptr) + { + return GL_NONE; + } + + RenderTargetD3D *attachmentRenderTarget = NULL; + gl::Error error = GetAttachmentRenderTarget(readAttachment, &attachmentRenderTarget); + if (error.isError()) + { + return GL_NONE; + } + + GLenum implementationFormat = getRenderTargetImplementationFormat(attachmentRenderTarget); + const gl::InternalFormat &implementationFormatInfo = gl::GetInternalFormatInfo(implementationFormat); + + return implementationFormatInfo.format; +} + +GLenum FramebufferD3D::getImplementationColorReadType() const +{ + const gl::FramebufferAttachment *readAttachment = mData.getReadAttachment(); + + if (readAttachment == nullptr) + { + return GL_NONE; + } + + RenderTargetD3D *attachmentRenderTarget = NULL; + gl::Error error = GetAttachmentRenderTarget(readAttachment, &attachmentRenderTarget); + if (error.isError()) + { + return GL_NONE; + } + + GLenum implementationFormat = getRenderTargetImplementationFormat(attachmentRenderTarget); + const gl::InternalFormat &implementationFormatInfo = gl::GetInternalFormatInfo(implementationFormat); + + return implementationFormatInfo.type; +} + +gl::Error FramebufferD3D::readPixels(const gl::State &state, const gl::Rectangle &area, GLenum format, GLenum type, GLvoid *pixels) const +{ + const gl::PixelPackState &packState = state.getPackState(); + + if (packState.rowLength != 0 || packState.skipRows != 0 || packState.skipPixels != 0) + { + UNIMPLEMENTED(); + return gl::Error(GL_INVALID_OPERATION, "invalid pixel store parameters in readPixels"); + } + + GLenum sizedInternalFormat = gl::GetSizedInternalFormat(format, type); + const gl::InternalFormat &sizedFormatInfo = gl::GetInternalFormatInfo(sizedInternalFormat); + GLuint outputPitch = sizedFormatInfo.computeRowPitch(type, area.width, packState.alignment, 0); + + return readPixels(area, format, type, outputPitch, packState, reinterpret_cast(pixels)); +} + +gl::Error FramebufferD3D::blit(const gl::State &state, const gl::Rectangle &sourceArea, const gl::Rectangle &destArea, + GLbitfield mask, GLenum filter, const gl::Framebuffer *sourceFramebuffer) +{ + bool blitRenderTarget = false; + if ((mask & GL_COLOR_BUFFER_BIT) && + sourceFramebuffer->getReadColorbuffer() != nullptr && + mData.getFirstColorAttachment() != nullptr) + { + blitRenderTarget = true; + } + + bool blitStencil = false; + if ((mask & GL_STENCIL_BUFFER_BIT) && + sourceFramebuffer->getStencilbuffer() != nullptr && + mData.mStencilAttachment != nullptr) + { + blitStencil = true; + } + + bool blitDepth = false; + if ((mask & GL_DEPTH_BUFFER_BIT) && + sourceFramebuffer->getDepthbuffer() != nullptr && + mData.mDepthAttachment != nullptr) + { + blitDepth = true; + } + + if (blitRenderTarget || blitDepth || blitStencil) + { + const gl::Rectangle *scissor = state.isScissorTestEnabled() ? &state.getScissor() : NULL; + gl::Error error = blit(sourceArea, destArea, scissor, blitRenderTarget, blitDepth, blitStencil, + filter, sourceFramebuffer); + if (error.isError()) + { + return error; + } + } + + return gl::Error(GL_NO_ERROR); +} + +GLenum FramebufferD3D::checkStatus() const +{ + // D3D11 does not allow for overlapping RenderTargetViews, so ensure uniqueness + for (size_t colorAttachment = 0; colorAttachment < mData.mColorAttachments.size(); colorAttachment++) + { + const gl::FramebufferAttachment *attachment = mData.mColorAttachments[colorAttachment]; + if (attachment != nullptr) + { + for (size_t prevColorAttachment = 0; prevColorAttachment < colorAttachment; prevColorAttachment++) + { + const gl::FramebufferAttachment *prevAttachment = mData.mColorAttachments[prevColorAttachment]; + if (prevAttachment != nullptr && + (attachment->id() == prevAttachment->id() && + attachment->type() == prevAttachment->type())) + { + return GL_FRAMEBUFFER_UNSUPPORTED; + } + } + } + } + + return GL_FRAMEBUFFER_COMPLETE; +} + +const gl::AttachmentList &FramebufferD3D::getColorAttachmentsForRender(const Workarounds &workarounds) const +{ + if (!workarounds.mrtPerfWorkaround) + { + return mData.mColorAttachments; + } + + if (!mInvalidateColorAttachmentCache) + { + return mColorAttachmentsForRender; + } + + // Does not actually free memory + mColorAttachmentsForRender.clear(); + + for (size_t attachmentIndex = 0; attachmentIndex < mData.mColorAttachments.size(); ++attachmentIndex) + { + GLenum drawBufferState = mData.mDrawBufferStates[attachmentIndex]; + gl::FramebufferAttachment *colorAttachment = mData.mColorAttachments[attachmentIndex]; + + if (colorAttachment != nullptr && drawBufferState != GL_NONE) + { + ASSERT(drawBufferState == GL_BACK || drawBufferState == (GL_COLOR_ATTACHMENT0_EXT + attachmentIndex)); + mColorAttachmentsForRender.push_back(colorAttachment); + } + } + + mInvalidateColorAttachmentCache = false; + return mColorAttachmentsForRender; +} + +gl::Error GetAttachmentRenderTarget(const gl::FramebufferAttachment *attachment, RenderTargetD3D **outRT) +{ + if (attachment->type() == GL_TEXTURE) + { + gl::Texture *texture = attachment->getTexture(); + ASSERT(texture); + TextureD3D *textureD3D = GetImplAs(texture); + const gl::ImageIndex *index = attachment->getTextureImageIndex(); + ASSERT(index); + return textureD3D->getRenderTarget(*index, outRT); + } + else if (attachment->type() == GL_RENDERBUFFER) + { + gl::Renderbuffer *renderbuffer = attachment->getRenderbuffer(); + ASSERT(renderbuffer); + RenderbufferD3D *renderbufferD3D = RenderbufferD3D::makeRenderbufferD3D(renderbuffer->getImplementation()); + *outRT = renderbufferD3D->getRenderTarget(); + return gl::Error(GL_NO_ERROR); + } + else if (attachment->type() == GL_FRAMEBUFFER_DEFAULT) + { + const gl::DefaultAttachment *defaultAttachment = static_cast(attachment); + const egl::Surface *surface = defaultAttachment->getSurface(); + ASSERT(surface); + const SurfaceD3D *surfaceD3D = GetImplAs(surface); + ASSERT(surfaceD3D); + + if (defaultAttachment->getBinding() == GL_BACK) + { + *outRT = surfaceD3D->getSwapChain()->getColorRenderTarget(); + } + else + { + *outRT = surfaceD3D->getSwapChain()->getDepthStencilRenderTarget(); + } + return gl::Error(GL_NO_ERROR); + } + else + { + UNREACHABLE(); + return gl::Error(GL_INVALID_OPERATION); + } +} + +// Note: RenderTarget serials should ideally be in the RenderTargets themselves. +unsigned int GetAttachmentSerial(const gl::FramebufferAttachment *attachment) +{ + if (attachment->type() == GL_TEXTURE) + { + gl::Texture *texture = attachment->getTexture(); + ASSERT(texture); + TextureD3D *textureD3D = GetImplAs(texture); + const gl::ImageIndex *index = attachment->getTextureImageIndex(); + ASSERT(index); + return textureD3D->getRenderTargetSerial(*index); + } + else if (attachment->type() == GL_RENDERBUFFER) + { + gl::Renderbuffer *renderbuffer = attachment->getRenderbuffer(); + ASSERT(renderbuffer); + RenderbufferD3D *renderbufferD3D = RenderbufferD3D::makeRenderbufferD3D(renderbuffer->getImplementation()); + return renderbufferD3D->getRenderTargetSerial(); + } + else if (attachment->type() == GL_FRAMEBUFFER_DEFAULT) + { + const gl::DefaultAttachment *defaultAttachment = static_cast(attachment); + const egl::Surface *surface = defaultAttachment->getSurface(); + ASSERT(surface); + const SurfaceD3D *surfaceD3D = GetImplAs(surface); + ASSERT(surfaceD3D); + + if (defaultAttachment->getBinding() == GL_BACK) + { + return surfaceD3D->getSwapChain()->getColorRenderTarget()->getSerial(); + } + else + { + return surfaceD3D->getSwapChain()->getDepthStencilRenderTarget()->getSerial(); + } + } + else + { + UNREACHABLE(); + return 0; + } +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/FramebufferD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/FramebufferD3D.h new file mode 100644 index 0000000000..d5d2dae8bd --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/FramebufferD3D.h @@ -0,0 +1,111 @@ +// +// Copyright 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// FramebufferD3D.h: Defines the DefaultAttachmentD3D and FramebufferD3D classes. + +#ifndef LIBANGLE_RENDERER_D3D_FRAMBUFFERD3D_H_ +#define LIBANGLE_RENDERER_D3D_FRAMBUFFERD3D_H_ + +#include +#include + +#include "libANGLE/angletypes.h" +#include "libANGLE/renderer/FramebufferImpl.h" + +namespace gl +{ +class FramebufferAttachment; +struct PixelPackState; +} + +namespace rx +{ +class RenderTargetD3D; +class RendererD3D; + +struct ClearParameters +{ + bool clearColor[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS]; + gl::ColorF colorFClearValue; + gl::ColorI colorIClearValue; + gl::ColorUI colorUIClearValue; + GLenum colorClearType; + bool colorMaskRed; + bool colorMaskGreen; + bool colorMaskBlue; + bool colorMaskAlpha; + + bool clearDepth; + float depthClearValue; + + bool clearStencil; + GLint stencilClearValue; + GLuint stencilWriteMask; + + bool scissorEnabled; + gl::Rectangle scissor; +}; + +class FramebufferD3D : public FramebufferImpl +{ + public: + FramebufferD3D(const gl::Framebuffer::Data &data, RendererD3D *renderer); + virtual ~FramebufferD3D(); + + void setColorAttachment(size_t index, const gl::FramebufferAttachment *attachment) override; + void setDepthAttachment(const gl::FramebufferAttachment *attachment) override; + void setStencilAttachment(const gl::FramebufferAttachment *attachment) override; + void setDepthStencilAttachment(const gl::FramebufferAttachment *attachment) override; + + void setDrawBuffers(size_t count, const GLenum *buffers) override; + void setReadBuffer(GLenum buffer) override; + + gl::Error invalidate(size_t count, const GLenum *attachments) override; + gl::Error invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area) override; + + gl::Error clear(const gl::Data &data, GLbitfield mask) override; + gl::Error clearBufferfv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLfloat *values) override; + gl::Error clearBufferuiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLuint *values) override; + gl::Error clearBufferiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLint *values) override; + gl::Error clearBufferfi(const gl::State &state, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) override; + + GLenum getImplementationColorReadFormat() const override; + GLenum getImplementationColorReadType() const override; + gl::Error readPixels(const gl::State &state, const gl::Rectangle &area, GLenum format, GLenum type, GLvoid *pixels) const override; + + gl::Error blit(const gl::State &state, const gl::Rectangle &sourceArea, const gl::Rectangle &destArea, + GLbitfield mask, GLenum filter, const gl::Framebuffer *sourceFramebuffer) override; + + GLenum checkStatus() const override; + + const gl::AttachmentList &getColorAttachmentsForRender(const Workarounds &workarounds) const; + + protected: + // Cache variable + mutable gl::AttachmentList mColorAttachmentsForRender; + mutable bool mInvalidateColorAttachmentCache; + + private: + RendererD3D *const mRenderer; + + virtual gl::Error clear(const gl::State &state, const ClearParameters &clearParams) = 0; + + virtual gl::Error readPixels(const gl::Rectangle &area, GLenum format, GLenum type, size_t outputPitch, + const gl::PixelPackState &pack, uint8_t *pixels) const = 0; + + virtual gl::Error blit(const gl::Rectangle &sourceArea, const gl::Rectangle &destArea, const gl::Rectangle *scissor, + bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter, + const gl::Framebuffer *sourceFramebuffer) = 0; + + virtual GLenum getRenderTargetImplementationFormat(RenderTargetD3D *renderTarget) const = 0; +}; + +gl::Error GetAttachmentRenderTarget(const gl::FramebufferAttachment *attachment, RenderTargetD3D **outRT); +unsigned int GetAttachmentSerial(const gl::FramebufferAttachment *attachment); + +} + +#endif // LIBANGLE_RENDERER_D3D_FRAMBUFFERD3D_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp new file mode 100644 index 0000000000..8961a36ec5 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp @@ -0,0 +1,340 @@ +// +// Copyright 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "libANGLE/renderer/d3d/HLSLCompiler.h" +#include "libANGLE/Program.h" +#include "libANGLE/features.h" + +#include "common/utilities.h" + +#include "third_party/trace_event/trace_event.h" + +#ifndef QT_D3DCOMPILER_DLL +#define QT_D3DCOMPILER_DLL D3DCOMPILER_DLL +#endif + +// Definitions local to the translation unit +namespace +{ + +#ifdef CREATE_COMPILER_FLAG_INFO + #undef CREATE_COMPILER_FLAG_INFO +#endif + +#define CREATE_COMPILER_FLAG_INFO(flag) { flag, #flag } + +#if defined(ANGLE_MINGW32_COMPAT) +#ifndef D3DCOMPILE_RESERVED16 +#define D3DCOMPILE_RESERVED16 0x10000 +#endif +#ifndef D3DCOMPILE_RESERVED17 +#define D3DCOMPILE_RESERVED17 0x20000 +#endif +#endif + +struct CompilerFlagInfo +{ + UINT mFlag; + const char *mName; +}; + +CompilerFlagInfo CompilerFlagInfos[] = +{ + // NOTE: The data below is copied from d3dcompiler.h + // If something changes there it should be changed here as well + CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_DEBUG), // (1 << 0) + CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_SKIP_VALIDATION), // (1 << 1) + CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_SKIP_OPTIMIZATION), // (1 << 2) + CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_PACK_MATRIX_ROW_MAJOR), // (1 << 3) + CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_PACK_MATRIX_COLUMN_MAJOR), // (1 << 4) + CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_PARTIAL_PRECISION), // (1 << 5) + CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_FORCE_VS_SOFTWARE_NO_OPT), // (1 << 6) + CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_FORCE_PS_SOFTWARE_NO_OPT), // (1 << 7) + CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_NO_PRESHADER), // (1 << 8) + CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_AVOID_FLOW_CONTROL), // (1 << 9) + CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_PREFER_FLOW_CONTROL), // (1 << 10) + CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_ENABLE_STRICTNESS), // (1 << 11) + CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_ENABLE_BACKWARDS_COMPATIBILITY), // (1 << 12) + CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_IEEE_STRICTNESS), // (1 << 13) + CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_OPTIMIZATION_LEVEL0), // (1 << 14) + CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_OPTIMIZATION_LEVEL1), // 0 + CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_OPTIMIZATION_LEVEL2), // ((1 << 14) | (1 << 15)) + CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_OPTIMIZATION_LEVEL3), // (1 << 15) + CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_RESERVED16), // (1 << 16) + CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_RESERVED17), // (1 << 17) + CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_WARNINGS_ARE_ERRORS) // (1 << 18) +}; + +#undef CREATE_COMPILER_FLAG_INFO + +bool IsCompilerFlagSet(UINT mask, UINT flag) +{ + bool isFlagSet = IsMaskFlagSet(mask, flag); + + switch(flag) + { + case D3DCOMPILE_OPTIMIZATION_LEVEL0: + return isFlagSet && !IsMaskFlagSet(mask, UINT(D3DCOMPILE_OPTIMIZATION_LEVEL3)); + + case D3DCOMPILE_OPTIMIZATION_LEVEL1: + return (mask & D3DCOMPILE_OPTIMIZATION_LEVEL2) == UINT(0); + + case D3DCOMPILE_OPTIMIZATION_LEVEL3: + return isFlagSet && !IsMaskFlagSet(mask, UINT(D3DCOMPILE_OPTIMIZATION_LEVEL0)); + + default: + return isFlagSet; + } +} + +const char *GetCompilerFlagName(UINT mask, size_t flagIx) +{ + const CompilerFlagInfo &flagInfo = CompilerFlagInfos[flagIx]; + if (IsCompilerFlagSet(mask, flagInfo.mFlag)) + { + return flagInfo.mName; + } + + return nullptr; +} + +} + +namespace rx +{ + +CompileConfig::CompileConfig() + : flags(0), + name() +{ +} + +CompileConfig::CompileConfig(UINT flags, const std::string &name) + : flags(flags), + name(name) +{ +} + +HLSLCompiler::HLSLCompiler() + : mD3DCompilerModule(NULL), + mD3DCompileFunc(NULL), + mD3DDisassembleFunc(NULL) +{ +} + +HLSLCompiler::~HLSLCompiler() +{ + release(); +} + +bool HLSLCompiler::initialize() +{ + TRACE_EVENT0("gpu", "initializeCompiler"); +#if !defined(ANGLE_ENABLE_WINDOWS_STORE) +#if defined(ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES) + // Find a D3DCompiler module that had already been loaded based on a predefined list of versions. + static const char *d3dCompilerNames[] = ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES; + + for (size_t i = 0; i < ArraySize(d3dCompilerNames); ++i) + { + if (GetModuleHandleExA(0, d3dCompilerNames[i], &mD3DCompilerModule)) + { + break; + } + } +#endif // ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES + + // Load the compiler DLL specified by the environment, or default to QT_D3DCOMPILER_DLL + const wchar_t *defaultCompiler = _wgetenv(L"QT_D3DCOMPILER_DLL"); + if (!defaultCompiler) + defaultCompiler = QT_D3DCOMPILER_DLL; + + const wchar_t *compilerDlls[] = { + defaultCompiler, + L"d3dcompiler_47.dll", + L"d3dcompiler_46.dll", + L"d3dcompiler_43.dll", + 0 + }; + + // Load the first available known compiler DLL + for (int i = 0; compilerDlls[i]; ++i) + { + mD3DCompilerModule = LoadLibrary(compilerDlls[i]); + if (mD3DCompilerModule) + break; + } + + if (!mD3DCompilerModule) + { + // Load the version of the D3DCompiler DLL associated with the Direct3D version ANGLE was built with. + mD3DCompilerModule = LoadLibrary(D3DCOMPILER_DLL); + } + + if (!mD3DCompilerModule) + { + ERR("No D3D compiler module found - aborting!\n"); + return false; + } + + mD3DCompileFunc = reinterpret_cast(GetProcAddress(mD3DCompilerModule, "D3DCompile")); + ASSERT(mD3DCompileFunc); + + mD3DDisassembleFunc = reinterpret_cast(GetProcAddress(mD3DCompilerModule, "D3DDisassemble")); + ASSERT(mD3DDisassembleFunc); + +#else + // D3D Shader compiler is linked already into this module, so the export + // can be directly assigned. + mD3DCompilerModule = NULL; + mD3DCompileFunc = reinterpret_cast(D3DCompile); + mD3DDisassembleFunc = reinterpret_cast(D3DDisassemble); +#endif + + return mD3DCompileFunc != NULL; +} + +void HLSLCompiler::release() +{ + if (mD3DCompilerModule) + { + FreeLibrary(mD3DCompilerModule); + mD3DCompilerModule = NULL; + mD3DCompileFunc = NULL; + mD3DDisassembleFunc = NULL; + } +} + +gl::Error HLSLCompiler::compileToBinary(gl::InfoLog &infoLog, const std::string &hlsl, const std::string &profile, + const std::vector &configs, const D3D_SHADER_MACRO *overrideMacros, + ID3DBlob **outCompiledBlob, std::string *outDebugInfo) const +{ +#if !defined(ANGLE_ENABLE_WINDOWS_STORE) + ASSERT(mD3DCompilerModule); +#endif + ASSERT(mD3DCompileFunc); + +#if !defined(ANGLE_ENABLE_WINDOWS_STORE) + if (gl::DebugAnnotationsActive()) + { + std::string sourcePath = getTempPath(); + std::string sourceText = FormatString("#line 2 \"%s\"\n\n%s", sourcePath.c_str(), hlsl.c_str()); + writeFile(sourcePath.c_str(), sourceText.c_str(), sourceText.size()); + } +#endif + + const D3D_SHADER_MACRO *macros = overrideMacros ? overrideMacros : NULL; + + for (size_t i = 0; i < configs.size(); ++i) + { + ID3DBlob *errorMessage = NULL; + ID3DBlob *binary = NULL; + + HRESULT result = mD3DCompileFunc(hlsl.c_str(), hlsl.length(), gl::g_fakepath, macros, NULL, "main", profile.c_str(), + configs[i].flags, 0, &binary, &errorMessage); + + if (errorMessage) + { + std::string message = reinterpret_cast(errorMessage->GetBufferPointer()); + SafeRelease(errorMessage); + + infoLog.appendSanitized(message.c_str()); + TRACE("\n%s", hlsl.c_str()); + TRACE("\n%s", message.c_str()); + + if (message.find("error X3531:") != std::string::npos || // "can't unroll loops marked with loop attribute" + message.find("error X4014:") != std::string::npos) // "cannot have gradient operations inside loops with divergent flow control", + // even though it is counter-intuitive to disable unrolling for this error, + // some very long shaders have trouble deciding which loops to unroll and + // turning off forced unrolls allows them to compile properly. + { + macros = NULL; // Disable [loop] and [flatten] + + // Retry without changing compiler flags + i--; + continue; + } + } + + if (SUCCEEDED(result)) + { + *outCompiledBlob = binary; + +#if ANGLE_SHADER_DEBUG_INFO == ANGLE_ENABLED + (*outDebugInfo) += "// COMPILER INPUT HLSL BEGIN\n\n" + hlsl + "\n// COMPILER INPUT HLSL END\n"; + (*outDebugInfo) += "\n\n// ASSEMBLY BEGIN\n\n"; + (*outDebugInfo) += "// Compiler configuration: " + configs[i].name + "\n// Flags:\n"; + for (size_t fIx = 0; fIx < ArraySize(CompilerFlagInfos); ++fIx) + { + const char *flagName = GetCompilerFlagName(configs[i].flags, fIx); + if (flagName != nullptr) + { + (*outDebugInfo) += std::string("// ") + flagName + "\n"; + } + } + + (*outDebugInfo) += "// Macros:\n"; + if (macros == nullptr) + { + (*outDebugInfo) += "// - : -\n"; + } + else + { + for (const D3D_SHADER_MACRO *mIt = macros; mIt->Name != nullptr; ++mIt) + { + (*outDebugInfo) += std::string("// ") + mIt->Name + " : " + mIt->Definition + "\n"; + } + } + + (*outDebugInfo) += "\n" + disassembleBinary(binary) + "\n// ASSEMBLY END\n"; +#endif + + return gl::Error(GL_NO_ERROR); + } + else + { + if (result == E_OUTOFMEMORY) + { + *outCompiledBlob = NULL; + return gl::Error(GL_OUT_OF_MEMORY, "HLSL compiler had an unexpected failure, result: 0x%X.", result); + } + + infoLog.append("Warning: D3D shader compilation failed with %s flags.", configs[i].name.c_str()); + + if (i + 1 < configs.size()) + { + infoLog.append(" Retrying with %s.\n", configs[i + 1].name.c_str()); + } + } + } + + // None of the configurations succeeded in compiling this shader but the compiler is still intact + *outCompiledBlob = NULL; + return gl::Error(GL_NO_ERROR); +} + +std::string HLSLCompiler::disassembleBinary(ID3DBlob *shaderBinary) const +{ + // Retrieve disassembly + UINT flags = D3D_DISASM_ENABLE_DEFAULT_VALUE_PRINTS | D3D_DISASM_ENABLE_INSTRUCTION_NUMBERING; + ID3DBlob *disassembly = NULL; + pD3DDisassemble disassembleFunc = reinterpret_cast(mD3DDisassembleFunc); + LPCVOID buffer = shaderBinary->GetBufferPointer(); + SIZE_T bufSize = shaderBinary->GetBufferSize(); + HRESULT result = disassembleFunc(buffer, bufSize, flags, "", &disassembly); + + std::string asmSrc; + if (SUCCEEDED(result)) + { + asmSrc = reinterpret_cast(disassembly->GetBufferPointer()); + } + + SafeRelease(disassembly); + + return asmSrc; +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.h new file mode 100644 index 0000000000..a824952553 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.h @@ -0,0 +1,54 @@ +#ifndef LIBANGLE_RENDERER_D3D_HLSLCOMPILER_H_ +#define LIBANGLE_RENDERER_D3D_HLSLCOMPILER_H_ + +#include "libANGLE/Error.h" + +#include "common/angleutils.h" +#include "common/platform.h" + +#include +#include + +namespace gl +{ +class InfoLog; +} + +namespace rx +{ + +struct CompileConfig +{ + UINT flags; + std::string name; + + CompileConfig(); + CompileConfig(UINT flags, const std::string &name); +}; + +class HLSLCompiler : angle::NonCopyable +{ + public: + HLSLCompiler(); + ~HLSLCompiler(); + + bool initialize(); + void release(); + + // Attempt to compile a HLSL shader using the supplied configurations, may output a NULL compiled blob + // even if no GL errors are returned. + gl::Error compileToBinary(gl::InfoLog &infoLog, const std::string &hlsl, const std::string &profile, + const std::vector &configs, const D3D_SHADER_MACRO *overrideMacros, + ID3DBlob **outCompiledBlob, std::string *outDebugInfo) const; + + std::string disassembleBinary(ID3DBlob* shaderBinary) const; + + private: + HMODULE mD3DCompilerModule; + pD3DCompile mD3DCompileFunc; + pD3DDisassemble mD3DDisassembleFunc; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_HLSLCOMPILER_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/ImageD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ImageD3D.cpp new file mode 100644 index 0000000000..4e6f61150a --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ImageD3D.cpp @@ -0,0 +1,47 @@ +// +// Copyright (c) 2002-2015 The ANGLE Project 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 "libANGLE/renderer/d3d/ImageD3D.h" + +#include "libANGLE/Framebuffer.h" +#include "libANGLE/FramebufferAttachment.h" +#include "libANGLE/renderer/d3d/FramebufferD3D.h" + +namespace rx +{ + +ImageD3D::ImageD3D() + : mWidth(0), + mHeight(0), + mDepth(0), + mInternalFormat(GL_NONE), + mTarget(GL_NONE), + mRenderable(false), + mDirty(false) +{ +} + +gl::Error ImageD3D::copy(const gl::Offset &destOffset, const gl::Rectangle &sourceArea, const gl::Framebuffer *source) +{ + gl::FramebufferAttachment *colorbuffer = source->getReadColorbuffer(); + ASSERT(colorbuffer); + + RenderTargetD3D *renderTarget = NULL; + gl::Error error = GetAttachmentRenderTarget(colorbuffer, &renderTarget); + if (error.isError()) + { + return error; + } + + ASSERT(renderTarget); + return copy(destOffset, sourceArea, renderTarget); +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/ImageD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ImageD3D.h new file mode 100644 index 0000000000..0fe88a8f59 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ImageD3D.h @@ -0,0 +1,84 @@ +// +// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// ImageD3D.h: Defines the rx::ImageD3D class, an abstract base class for the +// renderer-specific classes which will define the interface to the underlying +// surfaces or resources. + +#ifndef LIBANGLE_RENDERER_D3D_IMAGED3D_H_ +#define LIBANGLE_RENDERER_D3D_IMAGED3D_H_ + +#include "common/debug.h" + +#include "libANGLE/Error.h" + +namespace gl +{ +class Framebuffer; +struct ImageIndex; +struct Box; +struct Extents; +struct Offset; +struct Rectangle; +struct PixelUnpackState; +} + +namespace rx +{ +class TextureStorage; +class RendererD3D; +class RenderTargetD3D; + +class ImageD3D : angle::NonCopyable +{ + public: + ImageD3D(); + virtual ~ImageD3D() {}; + + GLsizei getWidth() const { return mWidth; } + GLsizei getHeight() const { return mHeight; } + GLsizei getDepth() const { return mDepth; } + GLenum getInternalFormat() const { return mInternalFormat; } + GLenum getTarget() const { return mTarget; } + bool isRenderableFormat() const { return mRenderable; } + + void markDirty() { mDirty = true; } + void markClean() { mDirty = false; } + virtual bool isDirty() const = 0; + + virtual bool redefine(GLenum target, GLenum internalformat, const gl::Extents &size, bool forceRelease) = 0; + + virtual gl::Error loadData(const gl::Box &area, const gl::PixelUnpackState &unpack, GLenum type, const void *input) = 0; + virtual gl::Error loadCompressedData(const gl::Box &area, const void *input) = 0; + + virtual gl::Error setManagedSurface2D(TextureStorage *storage, int level) { return gl::Error(GL_NO_ERROR); }; + virtual gl::Error setManagedSurfaceCube(TextureStorage *storage, int face, int level) { return gl::Error(GL_NO_ERROR); }; + virtual gl::Error setManagedSurface3D(TextureStorage *storage, int level) { return gl::Error(GL_NO_ERROR); }; + virtual gl::Error setManagedSurface2DArray(TextureStorage *storage, int layer, int level) { return gl::Error(GL_NO_ERROR); }; + virtual gl::Error copyToStorage(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box ®ion) = 0; + + virtual gl::Error copy(const gl::Offset &destOffset, const gl::Box &sourceArea, + const gl::ImageIndex &sourceIndex, TextureStorage *source) = 0; + + gl::Error copy(const gl::Offset &destOffset, const gl::Rectangle &sourceArea, const gl::Framebuffer *source); + + protected: + GLsizei mWidth; + GLsizei mHeight; + GLsizei mDepth; + GLenum mInternalFormat; + bool mRenderable; + GLenum mTarget; + + bool mDirty; + + private: + virtual gl::Error copy(const gl::Offset &destOffset, const gl::Rectangle &sourceArea, RenderTargetD3D *source) = 0; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_IMAGED3D_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexBuffer.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexBuffer.cpp new file mode 100644 index 0000000000..677b8bb240 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexBuffer.cpp @@ -0,0 +1,196 @@ +// +// 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 "libANGLE/renderer/d3d/IndexBuffer.h" +#include "libANGLE/renderer/d3d/RendererD3D.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(BufferFactoryD3D *factory, bool dynamic) +{ + mIndexBuffer = factory->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(); +} + +gl::Error IndexBufferInterface::mapBuffer(unsigned int size, void **outMappedMemory, unsigned int *streamOffset) +{ + // Protect against integer overflow + if (mWritePosition + size < mWritePosition) + { + return gl::Error(GL_OUT_OF_MEMORY, "Mapping of internal index buffer would cause an integer overflow."); + } + + gl::Error error = mIndexBuffer->mapBuffer(mWritePosition, size, outMappedMemory); + if (error.isError()) + { + if (outMappedMemory) + { + *outMappedMemory = NULL; + } + return error; + } + + if (streamOffset) + { + *streamOffset = mWritePosition; + } + + mWritePosition += size; + return gl::Error(GL_NO_ERROR); +} + +gl::Error 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; +} + +gl::Error IndexBufferInterface::discard() +{ + return mIndexBuffer->discard(); +} + +gl::Error 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(BufferFactoryD3D *factory) + : IndexBufferInterface(factory, true) +{ +} + +StreamingIndexBufferInterface::~StreamingIndexBufferInterface() +{ +} + +gl::Error StreamingIndexBufferInterface::reserveBufferSpace(unsigned int size, GLenum indexType) +{ + unsigned int curBufferSize = getBufferSize(); + unsigned int writePos = getWritePosition(); + if (size > curBufferSize) + { + gl::Error error = setBufferSize(std::max(size, 2 * curBufferSize), indexType); + if (error.isError()) + { + return error; + } + setWritePosition(0); + } + else if (writePos + size > curBufferSize || writePos + size < writePos) + { + gl::Error error = discard(); + if (error.isError()) + { + return error; + } + setWritePosition(0); + } + + return gl::Error(GL_NO_ERROR); +} + + +StaticIndexBufferInterface::StaticIndexBufferInterface(BufferFactoryD3D *factory) + : IndexBufferInterface(factory, false) +{ +} + +StaticIndexBufferInterface::~StaticIndexBufferInterface() +{ +} + +gl::Error 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 gl::Error(GL_NO_ERROR); + } + else + { + UNREACHABLE(); + return gl::Error(GL_INVALID_OPERATION, "Internal static index buffers can't be resized"); + } +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexBuffer.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexBuffer.h new file mode 100644 index 0000000000..36262f1d09 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexBuffer.h @@ -0,0 +1,101 @@ +// +// 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 LIBANGLE_RENDERER_D3D_INDEXBUFFER_H_ +#define LIBANGLE_RENDERER_D3D_INDEXBUFFER_H_ + +#include "common/angleutils.h" +#include "libANGLE/Error.h" +#include "libANGLE/renderer/IndexRangeCache.h" + +namespace rx +{ +class BufferFactoryD3D; + +class IndexBuffer : angle::NonCopyable +{ + public: + IndexBuffer(); + virtual ~IndexBuffer(); + + virtual gl::Error initialize(unsigned int bufferSize, GLenum indexType, bool dynamic) = 0; + + virtual gl::Error mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory) = 0; + virtual gl::Error unmapBuffer() = 0; + + virtual gl::Error discard() = 0; + + virtual GLenum getIndexType() const = 0; + virtual unsigned int getBufferSize() const = 0; + virtual gl::Error setSize(unsigned int bufferSize, GLenum indexType) = 0; + + unsigned int getSerial() const; + + protected: + void updateSerial(); + + private: + unsigned int mSerial; + static unsigned int mNextSerial; +}; + +class IndexBufferInterface : angle::NonCopyable +{ + public: + IndexBufferInterface(BufferFactoryD3D *factory, bool dynamic); + virtual ~IndexBufferInterface(); + + virtual gl::Error reserveBufferSpace(unsigned int size, GLenum indexType) = 0; + + GLenum getIndexType() const; + unsigned int getBufferSize() const; + + unsigned int getSerial() const; + + gl::Error mapBuffer(unsigned int size, void** outMappedMemory, unsigned int *streamOffset); + gl::Error unmapBuffer(); + + IndexBuffer *getIndexBuffer() const; + + protected: + unsigned int getWritePosition() const; + void setWritePosition(unsigned int writePosition); + + gl::Error discard(); + + gl::Error setBufferSize(unsigned int bufferSize, GLenum indexType); + + private: + IndexBuffer *mIndexBuffer; + + unsigned int mWritePosition; + bool mDynamic; +}; + +class StreamingIndexBufferInterface : public IndexBufferInterface +{ + public: + explicit StreamingIndexBufferInterface(BufferFactoryD3D *factory); + ~StreamingIndexBufferInterface(); + + gl::Error reserveBufferSpace(unsigned int size, GLenum indexType) override; +}; + +class StaticIndexBufferInterface : public IndexBufferInterface +{ + public: + explicit StaticIndexBufferInterface(BufferFactoryD3D *factory); + ~StaticIndexBufferInterface(); + + gl::Error reserveBufferSpace(unsigned int size, GLenum indexType) override; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_INDEXBUFFER_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexDataManager.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexDataManager.cpp new file mode 100644 index 0000000000..7dad269435 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexDataManager.cpp @@ -0,0 +1,267 @@ +// +// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// IndexDataManager.cpp: Defines the IndexDataManager, a class that +// runs the Buffer translation process for index buffers. + +#include "libANGLE/renderer/d3d/IndexDataManager.h" +#include "libANGLE/renderer/d3d/BufferD3D.h" +#include "libANGLE/renderer/d3d/IndexBuffer.h" +#include "libANGLE/Buffer.h" +#include "libANGLE/formatutils.h" + +namespace rx +{ + +static void ConvertIndices(GLenum sourceType, GLenum destinationType, const void *input, GLsizei count, void *output) +{ + if (sourceType == GL_UNSIGNED_BYTE) + { + ASSERT(destinationType == GL_UNSIGNED_SHORT); + const GLubyte *in = static_cast(input); + GLushort *out = static_cast(output); + + for (GLsizei i = 0; i < count; i++) + { + out[i] = in[i]; + } + } + else if (sourceType == GL_UNSIGNED_INT) + { + ASSERT(destinationType == GL_UNSIGNED_INT); + memcpy(output, input, count * sizeof(GLuint)); + } + else if (sourceType == GL_UNSIGNED_SHORT) + { + if (destinationType == GL_UNSIGNED_SHORT) + { + memcpy(output, input, count * sizeof(GLushort)); + } + else if (destinationType == GL_UNSIGNED_INT) + { + const GLushort *in = static_cast(input); + GLuint *out = static_cast(output); + + for (GLsizei i = 0; i < count; i++) + { + out[i] = in[i]; + } + } + else UNREACHABLE(); + } + else UNREACHABLE(); +} + +IndexDataManager::IndexDataManager(BufferFactoryD3D *factory, RendererClass rendererClass) + : mFactory(factory), + mRendererClass(rendererClass), + mStreamingBufferShort(nullptr), + mStreamingBufferInt(nullptr) +{ +} + +IndexDataManager::~IndexDataManager() +{ + SafeDelete(mStreamingBufferShort); + SafeDelete(mStreamingBufferInt); +} + +gl::Error IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer *buffer, const GLvoid *indices, TranslatedIndexData *translated) +{ + const gl::Type &typeInfo = gl::GetTypeInfo(type); + + GLenum destinationIndexType = (type == GL_UNSIGNED_INT) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT; + + unsigned int offset = 0; + bool alignedOffset = false; + + BufferD3D *storage = NULL; + + if (buffer != NULL) + { + offset = static_cast(reinterpret_cast(indices)); + + storage = GetImplAs(buffer); + + // We'll trust that the compiler will optimize the % below: + // the operands are unsigned and the divisor is a constant. + 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; + } + + ASSERT(typeInfo.bytes * static_cast(count) + offset <= storage->getSize()); + + const uint8_t *bufferData = NULL; + gl::Error error = storage->getData(&bufferData); + if (error.isError()) + { + return error; + } + + indices = bufferData + offset; + } + + StaticIndexBufferInterface *staticBuffer = storage ? storage->getStaticIndexBuffer() : NULL; + IndexBufferInterface *indexBuffer = NULL; + bool directStorage = alignedOffset && storage && storage->supportsDirectBinding() && + destinationIndexType == type; + unsigned int streamOffset = 0; + + if (directStorage) + { + streamOffset = offset; + } + else if (staticBuffer && staticBuffer->getBufferSize() != 0 && staticBuffer->getIndexType() == type && alignedOffset) + { + indexBuffer = staticBuffer; + + // Using bit-shift here is faster than using division. + streamOffset = (offset >> typeInfo.bytesShift) << gl::GetTypeInfo(destinationIndexType).bytesShift; + } + + // Avoid D3D11's primitive restart index value + // see http://msdn.microsoft.com/en-us/library/windows/desktop/bb205124(v=vs.85).aspx + if (translated->indexRange.end == 0xFFFF && type == GL_UNSIGNED_SHORT && mRendererClass == RENDERER_D3D11) + { + destinationIndexType = GL_UNSIGNED_INT; + directStorage = false; + indexBuffer = NULL; + } + + const gl::Type &destTypeInfo = gl::GetTypeInfo(destinationIndexType); + + if (!directStorage && !indexBuffer) + { + gl::Error error = getStreamingIndexBuffer(destinationIndexType, &indexBuffer); + if (error.isError()) + { + return error; + } + + unsigned int convertCount = count; + + if (staticBuffer) + { + if (staticBuffer->getBufferSize() == 0 && alignedOffset) + { + indexBuffer = staticBuffer; + // Using bit-shift here is faster than using division. + convertCount = storage->getSize() >> typeInfo.bytesShift; + } + else + { + storage->invalidateStaticData(); + staticBuffer = NULL; + } + } + + ASSERT(indexBuffer); + + // Using bit-shift here is faster than using division. + if (convertCount > (std::numeric_limits::max() >> destTypeInfo.bytesShift)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Reserving %u indices of %u bytes each exceeds the maximum buffer size.", + convertCount, destTypeInfo.bytes); + } + + unsigned int bufferSizeRequired = convertCount << destTypeInfo.bytesShift; + error = indexBuffer->reserveBufferSpace(bufferSizeRequired, type); + if (error.isError()) + { + return error; + } + + void* output = NULL; + error = indexBuffer->mapBuffer(bufferSizeRequired, &output, &streamOffset); + if (error.isError()) + { + return error; + } + + const uint8_t *dataPointer = reinterpret_cast(indices); + if (staticBuffer) + { + error = storage->getData(&dataPointer); + if (error.isError()) + { + return error; + } + } + ConvertIndices(type, destinationIndexType, dataPointer, convertCount, output); + + error = indexBuffer->unmapBuffer(); + if (error.isError()) + { + return error; + } + + if (staticBuffer) + { + // Using bit-shift here is faster than using division. + streamOffset = (offset >> typeInfo.bytesShift) << destTypeInfo.bytesShift; + } + } + + translated->storage = directStorage ? storage : NULL; + translated->indexBuffer = indexBuffer ? indexBuffer->getIndexBuffer() : NULL; + translated->serial = directStorage ? storage->getSerial() : indexBuffer->getSerial(); + // Using bit-shift here is faster than using division. + translated->startIndex = (streamOffset >> destTypeInfo.bytesShift); + translated->startOffset = streamOffset; + translated->indexType = destinationIndexType; + + if (storage) + { + storage->promoteStaticUsage(count << typeInfo.bytesShift); + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error IndexDataManager::getStreamingIndexBuffer(GLenum destinationIndexType, IndexBufferInterface **outBuffer) +{ + ASSERT(outBuffer); + if (destinationIndexType == GL_UNSIGNED_INT) + { + if (!mStreamingBufferInt) + { + mStreamingBufferInt = new StreamingIndexBufferInterface(mFactory); + gl::Error error = mStreamingBufferInt->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT); + if (error.isError()) + { + SafeDelete(mStreamingBufferInt); + return error; + } + } + + *outBuffer = mStreamingBufferInt; + return gl::Error(GL_NO_ERROR); + } + else + { + ASSERT(destinationIndexType == GL_UNSIGNED_SHORT); + + if (!mStreamingBufferShort) + { + mStreamingBufferShort = new StreamingIndexBufferInterface(mFactory); + gl::Error error = mStreamingBufferShort->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_SHORT); + if (error.isError()) + { + SafeDelete(mStreamingBufferShort); + return error; + } + } + + *outBuffer = mStreamingBufferShort; + return gl::Error(GL_NO_ERROR); + } +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexDataManager.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexDataManager.h new file mode 100644 index 0000000000..275b3720c5 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexDataManager.h @@ -0,0 +1,70 @@ +// +// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// IndexDataManager.h: Defines the IndexDataManager, a class that +// runs the Buffer translation process for index buffers. + +#ifndef LIBANGLE_INDEXDATAMANAGER_H_ +#define LIBANGLE_INDEXDATAMANAGER_H_ + +#include + +#include "common/angleutils.h" +#include "common/mathutil.h" +#include "libANGLE/Error.h" +#include "libANGLE/renderer/d3d/RendererD3D.h" + +namespace +{ + enum { INITIAL_INDEX_BUFFER_SIZE = 4096 * sizeof(GLuint) }; +} + +namespace gl +{ +class Buffer; +} + +namespace rx +{ +class IndexBufferInterface; +class StaticIndexBufferInterface; +class StreamingIndexBufferInterface; +class IndexBuffer; +class BufferD3D; +class RendererD3D; + +struct TranslatedIndexData +{ + RangeUI indexRange; + unsigned int startIndex; + unsigned int startOffset; // In bytes + + IndexBuffer *indexBuffer; + BufferD3D *storage; + GLenum indexType; + unsigned int serial; +}; + +class IndexDataManager : angle::NonCopyable +{ + public: + explicit IndexDataManager(BufferFactoryD3D *factory, RendererClass rendererClass); + virtual ~IndexDataManager(); + + gl::Error prepareIndexData(GLenum type, GLsizei count, gl::Buffer *arrayElementBuffer, const GLvoid *indices, TranslatedIndexData *translated); + + private: + gl::Error getStreamingIndexBuffer(GLenum destinationIndexType, IndexBufferInterface **outBuffer); + + BufferFactoryD3D *const mFactory; + RendererClass mRendererClass; + StreamingIndexBufferInterface *mStreamingBufferShort; + StreamingIndexBufferInterface *mStreamingBufferInt; +}; + +} + +#endif // LIBANGLE_INDEXDATAMANAGER_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/ProgramD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ProgramD3D.cpp new file mode 100644 index 0000000000..9ce9a27cd3 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ProgramD3D.cpp @@ -0,0 +1,2005 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// ProgramD3D.cpp: Defines the rx::ProgramD3D class which implements rx::ProgramImpl. + +#include "libANGLE/renderer/d3d/ProgramD3D.h" + +#include "common/utilities.h" +#include "libANGLE/Framebuffer.h" +#include "libANGLE/FramebufferAttachment.h" +#include "libANGLE/Program.h" +#include "libANGLE/features.h" +#include "libANGLE/renderer/d3d/DynamicHLSL.h" +#include "libANGLE/renderer/d3d/FramebufferD3D.h" +#include "libANGLE/renderer/d3d/RendererD3D.h" +#include "libANGLE/renderer/d3d/ShaderD3D.h" +#include "libANGLE/renderer/d3d/ShaderExecutableD3D.h" +#include "libANGLE/renderer/d3d/VertexDataManager.h" + +namespace rx +{ + +namespace +{ + +GLenum GetTextureType(GLenum samplerType) +{ + switch (samplerType) + { + case GL_SAMPLER_2D: + case GL_INT_SAMPLER_2D: + case GL_UNSIGNED_INT_SAMPLER_2D: + case GL_SAMPLER_2D_SHADOW: + return GL_TEXTURE_2D; + case GL_SAMPLER_3D: + case GL_INT_SAMPLER_3D: + case GL_UNSIGNED_INT_SAMPLER_3D: + return GL_TEXTURE_3D; + case GL_SAMPLER_CUBE: + case GL_SAMPLER_CUBE_SHADOW: + return GL_TEXTURE_CUBE_MAP; + case GL_INT_SAMPLER_CUBE: + case GL_UNSIGNED_INT_SAMPLER_CUBE: + return GL_TEXTURE_CUBE_MAP; + case GL_SAMPLER_2D_ARRAY: + case GL_INT_SAMPLER_2D_ARRAY: + case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: + case GL_SAMPLER_2D_ARRAY_SHADOW: + return GL_TEXTURE_2D_ARRAY; + default: UNREACHABLE(); + } + + return GL_TEXTURE_2D; +} + +void GetDefaultInputLayoutFromShader(const std::vector &shaderAttributes, gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS]) +{ + size_t layoutIndex = 0; + for (size_t attributeIndex = 0; attributeIndex < shaderAttributes.size(); attributeIndex++) + { + ASSERT(layoutIndex < gl::MAX_VERTEX_ATTRIBS); + + const sh::Attribute &shaderAttr = shaderAttributes[attributeIndex]; + + if (shaderAttr.type != GL_NONE) + { + GLenum transposedType = gl::TransposeMatrixType(shaderAttr.type); + + for (size_t rowIndex = 0; static_cast(rowIndex) < gl::VariableRowCount(transposedType); rowIndex++, layoutIndex++) + { + gl::VertexFormat *defaultFormat = &inputLayout[layoutIndex]; + + defaultFormat->mType = gl::VariableComponentType(transposedType); + defaultFormat->mNormalized = false; + defaultFormat->mPureInteger = (defaultFormat->mType != GL_FLOAT); // note: inputs can not be bool + defaultFormat->mComponents = gl::VariableColumnCount(transposedType); + } + } + } +} + +std::vector GetDefaultOutputLayoutFromShader(const std::vector &shaderOutputVars) +{ + std::vector defaultPixelOutput; + + if (!shaderOutputVars.empty()) + { + defaultPixelOutput.push_back(GL_COLOR_ATTACHMENT0 + shaderOutputVars[0].outputIndex); + } + + return defaultPixelOutput; +} + +bool IsRowMajorLayout(const sh::InterfaceBlockField &var) +{ + return var.isRowMajorLayout; +} + +bool IsRowMajorLayout(const sh::ShaderVariable &var) +{ + return false; +} + +struct AttributeSorter +{ + AttributeSorter(const ProgramImpl::SemanticIndexArray &semanticIndices) + : originalIndices(&semanticIndices) + { + } + + bool operator()(int a, int b) + { + int indexA = (*originalIndices)[a]; + int indexB = (*originalIndices)[b]; + + if (indexA == -1) return false; + if (indexB == -1) return true; + return (indexA < indexB); + } + + const ProgramImpl::SemanticIndexArray *originalIndices; +}; + +} + +ProgramD3D::VertexExecutable::VertexExecutable(const gl::VertexFormat inputLayout[], + const GLenum signature[], + ShaderExecutableD3D *shaderExecutable) + : mShaderExecutable(shaderExecutable) +{ + for (size_t attributeIndex = 0; attributeIndex < gl::MAX_VERTEX_ATTRIBS; attributeIndex++) + { + mInputs[attributeIndex] = inputLayout[attributeIndex]; + mSignature[attributeIndex] = signature[attributeIndex]; + } +} + +ProgramD3D::VertexExecutable::~VertexExecutable() +{ + SafeDelete(mShaderExecutable); +} + +bool ProgramD3D::VertexExecutable::matchesSignature(const GLenum signature[]) const +{ + for (size_t attributeIndex = 0; attributeIndex < gl::MAX_VERTEX_ATTRIBS; attributeIndex++) + { + if (mSignature[attributeIndex] != signature[attributeIndex]) + { + return false; + } + } + + return true; +} + +ProgramD3D::PixelExecutable::PixelExecutable(const std::vector &outputSignature, ShaderExecutableD3D *shaderExecutable) + : mOutputSignature(outputSignature), + mShaderExecutable(shaderExecutable) +{ +} + +ProgramD3D::PixelExecutable::~PixelExecutable() +{ + SafeDelete(mShaderExecutable); +} + +ProgramD3D::Sampler::Sampler() : active(false), logicalTextureUnit(0), textureType(GL_TEXTURE_2D) +{ +} + +unsigned int ProgramD3D::mCurrentSerial = 1; + +ProgramD3D::ProgramD3D(RendererD3D *renderer) + : ProgramImpl(), + mRenderer(renderer), + mDynamicHLSL(NULL), + mGeometryExecutable(NULL), + mUsesPointSize(false), + mVertexUniformStorage(NULL), + mFragmentUniformStorage(NULL), + mUsedVertexSamplerRange(0), + mUsedPixelSamplerRange(0), + mDirtySamplerMapping(true), + mTextureUnitTypesCache(renderer->getRendererCaps().maxCombinedTextureImageUnits), + mShaderVersion(100), + mSerial(issueSerial()) +{ + mDynamicHLSL = new DynamicHLSL(renderer); +} + +ProgramD3D::~ProgramD3D() +{ + reset(); + SafeDelete(mDynamicHLSL); +} + +bool ProgramD3D::usesPointSpriteEmulation() const +{ + return mUsesPointSize && mRenderer->getMajorShaderModel() >= 4; +} + +bool ProgramD3D::usesGeometryShader() const +{ + return usesPointSpriteEmulation() && !usesInstancedPointSpriteEmulation(); +} + +bool ProgramD3D::usesInstancedPointSpriteEmulation() const +{ + return mRenderer->getWorkarounds().useInstancedPointSpriteEmulation; +} + +GLint ProgramD3D::getSamplerMapping(gl::SamplerType type, unsigned int samplerIndex, const gl::Caps &caps) const +{ + GLint logicalTextureUnit = -1; + + switch (type) + { + case gl::SAMPLER_PIXEL: + ASSERT(samplerIndex < caps.maxTextureImageUnits); + if (samplerIndex < mSamplersPS.size() && mSamplersPS[samplerIndex].active) + { + logicalTextureUnit = mSamplersPS[samplerIndex].logicalTextureUnit; + } + break; + case gl::SAMPLER_VERTEX: + ASSERT(samplerIndex < caps.maxVertexTextureImageUnits); + if (samplerIndex < mSamplersVS.size() && mSamplersVS[samplerIndex].active) + { + logicalTextureUnit = mSamplersVS[samplerIndex].logicalTextureUnit; + } + break; + default: UNREACHABLE(); + } + + if (logicalTextureUnit >= 0 && logicalTextureUnit < static_cast(caps.maxCombinedTextureImageUnits)) + { + return logicalTextureUnit; + } + + return -1; +} + +// Returns the texture type for a given Direct3D 9 sampler type and +// index (0-15 for the pixel shader and 0-3 for the vertex shader). +GLenum ProgramD3D::getSamplerTextureType(gl::SamplerType type, unsigned int samplerIndex) const +{ + switch (type) + { + case gl::SAMPLER_PIXEL: + ASSERT(samplerIndex < mSamplersPS.size()); + ASSERT(mSamplersPS[samplerIndex].active); + return mSamplersPS[samplerIndex].textureType; + case gl::SAMPLER_VERTEX: + ASSERT(samplerIndex < mSamplersVS.size()); + ASSERT(mSamplersVS[samplerIndex].active); + return mSamplersVS[samplerIndex].textureType; + default: UNREACHABLE(); + } + + return GL_TEXTURE_2D; +} + +GLint ProgramD3D::getUsedSamplerRange(gl::SamplerType type) const +{ + switch (type) + { + case gl::SAMPLER_PIXEL: + return mUsedPixelSamplerRange; + case gl::SAMPLER_VERTEX: + return mUsedVertexSamplerRange; + default: + UNREACHABLE(); + return 0; + } +} + +void ProgramD3D::updateSamplerMapping() +{ + if (!mDirtySamplerMapping) + { + return; + } + + mDirtySamplerMapping = false; + + // Retrieve sampler uniform values + for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++) + { + gl::LinkedUniform *targetUniform = mUniforms[uniformIndex]; + + if (targetUniform->dirty) + { + if (gl::IsSamplerType(targetUniform->type)) + { + int count = targetUniform->elementCount(); + GLint (*v)[4] = reinterpret_cast(targetUniform->data); + + if (targetUniform->isReferencedByFragmentShader()) + { + unsigned int firstIndex = targetUniform->psRegisterIndex; + + for (int i = 0; i < count; i++) + { + unsigned int samplerIndex = firstIndex + i; + + if (samplerIndex < mSamplersPS.size()) + { + ASSERT(mSamplersPS[samplerIndex].active); + mSamplersPS[samplerIndex].logicalTextureUnit = v[i][0]; + } + } + } + + if (targetUniform->isReferencedByVertexShader()) + { + unsigned int firstIndex = targetUniform->vsRegisterIndex; + + for (int i = 0; i < count; i++) + { + unsigned int samplerIndex = firstIndex + i; + + if (samplerIndex < mSamplersVS.size()) + { + ASSERT(mSamplersVS[samplerIndex].active); + mSamplersVS[samplerIndex].logicalTextureUnit = v[i][0]; + } + } + } + } + } + } +} + +bool ProgramD3D::validateSamplers(gl::InfoLog *infoLog, const gl::Caps &caps) +{ + // if any two active samplers in a program are of different types, but refer to the same + // texture image unit, and this is the current program, then ValidateProgram will fail, and + // DrawArrays and DrawElements will issue the INVALID_OPERATION error. + updateSamplerMapping(); + + std::fill(mTextureUnitTypesCache.begin(), mTextureUnitTypesCache.end(), GL_NONE); + + for (unsigned int i = 0; i < mUsedPixelSamplerRange; ++i) + { + if (mSamplersPS[i].active) + { + unsigned int unit = mSamplersPS[i].logicalTextureUnit; + + if (unit >= caps.maxCombinedTextureImageUnits) + { + if (infoLog) + { + infoLog->append("Sampler uniform (%d) exceeds GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, caps.maxCombinedTextureImageUnits); + } + + return false; + } + + if (mTextureUnitTypesCache[unit] != GL_NONE) + { + if (mSamplersPS[i].textureType != mTextureUnitTypesCache[unit]) + { + if (infoLog) + { + infoLog->append("Samplers of conflicting types refer to the same texture image unit (%d).", unit); + } + + return false; + } + } + else + { + mTextureUnitTypesCache[unit] = mSamplersPS[i].textureType; + } + } + } + + for (unsigned int i = 0; i < mUsedVertexSamplerRange; ++i) + { + if (mSamplersVS[i].active) + { + unsigned int unit = mSamplersVS[i].logicalTextureUnit; + + if (unit >= caps.maxCombinedTextureImageUnits) + { + if (infoLog) + { + infoLog->append("Sampler uniform (%d) exceeds GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, caps.maxCombinedTextureImageUnits); + } + + return false; + } + + if (mTextureUnitTypesCache[unit] != GL_NONE) + { + if (mSamplersVS[i].textureType != mTextureUnitTypesCache[unit]) + { + if (infoLog) + { + infoLog->append("Samplers of conflicting types refer to the same texture image unit (%d).", unit); + } + + return false; + } + } + else + { + mTextureUnitTypesCache[unit] = mSamplersVS[i].textureType; + } + } + } + + return true; +} + +LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) +{ + int compileFlags = stream->readInt(); + if (compileFlags != ANGLE_COMPILE_OPTIMIZATION_LEVEL) + { + infoLog.append("Mismatched compilation flags."); + return LinkResult(false, gl::Error(GL_NO_ERROR)); + } + + stream->readInt(&mShaderVersion); + + const unsigned int psSamplerCount = stream->readInt(); + for (unsigned int i = 0; i < psSamplerCount; ++i) + { + Sampler sampler; + stream->readBool(&sampler.active); + stream->readInt(&sampler.logicalTextureUnit); + stream->readInt(&sampler.textureType); + mSamplersPS.push_back(sampler); + } + const unsigned int vsSamplerCount = stream->readInt(); + for (unsigned int i = 0; i < vsSamplerCount; ++i) + { + Sampler sampler; + stream->readBool(&sampler.active); + stream->readInt(&sampler.logicalTextureUnit); + stream->readInt(&sampler.textureType); + mSamplersVS.push_back(sampler); + } + + stream->readInt(&mUsedVertexSamplerRange); + stream->readInt(&mUsedPixelSamplerRange); + + const unsigned int uniformCount = stream->readInt(); + if (stream->error()) + { + infoLog.append("Invalid program binary."); + return LinkResult(false, gl::Error(GL_NO_ERROR)); + } + + mUniforms.resize(uniformCount); + for (unsigned int uniformIndex = 0; uniformIndex < uniformCount; uniformIndex++) + { + GLenum type = stream->readInt(); + GLenum precision = stream->readInt(); + std::string name = stream->readString(); + unsigned int arraySize = stream->readInt(); + int blockIndex = stream->readInt(); + + int offset = stream->readInt(); + int arrayStride = stream->readInt(); + int matrixStride = stream->readInt(); + bool isRowMajorMatrix = stream->readBool(); + + const sh::BlockMemberInfo blockInfo(offset, arrayStride, matrixStride, isRowMajorMatrix); + + gl::LinkedUniform *uniform = new gl::LinkedUniform(type, precision, name, arraySize, blockIndex, blockInfo); + + stream->readInt(&uniform->psRegisterIndex); + stream->readInt(&uniform->vsRegisterIndex); + stream->readInt(&uniform->registerCount); + stream->readInt(&uniform->registerElement); + + mUniforms[uniformIndex] = uniform; + } + + const unsigned int uniformIndexCount = stream->readInt(); + if (stream->error()) + { + infoLog.append("Invalid program binary."); + return LinkResult(false, gl::Error(GL_NO_ERROR)); + } + + mUniformIndex.resize(uniformIndexCount); + for (unsigned int uniformIndexIndex = 0; uniformIndexIndex < uniformIndexCount; uniformIndexIndex++) + { + stream->readString(&mUniformIndex[uniformIndexIndex].name); + stream->readInt(&mUniformIndex[uniformIndexIndex].element); + stream->readInt(&mUniformIndex[uniformIndexIndex].index); + } + + unsigned int uniformBlockCount = stream->readInt(); + if (stream->error()) + { + infoLog.append("Invalid program binary."); + return LinkResult(false, gl::Error(GL_NO_ERROR)); + } + + mUniformBlocks.resize(uniformBlockCount); + for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < uniformBlockCount; ++uniformBlockIndex) + { + std::string name = stream->readString(); + unsigned int elementIndex = stream->readInt(); + unsigned int dataSize = stream->readInt(); + + gl::UniformBlock *uniformBlock = new gl::UniformBlock(name, elementIndex, dataSize); + + stream->readInt(&uniformBlock->psRegisterIndex); + stream->readInt(&uniformBlock->vsRegisterIndex); + + unsigned int numMembers = stream->readInt(); + uniformBlock->memberUniformIndexes.resize(numMembers); + for (unsigned int blockMemberIndex = 0; blockMemberIndex < numMembers; blockMemberIndex++) + { + stream->readInt(&uniformBlock->memberUniformIndexes[blockMemberIndex]); + } + + mUniformBlocks[uniformBlockIndex] = uniformBlock; + } + + stream->readInt(&mTransformFeedbackBufferMode); + const unsigned int transformFeedbackVaryingCount = stream->readInt(); + mTransformFeedbackLinkedVaryings.resize(transformFeedbackVaryingCount); + for (unsigned int varyingIndex = 0; varyingIndex < transformFeedbackVaryingCount; varyingIndex++) + { + gl::LinkedVarying &varying = mTransformFeedbackLinkedVaryings[varyingIndex]; + + stream->readString(&varying.name); + stream->readInt(&varying.type); + stream->readInt(&varying.size); + stream->readString(&varying.semanticName); + stream->readInt(&varying.semanticIndex); + stream->readInt(&varying.semanticIndexCount); + } + + stream->readString(&mVertexHLSL); + stream->readBytes(reinterpret_cast(&mVertexWorkarounds), sizeof(D3DCompilerWorkarounds)); + stream->readString(&mPixelHLSL); + stream->readBytes(reinterpret_cast(&mPixelWorkarounds), sizeof(D3DCompilerWorkarounds)); + stream->readBool(&mUsesFragDepth); + stream->readBool(&mUsesPointSize); + + const size_t pixelShaderKeySize = stream->readInt(); + mPixelShaderKey.resize(pixelShaderKeySize); + for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKeySize; pixelShaderKeyIndex++) + { + stream->readInt(&mPixelShaderKey[pixelShaderKeyIndex].type); + stream->readString(&mPixelShaderKey[pixelShaderKeyIndex].name); + stream->readString(&mPixelShaderKey[pixelShaderKeyIndex].source); + stream->readInt(&mPixelShaderKey[pixelShaderKeyIndex].outputIndex); + } + + const unsigned char* binary = reinterpret_cast(stream->data()); + + const unsigned int vertexShaderCount = stream->readInt(); + for (unsigned int vertexShaderIndex = 0; vertexShaderIndex < vertexShaderCount; vertexShaderIndex++) + { + gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS]; + + for (size_t inputIndex = 0; inputIndex < gl::MAX_VERTEX_ATTRIBS; inputIndex++) + { + gl::VertexFormat *vertexInput = &inputLayout[inputIndex]; + stream->readInt(&vertexInput->mType); + stream->readInt(&vertexInput->mNormalized); + stream->readInt(&vertexInput->mComponents); + stream->readBool(&vertexInput->mPureInteger); + } + + unsigned int vertexShaderSize = stream->readInt(); + const unsigned char *vertexShaderFunction = binary + stream->offset(); + + ShaderExecutableD3D *shaderExecutable = NULL; + gl::Error error = mRenderer->loadExecutable(vertexShaderFunction, vertexShaderSize, + SHADER_VERTEX, + mTransformFeedbackLinkedVaryings, + (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS), + &shaderExecutable); + if (error.isError()) + { + return LinkResult(false, error); + } + + if (!shaderExecutable) + { + infoLog.append("Could not create vertex shader."); + return LinkResult(false, gl::Error(GL_NO_ERROR)); + } + + // generated converted input layout + GLenum signature[gl::MAX_VERTEX_ATTRIBS]; + getInputLayoutSignature(inputLayout, signature); + + // add new binary + mVertexExecutables.push_back(new VertexExecutable(inputLayout, signature, shaderExecutable)); + + stream->skip(vertexShaderSize); + } + + const size_t pixelShaderCount = stream->readInt(); + for (size_t pixelShaderIndex = 0; pixelShaderIndex < pixelShaderCount; pixelShaderIndex++) + { + const size_t outputCount = stream->readInt(); + std::vector outputs(outputCount); + for (size_t outputIndex = 0; outputIndex < outputCount; outputIndex++) + { + stream->readInt(&outputs[outputIndex]); + } + + const size_t pixelShaderSize = stream->readInt(); + const unsigned char *pixelShaderFunction = binary + stream->offset(); + ShaderExecutableD3D *shaderExecutable = NULL; + gl::Error error = mRenderer->loadExecutable(pixelShaderFunction, pixelShaderSize, SHADER_PIXEL, + mTransformFeedbackLinkedVaryings, + (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS), + &shaderExecutable); + if (error.isError()) + { + return LinkResult(false, error); + } + + if (!shaderExecutable) + { + infoLog.append("Could not create pixel shader."); + return LinkResult(false, gl::Error(GL_NO_ERROR)); + } + + // add new binary + mPixelExecutables.push_back(new PixelExecutable(outputs, shaderExecutable)); + + stream->skip(pixelShaderSize); + } + + unsigned int geometryShaderSize = stream->readInt(); + + if (geometryShaderSize > 0) + { + const unsigned char *geometryShaderFunction = binary + stream->offset(); + gl::Error error = mRenderer->loadExecutable(geometryShaderFunction, geometryShaderSize, SHADER_GEOMETRY, + mTransformFeedbackLinkedVaryings, + (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS), + &mGeometryExecutable); + if (error.isError()) + { + return LinkResult(false, error); + } + + if (!mGeometryExecutable) + { + infoLog.append("Could not create geometry shader."); + return LinkResult(false, gl::Error(GL_NO_ERROR)); + } + stream->skip(geometryShaderSize); + } + + GUID binaryIdentifier = {0}; + stream->readBytes(reinterpret_cast(&binaryIdentifier), sizeof(GUID)); + + GUID identifier = mRenderer->getAdapterIdentifier(); + if (memcmp(&identifier, &binaryIdentifier, sizeof(GUID)) != 0) + { + infoLog.append("Invalid program binary."); + return LinkResult(false, gl::Error(GL_NO_ERROR)); + } + + initializeUniformStorage(); + initAttributesByLayout(); + + return LinkResult(true, gl::Error(GL_NO_ERROR)); +} + +gl::Error ProgramD3D::save(gl::BinaryOutputStream *stream) +{ + stream->writeInt(ANGLE_COMPILE_OPTIMIZATION_LEVEL); + + stream->writeInt(mShaderVersion); + + stream->writeInt(mSamplersPS.size()); + for (unsigned int i = 0; i < mSamplersPS.size(); ++i) + { + stream->writeInt(mSamplersPS[i].active); + stream->writeInt(mSamplersPS[i].logicalTextureUnit); + stream->writeInt(mSamplersPS[i].textureType); + } + + stream->writeInt(mSamplersVS.size()); + for (unsigned int i = 0; i < mSamplersVS.size(); ++i) + { + stream->writeInt(mSamplersVS[i].active); + stream->writeInt(mSamplersVS[i].logicalTextureUnit); + stream->writeInt(mSamplersVS[i].textureType); + } + + stream->writeInt(mUsedVertexSamplerRange); + stream->writeInt(mUsedPixelSamplerRange); + + stream->writeInt(mUniforms.size()); + for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); ++uniformIndex) + { + const gl::LinkedUniform &uniform = *mUniforms[uniformIndex]; + + stream->writeInt(uniform.type); + stream->writeInt(uniform.precision); + stream->writeString(uniform.name); + stream->writeInt(uniform.arraySize); + stream->writeInt(uniform.blockIndex); + + stream->writeInt(uniform.blockInfo.offset); + stream->writeInt(uniform.blockInfo.arrayStride); + stream->writeInt(uniform.blockInfo.matrixStride); + stream->writeInt(uniform.blockInfo.isRowMajorMatrix); + + stream->writeInt(uniform.psRegisterIndex); + stream->writeInt(uniform.vsRegisterIndex); + stream->writeInt(uniform.registerCount); + stream->writeInt(uniform.registerElement); + } + + stream->writeInt(mUniformIndex.size()); + for (size_t i = 0; i < mUniformIndex.size(); ++i) + { + stream->writeString(mUniformIndex[i].name); + stream->writeInt(mUniformIndex[i].element); + stream->writeInt(mUniformIndex[i].index); + } + + stream->writeInt(mUniformBlocks.size()); + for (size_t uniformBlockIndex = 0; uniformBlockIndex < mUniformBlocks.size(); ++uniformBlockIndex) + { + const gl::UniformBlock& uniformBlock = *mUniformBlocks[uniformBlockIndex]; + + stream->writeString(uniformBlock.name); + stream->writeInt(uniformBlock.elementIndex); + stream->writeInt(uniformBlock.dataSize); + + stream->writeInt(uniformBlock.memberUniformIndexes.size()); + for (unsigned int blockMemberIndex = 0; blockMemberIndex < uniformBlock.memberUniformIndexes.size(); blockMemberIndex++) + { + stream->writeInt(uniformBlock.memberUniformIndexes[blockMemberIndex]); + } + + stream->writeInt(uniformBlock.psRegisterIndex); + stream->writeInt(uniformBlock.vsRegisterIndex); + } + + stream->writeInt(mTransformFeedbackBufferMode); + stream->writeInt(mTransformFeedbackLinkedVaryings.size()); + for (size_t i = 0; i < mTransformFeedbackLinkedVaryings.size(); i++) + { + const gl::LinkedVarying &varying = mTransformFeedbackLinkedVaryings[i]; + + stream->writeString(varying.name); + stream->writeInt(varying.type); + stream->writeInt(varying.size); + stream->writeString(varying.semanticName); + stream->writeInt(varying.semanticIndex); + stream->writeInt(varying.semanticIndexCount); + } + + stream->writeString(mVertexHLSL); + stream->writeBytes(reinterpret_cast(&mVertexWorkarounds), sizeof(D3DCompilerWorkarounds)); + stream->writeString(mPixelHLSL); + stream->writeBytes(reinterpret_cast(&mPixelWorkarounds), sizeof(D3DCompilerWorkarounds)); + stream->writeInt(mUsesFragDepth); + stream->writeInt(mUsesPointSize); + + const std::vector &pixelShaderKey = mPixelShaderKey; + stream->writeInt(pixelShaderKey.size()); + for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKey.size(); pixelShaderKeyIndex++) + { + const PixelShaderOutputVariable &variable = pixelShaderKey[pixelShaderKeyIndex]; + stream->writeInt(variable.type); + stream->writeString(variable.name); + stream->writeString(variable.source); + stream->writeInt(variable.outputIndex); + } + + stream->writeInt(mVertexExecutables.size()); + for (size_t vertexExecutableIndex = 0; vertexExecutableIndex < mVertexExecutables.size(); vertexExecutableIndex++) + { + VertexExecutable *vertexExecutable = mVertexExecutables[vertexExecutableIndex]; + + for (size_t inputIndex = 0; inputIndex < gl::MAX_VERTEX_ATTRIBS; inputIndex++) + { + const gl::VertexFormat &vertexInput = vertexExecutable->inputs()[inputIndex]; + stream->writeInt(vertexInput.mType); + stream->writeInt(vertexInput.mNormalized); + stream->writeInt(vertexInput.mComponents); + stream->writeInt(vertexInput.mPureInteger); + } + + size_t vertexShaderSize = vertexExecutable->shaderExecutable()->getLength(); + stream->writeInt(vertexShaderSize); + + const uint8_t *vertexBlob = vertexExecutable->shaderExecutable()->getFunction(); + stream->writeBytes(vertexBlob, vertexShaderSize); + } + + stream->writeInt(mPixelExecutables.size()); + for (size_t pixelExecutableIndex = 0; pixelExecutableIndex < mPixelExecutables.size(); pixelExecutableIndex++) + { + PixelExecutable *pixelExecutable = mPixelExecutables[pixelExecutableIndex]; + + const std::vector outputs = pixelExecutable->outputSignature(); + stream->writeInt(outputs.size()); + for (size_t outputIndex = 0; outputIndex < outputs.size(); outputIndex++) + { + stream->writeInt(outputs[outputIndex]); + } + + size_t pixelShaderSize = pixelExecutable->shaderExecutable()->getLength(); + stream->writeInt(pixelShaderSize); + + const uint8_t *pixelBlob = pixelExecutable->shaderExecutable()->getFunction(); + stream->writeBytes(pixelBlob, pixelShaderSize); + } + + size_t geometryShaderSize = (mGeometryExecutable != NULL) ? mGeometryExecutable->getLength() : 0; + stream->writeInt(geometryShaderSize); + + if (mGeometryExecutable != NULL && geometryShaderSize > 0) + { + const uint8_t *geometryBlob = mGeometryExecutable->getFunction(); + stream->writeBytes(geometryBlob, geometryShaderSize); + } + + GUID binaryIdentifier = mRenderer->getAdapterIdentifier(); + stream->writeBytes(reinterpret_cast(&binaryIdentifier), sizeof(GUID)); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error ProgramD3D::getPixelExecutableForFramebuffer(const gl::Framebuffer *fbo, ShaderExecutableD3D **outExecutable) +{ + mPixelShaderOutputFormatCache.clear(); + + const FramebufferD3D *fboD3D = GetImplAs(fbo); + const gl::AttachmentList &colorbuffers = fboD3D->getColorAttachmentsForRender(mRenderer->getWorkarounds()); + + for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment) + { + const gl::FramebufferAttachment *colorbuffer = colorbuffers[colorAttachment]; + + if (colorbuffer) + { + mPixelShaderOutputFormatCache.push_back(colorbuffer->getBinding() == GL_BACK ? GL_COLOR_ATTACHMENT0 : colorbuffer->getBinding()); + } + else + { + mPixelShaderOutputFormatCache.push_back(GL_NONE); + } + } + + return getPixelExecutableForOutputLayout(mPixelShaderOutputFormatCache, outExecutable, nullptr); +} + +gl::Error ProgramD3D::getPixelExecutableForOutputLayout(const std::vector &outputSignature, + ShaderExecutableD3D **outExectuable, + gl::InfoLog *infoLog) +{ + for (size_t executableIndex = 0; executableIndex < mPixelExecutables.size(); executableIndex++) + { + if (mPixelExecutables[executableIndex]->matchesSignature(outputSignature)) + { + *outExectuable = mPixelExecutables[executableIndex]->shaderExecutable(); + return gl::Error(GL_NO_ERROR); + } + } + + std::string finalPixelHLSL = mDynamicHLSL->generatePixelShaderForOutputSignature(mPixelHLSL, mPixelShaderKey, mUsesFragDepth, + outputSignature); + + // Generate new pixel executable + ShaderExecutableD3D *pixelExecutable = NULL; + + gl::InfoLog tempInfoLog; + gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog; + + gl::Error error = mRenderer->compileToExecutable(*currentInfoLog, finalPixelHLSL, SHADER_PIXEL, + mTransformFeedbackLinkedVaryings, + (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS), + mPixelWorkarounds, &pixelExecutable); + if (error.isError()) + { + return error; + } + + if (pixelExecutable) + { + mPixelExecutables.push_back(new PixelExecutable(outputSignature, pixelExecutable)); + } + else if (!infoLog) + { + std::vector tempCharBuffer(tempInfoLog.getLength() + 3); + tempInfoLog.getLog(tempInfoLog.getLength(), NULL, &tempCharBuffer[0]); + ERR("Error compiling dynamic pixel executable:\n%s\n", &tempCharBuffer[0]); + } + + *outExectuable = pixelExecutable; + return gl::Error(GL_NO_ERROR); +} + +gl::Error ProgramD3D::getVertexExecutableForInputLayout(const gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS], + ShaderExecutableD3D **outExectuable, + gl::InfoLog *infoLog) +{ + GLenum signature[gl::MAX_VERTEX_ATTRIBS]; + getInputLayoutSignature(inputLayout, signature); + + for (size_t executableIndex = 0; executableIndex < mVertexExecutables.size(); executableIndex++) + { + if (mVertexExecutables[executableIndex]->matchesSignature(signature)) + { + *outExectuable = mVertexExecutables[executableIndex]->shaderExecutable(); + return gl::Error(GL_NO_ERROR); + } + } + + // Generate new dynamic layout with attribute conversions + std::string finalVertexHLSL = mDynamicHLSL->generateVertexShaderForInputLayout(mVertexHLSL, inputLayout, mShaderAttributes); + + // Generate new vertex executable + ShaderExecutableD3D *vertexExecutable = NULL; + + gl::InfoLog tempInfoLog; + gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog; + + gl::Error error = mRenderer->compileToExecutable(*currentInfoLog, finalVertexHLSL, SHADER_VERTEX, + mTransformFeedbackLinkedVaryings, + (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS), + mVertexWorkarounds, &vertexExecutable); + if (error.isError()) + { + return error; + } + + if (vertexExecutable) + { + mVertexExecutables.push_back(new VertexExecutable(inputLayout, signature, vertexExecutable)); + } + else if (!infoLog) + { + std::vector tempCharBuffer(tempInfoLog.getLength() + 3); + tempInfoLog.getLog(tempInfoLog.getLength(), NULL, &tempCharBuffer[0]); + ERR("Error compiling dynamic vertex executable:\n%s\n", &tempCharBuffer[0]); + } + + *outExectuable = vertexExecutable; + return gl::Error(GL_NO_ERROR); +} + +LinkResult ProgramD3D::compileProgramExecutables(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader, + int registers) +{ + ShaderD3D *vertexShaderD3D = ShaderD3D::makeShaderD3D(vertexShader->getImplementation()); + ShaderD3D *fragmentShaderD3D = ShaderD3D::makeShaderD3D(fragmentShader->getImplementation()); + + gl::VertexFormat defaultInputLayout[gl::MAX_VERTEX_ATTRIBS]; + GetDefaultInputLayoutFromShader(vertexShader->getActiveAttributes(), defaultInputLayout); + ShaderExecutableD3D *defaultVertexExecutable = NULL; + gl::Error error = getVertexExecutableForInputLayout(defaultInputLayout, &defaultVertexExecutable, &infoLog); + if (error.isError()) + { + return LinkResult(false, error); + } + + std::vector defaultPixelOutput = GetDefaultOutputLayoutFromShader(getPixelShaderKey()); + ShaderExecutableD3D *defaultPixelExecutable = NULL; + error = getPixelExecutableForOutputLayout(defaultPixelOutput, &defaultPixelExecutable, &infoLog); + if (error.isError()) + { + return LinkResult(false, error); + } + + if (usesGeometryShader()) + { + std::string geometryHLSL = mDynamicHLSL->generateGeometryShaderHLSL(registers, fragmentShaderD3D, vertexShaderD3D); + + + error = mRenderer->compileToExecutable(infoLog, geometryHLSL, SHADER_GEOMETRY, mTransformFeedbackLinkedVaryings, + (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS), + D3DCompilerWorkarounds(), &mGeometryExecutable); + if (error.isError()) + { + return LinkResult(false, error); + } + } + +#if ANGLE_SHADER_DEBUG_INFO == ANGLE_ENABLED + if (usesGeometryShader() && mGeometryExecutable) + { + // Geometry shaders are currently only used internally, so there is no corresponding shader object at the interface level + // For now the geometry shader debug info is pre-pended to the vertex shader, this is a bit of a clutch + vertexShaderD3D->appendDebugInfo("// GEOMETRY SHADER BEGIN\n\n"); + vertexShaderD3D->appendDebugInfo(mGeometryExecutable->getDebugInfo()); + vertexShaderD3D->appendDebugInfo("\nGEOMETRY SHADER END\n\n\n"); + } + + if (defaultVertexExecutable) + { + vertexShaderD3D->appendDebugInfo(defaultVertexExecutable->getDebugInfo()); + } + + if (defaultPixelExecutable) + { + fragmentShaderD3D->appendDebugInfo(defaultPixelExecutable->getDebugInfo()); + } +#endif + + bool linkSuccess = (defaultVertexExecutable && defaultPixelExecutable && (!usesGeometryShader() || mGeometryExecutable)); + return LinkResult(linkSuccess, gl::Error(GL_NO_ERROR)); +} + +LinkResult ProgramD3D::link(const gl::Data &data, gl::InfoLog &infoLog, + gl::Shader *fragmentShader, gl::Shader *vertexShader, + const std::vector &transformFeedbackVaryings, + GLenum transformFeedbackBufferMode, + int *registers, std::vector *linkedVaryings, + std::map *outputVariables) +{ + ShaderD3D *vertexShaderD3D = ShaderD3D::makeShaderD3D(vertexShader->getImplementation()); + ShaderD3D *fragmentShaderD3D = ShaderD3D::makeShaderD3D(fragmentShader->getImplementation()); + + mSamplersPS.resize(data.caps->maxTextureImageUnits); + mSamplersVS.resize(data.caps->maxVertexTextureImageUnits); + + mTransformFeedbackBufferMode = transformFeedbackBufferMode; + + mPixelHLSL = fragmentShaderD3D->getTranslatedSource(); + fragmentShaderD3D->generateWorkarounds(&mPixelWorkarounds); + + mVertexHLSL = vertexShaderD3D->getTranslatedSource(); + vertexShaderD3D->generateWorkarounds(&mVertexWorkarounds); + mShaderVersion = vertexShaderD3D->getShaderVersion(); + + // Map the varyings to the register file + VaryingPacking packing = { NULL }; + *registers = mDynamicHLSL->packVaryings(infoLog, packing, fragmentShaderD3D, vertexShaderD3D, transformFeedbackVaryings); + + if (*registers < 0) + { + return LinkResult(false, gl::Error(GL_NO_ERROR)); + } + + if (!gl::Program::linkVaryings(infoLog, fragmentShader, vertexShader)) + { + return LinkResult(false, gl::Error(GL_NO_ERROR)); + } + + if (!mDynamicHLSL->generateShaderLinkHLSL(data, infoLog, *registers, packing, mPixelHLSL, mVertexHLSL, + fragmentShaderD3D, vertexShaderD3D, transformFeedbackVaryings, + linkedVaryings, outputVariables, &mPixelShaderKey, &mUsesFragDepth)) + { + return LinkResult(false, gl::Error(GL_NO_ERROR)); + } + + mUsesPointSize = vertexShaderD3D->usesPointSize(); + + initAttributesByLayout(); + + return LinkResult(true, gl::Error(GL_NO_ERROR)); +} + +void ProgramD3D::getInputLayoutSignature(const gl::VertexFormat inputLayout[], GLenum signature[]) const +{ + mDynamicHLSL->getInputLayoutSignature(inputLayout, signature); +} + +void ProgramD3D::initializeUniformStorage() +{ + // Compute total default block size + unsigned int vertexRegisters = 0; + unsigned int fragmentRegisters = 0; + for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++) + { + const gl::LinkedUniform &uniform = *mUniforms[uniformIndex]; + + if (!gl::IsSamplerType(uniform.type)) + { + if (uniform.isReferencedByVertexShader()) + { + vertexRegisters = std::max(vertexRegisters, uniform.vsRegisterIndex + uniform.registerCount); + } + if (uniform.isReferencedByFragmentShader()) + { + fragmentRegisters = std::max(fragmentRegisters, uniform.psRegisterIndex + uniform.registerCount); + } + } + } + + mVertexUniformStorage = mRenderer->createUniformStorage(vertexRegisters * 16u); + mFragmentUniformStorage = mRenderer->createUniformStorage(fragmentRegisters * 16u); +} + +gl::Error ProgramD3D::applyUniforms() +{ + updateSamplerMapping(); + + gl::Error error = mRenderer->applyUniforms(*this, mUniforms); + if (error.isError()) + { + return error; + } + + for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++) + { + mUniforms[uniformIndex]->dirty = false; + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error ProgramD3D::applyUniformBuffers(const gl::Data &data, GLuint uniformBlockBindings[]) +{ + GLint vertexUniformBuffers[gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS]; + GLint fragmentUniformBuffers[gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS]; + + for (unsigned int registerIndex = 0; registerIndex < gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS; ++registerIndex) + { + vertexUniformBuffers[registerIndex] = -1; + } + + for (unsigned int registerIndex = 0; registerIndex < gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS; ++registerIndex) + { + fragmentUniformBuffers[registerIndex] = -1; + } + + const unsigned int reservedBuffersInVS = mRenderer->getReservedVertexUniformBuffers(); + const unsigned int reservedBuffersInFS = mRenderer->getReservedFragmentUniformBuffers(); + + for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < mUniformBlocks.size(); uniformBlockIndex++) + { + gl::UniformBlock *uniformBlock = mUniformBlocks[uniformBlockIndex]; + GLuint blockBinding = uniformBlockBindings[uniformBlockIndex]; + + ASSERT(uniformBlock); + + // Unnecessary to apply an unreferenced standard or shared UBO + if (!uniformBlock->isReferencedByVertexShader() && !uniformBlock->isReferencedByFragmentShader()) + { + continue; + } + + if (uniformBlock->isReferencedByVertexShader()) + { + unsigned int registerIndex = uniformBlock->vsRegisterIndex - reservedBuffersInVS; + ASSERT(vertexUniformBuffers[registerIndex] == -1); + ASSERT(registerIndex < data.caps->maxVertexUniformBlocks); + vertexUniformBuffers[registerIndex] = blockBinding; + } + + if (uniformBlock->isReferencedByFragmentShader()) + { + unsigned int registerIndex = uniformBlock->psRegisterIndex - reservedBuffersInFS; + ASSERT(fragmentUniformBuffers[registerIndex] == -1); + ASSERT(registerIndex < data.caps->maxFragmentUniformBlocks); + fragmentUniformBuffers[registerIndex] = blockBinding; + } + } + + return mRenderer->setUniformBuffers(data, vertexUniformBuffers, fragmentUniformBuffers); +} + +bool ProgramD3D::assignUniformBlockRegister(gl::InfoLog &infoLog, gl::UniformBlock *uniformBlock, GLenum shader, + unsigned int registerIndex, const gl::Caps &caps) +{ + if (shader == GL_VERTEX_SHADER) + { + uniformBlock->vsRegisterIndex = registerIndex; + if (registerIndex - mRenderer->getReservedVertexUniformBuffers() >= caps.maxVertexUniformBlocks) + { + infoLog.append("Vertex shader uniform block count exceed GL_MAX_VERTEX_UNIFORM_BLOCKS (%u)", caps.maxVertexUniformBlocks); + return false; + } + } + else if (shader == GL_FRAGMENT_SHADER) + { + uniformBlock->psRegisterIndex = registerIndex; + if (registerIndex - mRenderer->getReservedFragmentUniformBuffers() >= caps.maxFragmentUniformBlocks) + { + infoLog.append("Fragment shader uniform block count exceed GL_MAX_FRAGMENT_UNIFORM_BLOCKS (%u)", caps.maxFragmentUniformBlocks); + return false; + } + } + else UNREACHABLE(); + + return true; +} + +void ProgramD3D::dirtyAllUniforms() +{ + unsigned int numUniforms = mUniforms.size(); + for (unsigned int index = 0; index < numUniforms; index++) + { + mUniforms[index]->dirty = true; + } +} + +void ProgramD3D::setUniform1fv(GLint location, GLsizei count, const GLfloat* v) +{ + setUniform(location, count, v, GL_FLOAT); +} + +void ProgramD3D::setUniform2fv(GLint location, GLsizei count, const GLfloat *v) +{ + setUniform(location, count, v, GL_FLOAT_VEC2); +} + +void ProgramD3D::setUniform3fv(GLint location, GLsizei count, const GLfloat *v) +{ + setUniform(location, count, v, GL_FLOAT_VEC3); +} + +void ProgramD3D::setUniform4fv(GLint location, GLsizei count, const GLfloat *v) +{ + setUniform(location, count, v, GL_FLOAT_VEC4); +} + +void ProgramD3D::setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) +{ + setUniformMatrixfv<2, 2>(location, count, transpose, value, GL_FLOAT_MAT2); +} + +void ProgramD3D::setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) +{ + setUniformMatrixfv<3, 3>(location, count, transpose, value, GL_FLOAT_MAT3); +} + +void ProgramD3D::setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) +{ + setUniformMatrixfv<4, 4>(location, count, transpose, value, GL_FLOAT_MAT4); +} + +void ProgramD3D::setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) +{ + setUniformMatrixfv<2, 3>(location, count, transpose, value, GL_FLOAT_MAT2x3); +} + +void ProgramD3D::setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) +{ + setUniformMatrixfv<3, 2>(location, count, transpose, value, GL_FLOAT_MAT3x2); +} + +void ProgramD3D::setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) +{ + setUniformMatrixfv<2, 4>(location, count, transpose, value, GL_FLOAT_MAT2x4); +} + +void ProgramD3D::setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) +{ + setUniformMatrixfv<4, 2>(location, count, transpose, value, GL_FLOAT_MAT4x2); +} + +void ProgramD3D::setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) +{ + setUniformMatrixfv<3, 4>(location, count, transpose, value, GL_FLOAT_MAT3x4); +} + +void ProgramD3D::setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) +{ + setUniformMatrixfv<4, 3>(location, count, transpose, value, GL_FLOAT_MAT4x3); +} + +void ProgramD3D::setUniform1iv(GLint location, GLsizei count, const GLint *v) +{ + setUniform(location, count, v, GL_INT); +} + +void ProgramD3D::setUniform2iv(GLint location, GLsizei count, const GLint *v) +{ + setUniform(location, count, v, GL_INT_VEC2); +} + +void ProgramD3D::setUniform3iv(GLint location, GLsizei count, const GLint *v) +{ + setUniform(location, count, v, GL_INT_VEC3); +} + +void ProgramD3D::setUniform4iv(GLint location, GLsizei count, const GLint *v) +{ + setUniform(location, count, v, GL_INT_VEC4); +} + +void ProgramD3D::setUniform1uiv(GLint location, GLsizei count, const GLuint *v) +{ + setUniform(location, count, v, GL_UNSIGNED_INT); +} + +void ProgramD3D::setUniform2uiv(GLint location, GLsizei count, const GLuint *v) +{ + setUniform(location, count, v, GL_UNSIGNED_INT_VEC2); +} + +void ProgramD3D::setUniform3uiv(GLint location, GLsizei count, const GLuint *v) +{ + setUniform(location, count, v, GL_UNSIGNED_INT_VEC3); +} + +void ProgramD3D::setUniform4uiv(GLint location, GLsizei count, const GLuint *v) +{ + setUniform(location, count, v, GL_UNSIGNED_INT_VEC4); +} + +void ProgramD3D::getUniformfv(GLint location, GLfloat *params) +{ + getUniformv(location, params, GL_FLOAT); +} + +void ProgramD3D::getUniformiv(GLint location, GLint *params) +{ + getUniformv(location, params, GL_INT); +} + +void ProgramD3D::getUniformuiv(GLint location, GLuint *params) +{ + getUniformv(location, params, GL_UNSIGNED_INT); +} + +bool ProgramD3D::linkUniforms(gl::InfoLog &infoLog, const gl::Shader &vertexShader, const gl::Shader &fragmentShader, + const gl::Caps &caps) +{ + const ShaderD3D *vertexShaderD3D = ShaderD3D::makeShaderD3D(vertexShader.getImplementation()); + const ShaderD3D *fragmentShaderD3D = ShaderD3D::makeShaderD3D(fragmentShader.getImplementation()); + + const std::vector &vertexUniforms = vertexShader.getUniforms(); + const std::vector &fragmentUniforms = fragmentShader.getUniforms(); + + // Check that uniforms defined in the vertex and fragment shaders are identical + typedef std::map UniformMap; + UniformMap linkedUniforms; + + for (unsigned int vertexUniformIndex = 0; vertexUniformIndex < vertexUniforms.size(); vertexUniformIndex++) + { + const sh::Uniform &vertexUniform = vertexUniforms[vertexUniformIndex]; + linkedUniforms[vertexUniform.name] = &vertexUniform; + } + + for (unsigned int fragmentUniformIndex = 0; fragmentUniformIndex < fragmentUniforms.size(); fragmentUniformIndex++) + { + const sh::Uniform &fragmentUniform = fragmentUniforms[fragmentUniformIndex]; + UniformMap::const_iterator entry = linkedUniforms.find(fragmentUniform.name); + if (entry != linkedUniforms.end()) + { + const sh::Uniform &vertexUniform = *entry->second; + const std::string &uniformName = "uniform '" + vertexUniform.name + "'"; + if (!gl::Program::linkValidateUniforms(infoLog, uniformName, vertexUniform, fragmentUniform)) + { + return false; + } + } + } + + for (unsigned int uniformIndex = 0; uniformIndex < vertexUniforms.size(); uniformIndex++) + { + const sh::Uniform &uniform = vertexUniforms[uniformIndex]; + + if (uniform.staticUse) + { + defineUniformBase(vertexShaderD3D, uniform, vertexShaderD3D->getUniformRegister(uniform.name)); + } + } + + for (unsigned int uniformIndex = 0; uniformIndex < fragmentUniforms.size(); uniformIndex++) + { + const sh::Uniform &uniform = fragmentUniforms[uniformIndex]; + + if (uniform.staticUse) + { + defineUniformBase(fragmentShaderD3D, uniform, fragmentShaderD3D->getUniformRegister(uniform.name)); + } + } + + if (!indexUniforms(infoLog, caps)) + { + return false; + } + + initializeUniformStorage(); + + // special case for gl_DepthRange, the only built-in uniform (also a struct) + if (vertexShaderD3D->usesDepthRange() || fragmentShaderD3D->usesDepthRange()) + { + const sh::BlockMemberInfo &defaultInfo = sh::BlockMemberInfo::getDefaultBlockInfo(); + + mUniforms.push_back(new gl::LinkedUniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.near", 0, -1, defaultInfo)); + mUniforms.push_back(new gl::LinkedUniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.far", 0, -1, defaultInfo)); + mUniforms.push_back(new gl::LinkedUniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.diff", 0, -1, defaultInfo)); + } + + return true; +} + +void ProgramD3D::defineUniformBase(const ShaderD3D *shader, const sh::Uniform &uniform, unsigned int uniformRegister) +{ + ShShaderOutput outputType = shader->getCompilerOutputType(); + sh::HLSLBlockEncoder encoder(sh::HLSLBlockEncoder::GetStrategyFor(outputType)); + encoder.skipRegisters(uniformRegister); + + defineUniform(shader, uniform, uniform.name, &encoder); +} + +void ProgramD3D::defineUniform(const ShaderD3D *shader, const sh::ShaderVariable &uniform, + const std::string &fullName, sh::HLSLBlockEncoder *encoder) +{ + if (uniform.isStruct()) + { + for (unsigned int elementIndex = 0; elementIndex < uniform.elementCount(); elementIndex++) + { + const std::string &elementString = (uniform.isArray() ? ArrayString(elementIndex) : ""); + + encoder->enterAggregateType(); + + for (size_t fieldIndex = 0; fieldIndex < uniform.fields.size(); fieldIndex++) + { + const sh::ShaderVariable &field = uniform.fields[fieldIndex]; + const std::string &fieldFullName = (fullName + elementString + "." + field.name); + + defineUniform(shader, field, fieldFullName, encoder); + } + + encoder->exitAggregateType(); + } + } + else // Not a struct + { + // Arrays are treated as aggregate types + if (uniform.isArray()) + { + encoder->enterAggregateType(); + } + + gl::LinkedUniform *linkedUniform = getUniformByName(fullName); + + // Advance the uniform offset, to track registers allocation for structs + sh::BlockMemberInfo blockInfo = encoder->encodeType(uniform.type, uniform.arraySize, false); + + if (!linkedUniform) + { + linkedUniform = new gl::LinkedUniform(uniform.type, uniform.precision, fullName, uniform.arraySize, + -1, sh::BlockMemberInfo::getDefaultBlockInfo()); + ASSERT(linkedUniform); + linkedUniform->registerElement = sh::HLSLBlockEncoder::getBlockRegisterElement(blockInfo); + mUniforms.push_back(linkedUniform); + } + + if (shader->getShaderType() == GL_FRAGMENT_SHADER) + { + linkedUniform->psRegisterIndex = sh::HLSLBlockEncoder::getBlockRegister(blockInfo); + } + else if (shader->getShaderType() == GL_VERTEX_SHADER) + { + linkedUniform->vsRegisterIndex = sh::HLSLBlockEncoder::getBlockRegister(blockInfo); + } + else UNREACHABLE(); + + // Arrays are treated as aggregate types + if (uniform.isArray()) + { + encoder->exitAggregateType(); + } + } +} + +template +static inline void SetIfDirty(T *dest, const T& source, bool *dirtyFlag) +{ + ASSERT(dest != NULL); + ASSERT(dirtyFlag != NULL); + + *dirtyFlag = *dirtyFlag || (memcmp(dest, &source, sizeof(T)) != 0); + *dest = source; +} + +template +void ProgramD3D::setUniform(GLint location, GLsizei count, const T* v, GLenum targetUniformType) +{ + const int components = gl::VariableComponentCount(targetUniformType); + const GLenum targetBoolType = gl::VariableBoolVectorType(targetUniformType); + + gl::LinkedUniform *targetUniform = getUniformByLocation(location); + + int elementCount = targetUniform->elementCount(); + + count = std::min(elementCount - (int)mUniformIndex[location].element, count); + + if (targetUniform->type == targetUniformType) + { + T *target = reinterpret_cast(targetUniform->data) + mUniformIndex[location].element * 4; + + for (int i = 0; i < count; i++) + { + T *dest = target + (i * 4); + const T *source = v + (i * components); + + for (int c = 0; c < components; c++) + { + SetIfDirty(dest + c, source[c], &targetUniform->dirty); + } + for (int c = components; c < 4; c++) + { + SetIfDirty(dest + c, T(0), &targetUniform->dirty); + } + } + } + else if (targetUniform->type == targetBoolType) + { + GLint *boolParams = reinterpret_cast(targetUniform->data) + mUniformIndex[location].element * 4; + + for (int i = 0; i < count; i++) + { + GLint *dest = boolParams + (i * 4); + const T *source = v + (i * components); + + for (int c = 0; c < components; c++) + { + SetIfDirty(dest + c, (source[c] == static_cast(0)) ? GL_FALSE : GL_TRUE, &targetUniform->dirty); + } + for (int c = components; c < 4; c++) + { + SetIfDirty(dest + c, GL_FALSE, &targetUniform->dirty); + } + } + } + else if (gl::IsSamplerType(targetUniform->type)) + { + ASSERT(targetUniformType == GL_INT); + + GLint *target = reinterpret_cast(targetUniform->data) + mUniformIndex[location].element * 4; + + bool wasDirty = targetUniform->dirty; + + for (int i = 0; i < count; i++) + { + GLint *dest = target + (i * 4); + const GLint *source = reinterpret_cast(v) + (i * components); + + SetIfDirty(dest + 0, source[0], &targetUniform->dirty); + SetIfDirty(dest + 1, 0, &targetUniform->dirty); + SetIfDirty(dest + 2, 0, &targetUniform->dirty); + SetIfDirty(dest + 3, 0, &targetUniform->dirty); + } + + if (!wasDirty && targetUniform->dirty) + { + mDirtySamplerMapping = true; + } + } + else UNREACHABLE(); +} + +template +bool transposeMatrix(T *target, const GLfloat *value, int targetWidth, int targetHeight, int srcWidth, int srcHeight) +{ + bool dirty = false; + int copyWidth = std::min(targetHeight, srcWidth); + int copyHeight = std::min(targetWidth, srcHeight); + + for (int x = 0; x < copyWidth; x++) + { + for (int y = 0; y < copyHeight; y++) + { + SetIfDirty(target + (x * targetWidth + y), static_cast(value[y * srcWidth + x]), &dirty); + } + } + // clear unfilled right side + for (int y = 0; y < copyWidth; y++) + { + for (int x = copyHeight; x < targetWidth; x++) + { + SetIfDirty(target + (y * targetWidth + x), static_cast(0), &dirty); + } + } + // clear unfilled bottom. + for (int y = copyWidth; y < targetHeight; y++) + { + for (int x = 0; x < targetWidth; x++) + { + SetIfDirty(target + (y * targetWidth + x), static_cast(0), &dirty); + } + } + + return dirty; +} + +template +bool expandMatrix(T *target, const GLfloat *value, int targetWidth, int targetHeight, int srcWidth, int srcHeight) +{ + bool dirty = false; + int copyWidth = std::min(targetWidth, srcWidth); + int copyHeight = std::min(targetHeight, srcHeight); + + for (int y = 0; y < copyHeight; y++) + { + for (int x = 0; x < copyWidth; x++) + { + SetIfDirty(target + (y * targetWidth + x), static_cast(value[y * srcWidth + x]), &dirty); + } + } + // clear unfilled right side + for (int y = 0; y < copyHeight; y++) + { + for (int x = copyWidth; x < targetWidth; x++) + { + SetIfDirty(target + (y * targetWidth + x), static_cast(0), &dirty); + } + } + // clear unfilled bottom. + for (int y = copyHeight; y < targetHeight; y++) + { + for (int x = 0; x < targetWidth; x++) + { + SetIfDirty(target + (y * targetWidth + x), static_cast(0), &dirty); + } + } + + return dirty; +} + +template +void ProgramD3D::setUniformMatrixfv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value, GLenum targetUniformType) +{ + gl::LinkedUniform *targetUniform = getUniformByLocation(location); + + int elementCount = targetUniform->elementCount(); + + count = std::min(elementCount - (int)mUniformIndex[location].element, count); + const unsigned int targetMatrixStride = (4 * rows); + GLfloat *target = (GLfloat*)(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * targetMatrixStride); + + for (int i = 0; i < count; i++) + { + // Internally store matrices as transposed versions to accomodate HLSL matrix indexing + if (transpose == GL_FALSE) + { + targetUniform->dirty = transposeMatrix(target, value, 4, rows, rows, cols) || targetUniform->dirty; + } + else + { + targetUniform->dirty = expandMatrix(target, value, 4, rows, cols, rows) || targetUniform->dirty; + } + target += targetMatrixStride; + value += cols * rows; + } +} + +template +void ProgramD3D::getUniformv(GLint location, T *params, GLenum uniformType) +{ + gl::LinkedUniform *targetUniform = mUniforms[mUniformIndex[location].index]; + + if (gl::IsMatrixType(targetUniform->type)) + { + const int rows = gl::VariableRowCount(targetUniform->type); + const int cols = gl::VariableColumnCount(targetUniform->type); + transposeMatrix(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4 * rows, rows, cols, 4, rows); + } + else if (uniformType == gl::VariableComponentType(targetUniform->type)) + { + unsigned int size = gl::VariableComponentCount(targetUniform->type); + memcpy(params, targetUniform->data + mUniformIndex[location].element * 4 * sizeof(T), + size * sizeof(T)); + } + else + { + unsigned int size = gl::VariableComponentCount(targetUniform->type); + switch (gl::VariableComponentType(targetUniform->type)) + { + case GL_BOOL: + { + GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; + + for (unsigned int i = 0; i < size; i++) + { + params[i] = (boolParams[i] == GL_FALSE) ? static_cast(0) : static_cast(1); + } + } + break; + + case GL_FLOAT: + { + GLfloat *floatParams = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4; + + for (unsigned int i = 0; i < size; i++) + { + params[i] = static_cast(floatParams[i]); + } + } + break; + + case GL_INT: + { + GLint *intParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; + + for (unsigned int i = 0; i < size; i++) + { + params[i] = static_cast(intParams[i]); + } + } + break; + + case GL_UNSIGNED_INT: + { + GLuint *uintParams = (GLuint*)targetUniform->data + mUniformIndex[location].element * 4; + + for (unsigned int i = 0; i < size; i++) + { + params[i] = static_cast(uintParams[i]); + } + } + break; + + default: UNREACHABLE(); + } + } +} + +template +void ProgramD3D::defineUniformBlockMembers(const std::vector &fields, const std::string &prefix, int blockIndex, + sh::BlockLayoutEncoder *encoder, std::vector *blockUniformIndexes, + bool inRowMajorLayout) +{ + for (unsigned int uniformIndex = 0; uniformIndex < fields.size(); uniformIndex++) + { + const VarT &field = fields[uniformIndex]; + const std::string &fieldName = (prefix.empty() ? field.name : prefix + "." + field.name); + + if (field.isStruct()) + { + bool rowMajorLayout = (inRowMajorLayout || IsRowMajorLayout(field)); + + for (unsigned int arrayElement = 0; arrayElement < field.elementCount(); arrayElement++) + { + encoder->enterAggregateType(); + + const std::string uniformElementName = fieldName + (field.isArray() ? ArrayString(arrayElement) : ""); + defineUniformBlockMembers(field.fields, uniformElementName, blockIndex, encoder, blockUniformIndexes, rowMajorLayout); + + encoder->exitAggregateType(); + } + } + else + { + bool isRowMajorMatrix = (gl::IsMatrixType(field.type) && inRowMajorLayout); + + sh::BlockMemberInfo memberInfo = encoder->encodeType(field.type, field.arraySize, isRowMajorMatrix); + + gl::LinkedUniform *newUniform = new gl::LinkedUniform(field.type, field.precision, fieldName, field.arraySize, + blockIndex, memberInfo); + + // add to uniform list, but not index, since uniform block uniforms have no location + blockUniformIndexes->push_back(mUniforms.size()); + mUniforms.push_back(newUniform); + } + } +} + +bool ProgramD3D::defineUniformBlock(gl::InfoLog &infoLog, const gl::Shader &shader, const sh::InterfaceBlock &interfaceBlock, + const gl::Caps &caps) +{ + const ShaderD3D* shaderD3D = ShaderD3D::makeShaderD3D(shader.getImplementation()); + + // create uniform block entries if they do not exist + if (getUniformBlockIndex(interfaceBlock.name) == GL_INVALID_INDEX) + { + std::vector blockUniformIndexes; + const unsigned int blockIndex = mUniformBlocks.size(); + + // define member uniforms + sh::BlockLayoutEncoder *encoder = NULL; + + if (interfaceBlock.layout == sh::BLOCKLAYOUT_STANDARD) + { + encoder = new sh::Std140BlockEncoder; + } + else + { + encoder = new sh::HLSLBlockEncoder(sh::HLSLBlockEncoder::ENCODE_PACKED); + } + ASSERT(encoder); + + defineUniformBlockMembers(interfaceBlock.fields, "", blockIndex, encoder, &blockUniformIndexes, interfaceBlock.isRowMajorLayout); + + size_t dataSize = encoder->getBlockSize(); + + // create all the uniform blocks + if (interfaceBlock.arraySize > 0) + { + for (unsigned int uniformBlockElement = 0; uniformBlockElement < interfaceBlock.arraySize; uniformBlockElement++) + { + gl::UniformBlock *newUniformBlock = new gl::UniformBlock(interfaceBlock.name, uniformBlockElement, dataSize); + newUniformBlock->memberUniformIndexes = blockUniformIndexes; + mUniformBlocks.push_back(newUniformBlock); + } + } + else + { + gl::UniformBlock *newUniformBlock = new gl::UniformBlock(interfaceBlock.name, GL_INVALID_INDEX, dataSize); + newUniformBlock->memberUniformIndexes = blockUniformIndexes; + mUniformBlocks.push_back(newUniformBlock); + } + } + + if (interfaceBlock.staticUse) + { + // Assign registers to the uniform blocks + const GLuint blockIndex = getUniformBlockIndex(interfaceBlock.name); + const unsigned int elementCount = std::max(1u, interfaceBlock.arraySize); + ASSERT(blockIndex != GL_INVALID_INDEX); + ASSERT(blockIndex + elementCount <= mUniformBlocks.size()); + + unsigned int interfaceBlockRegister = shaderD3D->getInterfaceBlockRegister(interfaceBlock.name); + + for (unsigned int uniformBlockElement = 0; uniformBlockElement < elementCount; uniformBlockElement++) + { + gl::UniformBlock *uniformBlock = mUniformBlocks[blockIndex + uniformBlockElement]; + ASSERT(uniformBlock->name == interfaceBlock.name); + + if (!assignUniformBlockRegister(infoLog, uniformBlock, shader.getType(), + interfaceBlockRegister + uniformBlockElement, caps)) + { + return false; + } + } + } + + return true; +} + +bool ProgramD3D::assignSamplers(unsigned int startSamplerIndex, + GLenum samplerType, + unsigned int samplerCount, + std::vector &outSamplers, + GLuint *outUsedRange) +{ + unsigned int samplerIndex = startSamplerIndex; + + do + { + if (samplerIndex < outSamplers.size()) + { + Sampler& sampler = outSamplers[samplerIndex]; + sampler.active = true; + sampler.textureType = GetTextureType(samplerType); + sampler.logicalTextureUnit = 0; + *outUsedRange = std::max(samplerIndex + 1, *outUsedRange); + } + else + { + return false; + } + + samplerIndex++; + } while (samplerIndex < startSamplerIndex + samplerCount); + + return true; +} + +bool ProgramD3D::indexSamplerUniform(const gl::LinkedUniform &uniform, gl::InfoLog &infoLog, const gl::Caps &caps) +{ + ASSERT(gl::IsSamplerType(uniform.type)); + ASSERT(uniform.vsRegisterIndex != GL_INVALID_INDEX || uniform.psRegisterIndex != GL_INVALID_INDEX); + + if (uniform.vsRegisterIndex != GL_INVALID_INDEX) + { + if (!assignSamplers(uniform.vsRegisterIndex, uniform.type, uniform.arraySize, mSamplersVS, + &mUsedVertexSamplerRange)) + { + infoLog.append("Vertex shader sampler count exceeds the maximum vertex texture units (%d).", + mSamplersVS.size()); + return false; + } + + unsigned int maxVertexVectors = mRenderer->getReservedVertexUniformVectors() + caps.maxVertexUniformVectors; + if (uniform.vsRegisterIndex + uniform.registerCount > maxVertexVectors) + { + infoLog.append("Vertex shader active uniforms exceed GL_MAX_VERTEX_UNIFORM_VECTORS (%u)", + caps.maxVertexUniformVectors); + return false; + } + } + + if (uniform.psRegisterIndex != GL_INVALID_INDEX) + { + if (!assignSamplers(uniform.psRegisterIndex, uniform.type, uniform.arraySize, mSamplersPS, + &mUsedPixelSamplerRange)) + { + infoLog.append("Pixel shader sampler count exceeds MAX_TEXTURE_IMAGE_UNITS (%d).", + mSamplersPS.size()); + return false; + } + + unsigned int maxFragmentVectors = mRenderer->getReservedFragmentUniformVectors() + caps.maxFragmentUniformVectors; + if (uniform.psRegisterIndex + uniform.registerCount > maxFragmentVectors) + { + infoLog.append("Fragment shader active uniforms exceed GL_MAX_FRAGMENT_UNIFORM_VECTORS (%u)", + caps.maxFragmentUniformVectors); + return false; + } + } + + return true; +} + +bool ProgramD3D::indexUniforms(gl::InfoLog &infoLog, const gl::Caps &caps) +{ + for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++) + { + const gl::LinkedUniform &uniform = *mUniforms[uniformIndex]; + + if (gl::IsSamplerType(uniform.type)) + { + if (!indexSamplerUniform(uniform, infoLog, caps)) + { + return false; + } + } + + for (unsigned int arrayElementIndex = 0; arrayElementIndex < uniform.elementCount(); arrayElementIndex++) + { + mUniformIndex.push_back(gl::VariableLocation(uniform.name, arrayElementIndex, uniformIndex)); + } + } + + return true; +} + +void ProgramD3D::reset() +{ + ProgramImpl::reset(); + + SafeDeleteContainer(mVertexExecutables); + SafeDeleteContainer(mPixelExecutables); + SafeDelete(mGeometryExecutable); + + mTransformFeedbackBufferMode = GL_NONE; + + mVertexHLSL.clear(); + mVertexWorkarounds.reset(); + mShaderVersion = 100; + + mPixelHLSL.clear(); + mPixelWorkarounds.reset(); + mUsesFragDepth = false; + mPixelShaderKey.clear(); + mUsesPointSize = false; + + SafeDelete(mVertexUniformStorage); + SafeDelete(mFragmentUniformStorage); + + mSamplersPS.clear(); + mSamplersVS.clear(); + + mUsedVertexSamplerRange = 0; + mUsedPixelSamplerRange = 0; + mDirtySamplerMapping = true; + + std::fill(mAttributesByLayout, mAttributesByLayout + ArraySize(mAttributesByLayout), -1); +} + +unsigned int ProgramD3D::getSerial() const +{ + return mSerial; +} + +unsigned int ProgramD3D::issueSerial() +{ + return mCurrentSerial++; +} + +void ProgramD3D::initAttributesByLayout() +{ + for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + mAttributesByLayout[i] = i; + } + + std::sort(&mAttributesByLayout[0], &mAttributesByLayout[gl::MAX_VERTEX_ATTRIBS], AttributeSorter(mSemanticIndex)); +} + +void ProgramD3D::sortAttributesByLayout(rx::TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS], + int sortedSemanticIndices[gl::MAX_VERTEX_ATTRIBS]) const +{ + rx::TranslatedAttribute oldTranslatedAttributes[gl::MAX_VERTEX_ATTRIBS]; + + for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + oldTranslatedAttributes[i] = attributes[i]; + } + + for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + int oldIndex = mAttributesByLayout[i]; + sortedSemanticIndices[i] = mSemanticIndex[oldIndex]; + attributes[i] = oldTranslatedAttributes[oldIndex]; + } +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/ProgramD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ProgramD3D.h new file mode 100644 index 0000000000..6f3eade81d --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ProgramD3D.h @@ -0,0 +1,244 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// ProgramD3D.h: Defines the rx::ProgramD3D class which implements rx::ProgramImpl. + +#ifndef LIBANGLE_RENDERER_D3D_PROGRAMD3D_H_ +#define LIBANGLE_RENDERER_D3D_PROGRAMD3D_H_ + +#include "compiler/translator/blocklayoutHLSL.h" +#include "libANGLE/Constants.h" +#include "libANGLE/renderer/ProgramImpl.h" +#include "libANGLE/renderer/Workarounds.h" +#include "libANGLE/renderer/d3d/DynamicHLSL.h" + +#include +#include + +namespace gl +{ +struct LinkedUniform; +struct VariableLocation; +struct VertexFormat; +} + +namespace rx +{ +class RendererD3D; +class UniformStorageD3D; +class ShaderExecutableD3D; + +#if !defined(ANGLE_COMPILE_OPTIMIZATION_LEVEL) +// WARNING: D3DCOMPILE_OPTIMIZATION_LEVEL3 may lead to a DX9 shader compiler hang. +// It should only be used selectively to work around specific bugs. +#define ANGLE_COMPILE_OPTIMIZATION_LEVEL D3DCOMPILE_OPTIMIZATION_LEVEL1 +#endif + +class ProgramD3D : public ProgramImpl +{ + public: + ProgramD3D(RendererD3D *renderer); + virtual ~ProgramD3D(); + + const std::vector &getPixelShaderKey() { return mPixelShaderKey; } + int getShaderVersion() const { return mShaderVersion; } + GLenum getTransformFeedbackBufferMode() const { return mTransformFeedbackBufferMode; } + + GLint getSamplerMapping(gl::SamplerType type, unsigned int samplerIndex, const gl::Caps &caps) const; + GLenum getSamplerTextureType(gl::SamplerType type, unsigned int samplerIndex) const; + GLint getUsedSamplerRange(gl::SamplerType type) const; + void updateSamplerMapping(); + bool validateSamplers(gl::InfoLog *infoLog, const gl::Caps &caps); + + bool usesPointSize() const { return mUsesPointSize; } + bool usesPointSpriteEmulation() const; + bool usesGeometryShader() const; + bool usesInstancedPointSpriteEmulation() const; + + GLenum getBinaryFormat() { return GL_PROGRAM_BINARY_ANGLE; } + LinkResult load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream); + gl::Error save(gl::BinaryOutputStream *stream); + + gl::Error getPixelExecutableForFramebuffer(const gl::Framebuffer *fbo, ShaderExecutableD3D **outExectuable); + gl::Error getPixelExecutableForOutputLayout(const std::vector &outputLayout, ShaderExecutableD3D **outExectuable, gl::InfoLog *infoLog); + gl::Error getVertexExecutableForInputLayout(const gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS], ShaderExecutableD3D **outExectuable, gl::InfoLog *infoLog); + ShaderExecutableD3D *getGeometryExecutable() const { return mGeometryExecutable; } + + LinkResult compileProgramExecutables(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader, + int registers); + + LinkResult link(const gl::Data &data, gl::InfoLog &infoLog, + gl::Shader *fragmentShader, gl::Shader *vertexShader, + const std::vector &transformFeedbackVaryings, + GLenum transformFeedbackBufferMode, + int *registers, std::vector *linkedVaryings, + std::map *outputVariables); + + void getInputLayoutSignature(const gl::VertexFormat inputLayout[], GLenum signature[]) const; + + void initializeUniformStorage(); + gl::Error applyUniforms(); + gl::Error applyUniformBuffers(const gl::Data &data, GLuint uniformBlockBindings[]) override; + bool assignUniformBlockRegister(gl::InfoLog &infoLog, gl::UniformBlock *uniformBlock, GLenum shader, + unsigned int registerIndex, const gl::Caps &caps); + void dirtyAllUniforms(); + + void setUniform1fv(GLint location, GLsizei count, const GLfloat *v); + void setUniform2fv(GLint location, GLsizei count, const GLfloat *v); + void setUniform3fv(GLint location, GLsizei count, const GLfloat *v); + void setUniform4fv(GLint location, GLsizei count, const GLfloat *v); + void setUniform1iv(GLint location, GLsizei count, const GLint *v); + void setUniform2iv(GLint location, GLsizei count, const GLint *v); + void setUniform3iv(GLint location, GLsizei count, const GLint *v); + void setUniform4iv(GLint location, GLsizei count, const GLint *v); + void setUniform1uiv(GLint location, GLsizei count, const GLuint *v); + void setUniform2uiv(GLint location, GLsizei count, const GLuint *v); + void setUniform3uiv(GLint location, GLsizei count, const GLuint *v); + void setUniform4uiv(GLint location, GLsizei count, const GLuint *v); + void setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); + void setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); + void setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); + void setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); + void setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); + void setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); + void setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); + void setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); + void setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); + + void getUniformfv(GLint location, GLfloat *params); + void getUniformiv(GLint location, GLint *params); + void getUniformuiv(GLint location, GLuint *params); + + const UniformStorageD3D &getVertexUniformStorage() const { return *mVertexUniformStorage; } + const UniformStorageD3D &getFragmentUniformStorage() const { return *mFragmentUniformStorage; } + + bool linkUniforms(gl::InfoLog &infoLog, const gl::Shader &vertexShader, const gl::Shader &fragmentShader, + const gl::Caps &caps); + bool defineUniformBlock(gl::InfoLog &infoLog, const gl::Shader &shader, const sh::InterfaceBlock &interfaceBlock, const gl::Caps &caps); + + void reset(); + + unsigned int getSerial() const; + + void initAttributesByLayout(); + void sortAttributesByLayout(rx::TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS], + int sortedSemanticIndices[gl::MAX_VERTEX_ATTRIBS]) const; + + private: + class VertexExecutable + { + public: + VertexExecutable(const gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS], + const GLenum signature[gl::MAX_VERTEX_ATTRIBS], + ShaderExecutableD3D *shaderExecutable); + ~VertexExecutable(); + + bool matchesSignature(const GLenum convertedLayout[gl::MAX_VERTEX_ATTRIBS]) const; + + const gl::VertexFormat *inputs() const { return mInputs; } + const GLenum *signature() const { return mSignature; } + ShaderExecutableD3D *shaderExecutable() const { return mShaderExecutable; } + + private: + gl::VertexFormat mInputs[gl::MAX_VERTEX_ATTRIBS]; + GLenum mSignature[gl::MAX_VERTEX_ATTRIBS]; + ShaderExecutableD3D *mShaderExecutable; + }; + + class PixelExecutable + { + public: + PixelExecutable(const std::vector &outputSignature, ShaderExecutableD3D *shaderExecutable); + ~PixelExecutable(); + + bool matchesSignature(const std::vector &signature) const { return mOutputSignature == signature; } + + const std::vector &outputSignature() const { return mOutputSignature; } + ShaderExecutableD3D *shaderExecutable() const { return mShaderExecutable; } + + private: + std::vector mOutputSignature; + ShaderExecutableD3D *mShaderExecutable; + }; + + struct Sampler + { + Sampler(); + + bool active; + GLint logicalTextureUnit; + GLenum textureType; + }; + + void defineUniformBase(const ShaderD3D *shader, const sh::Uniform &uniform, unsigned int uniformRegister); + void defineUniform(const ShaderD3D *shader, const sh::ShaderVariable &uniform, const std::string &fullName, + sh::HLSLBlockEncoder *encoder); + bool indexSamplerUniform(const gl::LinkedUniform &uniform, gl::InfoLog &infoLog, const gl::Caps &caps); + bool indexUniforms(gl::InfoLog &infoLog, const gl::Caps &caps); + static bool assignSamplers(unsigned int startSamplerIndex, GLenum samplerType, unsigned int samplerCount, + std::vector &outSamplers, GLuint *outUsedRange); + + template + void setUniform(GLint location, GLsizei count, const T* v, GLenum targetUniformType); + + template + void setUniformMatrixfv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value, GLenum targetUniformType); + + template + void getUniformv(GLint location, T *params, GLenum uniformType); + + template + void defineUniformBlockMembers(const std::vector &fields, const std::string &prefix, int blockIndex, + sh::BlockLayoutEncoder *encoder, std::vector *blockUniformIndexes, + bool inRowMajorLayout); + + RendererD3D *mRenderer; + DynamicHLSL *mDynamicHLSL; + + std::vector mVertexExecutables; + std::vector mPixelExecutables; + ShaderExecutableD3D *mGeometryExecutable; + + std::string mVertexHLSL; + D3DCompilerWorkarounds mVertexWorkarounds; + + std::string mPixelHLSL; + D3DCompilerWorkarounds mPixelWorkarounds; + bool mUsesFragDepth; + std::vector mPixelShaderKey; + + bool mUsesPointSize; + + UniformStorageD3D *mVertexUniformStorage; + UniformStorageD3D *mFragmentUniformStorage; + + GLenum mTransformFeedbackBufferMode; + + std::vector mSamplersPS; + std::vector mSamplersVS; + GLuint mUsedVertexSamplerRange; + GLuint mUsedPixelSamplerRange; + bool mDirtySamplerMapping; + + // Cache for validateSamplers + std::vector mTextureUnitTypesCache; + + // Cache for getPixelExecutableForFramebuffer + std::vector mPixelShaderOutputFormatCache; + + int mShaderVersion; + + int mAttributesByLayout[gl::MAX_VERTEX_ATTRIBS]; + + unsigned int mSerial; + + static unsigned int issueSerial(); + static unsigned int mCurrentSerial; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_PROGRAMD3D_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderTargetD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderTargetD3D.cpp new file mode 100644 index 0000000000..84b30aa106 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderTargetD3D.cpp @@ -0,0 +1,36 @@ +// +// Copyright (c) 2012-2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// RenderTargetD3D.cpp: Implements serial handling for rx::RenderTargetD3D + +#include "libANGLE/renderer/d3d/RenderTargetD3D.h" + +namespace rx +{ +unsigned int RenderTargetD3D::mCurrentSerial = 1; + +RenderTargetD3D::RenderTargetD3D() + : mSerial(issueSerials(1)) +{ +} + +RenderTargetD3D::~RenderTargetD3D() +{ +} + +unsigned int RenderTargetD3D::getSerial() const +{ + return mSerial; +} + +unsigned int RenderTargetD3D::issueSerials(unsigned int count) +{ + unsigned int firstSerial = mCurrentSerial; + mCurrentSerial += count; + return firstSerial; +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderTargetD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderTargetD3D.h new file mode 100644 index 0000000000..fe6afcecae --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderTargetD3D.h @@ -0,0 +1,42 @@ +// +// Copyright (c) 2012-2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// RenderTargetD3D.h: Defines an abstract wrapper class to manage IDirect3DSurface9 +// and ID3D11View objects belonging to renderbuffers and renderable textures. + +#ifndef LIBANGLE_RENDERER_D3D_RENDERTARGETD3D_H_ +#define LIBANGLE_RENDERER_D3D_RENDERTARGETD3D_H_ + +#include "common/angleutils.h" +#include "libANGLE/angletypes.h" + +namespace rx +{ + +class RenderTargetD3D : angle::NonCopyable +{ + public: + RenderTargetD3D(); + virtual ~RenderTargetD3D(); + + virtual GLsizei getWidth() const = 0; + virtual GLsizei getHeight() const = 0; + virtual GLsizei getDepth() const = 0; + virtual GLenum getInternalFormat() const = 0; + virtual GLsizei getSamples() const = 0; + gl::Extents getExtents() const { return gl::Extents(getWidth(), getHeight(), getDepth()); } + + virtual unsigned int getSerial() const; + static unsigned int issueSerials(unsigned int count); + + private: + const unsigned int mSerial; + static unsigned int mCurrentSerial; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_RENDERTARGETD3D_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderbufferD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderbufferD3D.cpp new file mode 100644 index 0000000000..c91fedff06 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderbufferD3D.cpp @@ -0,0 +1,73 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// RenderbufferD3d.cpp: Implements the RenderbufferD3D class, a specialization of RenderbufferImpl + + +#include "libANGLE/renderer/d3d/RenderbufferD3D.h" + +#include "libANGLE/renderer/d3d/RendererD3D.h" +#include "libANGLE/renderer/d3d/RenderTargetD3D.h" + +namespace rx +{ +RenderbufferD3D::RenderbufferD3D(RendererD3D *renderer) : mRenderer(renderer) +{ + mRenderTarget = NULL; +} + +RenderbufferD3D::~RenderbufferD3D() +{ + SafeDelete(mRenderTarget); +} + +RenderbufferD3D *RenderbufferD3D::makeRenderbufferD3D(RenderbufferImpl *renderbuffer) +{ + ASSERT(HAS_DYNAMIC_TYPE(RenderbufferD3D*, renderbuffer)); + return static_cast(renderbuffer); +} + +gl::Error RenderbufferD3D::setStorage(GLenum internalformat, size_t width, size_t height) +{ + return setStorageMultisample(0, internalformat, width, height); +} + +gl::Error RenderbufferD3D::setStorageMultisample(size_t samples, GLenum internalformat, size_t width, size_t height) +{ + // If the renderbuffer parameters are queried, the calling function + // will expect one of the valid renderbuffer formats for use in + // glRenderbufferStorage, but we should create depth and stencil buffers + // as DEPTH24_STENCIL8 + GLenum creationFormat = internalformat; + if (internalformat == GL_DEPTH_COMPONENT16 || internalformat == GL_STENCIL_INDEX8) + { + creationFormat = GL_DEPTH24_STENCIL8_OES; + } + + RenderTargetD3D *newRT = NULL; + gl::Error error = mRenderer->createRenderTarget(width, height, creationFormat, samples, &newRT); + if (error.isError()) + { + return error; + } + + SafeDelete(mRenderTarget); + mRenderTarget = newRT; + + return gl::Error(GL_NO_ERROR); +} + +RenderTargetD3D *RenderbufferD3D::getRenderTarget() +{ + return mRenderTarget; +} + +unsigned int RenderbufferD3D::getRenderTargetSerial() const +{ + return (mRenderTarget ? mRenderTarget->getSerial() : 0); +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderbufferD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderbufferD3D.h new file mode 100644 index 0000000000..4c4b998683 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderbufferD3D.h @@ -0,0 +1,43 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// RenderbufferD3d.h: Defines the RenderbufferD3D class which implements RenderbufferImpl. + +#ifndef LIBANGLE_RENDERER_D3D_RENDERBUFFERD3D_H_ +#define LIBANGLE_RENDERER_D3D_RENDERBUFFERD3D_H_ + +#include "angle_gl.h" + +#include "common/angleutils.h" +#include "libANGLE/renderer/RenderbufferImpl.h" + +namespace rx +{ +class RendererD3D; +class RenderTargetD3D; +class SwapChainD3D; + +class RenderbufferD3D : public RenderbufferImpl +{ + public: + RenderbufferD3D(RendererD3D *renderer); + virtual ~RenderbufferD3D(); + + static RenderbufferD3D *makeRenderbufferD3D(RenderbufferImpl *renderbuffer); + + virtual gl::Error setStorage(GLenum internalformat, size_t width, size_t height) override; + virtual gl::Error setStorageMultisample(size_t samples, GLenum internalformat, size_t width, size_t height) override; + + RenderTargetD3D *getRenderTarget(); + unsigned int getRenderTargetSerial() const; + + private: + RendererD3D *mRenderer; + RenderTargetD3D *mRenderTarget; +}; +} + +#endif // LIBANGLE_RENDERER_D3D_RENDERBUFFERD3D_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/RendererD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/RendererD3D.cpp new file mode 100644 index 0000000000..2ce0ce5a1b --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/RendererD3D.cpp @@ -0,0 +1,628 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// RendererD3D.cpp: Implementation of the base D3D Renderer. + +#include "libANGLE/renderer/d3d/RendererD3D.h" + +#include "common/MemoryBuffer.h" +#include "common/utilities.h" +#include "libANGLE/Display.h" +#include "libANGLE/Framebuffer.h" +#include "libANGLE/FramebufferAttachment.h" +#include "libANGLE/ResourceManager.h" +#include "libANGLE/State.h" +#include "libANGLE/VertexArray.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/renderer/d3d/BufferD3D.h" +#include "libANGLE/renderer/d3d/DisplayD3D.h" +#include "libANGLE/renderer/d3d/IndexDataManager.h" + +namespace rx +{ + +namespace +{ +// If we request a scratch buffer requesting a smaller size this many times, +// release and recreate the scratch buffer. This ensures we don't have a +// degenerate case where we are stuck hogging memory. +const int ScratchMemoryBufferLifetime = 1000; +} + +RendererD3D::RendererD3D(egl::Display *display) + : mDisplay(display), + mDeviceLost(false), + mScratchMemoryBufferResetCounter(0) +{ +} + +RendererD3D::~RendererD3D() +{ + cleanup(); +} + +void RendererD3D::cleanup() +{ + mScratchMemoryBuffer.resize(0); + for (auto it = mIncompleteTextures.begin(); it != mIncompleteTextures.end(); ++it) + { + it->second.set(NULL); + } + mIncompleteTextures.clear(); +} + +// static +RendererD3D *RendererD3D::makeRendererD3D(Renderer *renderer) +{ + ASSERT(HAS_DYNAMIC_TYPE(RendererD3D*, renderer)); + return static_cast(renderer); +} + +gl::Error RendererD3D::drawElements(const gl::Data &data, + GLenum mode, GLsizei count, GLenum type, + const GLvoid *indices, GLsizei instances, + const RangeUI &indexRange) +{ + if (data.state->isPrimitiveRestartEnabled()) + { + UNIMPLEMENTED(); + return gl::Error(GL_INVALID_OPERATION, "Primitive restart not implemented"); + } + + gl::Program *program = data.state->getProgram(); + ASSERT(program != NULL); + + program->updateSamplerMapping(); + + gl::Error error = generateSwizzles(data); + if (error.isError()) + { + return error; + } + + if (!applyPrimitiveType(mode, count, program->usesPointSize())) + { + return gl::Error(GL_NO_ERROR); + } + + error = applyRenderTarget(data, mode, false); + if (error.isError()) + { + return error; + } + + error = applyState(data, mode); + if (error.isError()) + { + return error; + } + + gl::VertexArray *vao = data.state->getVertexArray(); + TranslatedIndexData indexInfo; + indexInfo.indexRange = indexRange; + error = applyIndexBuffer(indices, vao->getElementArrayBuffer(), count, mode, type, &indexInfo); + if (error.isError()) + { + return error; + } + + applyTransformFeedbackBuffers(*data.state); + // Transform feedback is not allowed for DrawElements, this error should have been caught at the API validation + // layer. + ASSERT(!data.state->isTransformFeedbackActiveUnpaused()); + + GLsizei vertexCount = indexInfo.indexRange.length() + 1; + error = applyVertexBuffer(*data.state, mode, indexInfo.indexRange.start, vertexCount, instances); + if (error.isError()) + { + return error; + } + + error = applyShaders(data); + if (error.isError()) + { + return error; + } + + error = applyTextures(data); + if (error.isError()) + { + return error; + } + + error = program->applyUniformBuffers(data); + if (error.isError()) + { + return error; + } + + if (!skipDraw(data, mode)) + { + error = drawElements(mode, count, type, indices, vao->getElementArrayBuffer(), indexInfo, instances); + if (error.isError()) + { + return error; + } + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error RendererD3D::drawArrays(const gl::Data &data, + GLenum mode, GLint first, + GLsizei count, GLsizei instances) +{ + gl::Program *program = data.state->getProgram(); + ASSERT(program != NULL); + + program->updateSamplerMapping(); + + gl::Error error = generateSwizzles(data); + if (error.isError()) + { + return error; + } + + if (!applyPrimitiveType(mode, count, program->usesPointSize())) + { + return gl::Error(GL_NO_ERROR); + } + + error = applyRenderTarget(data, mode, false); + if (error.isError()) + { + return error; + } + + error = applyState(data, mode); + if (error.isError()) + { + return error; + } + + applyTransformFeedbackBuffers(*data.state); + + error = applyVertexBuffer(*data.state, mode, first, count, instances); + if (error.isError()) + { + return error; + } + + error = applyShaders(data); + if (error.isError()) + { + return error; + } + + error = applyTextures(data); + if (error.isError()) + { + return error; + } + + error = program->applyUniformBuffers(data); + if (error.isError()) + { + return error; + } + + if (!skipDraw(data, mode)) + { + error = drawArrays(data, mode, count, instances, program->usesPointSize()); + if (error.isError()) + { + return error; + } + + if (data.state->isTransformFeedbackActiveUnpaused()) + { + markTransformFeedbackUsage(data); + } + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error RendererD3D::generateSwizzles(const gl::Data &data, gl::SamplerType type) +{ + gl::Program *program = data.state->getProgram(); + + size_t samplerRange = program->getUsedSamplerRange(type); + + for (size_t i = 0; i < samplerRange; i++) + { + GLenum textureType = program->getSamplerTextureType(type, i); + GLint textureUnit = program->getSamplerMapping(type, i, *data.caps); + if (textureUnit != -1) + { + gl::Texture *texture = data.state->getSamplerTexture(textureUnit, textureType); + ASSERT(texture); + if (texture->getSamplerState().swizzleRequired()) + { + gl::Error error = generateSwizzle(texture); + if (error.isError()) + { + return error; + } + } + } + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error RendererD3D::generateSwizzles(const gl::Data &data) +{ + gl::Error error = generateSwizzles(data, gl::SAMPLER_VERTEX); + if (error.isError()) + { + return error; + } + + error = generateSwizzles(data, gl::SAMPLER_PIXEL); + if (error.isError()) + { + return error; + } + + return gl::Error(GL_NO_ERROR); +} + +// Applies the render target surface, depth stencil surface, viewport rectangle and +// scissor rectangle to the renderer +gl::Error RendererD3D::applyRenderTarget(const gl::Data &data, GLenum drawMode, bool ignoreViewport) +{ + const gl::Framebuffer *framebufferObject = data.state->getDrawFramebuffer(); + ASSERT(framebufferObject && framebufferObject->checkStatus(data) == GL_FRAMEBUFFER_COMPLETE); + + gl::Error error = applyRenderTarget(framebufferObject); + if (error.isError()) + { + return error; + } + + float nearZ, farZ; + data.state->getDepthRange(&nearZ, &farZ); + setViewport(data.state->getViewport(), nearZ, farZ, drawMode, + data.state->getRasterizerState().frontFace, ignoreViewport); + + setScissorRectangle(data.state->getScissor(), data.state->isScissorTestEnabled()); + + return gl::Error(GL_NO_ERROR); +} + +// Applies the fixed-function state (culling, depth test, alpha blending, stenciling, etc) to the Direct3D device +gl::Error RendererD3D::applyState(const gl::Data &data, GLenum drawMode) +{ + const gl::Framebuffer *framebufferObject = data.state->getDrawFramebuffer(); + int samples = framebufferObject->getSamples(data); + + gl::RasterizerState rasterizer = data.state->getRasterizerState(); + rasterizer.pointDrawMode = (drawMode == GL_POINTS); + rasterizer.multiSample = (samples != 0); + + gl::Error error = setRasterizerState(rasterizer); + if (error.isError()) + { + return error; + } + + unsigned int mask = 0; + if (data.state->isSampleCoverageEnabled()) + { + GLclampf coverageValue; + bool coverageInvert = false; + data.state->getSampleCoverageParams(&coverageValue, &coverageInvert); + if (coverageValue != 0) + { + float threshold = 0.5f; + + for (int i = 0; i < samples; ++i) + { + mask <<= 1; + + if ((i + 1) * coverageValue >= threshold) + { + threshold += 1.0f; + mask |= 1; + } + } + } + + if (coverageInvert) + { + mask = ~mask; + } + } + else + { + mask = 0xFFFFFFFF; + } + error = setBlendState(framebufferObject, data.state->getBlendState(), data.state->getBlendColor(), mask); + if (error.isError()) + { + return error; + } + + error = setDepthStencilState(data.state->getDepthStencilState(), data.state->getStencilRef(), + data.state->getStencilBackRef(), rasterizer.frontFace == GL_CCW); + if (error.isError()) + { + return error; + } + + return gl::Error(GL_NO_ERROR); +} + +// Applies the shaders and shader constants to the Direct3D device +gl::Error RendererD3D::applyShaders(const gl::Data &data) +{ + gl::Program *program = data.state->getProgram(); + + gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS]; + gl::VertexFormat::GetInputLayout(inputLayout, program, *data.state); + + const gl::Framebuffer *fbo = data.state->getDrawFramebuffer(); + + gl::Error error = applyShaders(program, inputLayout, fbo, data.state->getRasterizerState().rasterizerDiscard, data.state->isTransformFeedbackActiveUnpaused()); + if (error.isError()) + { + return error; + } + + return program->applyUniforms(); +} + +// For each Direct3D 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). +gl::Error RendererD3D::applyTextures(const gl::Data &data, gl::SamplerType shaderType, + const FramebufferTextureSerialArray &framebufferSerials, size_t framebufferSerialCount) +{ + gl::Program *program = data.state->getProgram(); + + size_t samplerRange = program->getUsedSamplerRange(shaderType); + for (size_t samplerIndex = 0; samplerIndex < samplerRange; samplerIndex++) + { + GLenum textureType = program->getSamplerTextureType(shaderType, samplerIndex); + GLint textureUnit = program->getSamplerMapping(shaderType, samplerIndex, *data.caps); + if (textureUnit != -1) + { + gl::Texture *texture = data.state->getSamplerTexture(textureUnit, textureType); + ASSERT(texture); + gl::SamplerState sampler = texture->getSamplerState(); + + gl::Sampler *samplerObject = data.state->getSampler(textureUnit); + if (samplerObject) + { + samplerObject->getState(&sampler); + } + + // TODO: std::binary_search may become unavailable using older versions of GCC + if (texture->isSamplerComplete(sampler, data) && + !std::binary_search(framebufferSerials.begin(), framebufferSerials.begin() + framebufferSerialCount, texture->getTextureSerial())) + { + gl::Error error = setSamplerState(shaderType, samplerIndex, texture, sampler); + if (error.isError()) + { + return error; + } + + error = setTexture(shaderType, samplerIndex, texture); + if (error.isError()) + { + return error; + } + } + else + { + // Texture is not sampler complete or it is in use by the framebuffer. Bind the incomplete texture. + gl::Texture *incompleteTexture = getIncompleteTexture(textureType); + gl::Error error = setTexture(shaderType, samplerIndex, incompleteTexture); + if (error.isError()) + { + return error; + } + } + } + else + { + // No texture bound to this slot even though it is used by the shader, bind a NULL texture + gl::Error error = setTexture(shaderType, samplerIndex, NULL); + if (error.isError()) + { + return error; + } + } + } + + // Set all the remaining textures to NULL + size_t samplerCount = (shaderType == gl::SAMPLER_PIXEL) ? data.caps->maxTextureImageUnits + : data.caps->maxVertexTextureImageUnits; + for (size_t samplerIndex = samplerRange; samplerIndex < samplerCount; samplerIndex++) + { + gl::Error error = setTexture(shaderType, samplerIndex, NULL); + if (error.isError()) + { + return error; + } + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error RendererD3D::applyTextures(const gl::Data &data) +{ + FramebufferTextureSerialArray framebufferSerials; + size_t framebufferSerialCount = getBoundFramebufferTextureSerials(data, &framebufferSerials); + + gl::Error error = applyTextures(data, gl::SAMPLER_VERTEX, framebufferSerials, framebufferSerialCount); + if (error.isError()) + { + return error; + } + + error = applyTextures(data, gl::SAMPLER_PIXEL, framebufferSerials, framebufferSerialCount); + if (error.isError()) + { + return error; + } + + return gl::Error(GL_NO_ERROR); +} + +bool RendererD3D::skipDraw(const gl::Data &data, GLenum drawMode) +{ + if (drawMode == GL_POINTS) + { + // ProgramBinary assumes non-point rendering if gl_PointSize isn't written, + // which affects varying interpolation. Since the value of gl_PointSize is + // undefined when not written, just skip drawing to avoid unexpected results. + if (!data.state->getProgram()->usesPointSize() && !data.state->isTransformFeedbackActiveUnpaused()) + { + // This is stictly speaking not an error, but developers should be + // notified of risking undefined behavior. + ERR("Point rendering without writing to gl_PointSize."); + + return true; + } + } + else if (gl::IsTriangleMode(drawMode)) + { + if (data.state->getRasterizerState().cullFace && data.state->getRasterizerState().cullMode == GL_FRONT_AND_BACK) + { + return true; + } + } + + return false; +} + +void RendererD3D::markTransformFeedbackUsage(const gl::Data &data) +{ + for (size_t i = 0; i < data.caps->maxTransformFeedbackSeparateAttributes; i++) + { + gl::Buffer *buffer = data.state->getIndexedTransformFeedbackBuffer(i); + if (buffer) + { + BufferD3D *bufferD3D = GetImplAs(buffer); + bufferD3D->markTransformFeedbackUsage(); + } + } +} + +size_t RendererD3D::getBoundFramebufferTextureSerials(const gl::Data &data, + FramebufferTextureSerialArray *outSerialArray) +{ + size_t serialCount = 0; + + const gl::Framebuffer *drawFramebuffer = data.state->getDrawFramebuffer(); + for (unsigned int i = 0; i < data.caps->maxColorAttachments; i++) + { + gl::FramebufferAttachment *attachment = drawFramebuffer->getColorbuffer(i); + if (attachment && attachment->type() == GL_TEXTURE) + { + gl::Texture *texture = attachment->getTexture(); + (*outSerialArray)[serialCount++] = texture->getTextureSerial(); + } + } + + gl::FramebufferAttachment *depthStencilAttachment = drawFramebuffer->getDepthOrStencilbuffer(); + if (depthStencilAttachment && depthStencilAttachment->type() == GL_TEXTURE) + { + gl::Texture *depthStencilTexture = depthStencilAttachment->getTexture(); + (*outSerialArray)[serialCount++] = depthStencilTexture->getTextureSerial(); + } + + std::sort(outSerialArray->begin(), outSerialArray->begin() + serialCount); + + return serialCount; +} + +gl::Texture *RendererD3D::getIncompleteTexture(GLenum type) +{ + if (mIncompleteTextures.find(type) == mIncompleteTextures.end()) + { + const GLubyte color[] = { 0, 0, 0, 255 }; + const gl::Extents colorSize(1, 1, 1); + const gl::PixelUnpackState incompleteUnpackState(1, 0); + + gl::Texture* t = new gl::Texture(createTexture(type), gl::Texture::INCOMPLETE_TEXTURE_ID, type); + + if (type == GL_TEXTURE_CUBE_MAP) + { + for (GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z; face++) + { + t->setImage(face, 0, GL_RGBA, colorSize, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); + } + } + else + { + t->setImage(type, 0, GL_RGBA, colorSize, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); + } + + mIncompleteTextures[type].set(t); + } + + return mIncompleteTextures[type].get(); +} + +bool RendererD3D::isDeviceLost() const +{ + return mDeviceLost; +} + +void RendererD3D::notifyDeviceLost() +{ + mDeviceLost = true; + mDisplay->notifyDeviceLost(); +} + +std::string RendererD3D::getVendorString() const +{ + LUID adapterLuid = { 0 }; + + if (getLUID(&adapterLuid)) + { + char adapterLuidString[64]; + sprintf_s(adapterLuidString, sizeof(adapterLuidString), "(adapter LUID: %08x%08x)", adapterLuid.HighPart, adapterLuid.LowPart); + return std::string(adapterLuidString); + } + + return std::string(""); +} + +gl::Error RendererD3D::getScratchMemoryBuffer(size_t requestedSize, MemoryBuffer **bufferOut) +{ + if (mScratchMemoryBuffer.size() == requestedSize) + { + mScratchMemoryBufferResetCounter = ScratchMemoryBufferLifetime; + *bufferOut = &mScratchMemoryBuffer; + return gl::Error(GL_NO_ERROR); + } + + if (mScratchMemoryBuffer.size() > requestedSize) + { + mScratchMemoryBufferResetCounter--; + } + + if (mScratchMemoryBufferResetCounter <= 0 || mScratchMemoryBuffer.size() < requestedSize) + { + mScratchMemoryBuffer.resize(0); + if (!mScratchMemoryBuffer.resize(requestedSize)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal buffer."); + } + mScratchMemoryBufferResetCounter = ScratchMemoryBufferLifetime; + } + + ASSERT(mScratchMemoryBuffer.size() >= requestedSize); + + *bufferOut = &mScratchMemoryBuffer; + return gl::Error(GL_NO_ERROR); +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/RendererD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/RendererD3D.h new file mode 100644 index 0000000000..3de6c20886 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/RendererD3D.h @@ -0,0 +1,241 @@ + +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// RendererD3D.h: Defines a back-end specific class for the DirectX renderer. + +#ifndef LIBANGLE_RENDERER_D3D_RENDERERD3D_H_ +#define LIBANGLE_RENDERER_D3D_RENDERERD3D_H_ + +#include "common/MemoryBuffer.h" +#include "libANGLE/Data.h" +#include "libANGLE/renderer/Renderer.h" +#include "libANGLE/renderer/d3d/formatutilsD3D.h" +#include "libANGLE/renderer/d3d/d3d11/NativeWindow.h" + +//FIXME(jmadill): std::array is currently prohibited by Chromium style guide +#include + +namespace egl +{ +class ConfigSet; +} + +namespace gl +{ +class InfoLog; +struct LinkedVarying; +class Texture; +} + +namespace rx +{ +class ImageD3D; +class IndexBuffer; +class RenderTargetD3D; +class ShaderExecutableD3D; +class SwapChainD3D; +class TextureStorage; +class UniformStorageD3D; +class VertexBuffer; + +enum ShaderType +{ + SHADER_VERTEX, + SHADER_PIXEL, + SHADER_GEOMETRY +}; + +enum RendererClass +{ + RENDERER_D3D11, + RENDERER_D3D9, +}; + +// Useful for unit testing +class BufferFactoryD3D +{ + public: + BufferFactoryD3D() {} + virtual ~BufferFactoryD3D() {} + + virtual VertexBuffer *createVertexBuffer() = 0; + virtual IndexBuffer *createIndexBuffer() = 0; + + // TODO(jmadill): add VertexFormatCaps + virtual VertexConversionType getVertexConversionType(const gl::VertexFormat &vertexFormat) const = 0; + virtual GLenum getVertexComponentType(const gl::VertexFormat &vertexFormat) const = 0; +}; + +class RendererD3D : public Renderer, public BufferFactoryD3D +{ + public: + explicit RendererD3D(egl::Display *display); + virtual ~RendererD3D(); + + virtual egl::Error initialize() = 0; + + static RendererD3D *makeRendererD3D(Renderer *renderer); + + virtual egl::ConfigSet generateConfigs() const = 0; + + gl::Error drawArrays(const gl::Data &data, + GLenum mode, GLint first, + GLsizei count, GLsizei instances) override; + + gl::Error drawElements(const gl::Data &data, + GLenum mode, GLsizei count, GLenum type, + const GLvoid *indices, GLsizei instances, + const RangeUI &indexRange) override; + + bool isDeviceLost() const override; + std::string getVendorString() const override; + + virtual int getMinorShaderModel() const = 0; + virtual std::string getShaderModelSuffix() const = 0; + + // Direct3D Specific methods + virtual GUID getAdapterIdentifier() const = 0; + + virtual SwapChainD3D *createSwapChain(NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) = 0; + + virtual gl::Error generateSwizzle(gl::Texture *texture) = 0; + virtual gl::Error setSamplerState(gl::SamplerType type, int index, gl::Texture *texture, const gl::SamplerState &sampler) = 0; + virtual gl::Error setTexture(gl::SamplerType type, int index, gl::Texture *texture) = 0; + + virtual gl::Error setUniformBuffers(const gl::Data &data, + const GLint vertexUniformBuffers[], + const GLint fragmentUniformBuffers[]) = 0; + + virtual gl::Error setRasterizerState(const gl::RasterizerState &rasterState) = 0; + virtual gl::Error setBlendState(const gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::ColorF &blendColor, + unsigned int sampleMask) = 0; + virtual gl::Error setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef, + int stencilBackRef, bool frontFaceCCW) = 0; + + virtual void setScissorRectangle(const gl::Rectangle &scissor, bool enabled) = 0; + virtual void setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace, + bool ignoreViewport) = 0; + + virtual gl::Error applyRenderTarget(const gl::Framebuffer *frameBuffer) = 0; + virtual gl::Error applyShaders(gl::Program *program, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer, + bool rasterizerDiscard, bool transformFeedbackActive) = 0; + virtual gl::Error applyUniforms(const ProgramImpl &program, const std::vector &uniformArray) = 0; + virtual bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount, bool usesPointSize) = 0; + virtual gl::Error applyVertexBuffer(const gl::State &state, GLenum mode, GLint first, GLsizei count, GLsizei instances) = 0; + virtual gl::Error applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo) = 0; + virtual void applyTransformFeedbackBuffers(const gl::State& state) = 0; + + virtual void markAllStateDirty() = 0; + + virtual unsigned int getReservedVertexUniformVectors() const = 0; + virtual unsigned int getReservedFragmentUniformVectors() const = 0; + virtual unsigned int getReservedVertexUniformBuffers() const = 0; + virtual unsigned int getReservedFragmentUniformBuffers() const = 0; + virtual bool getShareHandleSupport() const = 0; + virtual bool getPostSubBufferSupport() const = 0; + + virtual int getMajorShaderModel() const = 0; + + // Pixel operations + virtual gl::Error copyImage2D(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + const gl::Offset &destOffset, TextureStorage *storage, GLint level) = 0; + virtual gl::Error copyImageCube(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + const gl::Offset &destOffset, TextureStorage *storage, GLenum target, GLint level) = 0; + virtual gl::Error copyImage3D(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + const gl::Offset &destOffset, TextureStorage *storage, GLint level) = 0; + virtual gl::Error copyImage2DArray(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + const gl::Offset &destOffset, TextureStorage *storage, GLint level) = 0; + + // RenderTarget creation + virtual gl::Error createRenderTarget(int width, int height, GLenum format, GLsizei samples, RenderTargetD3D **outRT) = 0; + + // Shader operations + virtual gl::Error loadExecutable(const void *function, size_t length, ShaderType type, + const std::vector &transformFeedbackVaryings, + bool separatedOutputBuffers, ShaderExecutableD3D **outExecutable) = 0; + virtual gl::Error compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, ShaderType type, + const std::vector &transformFeedbackVaryings, + bool separatedOutputBuffers, const D3DCompilerWorkarounds &workarounds, + ShaderExecutableD3D **outExectuable) = 0; + virtual UniformStorageD3D *createUniformStorage(size_t storageSize) = 0; + + // Image operations + virtual ImageD3D *createImage() = 0; + virtual gl::Error generateMipmap(ImageD3D *dest, ImageD3D *source) = 0; + virtual TextureStorage *createTextureStorage2D(SwapChainD3D *swapChain) = 0; + virtual TextureStorage *createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels, bool hintLevelZeroOnly) = 0; + virtual TextureStorage *createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly) = 0; + virtual TextureStorage *createTextureStorage3D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) = 0; + virtual TextureStorage *createTextureStorage2DArray(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) = 0; + + // Buffer-to-texture and Texture-to-buffer copies + virtual bool supportsFastCopyBufferToTexture(GLenum internalFormat) const = 0; + virtual gl::Error fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTargetD3D *destRenderTarget, + GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea) = 0; + + // Device lost + void notifyDeviceLost() override; + virtual bool resetDevice() = 0; + + virtual RendererClass getRendererClass() const = 0; + + gl::Error getScratchMemoryBuffer(size_t requestedSize, MemoryBuffer **bufferOut); + + protected: + virtual gl::Error drawArrays(const gl::Data &data, GLenum mode, GLsizei count, GLsizei instances, bool usesPointSize) = 0; + virtual gl::Error drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, + gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances) = 0; + + virtual bool getLUID(LUID *adapterLuid) const = 0; + + void cleanup(); + + egl::Display *mDisplay; + bool mDeviceLost; + + private: + //FIXME(jmadill): std::array is currently prohibited by Chromium style guide + typedef std::array FramebufferTextureSerialArray; + + gl::Error generateSwizzles(const gl::Data &data, gl::SamplerType type); + gl::Error generateSwizzles(const gl::Data &data); + + gl::Error applyRenderTarget(const gl::Data &data, GLenum drawMode, bool ignoreViewport); + gl::Error applyState(const gl::Data &data, GLenum drawMode); + gl::Error applyShaders(const gl::Data &data); + gl::Error applyTextures(const gl::Data &data, gl::SamplerType shaderType, + const FramebufferTextureSerialArray &framebufferSerials, size_t framebufferSerialCount); + gl::Error applyTextures(const gl::Data &data); + + bool skipDraw(const gl::Data &data, GLenum drawMode); + void markTransformFeedbackUsage(const gl::Data &data); + + size_t getBoundFramebufferTextureSerials(const gl::Data &data, + FramebufferTextureSerialArray *outSerialArray); + gl::Texture *getIncompleteTexture(GLenum type); + + gl::TextureMap mIncompleteTextures; + MemoryBuffer mScratchMemoryBuffer; + unsigned int mScratchMemoryBufferResetCounter; +}; + +struct dx_VertexConstants +{ + float depthRange[4]; + float viewAdjust[4]; + float viewCoords[4]; +}; + +struct dx_PixelConstants +{ + float depthRange[4]; + float viewCoords[4]; + float depthFront[4]; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_RENDERERD3D_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderD3D.cpp new file mode 100644 index 0000000000..7d522a95d4 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderD3D.cpp @@ -0,0 +1,388 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// ShaderD3D.cpp: Defines the rx::ShaderD3D class which implements rx::ShaderImpl. + +#include "libANGLE/Shader.h" +#include "libANGLE/Compiler.h" +#include "libANGLE/renderer/d3d/RendererD3D.h" +#include "libANGLE/renderer/d3d/ShaderD3D.h" +#include "libANGLE/renderer/d3d/CompilerD3D.h" +#include "libANGLE/features.h" + +#include "common/utilities.h" + +// Definitions local to the translation unit +namespace +{ + +const char *GetShaderTypeString(GLenum type) +{ + switch (type) + { + case GL_VERTEX_SHADER: + return "VERTEX"; + + case GL_FRAGMENT_SHADER: + return "FRAGMENT"; + + default: + UNREACHABLE(); + return ""; + } +} + +} + +namespace rx +{ + +template +void FilterInactiveVariables(std::vector *variableList) +{ + ASSERT(variableList); + + for (size_t varIndex = 0; varIndex < variableList->size();) + { + if (!(*variableList)[varIndex].staticUse) + { + variableList->erase(variableList->begin() + varIndex); + } + else + { + varIndex++; + } + } +} + +template +const std::vector *GetShaderVariables(const std::vector *variableList) +{ + ASSERT(variableList); + return variableList; +} + +ShaderD3D::ShaderD3D(GLenum type) + : mShaderType(type), + mShaderVersion(100) +{ + uncompile(); +} + +ShaderD3D::~ShaderD3D() +{ +} + +ShaderD3D *ShaderD3D::makeShaderD3D(ShaderImpl *impl) +{ + ASSERT(HAS_DYNAMIC_TYPE(ShaderD3D*, impl)); + return static_cast(impl); +} + +const ShaderD3D *ShaderD3D::makeShaderD3D(const ShaderImpl *impl) +{ + ASSERT(HAS_DYNAMIC_TYPE(const ShaderD3D*, impl)); + return static_cast(impl); +} + +std::string ShaderD3D::getDebugInfo() const +{ + return mDebugInfo + std::string("\n// ") + GetShaderTypeString(mShaderType) + " SHADER END\n"; +} + + +void ShaderD3D::parseVaryings(ShHandle compiler) +{ + if (!mTranslatedSource.empty()) + { + const std::vector *varyings = ShGetVaryings(compiler); + ASSERT(varyings); + + for (size_t varyingIndex = 0; varyingIndex < varyings->size(); varyingIndex++) + { + mVaryings.push_back(gl::PackedVarying((*varyings)[varyingIndex])); + } + + mUsesMultipleRenderTargets = mTranslatedSource.find("GL_USES_MRT") != std::string::npos; + mUsesFragColor = mTranslatedSource.find("GL_USES_FRAG_COLOR") != std::string::npos; + mUsesFragData = mTranslatedSource.find("GL_USES_FRAG_DATA") != std::string::npos; + mUsesFragCoord = mTranslatedSource.find("GL_USES_FRAG_COORD") != std::string::npos; + mUsesFrontFacing = mTranslatedSource.find("GL_USES_FRONT_FACING") != std::string::npos; + mUsesPointSize = mTranslatedSource.find("GL_USES_POINT_SIZE") != std::string::npos; + mUsesPointCoord = mTranslatedSource.find("GL_USES_POINT_COORD") != std::string::npos; + mUsesDepthRange = mTranslatedSource.find("GL_USES_DEPTH_RANGE") != std::string::npos; + mUsesFragDepth = mTranslatedSource.find("GL_USES_FRAG_DEPTH") != std::string::npos; + mUsesDiscardRewriting = mTranslatedSource.find("ANGLE_USES_DISCARD_REWRITING") != std::string::npos; + mUsesNestedBreak = mTranslatedSource.find("ANGLE_USES_NESTED_BREAK") != std::string::npos; + mUsesDeferredInit = mTranslatedSource.find("ANGLE_USES_DEFERRED_INIT") != std::string::npos; + mRequiresIEEEStrictCompiling = mTranslatedSource.find("ANGLE_REQUIRES_IEEE_STRICT_COMPILING") != std::string::npos; + } +} + +void ShaderD3D::resetVaryingsRegisterAssignment() +{ + for (size_t varyingIndex = 0; varyingIndex < mVaryings.size(); varyingIndex++) + { + mVaryings[varyingIndex].resetRegisterAssignment(); + } +} + +// initialize/clean up previous state +void ShaderD3D::uncompile() +{ + // set by compileToHLSL + mCompilerOutputType = SH_ESSL_OUTPUT; + mTranslatedSource.clear(); + mInfoLog.clear(); + + mUsesMultipleRenderTargets = false; + mUsesFragColor = false; + mUsesFragData = false; + mUsesFragCoord = false; + mUsesFrontFacing = false; + mUsesPointSize = false; + mUsesPointCoord = false; + mUsesDepthRange = false; + mUsesFragDepth = false; + mShaderVersion = 100; + mUsesDiscardRewriting = false; + mUsesNestedBreak = false; + mUsesDeferredInit = false; + mRequiresIEEEStrictCompiling = false; + + mVaryings.clear(); + mUniforms.clear(); + mInterfaceBlocks.clear(); + mActiveAttributes.clear(); + mActiveOutputVariables.clear(); + mDebugInfo.clear(); +} + +void ShaderD3D::compileToHLSL(ShHandle compiler, const std::string &source) +{ + int compileOptions = (SH_OBJECT_CODE | SH_VARIABLES); + std::string sourcePath; + +#if !defined (ANGLE_ENABLE_WINDOWS_STORE) + if (gl::DebugAnnotationsActive()) + { + sourcePath = getTempPath(); + writeFile(sourcePath.c_str(), source.c_str(), source.length()); + compileOptions |= SH_LINE_DIRECTIVES; + } +#endif + + int result; + if (sourcePath.empty()) + { + const char* sourceStrings[] = + { + source.c_str(), + }; + + result = ShCompile(compiler, sourceStrings, ArraySize(sourceStrings), compileOptions); + } + else + { + const char* sourceStrings[] = + { + sourcePath.c_str(), + source.c_str(), + }; + + result = ShCompile(compiler, sourceStrings, ArraySize(sourceStrings), compileOptions | SH_SOURCE_PATH); + } + + mShaderVersion = ShGetShaderVersion(compiler); + + if (result) + { + mTranslatedSource = ShGetObjectCode(compiler); + +#ifdef _DEBUG + // Prefix hlsl shader with commented out glsl shader + // Useful in diagnostics tools like pix which capture the hlsl shaders + std::ostringstream hlslStream; + hlslStream << "// GLSL\n"; + hlslStream << "//\n"; + + size_t curPos = 0; + while (curPos != std::string::npos) + { + size_t nextLine = source.find("\n", curPos); + size_t len = (nextLine == std::string::npos) ? std::string::npos : (nextLine - curPos + 1); + + hlslStream << "// " << source.substr(curPos, len); + + curPos = (nextLine == std::string::npos) ? std::string::npos : (nextLine + 1); + } + hlslStream << "\n\n"; + hlslStream << mTranslatedSource; + mTranslatedSource = hlslStream.str(); +#endif + + mUniforms = *GetShaderVariables(ShGetUniforms(compiler)); + + for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++) + { + const sh::Uniform &uniform = mUniforms[uniformIndex]; + + if (uniform.staticUse) + { + unsigned int index = static_cast(-1); + bool getUniformRegisterResult = ShGetUniformRegister(compiler, uniform.name, &index); + UNUSED_ASSERTION_VARIABLE(getUniformRegisterResult); + ASSERT(getUniformRegisterResult); + + mUniformRegisterMap[uniform.name] = index; + } + } + + mInterfaceBlocks = *GetShaderVariables(ShGetInterfaceBlocks(compiler)); + + for (size_t blockIndex = 0; blockIndex < mInterfaceBlocks.size(); blockIndex++) + { + const sh::InterfaceBlock &interfaceBlock = mInterfaceBlocks[blockIndex]; + + if (interfaceBlock.staticUse) + { + unsigned int index = static_cast(-1); + bool blockRegisterResult = ShGetInterfaceBlockRegister(compiler, interfaceBlock.name, &index); + UNUSED_ASSERTION_VARIABLE(blockRegisterResult); + ASSERT(blockRegisterResult); + + mInterfaceBlockRegisterMap[interfaceBlock.name] = index; + } + } + } + else + { + mInfoLog = ShGetInfoLog(compiler); + + TRACE("\n%s", mInfoLog.c_str()); + } +} + +void ShaderD3D::generateWorkarounds(D3DCompilerWorkarounds *workarounds) const +{ + if (mUsesDiscardRewriting) + { + // ANGLE issue 486: + // Work-around a D3D9 compiler bug that presents itself when using conditional discard, by disabling optimization + workarounds->skipOptimization = true; + } + else if (mUsesNestedBreak) + { + // ANGLE issue 603: + // Work-around a D3D9 compiler bug that presents itself when using break in a nested loop, by maximizing optimization + // We want to keep the use of ANGLE_D3D_WORKAROUND_MAX_OPTIMIZATION minimal to prevent hangs, so usesDiscard takes precedence + workarounds->useMaxOptimization = true; + } + + if (mRequiresIEEEStrictCompiling) + { + // IEEE Strictness for D3D compiler needs to be enabled for NaNs to work. + workarounds->enableIEEEStrictness = true; + } +} + +// true if varying x has a higher priority in packing than y +bool ShaderD3D::compareVarying(const gl::PackedVarying &x, const gl::PackedVarying &y) +{ + if (x.type == y.type) + { + return x.arraySize > y.arraySize; + } + + // Special case for handling structs: we sort these to the end of the list + if (x.type == GL_STRUCT_ANGLEX) + { + return false; + } + + if (y.type == GL_STRUCT_ANGLEX) + { + return true; + } + + return gl::VariableSortOrder(x.type) < gl::VariableSortOrder(y.type); +} + +unsigned int ShaderD3D::getUniformRegister(const std::string &uniformName) const +{ + ASSERT(mUniformRegisterMap.count(uniformName) > 0); + return mUniformRegisterMap.find(uniformName)->second; +} + +unsigned int ShaderD3D::getInterfaceBlockRegister(const std::string &blockName) const +{ + ASSERT(mInterfaceBlockRegisterMap.count(blockName) > 0); + return mInterfaceBlockRegisterMap.find(blockName)->second; +} + +GLenum ShaderD3D::getShaderType() const +{ + return mShaderType; +} + +ShShaderOutput ShaderD3D::getCompilerOutputType() const +{ + return mCompilerOutputType; +} + +bool ShaderD3D::compile(gl::Compiler *compiler, const std::string &source) +{ + uncompile(); + + CompilerD3D *compilerD3D = CompilerD3D::makeCompilerD3D(compiler->getImplementation()); + ShHandle compilerHandle = compilerD3D->getCompilerHandle(mShaderType); + + mCompilerOutputType = ShGetShaderOutputType(compilerHandle); + + compileToHLSL(compilerHandle, source); + + if (mShaderType == GL_VERTEX_SHADER) + { + parseAttributes(compilerHandle); + } + + parseVaryings(compilerHandle); + + if (mShaderType == GL_FRAGMENT_SHADER) + { + std::sort(mVaryings.begin(), mVaryings.end(), compareVarying); + + const std::string &hlsl = getTranslatedSource(); + if (!hlsl.empty()) + { + mActiveOutputVariables = *GetShaderVariables(ShGetOutputVariables(compilerHandle)); + FilterInactiveVariables(&mActiveOutputVariables); + } + } + +#if ANGLE_SHADER_DEBUG_INFO == ANGLE_ENABLED + mDebugInfo += std::string("// ") + GetShaderTypeString(mShaderType) + " SHADER BEGIN\n"; + mDebugInfo += "\n// GLSL BEGIN\n\n" + source + "\n\n// GLSL END\n\n\n"; + mDebugInfo += "// INITIAL HLSL BEGIN\n\n" + getTranslatedSource() + "\n// INITIAL HLSL END\n\n\n"; + // Successive steps will append more info +#else + mDebugInfo += getTranslatedSource(); +#endif + + return !getTranslatedSource().empty(); +} + +void ShaderD3D::parseAttributes(ShHandle compiler) +{ + const std::string &hlsl = getTranslatedSource(); + if (!hlsl.empty()) + { + mActiveAttributes = *GetShaderVariables(ShGetAttributes(compiler)); + FilterInactiveVariables(&mActiveAttributes); + } +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderD3D.h new file mode 100644 index 0000000000..d0237b5985 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderD3D.h @@ -0,0 +1,89 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// ShaderD3D.h: Defines the rx::ShaderD3D class which implements rx::ShaderImpl. + +#ifndef LIBANGLE_RENDERER_D3D_SHADERD3D_H_ +#define LIBANGLE_RENDERER_D3D_SHADERD3D_H_ + +#include "libANGLE/renderer/ShaderImpl.h" +#include "libANGLE/renderer/Workarounds.h" +#include "libANGLE/Shader.h" + +#include + +namespace rx +{ +class DynamicHLSL; +class RendererD3D; + +class ShaderD3D : public ShaderImpl +{ + friend class DynamicHLSL; + + public: + ShaderD3D(GLenum type); + virtual ~ShaderD3D(); + + static ShaderD3D *makeShaderD3D(ShaderImpl *impl); + static const ShaderD3D *makeShaderD3D(const ShaderImpl *impl); + + // ShaderImpl implementation + virtual std::string getDebugInfo() const; + + // D3D-specific methods + virtual void uncompile(); + void resetVaryingsRegisterAssignment(); + unsigned int getUniformRegister(const std::string &uniformName) const; + unsigned int getInterfaceBlockRegister(const std::string &blockName) const; + void appendDebugInfo(const std::string &info) { mDebugInfo += info; } + + void generateWorkarounds(D3DCompilerWorkarounds *workarounds) const; + int getShaderVersion() const { return mShaderVersion; } + bool usesDepthRange() const { return mUsesDepthRange; } + bool usesPointSize() const { return mUsesPointSize; } + bool usesDeferredInit() const { return mUsesDeferredInit; } + + GLenum getShaderType() const; + ShShaderOutput getCompilerOutputType() const; + + virtual bool compile(gl::Compiler *compiler, const std::string &source); + + private: + void compileToHLSL(ShHandle compiler, const std::string &source); + void parseVaryings(ShHandle compiler); + + void parseAttributes(ShHandle compiler); + + static bool compareVarying(const gl::PackedVarying &x, const gl::PackedVarying &y); + + GLenum mShaderType; + + int mShaderVersion; + + bool mUsesMultipleRenderTargets; + bool mUsesFragColor; + bool mUsesFragData; + bool mUsesFragCoord; + bool mUsesFrontFacing; + bool mUsesPointSize; + bool mUsesPointCoord; + bool mUsesDepthRange; + bool mUsesFragDepth; + bool mUsesDiscardRewriting; + bool mUsesNestedBreak; + bool mUsesDeferredInit; + bool mRequiresIEEEStrictCompiling; + + ShShaderOutput mCompilerOutputType; + std::string mDebugInfo; + std::map mUniformRegisterMap; + std::map mInterfaceBlockRegisterMap; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_SHADERD3D_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderExecutableD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderExecutableD3D.cpp new file mode 100644 index 0000000000..97ffdf5094 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderExecutableD3D.cpp @@ -0,0 +1,61 @@ +// +// Copyright (c) 2012-2015 The ANGLE Project 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.cpp: Implements a class to contain D3D shader executable +// implementation details. + +#include "libANGLE/renderer/d3d/ShaderExecutableD3D.h" + +#include "common/angleutils.h" + +namespace rx +{ + +ShaderExecutableD3D::ShaderExecutableD3D(const void *function, size_t length) + : mFunctionBuffer(length) +{ + memcpy(mFunctionBuffer.data(), function, length); +} + +ShaderExecutableD3D::~ShaderExecutableD3D() +{ +} + +const uint8_t *ShaderExecutableD3D::getFunction() const +{ + return mFunctionBuffer.data(); +} + +size_t ShaderExecutableD3D::getLength() const +{ + return mFunctionBuffer.size(); +} + +const std::string &ShaderExecutableD3D::getDebugInfo() const +{ + return mDebugInfo; +} + +void ShaderExecutableD3D::appendDebugInfo(const std::string &info) +{ + mDebugInfo += info; +} + + +UniformStorageD3D::UniformStorageD3D(size_t initialSize) : mSize(initialSize) +{ +} + +UniformStorageD3D::~UniformStorageD3D() +{ +} + +size_t UniformStorageD3D::size() const +{ + return mSize; +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderExecutableD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderExecutableD3D.h new file mode 100644 index 0000000000..71b83b7954 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderExecutableD3D.h @@ -0,0 +1,54 @@ +// +// Copyright (c) 2012-2015 The ANGLE Project 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 class to contain D3D shader executable +// implementation details. + +#ifndef LIBANGLE_RENDERER_D3D_SHADEREXECUTABLED3D_H_ +#define LIBANGLE_RENDERER_D3D_SHADEREXECUTABLED3D_H_ + +#include "common/debug.h" + +#include +#include + +namespace rx +{ + +class ShaderExecutableD3D : angle::NonCopyable +{ + public: + ShaderExecutableD3D(const void *function, size_t length); + virtual ~ShaderExecutableD3D(); + + const uint8_t *getFunction() const; + + size_t getLength() const; + + const std::string &getDebugInfo() const; + + void appendDebugInfo(const std::string &info); + + private: + std::vector mFunctionBuffer; + std::string mDebugInfo; +}; + +class UniformStorageD3D : angle::NonCopyable +{ + public: + UniformStorageD3D(size_t initialSize); + virtual ~UniformStorageD3D(); + + size_t size() const; + + private: + size_t mSize; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_SHADEREXECUTABLED3D_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp new file mode 100644 index 0000000000..4fde295443 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp @@ -0,0 +1,396 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// SurfaceD3D.cpp: D3D implementation of an EGL surface + +#include "libANGLE/renderer/d3d/SurfaceD3D.h" + +#include "libANGLE/Display.h" +#include "libANGLE/Surface.h" +#include "libANGLE/renderer/d3d/RendererD3D.h" +#include "libANGLE/renderer/d3d/SwapChainD3D.h" + +#include +#include +#include + +namespace rx +{ + +SurfaceD3D *SurfaceD3D::createOffscreen(RendererD3D *renderer, egl::Display *display, const egl::Config *config, EGLClientBuffer shareHandle, + EGLint width, EGLint height) +{ + return new SurfaceD3D(renderer, display, config, width, height, EGL_TRUE, shareHandle, NULL); +} + +SurfaceD3D *SurfaceD3D::createFromWindow(RendererD3D *renderer, egl::Display *display, const egl::Config *config, EGLNativeWindowType window, + EGLint fixedSize, EGLint width, EGLint height) +{ + return new SurfaceD3D(renderer, display, config, width, height, fixedSize, static_cast(0), window); +} + +SurfaceD3D::SurfaceD3D(RendererD3D *renderer, egl::Display *display, const egl::Config *config, EGLint width, EGLint height, EGLint fixedSize, + EGLClientBuffer shareHandle, EGLNativeWindowType window) + : SurfaceImpl(), + mRenderer(renderer), + mDisplay(display), + mFixedSize(fixedSize == EGL_TRUE), + mRenderTargetFormat(config->renderTargetFormat), + mDepthStencilFormat(config->depthStencilFormat), + mSwapChain(nullptr), + mSwapIntervalDirty(true), + mWindowSubclassed(false), + mNativeWindow(window), + mWidth(width), + mHeight(height), + mSwapInterval(1), + mShareHandle(reinterpret_cast(shareHandle)) +{ + subclassWindow(); +} + +SurfaceD3D::~SurfaceD3D() +{ + unsubclassWindow(); + releaseSwapChain(); +} + +void SurfaceD3D::releaseSwapChain() +{ + SafeDelete(mSwapChain); +} + +egl::Error SurfaceD3D::initialize() +{ + if (mNativeWindow.getNativeWindow()) + { + if (!mNativeWindow.initialize()) + { + return egl::Error(EGL_BAD_SURFACE); + } + } + + egl::Error error = resetSwapChain(); + if (error.isError()) + { + return error; + } + + return egl::Error(EGL_SUCCESS); +} + +egl::Error SurfaceD3D::bindTexImage(EGLint) +{ + return egl::Error(EGL_SUCCESS); +} + +egl::Error SurfaceD3D::releaseTexImage(EGLint) +{ + return egl::Error(EGL_SUCCESS); +} + +egl::Error SurfaceD3D::resetSwapChain() +{ + ASSERT(!mSwapChain); + + int width; + int height; + + if (!mFixedSize) + { + RECT windowRect; + if (!mNativeWindow.getClientRect(&windowRect)) + { + ASSERT(false); + + return egl::Error(EGL_BAD_SURFACE, "Could not retrieve the window dimensions"); + } + + width = windowRect.right - windowRect.left; + height = windowRect.bottom - windowRect.top; + } + else + { + // non-window surface - size is determined at creation + width = mWidth; + height = mHeight; + } + + mSwapChain = mRenderer->createSwapChain(mNativeWindow, mShareHandle, mRenderTargetFormat, mDepthStencilFormat); + if (!mSwapChain) + { + return egl::Error(EGL_BAD_ALLOC); + } + + egl::Error error = resetSwapChain(width, height); + if (error.isError()) + { + SafeDelete(mSwapChain); + return error; + } + + return egl::Error(EGL_SUCCESS); +} + +egl::Error SurfaceD3D::resizeSwapChain(int backbufferWidth, int backbufferHeight) +{ + ASSERT(backbufferWidth >= 0 && backbufferHeight >= 0); + ASSERT(mSwapChain); + + EGLint status = mSwapChain->resize(std::max(1, backbufferWidth), std::max(1, backbufferHeight)); + + if (status == EGL_CONTEXT_LOST) + { + mDisplay->notifyDeviceLost(); + return egl::Error(status); + } + else if (status != EGL_SUCCESS) + { + return egl::Error(status); + } + + mWidth = backbufferWidth; + mHeight = backbufferHeight; + + return egl::Error(EGL_SUCCESS); +} + +egl::Error SurfaceD3D::resetSwapChain(int backbufferWidth, int backbufferHeight) +{ + ASSERT(backbufferWidth >= 0 && backbufferHeight >= 0); + ASSERT(mSwapChain); + + EGLint status = mSwapChain->reset(std::max(1, backbufferWidth), std::max(1, backbufferHeight), mSwapInterval); + + if (status == EGL_CONTEXT_LOST) + { + mRenderer->notifyDeviceLost(); + return egl::Error(status); + } + else if (status != EGL_SUCCESS) + { + return egl::Error(status); + } + + mWidth = backbufferWidth; + mHeight = backbufferHeight; + mSwapIntervalDirty = false; + + return egl::Error(EGL_SUCCESS); +} + +egl::Error SurfaceD3D::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) +{ + if (!mSwapChain) + { + return egl::Error(EGL_SUCCESS); + } + + if (x + width > mWidth) + { + width = mWidth - x; + } + + if (y + height > mHeight) + { + height = mHeight - y; + } + + if (width == 0 || height == 0) + { + return egl::Error(EGL_SUCCESS); + } + + EGLint status = mSwapChain->swapRect(x, y, width, height); + + if (status == EGL_CONTEXT_LOST) + { + mRenderer->notifyDeviceLost(); + return egl::Error(status); + } + else if (status != EGL_SUCCESS) + { + return egl::Error(status); + } + + checkForOutOfDateSwapChain(); + + return egl::Error(EGL_SUCCESS); +} + +#if !defined(ANGLE_ENABLE_WINDOWS_STORE) +#define kSurfaceProperty _TEXT("Egl::SurfaceOwner") +#define kParentWndProc _TEXT("Egl::SurfaceParentWndProc") + +static LRESULT CALLBACK SurfaceWindowProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) +{ + if (message == WM_SIZE) + { + SurfaceD3D* surf = reinterpret_cast(GetProp(hwnd, kSurfaceProperty)); + if(surf) + { + surf->checkForOutOfDateSwapChain(); + } + } + WNDPROC prevWndFunc = reinterpret_cast(GetProp(hwnd, kParentWndProc)); + return CallWindowProc(prevWndFunc, hwnd, message, wparam, lparam); +} +#endif + +void SurfaceD3D::subclassWindow() +{ +#if !defined(ANGLE_ENABLE_WINDOWS_STORE) + HWND window = mNativeWindow.getNativeWindow(); + if (!window) + { + return; + } + + DWORD processId; + DWORD threadId = GetWindowThreadProcessId(window, &processId); + if (processId != GetCurrentProcessId() || threadId != GetCurrentThreadId()) + { + return; + } + + SetLastError(0); + LONG_PTR oldWndProc = SetWindowLongPtr(window, GWLP_WNDPROC, reinterpret_cast(SurfaceWindowProc)); + if(oldWndProc == 0 && GetLastError() != ERROR_SUCCESS) + { + mWindowSubclassed = false; + return; + } + + SetProp(window, kSurfaceProperty, reinterpret_cast(this)); + SetProp(window, kParentWndProc, reinterpret_cast(oldWndProc)); + mWindowSubclassed = true; +#endif +} + +void SurfaceD3D::unsubclassWindow() +{ + if (!mWindowSubclassed) + { + return; + } + +#if !defined(ANGLE_ENABLE_WINDOWS_STORE) + HWND window = mNativeWindow.getNativeWindow(); + if (!window) + { + return; + } + + // un-subclass + LONG_PTR parentWndFunc = reinterpret_cast(GetProp(window, kParentWndProc)); + + // Check the windowproc is still SurfaceWindowProc. + // If this assert fails, then it is likely the application has subclassed the + // hwnd as well and did not unsubclass before destroying its EGL context. The + // application should be modified to either subclass before initializing the + // EGL context, or to unsubclass before destroying the EGL context. + if(parentWndFunc) + { + LONG_PTR prevWndFunc = SetWindowLongPtr(window, GWLP_WNDPROC, parentWndFunc); + UNUSED_ASSERTION_VARIABLE(prevWndFunc); + ASSERT(prevWndFunc == reinterpret_cast(SurfaceWindowProc)); + } + + RemoveProp(window, kSurfaceProperty); + RemoveProp(window, kParentWndProc); +#endif + mWindowSubclassed = false; +} + +bool SurfaceD3D::checkForOutOfDateSwapChain() +{ + RECT client; + int clientWidth = getWidth(); + int clientHeight = getHeight(); + bool sizeDirty = false; + if (!mFixedSize && !mNativeWindow.isIconic()) + { + // The window is automatically resized to 150x22 when it's minimized, but the swapchain shouldn't be resized + // because that's not a useful size to render to. + if (!mNativeWindow.getClientRect(&client)) + { + ASSERT(false); + return false; + } + + // Grow the buffer now, if the window has grown. We need to grow now to avoid losing information. + clientWidth = client.right - client.left; + clientHeight = client.bottom - client.top; + sizeDirty = clientWidth != getWidth() || clientHeight != getHeight(); + } + + bool wasDirty = (mSwapIntervalDirty || sizeDirty); + + if (mSwapIntervalDirty) + { + resetSwapChain(clientWidth, clientHeight); + } + else if (sizeDirty) + { + resizeSwapChain(clientWidth, clientHeight); + } + + return wasDirty; +} + +egl::Error SurfaceD3D::swap() +{ + return swapRect(0, 0, mWidth, mHeight); +} + +egl::Error SurfaceD3D::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) +{ + return swapRect(x, y, width, height); +} + +rx::SwapChainD3D *SurfaceD3D::getSwapChain() const +{ + return mSwapChain; +} + +void SurfaceD3D::setSwapInterval(EGLint interval) +{ + if (mSwapInterval == interval) + { + return; + } + + mSwapInterval = interval; + mSwapIntervalDirty = true; +} + +EGLint SurfaceD3D::getWidth() const +{ + return mWidth; +} + +EGLint SurfaceD3D::getHeight() const +{ + return mHeight; +} + +EGLint SurfaceD3D::isPostSubBufferSupported() const +{ + // post sub buffer is always possible on D3D surfaces + return EGL_TRUE; +} + +egl::Error SurfaceD3D::querySurfacePointerANGLE(EGLint attribute, void **value) +{ + ASSERT(attribute == EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE || attribute == EGL_DEVICE_EXT); + if (attribute == EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE) + *value = mSwapChain->getShareHandle(); + else if (attribute == EGL_DEVICE_EXT) + *value = mSwapChain->getDevice(); + return egl::Error(EGL_SUCCESS); +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.h new file mode 100644 index 0000000000..070b7cdbc4 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.h @@ -0,0 +1,92 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// SurfaceD3D.h: D3D implementation of an EGL surface + +#ifndef LIBANGLE_RENDERER_D3D_SURFACED3D_H_ +#define LIBANGLE_RENDERER_D3D_SURFACED3D_H_ + +#include "libANGLE/renderer/SurfaceImpl.h" +#include "libANGLE/renderer/d3d/d3d11/NativeWindow.h" + +namespace egl +{ +class Surface; +} + +namespace rx +{ +class SwapChainD3D; +class RendererD3D; + +class SurfaceD3D : public SurfaceImpl +{ + public: + static SurfaceD3D *createFromWindow(RendererD3D *renderer, egl::Display *display, const egl::Config *config, + EGLNativeWindowType window, EGLint fixedSize, EGLint width, EGLint height); + static SurfaceD3D *createOffscreen(RendererD3D *renderer, egl::Display *display, const egl::Config *config, + EGLClientBuffer shareHandle, EGLint width, EGLint height); + ~SurfaceD3D() override; + void releaseSwapChain(); + + egl::Error initialize() override; + + egl::Error swap() override; + egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) override; + egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override; + egl::Error bindTexImage(EGLint buffer) override; + egl::Error releaseTexImage(EGLint buffer) override; + void setSwapInterval(EGLint interval) override; + + EGLint getWidth() const override; + EGLint getHeight() const override; + + EGLint isPostSubBufferSupported() const override; + + // D3D implementations + SwapChainD3D *getSwapChain() const; + + egl::Error resetSwapChain(); + + // Returns true if swapchain changed due to resize or interval update + bool checkForOutOfDateSwapChain(); + + private: + SurfaceD3D(RendererD3D *renderer, egl::Display *display, const egl::Config *config, EGLint width, EGLint height, + EGLint fixedSize, EGLClientBuffer shareHandle, EGLNativeWindowType window); + + egl::Error swapRect(EGLint x, EGLint y, EGLint width, EGLint height); + egl::Error resetSwapChain(int backbufferWidth, int backbufferHeight); + egl::Error resizeSwapChain(int backbufferWidth, int backbufferHeight); + + void subclassWindow(); + void unsubclassWindow(); + + RendererD3D *mRenderer; + egl::Display *mDisplay; + + bool mFixedSize; + + GLenum mRenderTargetFormat; + GLenum mDepthStencilFormat; + + SwapChainD3D *mSwapChain; + bool mSwapIntervalDirty; + bool mWindowSubclassed; // Indicates whether we successfully subclassed mWindow for WM_RESIZE hooking + + NativeWindow mNativeWindow; // Handler for the Window that the surface is created for. + EGLint mWidth; + EGLint mHeight; + + EGLint mSwapInterval; + + HANDLE mShareHandle; +}; + + +} + +#endif // LIBANGLE_RENDERER_D3D_SURFACED3D_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/SwapChainD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SwapChainD3D.h new file mode 100644 index 0000000000..da36e52ea7 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SwapChainD3D.h @@ -0,0 +1,63 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// SwapChainD3D.h: Defines a back-end specific class that hides the details of the +// implementation-specific swapchain. + +#ifndef LIBANGLE_RENDERER_D3D_SWAPCHAIND3D_H_ +#define LIBANGLE_RENDERER_D3D_SWAPCHAIND3D_H_ + +#include +#include + +#include "common/angleutils.h" +#include "common/platform.h" + +// TODO: move out of D3D11 +#include "libANGLE/renderer/d3d/d3d11/NativeWindow.h" + +#if !defined(ANGLE_FORCE_VSYNC_OFF) +#define ANGLE_FORCE_VSYNC_OFF 0 +#endif + +namespace rx +{ +class RenderTargetD3D; + +class SwapChainD3D : angle::NonCopyable +{ + public: + SwapChainD3D(rx::NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) + : mNativeWindow(nativeWindow), mShareHandle(shareHandle), mBackBufferFormat(backBufferFormat), mDepthBufferFormat(depthBufferFormat) + { + } + + virtual ~SwapChainD3D() {}; + + 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 void *getDevice() { return NULL; } + + virtual RenderTargetD3D *getColorRenderTarget() = 0; + virtual RenderTargetD3D *getDepthStencilRenderTarget() = 0; + + GLenum GetBackBufferInternalFormat() const { return mBackBufferFormat; } + GLenum GetDepthBufferInternalFormat() const { return mDepthBufferFormat; } + + HANDLE getShareHandle() { return mShareHandle; } + + protected: + rx::NativeWindow mNativeWindow; // Handler for the Window that the surface is created for. + const GLenum mBackBufferFormat; + const GLenum mDepthBufferFormat; + + HANDLE mShareHandle; +}; + +} +#endif // LIBANGLE_RENDERER_D3D_SWAPCHAIND3D_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureD3D.cpp new file mode 100644 index 0000000000..78b03f2283 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureD3D.cpp @@ -0,0 +1,2916 @@ +// +// Copyright 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// TextureD3D.cpp: Implementations of the Texture interfaces shared betweeen the D3D backends. + +#include "libANGLE/renderer/d3d/TextureD3D.h" + +#include "common/mathutil.h" +#include "common/utilities.h" +#include "libANGLE/Buffer.h" +#include "libANGLE/Config.h" +#include "libANGLE/Framebuffer.h" +#include "libANGLE/Surface.h" +#include "libANGLE/Texture.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/renderer/BufferImpl.h" +#include "libANGLE/renderer/d3d/BufferD3D.h" +#include "libANGLE/renderer/d3d/ImageD3D.h" +#include "libANGLE/renderer/d3d/RendererD3D.h" +#include "libANGLE/renderer/d3d/RenderTargetD3D.h" +#include "libANGLE/renderer/d3d/SurfaceD3D.h" +#include "libANGLE/renderer/d3d/TextureStorage.h" + +namespace rx +{ + +namespace +{ + +gl::Error GetUnpackPointer(const gl::PixelUnpackState &unpack, const uint8_t *pixels, + ptrdiff_t layerOffset, const uint8_t **pointerOut) +{ + if (unpack.pixelBuffer.id() != 0) + { + // Do a CPU readback here, if we have an unpack buffer bound and the fast GPU path is not supported + gl::Buffer *pixelBuffer = unpack.pixelBuffer.get(); + ptrdiff_t offset = reinterpret_cast(pixels); + + // TODO: this is the only place outside of renderer that asks for a buffers raw data. + // This functionality should be moved into renderer and the getData method of BufferImpl removed. + BufferD3D *bufferD3D = GetImplAs(pixelBuffer); + ASSERT(bufferD3D); + const uint8_t *bufferData = NULL; + gl::Error error = bufferD3D->getData(&bufferData); + if (error.isError()) + { + return error; + } + + *pointerOut = bufferData + offset; + } + else + { + *pointerOut = pixels; + } + + // Offset the pointer for 2D array layer (if it's valid) + if (*pointerOut != nullptr) + { + *pointerOut += layerOffset; + } + + return gl::Error(GL_NO_ERROR); +} + +bool IsRenderTargetUsage(GLenum usage) +{ + return (usage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE); +} + +} + +TextureD3D::TextureD3D(RendererD3D *renderer) + : mRenderer(renderer), + mUsage(GL_NONE), + mDirtyImages(true), + mImmutable(false), + mTexStorage(NULL) +{ +} + +TextureD3D::~TextureD3D() +{ +} + +gl::Error TextureD3D::getNativeTexture(TextureStorage **outStorage) +{ + // ensure the underlying texture is created + gl::Error error = initializeStorage(false); + if (error.isError()) + { + return error; + } + + if (mTexStorage) + { + error = updateStorage(); + if (error.isError()) + { + return error; + } + } + + ASSERT(outStorage); + + *outStorage = mTexStorage; + return gl::Error(GL_NO_ERROR); +} + +GLint TextureD3D::getBaseLevelWidth() const +{ + const ImageD3D *baseImage = getBaseLevelImage(); + return (baseImage ? baseImage->getWidth() : 0); +} + +GLint TextureD3D::getBaseLevelHeight() const +{ + const ImageD3D *baseImage = getBaseLevelImage(); + return (baseImage ? baseImage->getHeight() : 0); +} + +GLint TextureD3D::getBaseLevelDepth() const +{ + const ImageD3D *baseImage = getBaseLevelImage(); + return (baseImage ? baseImage->getDepth() : 0); +} + +// Note: "base level image" is loosely defined to be any image from the base level, +// where in the base of 2D array textures and cube maps there are several. Don't use +// the base level image for anything except querying texture format and size. +GLenum TextureD3D::getBaseLevelInternalFormat() const +{ + const ImageD3D *baseImage = getBaseLevelImage(); + return (baseImage ? baseImage->getInternalFormat() : GL_NONE); +} + +bool TextureD3D::shouldUseSetData(const ImageD3D *image) const +{ + if (!mRenderer->getWorkarounds().setDataFasterThanImageUpload) + { + return false; + } + + gl::InternalFormat internalFormat = gl::GetInternalFormatInfo(image->getInternalFormat()); + + // We can only handle full updates for depth-stencil textures, so to avoid complications + // disable them entirely. + if (internalFormat.depthBits > 0 || internalFormat.stencilBits > 0) + { + return false; + } + + // TODO(jmadill): Handle compressed internal formats + return (mTexStorage && !internalFormat.compressed); +} + +gl::Error TextureD3D::setImage(const gl::ImageIndex &index, GLenum type, + const gl::PixelUnpackState &unpack, const uint8_t *pixels, + ptrdiff_t layerOffset) +{ + if (unpack.skipRows != 0 || unpack.skipPixels != 0 || unpack.imageHeight != 0 || unpack.skipImages != 0) + { + UNIMPLEMENTED(); + return gl::Error(GL_INVALID_OPERATION, "unimplemented pixel store state"); + } + + ImageD3D *image = getImage(index); + ASSERT(image); + + // No-op + if (image->getWidth() == 0 || image->getHeight() == 0 || image->getDepth() == 0) + { + return gl::Error(GL_NO_ERROR); + } + + // We no longer need the "GLenum format" parameter to TexImage to determine what data format "pixels" contains. + // From our image internal format we know how many channels to expect, and "type" gives the format of pixel's components. + const uint8_t *pixelData = NULL; + gl::Error error = GetUnpackPointer(unpack, pixels, layerOffset, &pixelData); + if (error.isError()) + { + return error; + } + + if (pixelData != NULL) + { + if (shouldUseSetData(image)) + { + error = mTexStorage->setData(index, image, NULL, type, unpack, pixelData); + } + else + { + gl::Box fullImageArea(0, 0, 0, image->getWidth(), image->getHeight(), image->getDepth()); + error = image->loadData(fullImageArea, unpack, type, pixelData); + } + + if (error.isError()) + { + return error; + } + + mDirtyImages = true; + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureD3D::subImage(const gl::ImageIndex &index, const gl::Box &area, GLenum format, GLenum type, + const gl::PixelUnpackState &unpack, const uint8_t *pixels, ptrdiff_t layerOffset) +{ + // CPU readback & copy where direct GPU copy is not supported + const uint8_t *pixelData = NULL; + gl::Error error = GetUnpackPointer(unpack, pixels, layerOffset, &pixelData); + if (error.isError()) + { + return error; + } + + if (pixelData != NULL) + { + ImageD3D *image = getImage(index); + ASSERT(image); + + if (shouldUseSetData(image)) + { + return mTexStorage->setData(index, image, &area, type, unpack, pixelData); + } + + error = image->loadData(area, unpack, type, pixelData); + if (error.isError()) + { + return error; + } + + error = commitRegion(index, area); + if (error.isError()) + { + return error; + } + + mDirtyImages = true; + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureD3D::setCompressedImage(const gl::ImageIndex &index, const gl::PixelUnpackState &unpack, + const uint8_t *pixels, ptrdiff_t layerOffset) +{ + if (unpack.skipRows != 0 || unpack.skipPixels != 0 || unpack.imageHeight != 0 || unpack.skipImages != 0) + { + UNIMPLEMENTED(); + return gl::Error(GL_INVALID_OPERATION, "unimplemented pixel store state"); + } + + // We no longer need the "GLenum format" parameter to TexImage to determine what data format "pixels" contains. + // From our image internal format we know how many channels to expect, and "type" gives the format of pixel's components. + const uint8_t *pixelData = NULL; + gl::Error error = GetUnpackPointer(unpack, pixels, layerOffset, &pixelData); + if (error.isError()) + { + return error; + } + + if (pixelData != NULL) + { + ImageD3D *image = getImage(index); + ASSERT(image); + + gl::Box fullImageArea(0, 0, 0, image->getWidth(), image->getHeight(), image->getDepth()); + error = image->loadCompressedData(fullImageArea, pixelData); + if (error.isError()) + { + return error; + } + + mDirtyImages = true; + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureD3D::subImageCompressed(const gl::ImageIndex &index, const gl::Box &area, GLenum format, + const gl::PixelUnpackState &unpack, const uint8_t *pixels, + ptrdiff_t layerOffset) +{ + if (unpack.skipRows != 0 || unpack.skipPixels != 0 || unpack.imageHeight != 0 || unpack.skipImages != 0) + { + UNIMPLEMENTED(); + return gl::Error(GL_INVALID_OPERATION, "unimplemented pixel store state"); + } + + const uint8_t *pixelData = NULL; + gl::Error error = GetUnpackPointer(unpack, pixels, layerOffset, &pixelData); + if (error.isError()) + { + return error; + } + + if (pixelData != NULL) + { + ImageD3D *image = getImage(index); + ASSERT(image); + + error = image->loadCompressedData(area, pixelData); + if (error.isError()) + { + return error; + } + + mDirtyImages = true; + } + + return gl::Error(GL_NO_ERROR); +} + +bool TextureD3D::isFastUnpackable(const gl::PixelUnpackState &unpack, GLenum sizedInternalFormat) +{ + return unpack.pixelBuffer.id() != 0 && mRenderer->supportsFastCopyBufferToTexture(sizedInternalFormat); +} + +gl::Error TextureD3D::fastUnpackPixels(const gl::PixelUnpackState &unpack, const uint8_t *pixels, const gl::Box &destArea, + GLenum sizedInternalFormat, GLenum type, RenderTargetD3D *destRenderTarget) +{ + // No-op + if (destArea.width <= 0 && destArea.height <= 0 && destArea.depth <= 0) + { + return gl::Error(GL_NO_ERROR); + } + + // In order to perform the fast copy through the shader, we must have the right format, and be able + // to create a render target. + ASSERT(mRenderer->supportsFastCopyBufferToTexture(sizedInternalFormat)); + + uintptr_t offset = reinterpret_cast(pixels); + + gl::Error error = mRenderer->fastCopyBufferToTexture(unpack, offset, destRenderTarget, sizedInternalFormat, type, destArea); + if (error.isError()) + { + return error; + } + + return gl::Error(GL_NO_ERROR); +} + +GLint TextureD3D::creationLevels(GLsizei width, GLsizei height, GLsizei depth) const +{ + if ((gl::isPow2(width) && gl::isPow2(height) && gl::isPow2(depth)) || mRenderer->getRendererExtensions().textureNPOT) + { + // Maximum number of levels + return gl::log2(std::max(std::max(width, height), depth)) + 1; + } + else + { + // OpenGL ES 2.0 without GL_OES_texture_npot does not permit NPOT mipmaps. + return 1; + } +} + +int TextureD3D::mipLevels() const +{ + return gl::log2(std::max(std::max(getBaseLevelWidth(), getBaseLevelHeight()), getBaseLevelDepth())) + 1; +} + +TextureStorage *TextureD3D::getStorage() +{ + ASSERT(mTexStorage); + return mTexStorage; +} + +ImageD3D *TextureD3D::getBaseLevelImage() const +{ + return getImage(getImageIndex(0, 0)); +} + +gl::Error TextureD3D::generateMipmaps() +{ + GLint mipCount = mipLevels(); + + if (mipCount == 1) + { + return gl::Error(GL_NO_ERROR); // no-op + } + + if (mTexStorage && mRenderer->getWorkarounds().zeroMaxLodWorkaround) + { + // Switch to using the mipmapped texture. + TextureStorage *textureStorage = NULL; + gl::Error error = getNativeTexture(&textureStorage); + if (error.isError()) + { + return error; + } + + error = textureStorage->useLevelZeroWorkaroundTexture(false); + if (error.isError()) + { + return error; + } + } + + // Set up proper mipmap chain in our Image array. + initMipmapsImages(); + + // We know that all layers have the same dimension, for the texture to be complete + GLint layerCount = static_cast(getLayerCount(0)); + + // When making mipmaps with the setData workaround enabled, the texture storage has + // the image data already. For non-render-target storage, we have to pull it out into + // an image layer. + if (mRenderer->getWorkarounds().setDataFasterThanImageUpload && mTexStorage) + { + if (!mTexStorage->isRenderTarget()) + { + // Copy from the storage mip 0 to Image mip 0 + for (GLint layer = 0; layer < layerCount; ++layer) + { + gl::ImageIndex srcIndex = getImageIndex(0, layer); + + ImageD3D *image = getImage(srcIndex); + gl::Box area(0, 0, 0, image->getWidth(), image->getHeight(), image->getDepth()); + gl::Offset offset(0, 0, 0); + gl::Error error = image->copy(offset, area, srcIndex, mTexStorage); + if (error.isError()) + { + return error; + } + } + } + else + { + gl::Error error = updateStorage(); + if (error.isError()) + { + return error; + } + } + } + + // TODO: Decouple this from zeroMaxLodWorkaround. This is a 9_3 restriction, unrelated to zeroMaxLodWorkaround. + // The restriction is because Feature Level 9_3 can't create SRVs on individual levels of the texture. + // As a result, even if the storage is a rendertarget, we can't use the GPU to generate the mipmaps without further work. + // The D3D9 renderer works around this by copying each level of the texture into its own single-layer GPU texture (in Blit9::boxFilter). + // Feature Level 9_3 could do something similar, or it could continue to use CPU-side mipmap generation, or something else. + bool renderableStorage = (mTexStorage && mTexStorage->isRenderTarget() && !(mRenderer->getWorkarounds().zeroMaxLodWorkaround)); + + for (GLint layer = 0; layer < layerCount; ++layer) + { + for (GLint mip = 1; mip < mipCount; ++mip) + { + ASSERT(getLayerCount(mip) == layerCount); + + gl::ImageIndex sourceIndex = getImageIndex(mip - 1, layer); + gl::ImageIndex destIndex = getImageIndex(mip, layer); + + if (renderableStorage) + { + // GPU-side mipmapping + gl::Error error = mTexStorage->generateMipmap(sourceIndex, destIndex); + if (error.isError()) + { + return error; + } + } + else + { + // CPU-side mipmapping + gl::Error error = mRenderer->generateMipmap(getImage(destIndex), getImage(sourceIndex)); + if (error.isError()) + { + return error; + } + } + } + } + + if (mTexStorage) + { + updateStorage(); + } + + return gl::Error(GL_NO_ERROR); +} + +bool TextureD3D::isBaseImageZeroSize() const +{ + ImageD3D *baseImage = getBaseLevelImage(); + + if (!baseImage || baseImage->getWidth() <= 0) + { + return true; + } + + if (!gl::IsCubeMapTextureTarget(baseImage->getTarget()) && baseImage->getHeight() <= 0) + { + return true; + } + + if (baseImage->getTarget() == GL_TEXTURE_3D && baseImage->getDepth() <= 0) + { + return true; + } + + if (baseImage->getTarget() == GL_TEXTURE_2D_ARRAY && getLayerCount(0) <= 0) + { + return true; + } + + return false; +} + +gl::Error TextureD3D::ensureRenderTarget() +{ + gl::Error error = initializeStorage(true); + if (error.isError()) + { + return error; + } + + if (!isBaseImageZeroSize()) + { + ASSERT(mTexStorage); + if (!mTexStorage->isRenderTarget()) + { + TextureStorage *newRenderTargetStorage = NULL; + error = createCompleteStorage(true, &newRenderTargetStorage); + if (error.isError()) + { + return error; + } + + error = mTexStorage->copyToStorage(newRenderTargetStorage); + if (error.isError()) + { + SafeDelete(newRenderTargetStorage); + return error; + } + + error = setCompleteTexStorage(newRenderTargetStorage); + if (error.isError()) + { + SafeDelete(newRenderTargetStorage); + return error; + } + } + } + + return gl::Error(GL_NO_ERROR); +} + +bool TextureD3D::canCreateRenderTargetForImage(const gl::ImageIndex &index) const +{ + ImageD3D *image = getImage(index); + bool levelsComplete = (isImageComplete(index) && isImageComplete(getImageIndex(0, 0))); + return (image->isRenderableFormat() && levelsComplete); +} + +gl::Error TextureD3D::commitRegion(const gl::ImageIndex &index, const gl::Box ®ion) +{ + if (mTexStorage) + { + ASSERT(isValidIndex(index)); + ImageD3D *image = getImage(index); + gl::Error error = image->copyToStorage(mTexStorage, index, region); + if (error.isError()) + { + return error; + } + + image->markClean(); + } + + return gl::Error(GL_NO_ERROR); +} + +TextureD3D_2D::TextureD3D_2D(RendererD3D *renderer) + : TextureD3D(renderer) +{ + for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i) + { + mImageArray[i] = renderer->createImage(); + } +} + +TextureD3D_2D::~TextureD3D_2D() +{ + // Delete the Images before the TextureStorage. + // Images might be relying on the TextureStorage for some of their data. + // If TextureStorage is deleted before the Images, then their data will be wastefully copied back from the GPU before we delete the Images. + for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i) + { + delete mImageArray[i]; + } + + SafeDelete(mTexStorage); +} + +ImageD3D *TextureD3D_2D::getImage(int level, int layer) const +{ + ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + ASSERT(layer == 0); + return mImageArray[level]; +} + +ImageD3D *TextureD3D_2D::getImage(const gl::ImageIndex &index) const +{ + ASSERT(index.mipIndex < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + ASSERT(!index.hasLayer()); + ASSERT(index.type == GL_TEXTURE_2D); + return mImageArray[index.mipIndex]; +} + +GLsizei TextureD3D_2D::getLayerCount(int level) const +{ + ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + return 1; +} + +GLsizei TextureD3D_2D::getWidth(GLint level) const +{ + if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + return mImageArray[level]->getWidth(); + else + return 0; +} + +GLsizei TextureD3D_2D::getHeight(GLint level) const +{ + if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + return mImageArray[level]->getHeight(); + else + return 0; +} + +GLenum TextureD3D_2D::getInternalFormat(GLint level) const +{ + if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + return mImageArray[level]->getInternalFormat(); + else + return GL_NONE; +} + +bool TextureD3D_2D::isDepth(GLint level) const +{ + return gl::GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0; +} + +gl::Error TextureD3D_2D::setImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, GLenum format, GLenum type, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) +{ + ASSERT(target == GL_TEXTURE_2D && size.depth == 1); + + GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, type); + + bool fastUnpacked = false; + + redefineImage(level, sizedInternalFormat, size); + + gl::ImageIndex index = gl::ImageIndex::Make2D(level); + + // Attempt a fast gpu copy of the pixel data to the surface + if (isFastUnpackable(unpack, sizedInternalFormat) && isLevelComplete(level)) + { + // Will try to create RT storage if it does not exist + RenderTargetD3D *destRenderTarget = NULL; + gl::Error error = getRenderTarget(index, &destRenderTarget); + if (error.isError()) + { + return error; + } + + gl::Box destArea(0, 0, 0, getWidth(level), getHeight(level), 1); + + error = fastUnpackPixels(unpack, pixels, destArea, sizedInternalFormat, type, destRenderTarget); + if (error.isError()) + { + return error; + } + + // Ensure we don't overwrite our newly initialized data + mImageArray[level]->markClean(); + + fastUnpacked = true; + } + + if (!fastUnpacked) + { + gl::Error error = TextureD3D::setImage(index, type, unpack, pixels, 0); + if (error.isError()) + { + return error; + } + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureD3D_2D::setSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, GLenum type, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) +{ + ASSERT(target == GL_TEXTURE_2D && area.depth == 1 && area.z == 0); + + if (unpack.skipRows != 0 || unpack.skipPixels != 0 || unpack.imageHeight != 0 || unpack.skipImages != 0) + { + UNIMPLEMENTED(); + return gl::Error(GL_INVALID_OPERATION, "unimplemented pixel store state"); + } + + gl::ImageIndex index = gl::ImageIndex::Make2D(level); + if (isFastUnpackable(unpack, getInternalFormat(level)) && isLevelComplete(level)) + { + RenderTargetD3D *renderTarget = NULL; + gl::Error error = getRenderTarget(index, &renderTarget); + if (error.isError()) + { + return error; + } + + ASSERT(!mImageArray[level]->isDirty()); + + return fastUnpackPixels(unpack, pixels, area, getInternalFormat(level), type, renderTarget); + } + else + { + return TextureD3D::subImage(index, area, format, type, unpack, pixels, 0); + } +} + + +gl::Error TextureD3D_2D::setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) +{ + ASSERT(target == GL_TEXTURE_2D && size.depth == 1); + + // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly + redefineImage(level, internalFormat, size); + + return TextureD3D::setCompressedImage(gl::ImageIndex::Make2D(level), unpack, pixels, 0); +} + +gl::Error TextureD3D_2D::setCompressedSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) +{ + ASSERT(target == GL_TEXTURE_2D && area.depth == 1 && area.z == 0); + + gl::ImageIndex index = gl::ImageIndex::Make2D(level); + gl::Error error = TextureD3D::subImageCompressed(index, area, format, unpack, pixels, 0); + if (error.isError()) + { + return error; + } + + return commitRegion(index, area); +} + +gl::Error TextureD3D_2D::copyImage(GLenum target, size_t level, const gl::Rectangle &sourceArea, GLenum internalFormat, + const gl::Framebuffer *source) +{ + ASSERT(target == GL_TEXTURE_2D); + + GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, GL_UNSIGNED_BYTE); + redefineImage(level, sizedInternalFormat, gl::Extents(sourceArea.width, sourceArea.height, 1)); + + gl::ImageIndex index = gl::ImageIndex::Make2D(level); + gl::Offset destOffset(0, 0, 0); + + // If the zero max LOD workaround is active, then we can't sample from individual layers of the framebuffer in shaders, + // so we should use the non-rendering copy path. + if (!canCreateRenderTargetForImage(index) || mRenderer->getWorkarounds().zeroMaxLodWorkaround) + { + gl::Error error = mImageArray[level]->copy(destOffset, sourceArea, source); + if (error.isError()) + { + return error; + } + + mDirtyImages = true; + } + else + { + gl::Error error = ensureRenderTarget(); + if (error.isError()) + { + return error; + } + + mImageArray[level]->markClean(); + + if (sourceArea.width != 0 && sourceArea.height != 0 && isValidLevel(level)) + { + error = mRenderer->copyImage2D(source, sourceArea, internalFormat, destOffset, mTexStorage, level); + if (error.isError()) + { + return error; + } + } + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureD3D_2D::copySubImage(GLenum target, size_t level, const gl::Offset &destOffset, const gl::Rectangle &sourceArea, + const gl::Framebuffer *source) +{ + ASSERT(target == GL_TEXTURE_2D && destOffset.z == 0); + + // can only make our texture storage to a render target if level 0 is defined (with a width & height) and + // the current level we're copying to is defined (with appropriate format, width & height) + + gl::ImageIndex index = gl::ImageIndex::Make2D(level); + + // If the zero max LOD workaround is active, then we can't sample from individual layers of the framebuffer in shaders, + // so we should use the non-rendering copy path. + if (!canCreateRenderTargetForImage(index) || mRenderer->getWorkarounds().zeroMaxLodWorkaround) + { + gl::Error error = mImageArray[level]->copy(destOffset, sourceArea, source); + if (error.isError()) + { + return error; + } + + mDirtyImages = true; + } + else + { + gl::Error error = ensureRenderTarget(); + if (error.isError()) + { + return error; + } + + if (isValidLevel(level)) + { + error = updateStorageLevel(level); + if (error.isError()) + { + return error; + } + + error = mRenderer->copyImage2D(source, sourceArea, + gl::GetInternalFormatInfo(getBaseLevelInternalFormat()).format, + destOffset, mTexStorage, level); + if (error.isError()) + { + return error; + } + } + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureD3D_2D::setStorage(GLenum target, size_t levels, GLenum internalFormat, const gl::Extents &size) +{ + ASSERT(GL_TEXTURE_2D && size.depth == 1); + + for (size_t level = 0; level < levels; level++) + { + gl::Extents levelSize(std::max(1, size.width >> level), + std::max(1, size.height >> level), + 1); + mImageArray[level]->redefine(GL_TEXTURE_2D, internalFormat, levelSize, true); + } + + for (int level = levels; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) + { + mImageArray[level]->redefine(GL_TEXTURE_2D, GL_NONE, gl::Extents(0, 0, 0), true); + } + + // TODO(geofflang): Verify storage creation had no errors + bool renderTarget = IsRenderTargetUsage(mUsage); + TextureStorage *storage = mRenderer->createTextureStorage2D(internalFormat, renderTarget, size.width, size.height, levels, false); + + gl::Error error = setCompleteTexStorage(storage); + if (error.isError()) + { + SafeDelete(storage); + return error; + } + + error = updateStorage(); + + if (error.isError()) + { + return error; + } + + mImmutable = true; + + return gl::Error(GL_NO_ERROR); +} + +void TextureD3D_2D::bindTexImage(egl::Surface *surface) +{ + GLenum internalformat = surface->getConfig()->renderTargetFormat; + + gl::Extents size(surface->getWidth(), surface->getHeight(), 1); + mImageArray[0]->redefine(GL_TEXTURE_2D, internalformat, size, true); + + if (mTexStorage) + { + SafeDelete(mTexStorage); + } + + SurfaceD3D *surfaceD3D = GetImplAs(surface); + ASSERT(surfaceD3D); + + mTexStorage = mRenderer->createTextureStorage2D(surfaceD3D->getSwapChain()); + + mDirtyImages = true; +} + +void TextureD3D_2D::releaseTexImage() +{ + if (mTexStorage) + { + SafeDelete(mTexStorage); + } + + for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) + { + mImageArray[i]->redefine(GL_TEXTURE_2D, GL_NONE, gl::Extents(0, 0, 0), true); + } +} + +void TextureD3D_2D::initMipmapsImages() +{ + // Purge array levels 1 through q and reset them to represent the generated mipmap levels. + int levelCount = mipLevels(); + for (int level = 1; level < levelCount; level++) + { + gl::Extents levelSize(std::max(getBaseLevelWidth() >> level, 1), + std::max(getBaseLevelHeight() >> level, 1), + 1); + + redefineImage(level, getBaseLevelInternalFormat(), levelSize); + } +} + +unsigned int TextureD3D_2D::getRenderTargetSerial(const gl::ImageIndex &index) +{ + ASSERT(!index.hasLayer()); + return (!ensureRenderTarget().isError() ? mTexStorage->getRenderTargetSerial(index) : 0); +} + +gl::Error TextureD3D_2D::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) +{ + ASSERT(!index.hasLayer()); + + // ensure the underlying texture is created + gl::Error error = ensureRenderTarget(); + if (error.isError()) + { + return error; + } + + error = updateStorageLevel(index.mipIndex); + if (error.isError()) + { + return error; + } + + return mTexStorage->getRenderTarget(index, outRT); +} + +bool TextureD3D_2D::isValidLevel(int level) const +{ + return (mTexStorage ? (level >= 0 && level < mTexStorage->getLevelCount()) : false); +} + +bool TextureD3D_2D::isLevelComplete(int level) const +{ + if (isImmutable()) + { + return true; + } + + const ImageD3D *baseImage = getBaseLevelImage(); + + GLsizei width = baseImage->getWidth(); + GLsizei height = baseImage->getHeight(); + + if (width <= 0 || height <= 0) + { + return false; + } + + // The base image level is complete if the width and height are positive + if (level == 0) + { + return true; + } + + ASSERT(level >= 1 && level <= (int)ArraySize(mImageArray) && mImageArray[level] != NULL); + ImageD3D *image = mImageArray[level]; + + if (image->getInternalFormat() != baseImage->getInternalFormat()) + { + return false; + } + + if (image->getWidth() != std::max(1, width >> level)) + { + return false; + } + + if (image->getHeight() != std::max(1, height >> level)) + { + return false; + } + + return true; +} + +bool TextureD3D_2D::isImageComplete(const gl::ImageIndex &index) const +{ + return isLevelComplete(index.mipIndex); +} + +// Constructs a native texture resource from the texture images +gl::Error TextureD3D_2D::initializeStorage(bool renderTarget) +{ + // Only initialize the first time this texture is used as a render target or shader resource + if (mTexStorage) + { + return gl::Error(GL_NO_ERROR); + } + + // do not attempt to create storage for nonexistant data + if (!isLevelComplete(0)) + { + return gl::Error(GL_NO_ERROR); + } + + bool createRenderTarget = (renderTarget || IsRenderTargetUsage(mUsage)); + + TextureStorage *storage = NULL; + gl::Error error = createCompleteStorage(createRenderTarget, &storage); + if (error.isError()) + { + return error; + } + + error = setCompleteTexStorage(storage); + if (error.isError()) + { + SafeDelete(storage); + return error; + } + + ASSERT(mTexStorage); + + // flush image data to the storage + error = updateStorage(); + if (error.isError()) + { + return error; + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureD3D_2D::createCompleteStorage(bool renderTarget, TextureStorage **outTexStorage) const +{ + GLsizei width = getBaseLevelWidth(); + GLsizei height = getBaseLevelHeight(); + GLenum internalFormat = getBaseLevelInternalFormat(); + + ASSERT(width > 0 && height > 0); + + // use existing storage level count, when previously specified by TexStorage*D + GLint levels = (mTexStorage ? mTexStorage->getLevelCount() : creationLevels(width, height, 1)); + + bool hintLevelZeroOnly = false; + if (mRenderer->getWorkarounds().zeroMaxLodWorkaround) + { + // If any of the CPU images (levels >= 1) are dirty, then the textureStorage2D should use the mipped texture to begin with. + // Otherwise, it should use the level-zero-only texture. + hintLevelZeroOnly = true; + for (int level = 1; level < levels && hintLevelZeroOnly; level++) + { + hintLevelZeroOnly = !(mImageArray[level]->isDirty() && isLevelComplete(level)); + } + } + + // TODO(geofflang): Determine if the texture creation succeeded + *outTexStorage = mRenderer->createTextureStorage2D(internalFormat, renderTarget, width, height, levels, hintLevelZeroOnly); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureD3D_2D::setCompleteTexStorage(TextureStorage *newCompleteTexStorage) +{ + if (newCompleteTexStorage && newCompleteTexStorage->isManaged()) + { + for (int level = 0; level < newCompleteTexStorage->getLevelCount(); level++) + { + gl::Error error = mImageArray[level]->setManagedSurface2D(newCompleteTexStorage, level); + if (error.isError()) + { + return error; + } + } + } + + SafeDelete(mTexStorage); + mTexStorage = newCompleteTexStorage; + + mDirtyImages = true; + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureD3D_2D::updateStorage() +{ + ASSERT(mTexStorage != NULL); + GLint storageLevels = mTexStorage->getLevelCount(); + for (int level = 0; level < storageLevels; level++) + { + if (mImageArray[level]->isDirty() && isLevelComplete(level)) + { + gl::Error error = updateStorageLevel(level); + if (error.isError()) + { + return error; + } + } + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureD3D_2D::updateStorageLevel(int level) +{ + ASSERT(level <= (int)ArraySize(mImageArray) && mImageArray[level] != NULL); + ASSERT(isLevelComplete(level)); + + if (mImageArray[level]->isDirty()) + { + gl::ImageIndex index = gl::ImageIndex::Make2D(level); + gl::Box region(0, 0, 0, getWidth(level), getHeight(level), 1); + gl::Error error = commitRegion(index, region); + if (error.isError()) + { + return error; + } + } + + return gl::Error(GL_NO_ERROR); +} + +void TextureD3D_2D::redefineImage(GLint level, GLenum internalformat, const gl::Extents &size) +{ + ASSERT(size.depth == 1); + + // If there currently is a corresponding storage texture image, it has these parameters + const int storageWidth = std::max(1, getBaseLevelWidth() >> level); + const int storageHeight = std::max(1, getBaseLevelHeight() >> level); + const GLenum storageFormat = getBaseLevelInternalFormat(); + + mImageArray[level]->redefine(GL_TEXTURE_2D, internalformat, size, false); + + if (mTexStorage) + { + const int storageLevels = mTexStorage->getLevelCount(); + + if ((level >= storageLevels && storageLevels != 0) || + size.width != storageWidth || + size.height != storageHeight || + internalformat != storageFormat) // Discard mismatched storage + { + for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) + { + mImageArray[i]->markDirty(); + } + + SafeDelete(mTexStorage); + mDirtyImages = true; + } + } +} + +gl::ImageIndexIterator TextureD3D_2D::imageIterator() const +{ + return gl::ImageIndexIterator::Make2D(0, mTexStorage->getLevelCount()); +} + +gl::ImageIndex TextureD3D_2D::getImageIndex(GLint mip, GLint /*layer*/) const +{ + // "layer" does not apply to 2D Textures. + return gl::ImageIndex::Make2D(mip); +} + +bool TextureD3D_2D::isValidIndex(const gl::ImageIndex &index) const +{ + return (mTexStorage && index.type == GL_TEXTURE_2D && + index.mipIndex >= 0 && index.mipIndex < mTexStorage->getLevelCount()); +} + +TextureD3D_Cube::TextureD3D_Cube(RendererD3D *renderer) + : TextureD3D(renderer) +{ + for (int i = 0; i < 6; i++) + { + for (int j = 0; j < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++j) + { + mImageArray[i][j] = renderer->createImage(); + } + } +} + +TextureD3D_Cube::~TextureD3D_Cube() +{ + // Delete the Images before the TextureStorage. + // Images might be relying on the TextureStorage for some of their data. + // If TextureStorage is deleted before the Images, then their data will be wastefully copied back from the GPU before we delete the Images. + for (int i = 0; i < 6; i++) + { + for (int j = 0; j < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++j) + { + SafeDelete(mImageArray[i][j]); + } + } + + SafeDelete(mTexStorage); +} + +ImageD3D *TextureD3D_Cube::getImage(int level, int layer) const +{ + ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + ASSERT(layer >= 0 && layer < 6); + return mImageArray[layer][level]; +} + +ImageD3D *TextureD3D_Cube::getImage(const gl::ImageIndex &index) const +{ + ASSERT(index.mipIndex < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + ASSERT(index.layerIndex >= 0 && index.layerIndex < 6); + return mImageArray[index.layerIndex][index.mipIndex]; +} + +GLsizei TextureD3D_Cube::getLayerCount(int level) const +{ + ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + return 6; +} + +GLenum TextureD3D_Cube::getInternalFormat(GLint level, GLint layer) const +{ + if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + return mImageArray[layer][level]->getInternalFormat(); + else + return GL_NONE; +} + +bool TextureD3D_Cube::isDepth(GLint level, GLint layer) const +{ + return gl::GetInternalFormatInfo(getInternalFormat(level, layer)).depthBits > 0; +} + +gl::Error TextureD3D_Cube::setImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, GLenum format, GLenum type, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) +{ + ASSERT(size.depth == 1); + + GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, type); + gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level); + + redefineImage(index.layerIndex, level, sizedInternalFormat, size); + + return TextureD3D::setImage(index, type, unpack, pixels, 0); +} + +gl::Error TextureD3D_Cube::setSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, GLenum type, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) +{ + ASSERT(area.depth == 1 && area.z == 0); + + gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level); + return TextureD3D::subImage(index, area, format, type, unpack, pixels, 0); +} + +gl::Error TextureD3D_Cube::setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) +{ + ASSERT(size.depth == 1); + + // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly + size_t faceIndex = gl::CubeMapTextureTargetToLayerIndex(target); + + redefineImage(faceIndex, level, internalFormat, size); + + gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level); + return TextureD3D::setCompressedImage(index, unpack, pixels, 0); +} + +gl::Error TextureD3D_Cube::setCompressedSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) +{ + ASSERT(area.depth == 1 && area.z == 0); + + gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level); + + gl::Error error = TextureD3D::subImageCompressed(index, area, format, unpack, pixels, 0); + if (error.isError()) + { + return error; + } + + return commitRegion(index, area); +} + +gl::Error TextureD3D_Cube::copyImage(GLenum target, size_t level, const gl::Rectangle &sourceArea, GLenum internalFormat, + const gl::Framebuffer *source) +{ + size_t faceIndex = gl::CubeMapTextureTargetToLayerIndex(target); + GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, GL_UNSIGNED_BYTE); + + gl::Extents size(sourceArea.width, sourceArea.height, 1); + redefineImage(faceIndex, level, sizedInternalFormat, size); + + gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level); + gl::Offset destOffset(0, 0, 0); + + // If the zero max LOD workaround is active, then we can't sample from individual layers of the framebuffer in shaders, + // so we should use the non-rendering copy path. + if (!canCreateRenderTargetForImage(index) || mRenderer->getWorkarounds().zeroMaxLodWorkaround) + { + gl::Error error = mImageArray[faceIndex][level]->copy(destOffset, sourceArea, source); + if (error.isError()) + { + return error; + } + + mDirtyImages = true; + } + else + { + gl::Error error = ensureRenderTarget(); + if (error.isError()) + { + return error; + } + + mImageArray[faceIndex][level]->markClean(); + + ASSERT(size.width == size.height); + + if (size.width > 0 && isValidFaceLevel(faceIndex, level)) + { + error = mRenderer->copyImageCube(source, sourceArea, internalFormat, destOffset, mTexStorage, target, level); + if (error.isError()) + { + return error; + } + } + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureD3D_Cube::copySubImage(GLenum target, size_t level, const gl::Offset &destOffset, const gl::Rectangle &sourceArea, + const gl::Framebuffer *source) +{ + size_t faceIndex = gl::CubeMapTextureTargetToLayerIndex(target); + + gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level); + + // If the zero max LOD workaround is active, then we can't sample from individual layers of the framebuffer in shaders, + // so we should use the non-rendering copy path. + if (!canCreateRenderTargetForImage(index) || mRenderer->getWorkarounds().zeroMaxLodWorkaround) + { + gl::Error error = mImageArray[faceIndex][level]->copy(destOffset, sourceArea, source); + if (error.isError()) + { + return error; + } + + mDirtyImages = true; + } + else + { + gl::Error error = ensureRenderTarget(); + if (error.isError()) + { + return error; + } + + if (isValidFaceLevel(faceIndex, level)) + { + error = updateStorageFaceLevel(faceIndex, level); + if (error.isError()) + { + return error; + } + + error = mRenderer->copyImageCube(source, sourceArea, gl::GetInternalFormatInfo(getBaseLevelInternalFormat()).format, + destOffset, mTexStorage, target, level); + if (error.isError()) + { + return error; + } + } + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureD3D_Cube::setStorage(GLenum target, size_t levels, GLenum internalFormat, const gl::Extents &size) +{ + ASSERT(size.width == size.height); + ASSERT(size.depth == 1); + + for (size_t level = 0; level < levels; level++) + { + GLsizei mipSize = std::max(1, size.width >> level); + for (int faceIndex = 0; faceIndex < 6; faceIndex++) + { + mImageArray[faceIndex][level]->redefine(GL_TEXTURE_CUBE_MAP, internalFormat, gl::Extents(mipSize, mipSize, 1), true); + } + } + + for (int level = levels; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) + { + for (int faceIndex = 0; faceIndex < 6; faceIndex++) + { + mImageArray[faceIndex][level]->redefine(GL_TEXTURE_CUBE_MAP, GL_NONE, gl::Extents(0, 0, 0), true); + } + } + + // TODO(geofflang): Verify storage creation had no errors + bool renderTarget = IsRenderTargetUsage(mUsage); + + TextureStorage *storage = mRenderer->createTextureStorageCube(internalFormat, renderTarget, size.width, levels, false); + + gl::Error error = setCompleteTexStorage(storage); + if (error.isError()) + { + SafeDelete(storage); + return error; + } + + error = updateStorage(); + + if (error.isError()) + { + return error; + } + + mImmutable = true; + + return gl::Error(GL_NO_ERROR); +} + +// Tests for cube texture completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81. +bool TextureD3D_Cube::isCubeComplete() const +{ + int baseWidth = getBaseLevelWidth(); + int baseHeight = getBaseLevelHeight(); + GLenum baseFormat = getBaseLevelInternalFormat(); + + if (baseWidth <= 0 || baseWidth != baseHeight) + { + return false; + } + + for (int faceIndex = 1; faceIndex < 6; faceIndex++) + { + const ImageD3D &faceBaseImage = *mImageArray[faceIndex][0]; + + if (faceBaseImage.getWidth() != baseWidth || + faceBaseImage.getHeight() != baseHeight || + faceBaseImage.getInternalFormat() != baseFormat ) + { + return false; + } + } + + return true; +} + +void TextureD3D_Cube::bindTexImage(egl::Surface *surface) +{ + UNREACHABLE(); +} + +void TextureD3D_Cube::releaseTexImage() +{ + UNREACHABLE(); +} + + +void TextureD3D_Cube::initMipmapsImages() +{ + // Purge array levels 1 through q and reset them to represent the generated mipmap levels. + int levelCount = mipLevels(); + for (int faceIndex = 0; faceIndex < 6; faceIndex++) + { + for (int level = 1; level < levelCount; level++) + { + int faceLevelSize = (std::max(mImageArray[faceIndex][0]->getWidth() >> level, 1)); + redefineImage(faceIndex, level, mImageArray[faceIndex][0]->getInternalFormat(), + gl::Extents(faceLevelSize, faceLevelSize, 1)); + } + } +} + +unsigned int TextureD3D_Cube::getRenderTargetSerial(const gl::ImageIndex &index) +{ + return (!ensureRenderTarget().isError() ? mTexStorage->getRenderTargetSerial(index) : 0); +} + +gl::Error TextureD3D_Cube::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) +{ + ASSERT(gl::IsCubeMapTextureTarget(index.type)); + + // ensure the underlying texture is created + gl::Error error = ensureRenderTarget(); + if (error.isError()) + { + return error; + } + + error = updateStorageFaceLevel(index.layerIndex, index.mipIndex); + if (error.isError()) + { + return error; + } + + return mTexStorage->getRenderTarget(index, outRT); +} + +gl::Error TextureD3D_Cube::initializeStorage(bool renderTarget) +{ + // Only initialize the first time this texture is used as a render target or shader resource + if (mTexStorage) + { + return gl::Error(GL_NO_ERROR); + } + + // do not attempt to create storage for nonexistant data + if (!isFaceLevelComplete(0, 0)) + { + return gl::Error(GL_NO_ERROR); + } + + bool createRenderTarget = (renderTarget || IsRenderTargetUsage(mUsage)); + + TextureStorage *storage = NULL; + gl::Error error = createCompleteStorage(createRenderTarget, &storage); + if (error.isError()) + { + return error; + } + + error = setCompleteTexStorage(storage); + if (error.isError()) + { + SafeDelete(storage); + return error; + } + + ASSERT(mTexStorage); + + // flush image data to the storage + error = updateStorage(); + if (error.isError()) + { + return error; + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureD3D_Cube::createCompleteStorage(bool renderTarget, TextureStorage **outTexStorage) const +{ + GLsizei size = getBaseLevelWidth(); + + ASSERT(size > 0); + + // use existing storage level count, when previously specified by TexStorage*D + GLint levels = (mTexStorage ? mTexStorage->getLevelCount() : creationLevels(size, size, 1)); + + bool hintLevelZeroOnly = false; + if (mRenderer->getWorkarounds().zeroMaxLodWorkaround) + { + // If any of the CPU images (levels >= 1) are dirty, then the textureStorage should use the mipped texture to begin with. + // Otherwise, it should use the level-zero-only texture. + hintLevelZeroOnly = true; + for (int faceIndex = 0; faceIndex < 6 && hintLevelZeroOnly; faceIndex++) + { + for (int level = 1; level < levels && hintLevelZeroOnly; level++) + { + hintLevelZeroOnly = !(mImageArray[faceIndex][level]->isDirty() && isFaceLevelComplete(faceIndex, level)); + } + } + } + + // TODO (geofflang): detect if storage creation succeeded + *outTexStorage = mRenderer->createTextureStorageCube(getBaseLevelInternalFormat(), renderTarget, size, levels, hintLevelZeroOnly); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureD3D_Cube::setCompleteTexStorage(TextureStorage *newCompleteTexStorage) +{ + if (newCompleteTexStorage && newCompleteTexStorage->isManaged()) + { + for (int faceIndex = 0; faceIndex < 6; faceIndex++) + { + for (int level = 0; level < newCompleteTexStorage->getLevelCount(); level++) + { + gl::Error error = mImageArray[faceIndex][level]->setManagedSurfaceCube(newCompleteTexStorage, faceIndex, level); + if (error.isError()) + { + return error; + } + } + } + } + + SafeDelete(mTexStorage); + mTexStorage = newCompleteTexStorage; + + mDirtyImages = true; + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureD3D_Cube::updateStorage() +{ + ASSERT(mTexStorage != NULL); + GLint storageLevels = mTexStorage->getLevelCount(); + for (int face = 0; face < 6; face++) + { + for (int level = 0; level < storageLevels; level++) + { + if (mImageArray[face][level]->isDirty() && isFaceLevelComplete(face, level)) + { + gl::Error error = updateStorageFaceLevel(face, level); + if (error.isError()) + { + return error; + } + } + } + } + + return gl::Error(GL_NO_ERROR); +} + +bool TextureD3D_Cube::isValidFaceLevel(int faceIndex, int level) const +{ + return (mTexStorage ? (level >= 0 && level < mTexStorage->getLevelCount()) : 0); +} + +bool TextureD3D_Cube::isFaceLevelComplete(int faceIndex, int level) const +{ + ASSERT(level >= 0 && faceIndex < 6 && level < (int)ArraySize(mImageArray[faceIndex]) && mImageArray[faceIndex][level] != NULL); + + if (isImmutable()) + { + return true; + } + + int baseSize = getBaseLevelWidth(); + + if (baseSize <= 0) + { + return false; + } + + // "isCubeComplete" checks for base level completeness and we must call that + // to determine if any face at level 0 is complete. We omit that check here + // to avoid re-checking cube-completeness for every face at level 0. + if (level == 0) + { + return true; + } + + // Check that non-zero levels are consistent with the base level. + const ImageD3D *faceLevelImage = mImageArray[faceIndex][level]; + + if (faceLevelImage->getInternalFormat() != getBaseLevelInternalFormat()) + { + return false; + } + + if (faceLevelImage->getWidth() != std::max(1, baseSize >> level)) + { + return false; + } + + return true; +} + +bool TextureD3D_Cube::isImageComplete(const gl::ImageIndex &index) const +{ + return isFaceLevelComplete(index.layerIndex, index.mipIndex); +} + +gl::Error TextureD3D_Cube::updateStorageFaceLevel(int faceIndex, int level) +{ + ASSERT(level >= 0 && faceIndex < 6 && level < (int)ArraySize(mImageArray[faceIndex]) && mImageArray[faceIndex][level] != NULL); + ImageD3D *image = mImageArray[faceIndex][level]; + + if (image->isDirty()) + { + GLenum faceTarget = gl::LayerIndexToCubeMapTextureTarget(faceIndex); + gl::ImageIndex index = gl::ImageIndex::MakeCube(faceTarget, level); + gl::Box region(0, 0, 0, image->getWidth(), image->getHeight(), 1); + gl::Error error = commitRegion(index, region); + if (error.isError()) + { + return error; + } + } + + return gl::Error(GL_NO_ERROR); +} + +void TextureD3D_Cube::redefineImage(int faceIndex, GLint level, GLenum internalformat, const gl::Extents &size) +{ + // If there currently is a corresponding storage texture image, it has these parameters + const int storageWidth = std::max(1, getBaseLevelWidth() >> level); + const int storageHeight = std::max(1, getBaseLevelHeight() >> level); + const GLenum storageFormat = getBaseLevelInternalFormat(); + + mImageArray[faceIndex][level]->redefine(GL_TEXTURE_CUBE_MAP, internalformat, size, false); + + if (mTexStorage) + { + const int storageLevels = mTexStorage->getLevelCount(); + + if ((level >= storageLevels && storageLevels != 0) || + size.width != storageWidth || + size.height != storageHeight || + internalformat != storageFormat) // Discard mismatched storage + { + for (int dirtyLevel = 0; dirtyLevel < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; dirtyLevel++) + { + for (int dirtyFace = 0; dirtyFace < 6; dirtyFace++) + { + mImageArray[dirtyFace][dirtyLevel]->markDirty(); + } + } + + SafeDelete(mTexStorage); + + mDirtyImages = true; + } + } +} + +gl::ImageIndexIterator TextureD3D_Cube::imageIterator() const +{ + return gl::ImageIndexIterator::MakeCube(0, mTexStorage->getLevelCount()); +} + +gl::ImageIndex TextureD3D_Cube::getImageIndex(GLint mip, GLint layer) const +{ + // The "layer" of the image index corresponds to the cube face + return gl::ImageIndex::MakeCube(gl::LayerIndexToCubeMapTextureTarget(layer), mip); +} + +bool TextureD3D_Cube::isValidIndex(const gl::ImageIndex &index) const +{ + return (mTexStorage && gl::IsCubeMapTextureTarget(index.type) && + index.mipIndex >= 0 && index.mipIndex < mTexStorage->getLevelCount()); +} + +TextureD3D_3D::TextureD3D_3D(RendererD3D *renderer) + : TextureD3D(renderer) +{ + for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i) + { + mImageArray[i] = renderer->createImage(); + } +} + +TextureD3D_3D::~TextureD3D_3D() +{ + // Delete the Images before the TextureStorage. + // Images might be relying on the TextureStorage for some of their data. + // If TextureStorage is deleted before the Images, then their data will be wastefully copied back from the GPU before we delete the Images. + for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i) + { + delete mImageArray[i]; + } + + SafeDelete(mTexStorage); +} + +ImageD3D *TextureD3D_3D::getImage(int level, int layer) const +{ + ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + ASSERT(layer == 0); + return mImageArray[level]; +} + +ImageD3D *TextureD3D_3D::getImage(const gl::ImageIndex &index) const +{ + ASSERT(index.mipIndex < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + ASSERT(!index.hasLayer()); + ASSERT(index.type == GL_TEXTURE_3D); + return mImageArray[index.mipIndex]; +} + +GLsizei TextureD3D_3D::getLayerCount(int level) const +{ + ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + return 1; +} + +GLsizei TextureD3D_3D::getWidth(GLint level) const +{ + if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + return mImageArray[level]->getWidth(); + else + return 0; +} + +GLsizei TextureD3D_3D::getHeight(GLint level) const +{ + if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + return mImageArray[level]->getHeight(); + else + return 0; +} + +GLsizei TextureD3D_3D::getDepth(GLint level) const +{ + if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + return mImageArray[level]->getDepth(); + else + return 0; +} + +GLenum TextureD3D_3D::getInternalFormat(GLint level) const +{ + if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + return mImageArray[level]->getInternalFormat(); + else + return GL_NONE; +} + +bool TextureD3D_3D::isDepth(GLint level) const +{ + return gl::GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0; +} + +gl::Error TextureD3D_3D::setImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, GLenum format, GLenum type, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) +{ + ASSERT(target == GL_TEXTURE_3D); + GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, type); + + redefineImage(level, sizedInternalFormat, size); + + bool fastUnpacked = false; + + gl::ImageIndex index = gl::ImageIndex::Make3D(level); + + // Attempt a fast gpu copy of the pixel data to the surface if the app bound an unpack buffer + if (isFastUnpackable(unpack, sizedInternalFormat) && !size.empty()) + { + // Will try to create RT storage if it does not exist + RenderTargetD3D *destRenderTarget = NULL; + gl::Error error = getRenderTarget(index, &destRenderTarget); + if (error.isError()) + { + return error; + } + + gl::Box destArea(0, 0, 0, getWidth(level), getHeight(level), getDepth(level)); + + error = fastUnpackPixels(unpack, pixels, destArea, sizedInternalFormat, type, destRenderTarget); + if (error.isError()) + { + return error; + } + + // Ensure we don't overwrite our newly initialized data + mImageArray[level]->markClean(); + + fastUnpacked = true; + } + + if (!fastUnpacked) + { + gl::Error error = TextureD3D::setImage(index, type, unpack, pixels, 0); + if (error.isError()) + { + return error; + } + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureD3D_3D::setSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, GLenum type, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) +{ + ASSERT(target == GL_TEXTURE_3D); + + gl::ImageIndex index = gl::ImageIndex::Make3D(level); + + // Attempt a fast gpu copy of the pixel data to the surface if the app bound an unpack buffer + if (isFastUnpackable(unpack, getInternalFormat(level))) + { + RenderTargetD3D *destRenderTarget = NULL; + gl::Error error = getRenderTarget(index, &destRenderTarget); + if (error.isError()) + { + return error; + } + + ASSERT(!mImageArray[level]->isDirty()); + + return fastUnpackPixels(unpack, pixels, area, getInternalFormat(level), type, destRenderTarget); + } + else + { + return TextureD3D::subImage(index, area, format, type, unpack, pixels, 0); + } +} + +gl::Error TextureD3D_3D::setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) +{ + ASSERT(target == GL_TEXTURE_3D); + + // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly + redefineImage(level, internalFormat, size); + + gl::ImageIndex index = gl::ImageIndex::Make3D(level); + return TextureD3D::setCompressedImage(index, unpack, pixels, 0); +} + +gl::Error TextureD3D_3D::setCompressedSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) +{ + ASSERT(target == GL_TEXTURE_3D); + + gl::ImageIndex index = gl::ImageIndex::Make3D(level); + gl::Error error = TextureD3D::subImageCompressed(index, area, format, unpack, pixels, 0); + if (error.isError()) + { + return error; + } + + return commitRegion(index, area); +} + +gl::Error TextureD3D_3D::copyImage(GLenum target, size_t level, const gl::Rectangle &sourceArea, GLenum internalFormat, + const gl::Framebuffer *source) +{ + UNIMPLEMENTED(); + return gl::Error(GL_INVALID_OPERATION, "Copying 3D textures is unimplemented."); +} + +gl::Error TextureD3D_3D::copySubImage(GLenum target, size_t level, const gl::Offset &destOffset, const gl::Rectangle &sourceArea, + const gl::Framebuffer *source) +{ + ASSERT(target == GL_TEXTURE_3D); + + gl::ImageIndex index = gl::ImageIndex::Make3D(level); + + if (canCreateRenderTargetForImage(index)) + { + gl::Error error = mImageArray[level]->copy(destOffset, sourceArea, source); + if (error.isError()) + { + return error; + } + + mDirtyImages = true; + } + else + { + gl::Error error = ensureRenderTarget(); + if (error.isError()) + { + return error; + } + + if (isValidLevel(level)) + { + error = updateStorageLevel(level); + if (error.isError()) + { + return error; + } + + error = mRenderer->copyImage3D(source, sourceArea, + gl::GetInternalFormatInfo(getBaseLevelInternalFormat()).format, + destOffset, mTexStorage, level); + if (error.isError()) + { + return error; + } + } + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureD3D_3D::setStorage(GLenum target, size_t levels, GLenum internalFormat, const gl::Extents &size) +{ + ASSERT(target == GL_TEXTURE_3D); + + for (size_t level = 0; level < levels; level++) + { + gl::Extents levelSize(std::max(1, size.width >> level), + std::max(1, size.height >> level), + std::max(1, size.depth >> level)); + mImageArray[level]->redefine(GL_TEXTURE_3D, internalFormat, levelSize, true); + } + + for (int level = levels; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) + { + mImageArray[level]->redefine(GL_TEXTURE_3D, GL_NONE, gl::Extents(0, 0, 0), true); + } + + // TODO(geofflang): Verify storage creation had no errors + bool renderTarget = IsRenderTargetUsage(mUsage); + TextureStorage *storage = mRenderer->createTextureStorage3D(internalFormat, renderTarget, size.width, size.height, size.depth, levels); + + gl::Error error = setCompleteTexStorage(storage); + if (error.isError()) + { + SafeDelete(storage); + return error; + } + + error = updateStorage(); + + if (error.isError()) + { + return error; + } + + mImmutable = true; + + return gl::Error(GL_NO_ERROR); +} + +void TextureD3D_3D::bindTexImage(egl::Surface *surface) +{ + UNREACHABLE(); +} + +void TextureD3D_3D::releaseTexImage() +{ + UNREACHABLE(); +} + + +void TextureD3D_3D::initMipmapsImages() +{ + // Purge array levels 1 through q and reset them to represent the generated mipmap levels. + int levelCount = mipLevels(); + for (int level = 1; level < levelCount; level++) + { + gl::Extents levelSize(std::max(getBaseLevelWidth() >> level, 1), + std::max(getBaseLevelHeight() >> level, 1), + std::max(getBaseLevelDepth() >> level, 1)); + redefineImage(level, getBaseLevelInternalFormat(), levelSize); + } +} + +unsigned int TextureD3D_3D::getRenderTargetSerial(const gl::ImageIndex &index) +{ + return (!ensureRenderTarget().isError() ? mTexStorage->getRenderTargetSerial(index) : 0); +} + +gl::Error TextureD3D_3D::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) +{ + // ensure the underlying texture is created + gl::Error error = ensureRenderTarget(); + if (error.isError()) + { + return error; + } + + if (index.hasLayer()) + { + error = updateStorage(); + if (error.isError()) + { + return error; + } + } + else + { + error = updateStorageLevel(index.mipIndex); + if (error.isError()) + { + return error; + } + } + + return mTexStorage->getRenderTarget(index, outRT); +} + +gl::Error TextureD3D_3D::initializeStorage(bool renderTarget) +{ + // Only initialize the first time this texture is used as a render target or shader resource + if (mTexStorage) + { + return gl::Error(GL_NO_ERROR); + } + + // do not attempt to create storage for nonexistant data + if (!isLevelComplete(0)) + { + return gl::Error(GL_NO_ERROR); + } + + bool createRenderTarget = (renderTarget || IsRenderTargetUsage(mUsage)); + + TextureStorage *storage = NULL; + gl::Error error = createCompleteStorage(createRenderTarget, &storage); + if (error.isError()) + { + return error; + } + + error = setCompleteTexStorage(storage); + if (error.isError()) + { + SafeDelete(storage); + return error; + } + + ASSERT(mTexStorage); + + // flush image data to the storage + error = updateStorage(); + if (error.isError()) + { + return error; + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureD3D_3D::createCompleteStorage(bool renderTarget, TextureStorage **outStorage) const +{ + GLsizei width = getBaseLevelWidth(); + GLsizei height = getBaseLevelHeight(); + GLsizei depth = getBaseLevelDepth(); + GLenum internalFormat = getBaseLevelInternalFormat(); + + ASSERT(width > 0 && height > 0 && depth > 0); + + // use existing storage level count, when previously specified by TexStorage*D + GLint levels = (mTexStorage ? mTexStorage->getLevelCount() : creationLevels(width, height, depth)); + + // TODO: Verify creation of the storage succeeded + *outStorage = mRenderer->createTextureStorage3D(internalFormat, renderTarget, width, height, depth, levels); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureD3D_3D::setCompleteTexStorage(TextureStorage *newCompleteTexStorage) +{ + SafeDelete(mTexStorage); + mTexStorage = newCompleteTexStorage; + mDirtyImages = true; + + // We do not support managed 3D storage, as that is D3D9/ES2-only + ASSERT(!mTexStorage->isManaged()); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureD3D_3D::updateStorage() +{ + ASSERT(mTexStorage != NULL); + GLint storageLevels = mTexStorage->getLevelCount(); + for (int level = 0; level < storageLevels; level++) + { + if (mImageArray[level]->isDirty() && isLevelComplete(level)) + { + gl::Error error = updateStorageLevel(level); + if (error.isError()) + { + return error; + } + } + } + + return gl::Error(GL_NO_ERROR); +} + +bool TextureD3D_3D::isValidLevel(int level) const +{ + return (mTexStorage ? (level >= 0 && level < mTexStorage->getLevelCount()) : 0); +} + +bool TextureD3D_3D::isLevelComplete(int level) const +{ + ASSERT(level >= 0 && level < (int)ArraySize(mImageArray) && mImageArray[level] != NULL); + + if (isImmutable()) + { + return true; + } + + GLsizei width = getBaseLevelWidth(); + GLsizei height = getBaseLevelHeight(); + GLsizei depth = getBaseLevelDepth(); + + if (width <= 0 || height <= 0 || depth <= 0) + { + return false; + } + + if (level == 0) + { + return true; + } + + ImageD3D *levelImage = mImageArray[level]; + + if (levelImage->getInternalFormat() != getBaseLevelInternalFormat()) + { + return false; + } + + if (levelImage->getWidth() != std::max(1, width >> level)) + { + return false; + } + + if (levelImage->getHeight() != std::max(1, height >> level)) + { + return false; + } + + if (levelImage->getDepth() != std::max(1, depth >> level)) + { + return false; + } + + return true; +} + +bool TextureD3D_3D::isImageComplete(const gl::ImageIndex &index) const +{ + return isLevelComplete(index.mipIndex); +} + +gl::Error TextureD3D_3D::updateStorageLevel(int level) +{ + ASSERT(level >= 0 && level < (int)ArraySize(mImageArray) && mImageArray[level] != NULL); + ASSERT(isLevelComplete(level)); + + if (mImageArray[level]->isDirty()) + { + gl::ImageIndex index = gl::ImageIndex::Make3D(level); + gl::Box region(0, 0, 0, getWidth(level), getHeight(level), getDepth(level)); + gl::Error error = commitRegion(index, region); + if (error.isError()) + { + return error; + } + } + + return gl::Error(GL_NO_ERROR); +} + +void TextureD3D_3D::redefineImage(GLint level, GLenum internalformat, const gl::Extents &size) +{ + // If there currently is a corresponding storage texture image, it has these parameters + const int storageWidth = std::max(1, getBaseLevelWidth() >> level); + const int storageHeight = std::max(1, getBaseLevelHeight() >> level); + const int storageDepth = std::max(1, getBaseLevelDepth() >> level); + const GLenum storageFormat = getBaseLevelInternalFormat(); + + mImageArray[level]->redefine(GL_TEXTURE_3D, internalformat, size, false); + + if (mTexStorage) + { + const int storageLevels = mTexStorage->getLevelCount(); + + if ((level >= storageLevels && storageLevels != 0) || + size.width != storageWidth || + size.height != storageHeight || + size.depth != storageDepth || + internalformat != storageFormat) // Discard mismatched storage + { + for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) + { + mImageArray[i]->markDirty(); + } + + SafeDelete(mTexStorage); + mDirtyImages = true; + } + } +} + +gl::ImageIndexIterator TextureD3D_3D::imageIterator() const +{ + return gl::ImageIndexIterator::Make3D(0, mTexStorage->getLevelCount(), + gl::ImageIndex::ENTIRE_LEVEL, gl::ImageIndex::ENTIRE_LEVEL); +} + +gl::ImageIndex TextureD3D_3D::getImageIndex(GLint mip, GLint /*layer*/) const +{ + // The "layer" here does not apply to 3D images. We use one Image per mip. + return gl::ImageIndex::Make3D(mip); +} + +bool TextureD3D_3D::isValidIndex(const gl::ImageIndex &index) const +{ + return (mTexStorage && index.type == GL_TEXTURE_3D && + index.mipIndex >= 0 && index.mipIndex < mTexStorage->getLevelCount()); +} + +TextureD3D_2DArray::TextureD3D_2DArray(RendererD3D *renderer) + : TextureD3D(renderer) +{ + for (int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++level) + { + mLayerCounts[level] = 0; + mImageArray[level] = NULL; + } +} + +TextureD3D_2DArray::~TextureD3D_2DArray() +{ + // Delete the Images before the TextureStorage. + // Images might be relying on the TextureStorage for some of their data. + // If TextureStorage is deleted before the Images, then their data will be wastefully copied back from the GPU before we delete the Images. + deleteImages(); + SafeDelete(mTexStorage); +} + +ImageD3D *TextureD3D_2DArray::getImage(int level, int layer) const +{ + ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + ASSERT((layer == 0 && mLayerCounts[level] == 0) || + layer < mLayerCounts[level]); + return (mImageArray[level] ? mImageArray[level][layer] : NULL); +} + +ImageD3D *TextureD3D_2DArray::getImage(const gl::ImageIndex &index) const +{ + ASSERT(index.mipIndex < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + ASSERT((index.layerIndex == 0 && mLayerCounts[index.mipIndex] == 0) || + index.layerIndex < mLayerCounts[index.mipIndex]); + ASSERT(index.type == GL_TEXTURE_2D_ARRAY); + return (mImageArray[index.mipIndex] ? mImageArray[index.mipIndex][index.layerIndex] : NULL); +} + +GLsizei TextureD3D_2DArray::getLayerCount(int level) const +{ + ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + return mLayerCounts[level]; +} + +GLsizei TextureD3D_2DArray::getWidth(GLint level) const +{ + return (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS && mLayerCounts[level] > 0) ? mImageArray[level][0]->getWidth() : 0; +} + +GLsizei TextureD3D_2DArray::getHeight(GLint level) const +{ + return (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS && mLayerCounts[level] > 0) ? mImageArray[level][0]->getHeight() : 0; +} + +GLenum TextureD3D_2DArray::getInternalFormat(GLint level) const +{ + return (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS && mLayerCounts[level] > 0) ? mImageArray[level][0]->getInternalFormat() : GL_NONE; +} + +bool TextureD3D_2DArray::isDepth(GLint level) const +{ + return gl::GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0; +} + +gl::Error TextureD3D_2DArray::setImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, GLenum format, GLenum type, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) +{ + ASSERT(target == GL_TEXTURE_2D_ARRAY); + + GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, type); + + redefineImage(level, sizedInternalFormat, size); + + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedInternalFormat); + GLsizei inputDepthPitch = formatInfo.computeDepthPitch(type, size.width, size.height, unpack.alignment, unpack.rowLength); + + for (int i = 0; i < size.depth; i++) + { + const ptrdiff_t layerOffset = (inputDepthPitch * i); + gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, i); + gl::Error error = TextureD3D::setImage(index, type, unpack, pixels, layerOffset); + if (error.isError()) + { + return error; + } + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureD3D_2DArray::setSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, GLenum type, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) +{ + ASSERT(target == GL_TEXTURE_2D_ARRAY); + + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(getInternalFormat(level)); + GLsizei inputDepthPitch = formatInfo.computeDepthPitch(type, area.width, area.height, unpack.alignment, unpack.rowLength); + + for (int i = 0; i < area.depth; i++) + { + int layer = area.z + i; + const ptrdiff_t layerOffset = (inputDepthPitch * i); + + gl::Box layerArea(area.x, area.y, 0, area.width, area.height, 1); + + gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, layer); + gl::Error error = TextureD3D::subImage(index, layerArea, format, type, unpack, pixels, layerOffset); + if (error.isError()) + { + return error; + } + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureD3D_2DArray::setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) +{ + ASSERT(target == GL_TEXTURE_2D_ARRAY); + + // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly + redefineImage(level, internalFormat, size); + + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat); + GLsizei inputDepthPitch = formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, size.width, size.height, 1, 0); + + for (int i = 0; i < size.depth; i++) + { + const ptrdiff_t layerOffset = (inputDepthPitch * i); + + gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, i); + gl::Error error = TextureD3D::setCompressedImage(index, unpack, pixels, layerOffset); + if (error.isError()) + { + return error; + } + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureD3D_2DArray::setCompressedSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) +{ + ASSERT(target == GL_TEXTURE_2D_ARRAY); + + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format); + GLsizei inputDepthPitch = formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, area.width, area.height, 1, 0); + + for (int i = 0; i < area.depth; i++) + { + int layer = area.z + i; + const ptrdiff_t layerOffset = (inputDepthPitch * i); + + gl::Box layerArea(area.x, area.y, 0, area.width, area.height, 1); + + gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, layer); + gl::Error error = TextureD3D::subImageCompressed(index, layerArea, format, unpack, pixels, layerOffset); + if (error.isError()) + { + return error; + } + + error = commitRegion(index, layerArea); + if (error.isError()) + { + return error; + } + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureD3D_2DArray::copyImage(GLenum target, size_t level, const gl::Rectangle &sourceArea, GLenum internalFormat, + const gl::Framebuffer *source) +{ + UNIMPLEMENTED(); + return gl::Error(GL_INVALID_OPERATION, "Copying 2D array textures is unimplemented."); +} + +gl::Error TextureD3D_2DArray::copySubImage(GLenum target, size_t level, const gl::Offset &destOffset, const gl::Rectangle &sourceArea, + const gl::Framebuffer *source) +{ + ASSERT(target == GL_TEXTURE_2D_ARRAY); + + gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, destOffset.z); + + if (canCreateRenderTargetForImage(index)) + { + gl::Offset destLayerOffset(destOffset.x, destOffset.y, 0); + gl::Error error = mImageArray[level][destOffset.z]->copy(destLayerOffset, sourceArea, source); + if (error.isError()) + { + return error; + } + + mDirtyImages = true; + } + else + { + gl::Error error = ensureRenderTarget(); + if (error.isError()) + { + return error; + } + + if (isValidLevel(level)) + { + error = updateStorageLevel(level); + if (error.isError()) + { + return error; + } + + error = mRenderer->copyImage2DArray(source, sourceArea, gl::GetInternalFormatInfo(getInternalFormat(0)).format, + destOffset, mTexStorage, level); + if (error.isError()) + { + return error; + } + } + } + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureD3D_2DArray::setStorage(GLenum target, size_t levels, GLenum internalFormat, const gl::Extents &size) +{ + ASSERT(target == GL_TEXTURE_2D_ARRAY); + + deleteImages(); + + for (size_t level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) + { + gl::Extents levelLayerSize(std::max(1, size.width >> level), + std::max(1, size.height >> level), + 1); + + mLayerCounts[level] = (level < levels ? size.depth : 0); + + if (mLayerCounts[level] > 0) + { + // Create new images for this level + mImageArray[level] = new ImageD3D*[mLayerCounts[level]]; + + for (int layer = 0; layer < mLayerCounts[level]; layer++) + { + mImageArray[level][layer] = mRenderer->createImage(); + mImageArray[level][layer]->redefine(GL_TEXTURE_2D_ARRAY, internalFormat, levelLayerSize, true); + } + } + } + + // TODO(geofflang): Verify storage creation had no errors + bool renderTarget = IsRenderTargetUsage(mUsage); + TextureStorage *storage = mRenderer->createTextureStorage2DArray(internalFormat, renderTarget, size.width, size.height, size.depth, levels); + + gl::Error error = setCompleteTexStorage(storage); + if (error.isError()) + { + SafeDelete(storage); + return error; + } + + error = updateStorage(); + + if (error.isError()) + { + return error; + } + + mImmutable = true; + + return gl::Error(GL_NO_ERROR); +} + +void TextureD3D_2DArray::bindTexImage(egl::Surface *surface) +{ + UNREACHABLE(); +} + +void TextureD3D_2DArray::releaseTexImage() +{ + UNREACHABLE(); +} + + +void TextureD3D_2DArray::initMipmapsImages() +{ + int baseWidth = getBaseLevelWidth(); + int baseHeight = getBaseLevelHeight(); + int baseDepth = getLayerCount(0); + GLenum baseFormat = getBaseLevelInternalFormat(); + + // Purge array levels 1 through q and reset them to represent the generated mipmap levels. + int levelCount = mipLevels(); + for (int level = 1; level < levelCount; level++) + { + gl::Extents levelLayerSize(std::max(baseWidth >> level, 1), + std::max(baseHeight >> level, 1), + baseDepth); + redefineImage(level, baseFormat, levelLayerSize); + } +} + +unsigned int TextureD3D_2DArray::getRenderTargetSerial(const gl::ImageIndex &index) +{ + return (!ensureRenderTarget().isError() ? mTexStorage->getRenderTargetSerial(index) : 0); +} + +gl::Error TextureD3D_2DArray::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) +{ + // ensure the underlying texture is created + gl::Error error = ensureRenderTarget(); + if (error.isError()) + { + return error; + } + + error = updateStorageLevel(index.mipIndex); + if (error.isError()) + { + return error; + } + + return mTexStorage->getRenderTarget(index, outRT); +} + +gl::Error TextureD3D_2DArray::initializeStorage(bool renderTarget) +{ + // Only initialize the first time this texture is used as a render target or shader resource + if (mTexStorage) + { + return gl::Error(GL_NO_ERROR); + } + + // do not attempt to create storage for nonexistant data + if (!isLevelComplete(0)) + { + return gl::Error(GL_NO_ERROR); + } + + bool createRenderTarget = (renderTarget || IsRenderTargetUsage(mUsage)); + + TextureStorage *storage = NULL; + gl::Error error = createCompleteStorage(createRenderTarget, &storage); + if (error.isError()) + { + return error; + } + + error = setCompleteTexStorage(storage); + if (error.isError()) + { + SafeDelete(storage); + return error; + } + + ASSERT(mTexStorage); + + // flush image data to the storage + error = updateStorage(); + if (error.isError()) + { + return error; + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureD3D_2DArray::createCompleteStorage(bool renderTarget, TextureStorage **outStorage) const +{ + GLsizei width = getBaseLevelWidth(); + GLsizei height = getBaseLevelHeight(); + GLsizei depth = getLayerCount(0); + GLenum internalFormat = getBaseLevelInternalFormat(); + + ASSERT(width > 0 && height > 0 && depth > 0); + + // use existing storage level count, when previously specified by TexStorage*D + GLint levels = (mTexStorage ? mTexStorage->getLevelCount() : creationLevels(width, height, 1)); + + // TODO(geofflang): Verify storage creation succeeds + *outStorage = mRenderer->createTextureStorage2DArray(internalFormat, renderTarget, width, height, depth, levels); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureD3D_2DArray::setCompleteTexStorage(TextureStorage *newCompleteTexStorage) +{ + SafeDelete(mTexStorage); + mTexStorage = newCompleteTexStorage; + mDirtyImages = true; + + // We do not support managed 2D array storage, as managed storage is ES2/D3D9 only + ASSERT(!mTexStorage->isManaged()); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureD3D_2DArray::updateStorage() +{ + ASSERT(mTexStorage != NULL); + GLint storageLevels = mTexStorage->getLevelCount(); + for (int level = 0; level < storageLevels; level++) + { + if (isLevelComplete(level)) + { + gl::Error error = updateStorageLevel(level); + if (error.isError()) + { + return error; + } + } + } + + return gl::Error(GL_NO_ERROR); +} + +bool TextureD3D_2DArray::isValidLevel(int level) const +{ + return (mTexStorage ? (level >= 0 && level < mTexStorage->getLevelCount()) : 0); +} + +bool TextureD3D_2DArray::isLevelComplete(int level) const +{ + ASSERT(level >= 0 && level < (int)ArraySize(mImageArray)); + + if (isImmutable()) + { + return true; + } + + GLsizei width = getBaseLevelWidth(); + GLsizei height = getBaseLevelHeight(); + GLsizei layers = getLayerCount(0); + + if (width <= 0 || height <= 0 || layers <= 0) + { + return false; + } + + if (level == 0) + { + return true; + } + + if (getInternalFormat(level) != getInternalFormat(0)) + { + return false; + } + + if (getWidth(level) != std::max(1, width >> level)) + { + return false; + } + + if (getHeight(level) != std::max(1, height >> level)) + { + return false; + } + + if (getLayerCount(level) != layers) + { + return false; + } + + return true; +} + +bool TextureD3D_2DArray::isImageComplete(const gl::ImageIndex &index) const +{ + return isLevelComplete(index.mipIndex); +} + +gl::Error TextureD3D_2DArray::updateStorageLevel(int level) +{ + ASSERT(level >= 0 && level < (int)ArraySize(mLayerCounts)); + ASSERT(isLevelComplete(level)); + + for (int layer = 0; layer < mLayerCounts[level]; layer++) + { + ASSERT(mImageArray[level] != NULL && mImageArray[level][layer] != NULL); + if (mImageArray[level][layer]->isDirty()) + { + gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, layer); + gl::Box region(0, 0, 0, getWidth(level), getHeight(level), 1); + gl::Error error = commitRegion(index, region); + if (error.isError()) + { + return error; + } + } + } + + return gl::Error(GL_NO_ERROR); +} + +void TextureD3D_2DArray::deleteImages() +{ + for (int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++level) + { + for (int layer = 0; layer < mLayerCounts[level]; ++layer) + { + delete mImageArray[level][layer]; + } + delete[] mImageArray[level]; + mImageArray[level] = NULL; + mLayerCounts[level] = 0; + } +} + +void TextureD3D_2DArray::redefineImage(GLint level, GLenum internalformat, const gl::Extents &size) +{ + // If there currently is a corresponding storage texture image, it has these parameters + const int storageWidth = std::max(1, getBaseLevelWidth() >> level); + const int storageHeight = std::max(1, getBaseLevelHeight() >> level); + const int storageDepth = getLayerCount(0); + const GLenum storageFormat = getBaseLevelInternalFormat(); + + for (int layer = 0; layer < mLayerCounts[level]; layer++) + { + delete mImageArray[level][layer]; + } + delete[] mImageArray[level]; + mImageArray[level] = NULL; + mLayerCounts[level] = size.depth; + + if (size.depth > 0) + { + mImageArray[level] = new ImageD3D*[size.depth](); + + for (int layer = 0; layer < mLayerCounts[level]; layer++) + { + mImageArray[level][layer] = mRenderer->createImage(); + mImageArray[level][layer]->redefine(GL_TEXTURE_2D_ARRAY, internalformat, + gl::Extents(size.width, size.height, 1), false); + } + } + + if (mTexStorage) + { + const int storageLevels = mTexStorage->getLevelCount(); + + if ((level >= storageLevels && storageLevels != 0) || + size.width != storageWidth || + size.height != storageHeight || + size.depth != storageDepth || + internalformat != storageFormat) // Discard mismatched storage + { + for (int dirtyLevel = 0; dirtyLevel < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; dirtyLevel++) + { + for (int dirtyLayer = 0; dirtyLayer < mLayerCounts[dirtyLevel]; dirtyLayer++) + { + mImageArray[dirtyLevel][dirtyLayer]->markDirty(); + } + } + + delete mTexStorage; + mTexStorage = NULL; + mDirtyImages = true; + } + } +} + +gl::ImageIndexIterator TextureD3D_2DArray::imageIterator() const +{ + return gl::ImageIndexIterator::Make2DArray(0, mTexStorage->getLevelCount(), mLayerCounts); +} + +gl::ImageIndex TextureD3D_2DArray::getImageIndex(GLint mip, GLint layer) const +{ + return gl::ImageIndex::Make2DArray(mip, layer); +} + +bool TextureD3D_2DArray::isValidIndex(const gl::ImageIndex &index) const +{ + // Check for having a storage and the right type of index + if (!mTexStorage || index.type != GL_TEXTURE_2D_ARRAY) + { + return false; + } + + // Check the mip index + if (index.mipIndex < 0 || index.mipIndex >= mTexStorage->getLevelCount()) + { + return false; + } + + // Check the layer index + return (!index.hasLayer() || (index.layerIndex >= 0 && index.layerIndex < mLayerCounts[index.mipIndex])); +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureD3D.h new file mode 100644 index 0000000000..d94be49a08 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureD3D.h @@ -0,0 +1,364 @@ +// +// Copyright 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// TextureD3D.h: Implementations of the Texture interfaces shared betweeen the D3D backends. + +#ifndef LIBANGLE_RENDERER_D3D_TEXTURED3D_H_ +#define LIBANGLE_RENDERER_D3D_TEXTURED3D_H_ + +#include "libANGLE/renderer/TextureImpl.h" +#include "libANGLE/angletypes.h" +#include "libANGLE/Constants.h" + +namespace gl +{ +class Framebuffer; +} + +namespace rx +{ + +class ImageD3D; +class ImageD3D; +class RendererD3D; +class RenderTargetD3D; +class TextureStorage; + +class TextureD3D : public TextureImpl +{ + public: + TextureD3D(RendererD3D *renderer); + virtual ~TextureD3D(); + + gl::Error getNativeTexture(TextureStorage **outStorage); + + virtual void setUsage(GLenum usage) { mUsage = usage; } + bool hasDirtyImages() const { return mDirtyImages; } + void resetDirty() { mDirtyImages = false; } + + virtual ImageD3D *getImage(const gl::ImageIndex &index) const = 0; + virtual GLsizei getLayerCount(int level) const = 0; + + GLint getBaseLevelWidth() const; + GLint getBaseLevelHeight() const; + GLint getBaseLevelDepth() const; + GLenum getBaseLevelInternalFormat() const; + + bool isImmutable() const { return mImmutable; } + + virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) = 0; + virtual unsigned int getRenderTargetSerial(const gl::ImageIndex &index) = 0; + + // Returns an iterator over all "Images" for this particular Texture. + virtual gl::ImageIndexIterator imageIterator() const = 0; + + // Returns an ImageIndex for a particular "Image". 3D Textures do not have images for + // slices of their depth texures, so 3D textures ignore the layer parameter. + virtual gl::ImageIndex getImageIndex(GLint mip, GLint layer) const = 0; + virtual bool isValidIndex(const gl::ImageIndex &index) const = 0; + + virtual gl::Error generateMipmaps(); + TextureStorage *getStorage(); + ImageD3D *getBaseLevelImage() const; + + protected: + gl::Error setImage(const gl::ImageIndex &index, GLenum type, + const gl::PixelUnpackState &unpack, const uint8_t *pixels, + ptrdiff_t layerOffset); + gl::Error subImage(const gl::ImageIndex &index, const gl::Box &area, GLenum format, GLenum type, + const gl::PixelUnpackState &unpack, const uint8_t *pixels, ptrdiff_t layerOffset); + gl::Error setCompressedImage(const gl::ImageIndex &index, const gl::PixelUnpackState &unpack, + const uint8_t *pixels, ptrdiff_t layerOffset); + gl::Error subImageCompressed(const gl::ImageIndex &index, const gl::Box &area, GLenum format, + const gl::PixelUnpackState &unpack, const uint8_t *pixels, ptrdiff_t layerOffset); + bool isFastUnpackable(const gl::PixelUnpackState &unpack, GLenum sizedInternalFormat); + gl::Error fastUnpackPixels(const gl::PixelUnpackState &unpack, const uint8_t *pixels, const gl::Box &destArea, + GLenum sizedInternalFormat, GLenum type, RenderTargetD3D *destRenderTarget); + + GLint creationLevels(GLsizei width, GLsizei height, GLsizei depth) const; + int mipLevels() const; + virtual void initMipmapsImages() = 0; + bool isBaseImageZeroSize() const; + virtual bool isImageComplete(const gl::ImageIndex &index) const = 0; + + bool canCreateRenderTargetForImage(const gl::ImageIndex &index) const; + virtual gl::Error ensureRenderTarget(); + + virtual gl::Error createCompleteStorage(bool renderTarget, TextureStorage **outTexStorage) const = 0; + virtual gl::Error setCompleteTexStorage(TextureStorage *newCompleteTexStorage) = 0; + gl::Error commitRegion(const gl::ImageIndex &index, const gl::Box ®ion); + + RendererD3D *mRenderer; + + GLenum mUsage; + + bool mDirtyImages; + + bool mImmutable; + TextureStorage *mTexStorage; + + private: + virtual gl::Error initializeStorage(bool renderTarget) = 0; + + virtual gl::Error updateStorage() = 0; + + bool shouldUseSetData(const ImageD3D *image) const; +}; + +class TextureD3D_2D : public TextureD3D +{ + public: + TextureD3D_2D(RendererD3D *renderer); + virtual ~TextureD3D_2D(); + + virtual ImageD3D *getImage(int level, int layer) const; + virtual ImageD3D *getImage(const gl::ImageIndex &index) const; + virtual GLsizei getLayerCount(int level) const; + + GLsizei getWidth(GLint level) const; + GLsizei getHeight(GLint level) const; + GLenum getInternalFormat(GLint level) const; + bool isDepth(GLint level) const; + + gl::Error setImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, GLenum format, GLenum type, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) override; + gl::Error setSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, GLenum type, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) override; + + gl::Error setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) override; + gl::Error setCompressedSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) override; + + gl::Error copyImage(GLenum target, size_t level, const gl::Rectangle &sourceArea, GLenum internalFormat, + const gl::Framebuffer *source) override; + gl::Error copySubImage(GLenum target, size_t level, const gl::Offset &destOffset, const gl::Rectangle &sourceArea, + const gl::Framebuffer *source) override; + + gl::Error setStorage(GLenum target, size_t levels, GLenum internalFormat, const gl::Extents &size) override; + + virtual void bindTexImage(egl::Surface *surface); + virtual void releaseTexImage(); + + virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT); + virtual unsigned int getRenderTargetSerial(const gl::ImageIndex &index); + + virtual gl::ImageIndexIterator imageIterator() const; + virtual gl::ImageIndex getImageIndex(GLint mip, GLint layer) const; + virtual bool isValidIndex(const gl::ImageIndex &index) const; + + private: + virtual gl::Error initializeStorage(bool renderTarget); + virtual gl::Error createCompleteStorage(bool renderTarget, TextureStorage **outTexStorage) const; + virtual gl::Error setCompleteTexStorage(TextureStorage *newCompleteTexStorage); + + virtual gl::Error updateStorage(); + virtual void initMipmapsImages(); + + bool isValidLevel(int level) const; + bool isLevelComplete(int level) const; + virtual bool isImageComplete(const gl::ImageIndex &index) const; + + gl::Error updateStorageLevel(int level); + + void redefineImage(GLint level, GLenum internalformat, const gl::Extents &size); + + ImageD3D *mImageArray[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; +}; + +class TextureD3D_Cube : public TextureD3D +{ + public: + TextureD3D_Cube(RendererD3D *renderer); + virtual ~TextureD3D_Cube(); + + virtual ImageD3D *getImage(int level, int layer) const; + virtual ImageD3D *getImage(const gl::ImageIndex &index) const; + virtual GLsizei getLayerCount(int level) const; + + virtual bool hasDirtyImages() const { return mDirtyImages; } + virtual void resetDirty() { mDirtyImages = false; } + virtual void setUsage(GLenum usage) { mUsage = usage; } + + GLenum getInternalFormat(GLint level, GLint layer) const; + bool isDepth(GLint level, GLint layer) const; + + gl::Error setImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, GLenum format, GLenum type, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) override; + gl::Error setSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, GLenum type, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) override; + + gl::Error setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) override; + gl::Error setCompressedSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) override; + + gl::Error copyImage(GLenum target, size_t level, const gl::Rectangle &sourceArea, GLenum internalFormat, + const gl::Framebuffer *source) override; + gl::Error copySubImage(GLenum target, size_t level, const gl::Offset &destOffset, const gl::Rectangle &sourceArea, + const gl::Framebuffer *source) override; + + gl::Error setStorage(GLenum target, size_t levels, GLenum internalFormat, const gl::Extents &size) override; + + virtual void bindTexImage(egl::Surface *surface); + virtual void releaseTexImage(); + + virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT); + virtual unsigned int getRenderTargetSerial(const gl::ImageIndex &index); + + virtual gl::ImageIndexIterator imageIterator() const; + virtual gl::ImageIndex getImageIndex(GLint mip, GLint layer) const; + virtual bool isValidIndex(const gl::ImageIndex &index) const; + + private: + virtual gl::Error initializeStorage(bool renderTarget); + virtual gl::Error createCompleteStorage(bool renderTarget, TextureStorage **outTexStorage) const; + virtual gl::Error setCompleteTexStorage(TextureStorage *newCompleteTexStorage); + + virtual gl::Error updateStorage(); + virtual void initMipmapsImages(); + + bool isValidFaceLevel(int faceIndex, int level) const; + bool isFaceLevelComplete(int faceIndex, int level) const; + bool isCubeComplete() const; + virtual bool isImageComplete(const gl::ImageIndex &index) const; + gl::Error updateStorageFaceLevel(int faceIndex, int level); + + void redefineImage(int faceIndex, GLint level, GLenum internalformat, const gl::Extents &size); + + ImageD3D *mImageArray[6][gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; +}; + +class TextureD3D_3D : public TextureD3D +{ + public: + TextureD3D_3D(RendererD3D *renderer); + virtual ~TextureD3D_3D(); + + virtual ImageD3D *getImage(int level, int layer) const; + virtual ImageD3D *getImage(const gl::ImageIndex &index) const; + virtual GLsizei getLayerCount(int level) const; + + GLsizei getWidth(GLint level) const; + GLsizei getHeight(GLint level) const; + GLsizei getDepth(GLint level) const; + GLenum getInternalFormat(GLint level) const; + bool isDepth(GLint level) const; + + gl::Error setImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, GLenum format, GLenum type, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) override; + gl::Error setSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, GLenum type, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) override; + + gl::Error setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) override; + gl::Error setCompressedSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) override; + + gl::Error copyImage(GLenum target, size_t level, const gl::Rectangle &sourceArea, GLenum internalFormat, + const gl::Framebuffer *source) override; + gl::Error copySubImage(GLenum target, size_t level, const gl::Offset &destOffset, const gl::Rectangle &sourceArea, + const gl::Framebuffer *source) override; + + gl::Error setStorage(GLenum target, size_t levels, GLenum internalFormat, const gl::Extents &size) override; + + virtual void bindTexImage(egl::Surface *surface); + virtual void releaseTexImage(); + + virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT); + virtual unsigned int getRenderTargetSerial(const gl::ImageIndex &index); + + virtual gl::ImageIndexIterator imageIterator() const; + virtual gl::ImageIndex getImageIndex(GLint mip, GLint layer) const; + virtual bool isValidIndex(const gl::ImageIndex &index) const; + + private: + virtual gl::Error initializeStorage(bool renderTarget); + virtual gl::Error createCompleteStorage(bool renderTarget, TextureStorage **outStorage) const; + virtual gl::Error setCompleteTexStorage(TextureStorage *newCompleteTexStorage); + + virtual gl::Error updateStorage(); + virtual void initMipmapsImages(); + + bool isValidLevel(int level) const; + bool isLevelComplete(int level) const; + virtual bool isImageComplete(const gl::ImageIndex &index) const; + gl::Error updateStorageLevel(int level); + + void redefineImage(GLint level, GLenum internalformat, const gl::Extents &size); + + ImageD3D *mImageArray[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; +}; + +class TextureD3D_2DArray : public TextureD3D +{ + public: + TextureD3D_2DArray(RendererD3D *renderer); + virtual ~TextureD3D_2DArray(); + + virtual ImageD3D *getImage(int level, int layer) const; + virtual ImageD3D *getImage(const gl::ImageIndex &index) const; + virtual GLsizei getLayerCount(int level) const; + + GLsizei getWidth(GLint level) const; + GLsizei getHeight(GLint level) const; + GLenum getInternalFormat(GLint level) const; + bool isDepth(GLint level) const; + + gl::Error setImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, GLenum format, GLenum type, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) override; + gl::Error setSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, GLenum type, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) override; + + gl::Error setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) override; + gl::Error setCompressedSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, + const gl::PixelUnpackState &unpack, const uint8_t *pixels) override; + + gl::Error copyImage(GLenum target, size_t level, const gl::Rectangle &sourceArea, GLenum internalFormat, + const gl::Framebuffer *source) override; + gl::Error copySubImage(GLenum target, size_t level, const gl::Offset &destOffset, const gl::Rectangle &sourceArea, + const gl::Framebuffer *source) override; + + gl::Error setStorage(GLenum target, size_t levels, GLenum internalFormat, const gl::Extents &size) override; + + virtual void bindTexImage(egl::Surface *surface); + virtual void releaseTexImage(); + + virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT); + virtual unsigned int getRenderTargetSerial(const gl::ImageIndex &index); + + virtual gl::ImageIndexIterator imageIterator() const; + virtual gl::ImageIndex getImageIndex(GLint mip, GLint layer) const; + virtual bool isValidIndex(const gl::ImageIndex &index) const; + + private: + virtual gl::Error initializeStorage(bool renderTarget); + virtual gl::Error createCompleteStorage(bool renderTarget, TextureStorage **outStorage) const; + virtual gl::Error setCompleteTexStorage(TextureStorage *newCompleteTexStorage); + + virtual gl::Error updateStorage(); + virtual void initMipmapsImages(); + + bool isValidLevel(int level) const; + bool isLevelComplete(int level) const; + virtual bool isImageComplete(const gl::ImageIndex &index) const; + gl::Error updateStorageLevel(int level); + + void deleteImages(); + void redefineImage(GLint level, GLenum internalformat, const gl::Extents &size); + + // Storing images as an array of single depth textures since D3D11 treats each array level of a + // Texture2D object as a separate subresource. Each layer would have to be looped over + // to update all the texture layers since they cannot all be updated at once and it makes the most + // sense for the Image class to not have to worry about layer subresource as well as mip subresources. + GLsizei mLayerCounts[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + ImageD3D **mImageArray[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_TEXTURED3D_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureStorage.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureStorage.cpp new file mode 100644 index 0000000000..abb83a14d5 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureStorage.cpp @@ -0,0 +1,39 @@ +// +// 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. +// + +// TextureStorage.cpp: Shared members of abstract rx::TextureStorage class. + +#include "libANGLE/renderer/d3d/TextureStorage.h" +#include "libANGLE/renderer/d3d/TextureD3D.h" +#include "libANGLE/renderer/d3d/RenderTargetD3D.h" +#include "libANGLE/renderer/Renderer.h" +#include "libANGLE/Renderbuffer.h" +#include "libANGLE/Texture.h" + +#include "common/debug.h" +#include "common/mathutil.h" + +namespace rx +{ + +TextureStorage::TextureStorage() + : mFirstRenderTargetSerial(0), + mRenderTargetSerialsLayerStride(0) +{} + +void TextureStorage::initializeSerials(unsigned int rtSerialsToReserve, unsigned int rtSerialsLayerStride) +{ + mFirstRenderTargetSerial = RenderTargetD3D::issueSerials(rtSerialsToReserve); + mRenderTargetSerialsLayerStride = rtSerialsLayerStride; +} + +unsigned int TextureStorage::getRenderTargetSerial(const gl::ImageIndex &index) const +{ + unsigned int layerOffset = (index.hasLayer() ? (static_cast(index.layerIndex) * mRenderTargetSerialsLayerStride) : 0); + return mFirstRenderTargetSerial + static_cast(index.mipIndex) + layerOffset; +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureStorage.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureStorage.h new file mode 100644 index 0000000000..ae2d42ca8a --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureStorage.h @@ -0,0 +1,67 @@ +// +// 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. +// + +// TextureStorage.h: Defines the abstract rx::TextureStorage class. + +#ifndef LIBANGLE_RENDERER_D3D_TEXTURESTORAGE_H_ +#define LIBANGLE_RENDERER_D3D_TEXTURESTORAGE_H_ + +#include "libANGLE/Error.h" + +#include "common/debug.h" +#include "libANGLE/Error.h" + +#include +#include + +namespace gl +{ +struct ImageIndex; +struct Box; +struct PixelUnpackState; +} + +namespace rx +{ +class SwapChainD3D; +class RenderTargetD3D; +class ImageD3D; + +class TextureStorage : angle::NonCopyable +{ + public: + TextureStorage(); + virtual ~TextureStorage() {}; + + virtual int getTopLevel() const = 0; + virtual bool isRenderTarget() const = 0; + virtual bool isManaged() const = 0; + virtual int getLevelCount() const = 0; + + virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) = 0; + virtual gl::Error generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex) = 0; + + virtual gl::Error copyToStorage(TextureStorage *destStorage) = 0; + virtual gl::Error setData(const gl::ImageIndex &index, ImageD3D *image, const gl::Box *destBox, GLenum type, + const gl::PixelUnpackState &unpack, const uint8_t *pixelData) = 0; + + unsigned int getRenderTargetSerial(const gl::ImageIndex &index) const; + unsigned int getTextureSerial() const; + + // This is a no-op for most implementations of TextureStorage. Some (e.g. TextureStorage11_2D) might override it. + virtual gl::Error useLevelZeroWorkaroundTexture(bool useLevelZeroTexture) { return gl::Error(GL_NO_ERROR); } + + protected: + void initializeSerials(unsigned int rtSerialsToReserve, unsigned int rtSerialsLayerStride); + + private: + unsigned int mFirstRenderTargetSerial; + unsigned int mRenderTargetSerialsLayerStride; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_TEXTURESTORAGE_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/TransformFeedbackD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/TransformFeedbackD3D.cpp new file mode 100644 index 0000000000..5c0bfdcd5b --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/TransformFeedbackD3D.cpp @@ -0,0 +1,38 @@ +// +// Copyright 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// TransformFeedbackD3D.cpp is a no-op implementation for both the D3D9 and D3D11 renderers. + +#include "libANGLE/renderer/d3d/TransformFeedbackD3D.h" + +namespace rx +{ + +TransformFeedbackD3D::TransformFeedbackD3D() +{ +} + +TransformFeedbackD3D::~TransformFeedbackD3D() +{ +} + +void TransformFeedbackD3D::begin(GLenum primitiveMode) +{ +} + +void TransformFeedbackD3D::end() +{ +} + +void TransformFeedbackD3D::pause() +{ +} + +void TransformFeedbackD3D::resume() +{ +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/TransformFeedbackD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/TransformFeedbackD3D.h new file mode 100644 index 0000000000..6b255b4a2b --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/TransformFeedbackD3D.h @@ -0,0 +1,32 @@ +// +// Copyright 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// TransformFeedbackD3D.h: Implements the abstract rx::TransformFeedbackImpl class. + +#ifndef LIBANGLE_RENDERER_D3D_TRANSFORMFEEDBACKD3D_H_ +#define LIBANGLE_RENDERER_D3D_TRANSFORMFEEDBACKD3D_H_ + +#include "libANGLE/renderer/TransformFeedbackImpl.h" +#include "libANGLE/angletypes.h" + +namespace rx +{ + +class TransformFeedbackD3D : public TransformFeedbackImpl +{ + public: + TransformFeedbackD3D(); + virtual ~TransformFeedbackD3D(); + + virtual void begin(GLenum primitiveMode); + virtual void end(); + virtual void pause(); + virtual void resume(); +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_TRANSFORMFEEDBACKD3D_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexBuffer.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexBuffer.cpp new file mode 100644 index 0000000000..19bd548fce --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexBuffer.cpp @@ -0,0 +1,311 @@ +// +// 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 "libANGLE/renderer/d3d/VertexBuffer.h" +#include "libANGLE/renderer/d3d/BufferD3D.h" +#include "libANGLE/renderer/d3d/RendererD3D.h" +#include "libANGLE/VertexAttribute.h" + +#include "common/mathutil.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(BufferFactoryD3D *factory, bool dynamic) + : mFactory(factory) +{ + mDynamic = dynamic; + mWritePosition = 0; + mReservedSpace = 0; + + mVertexBuffer = factory->createVertexBuffer(); +} + +VertexBufferInterface::~VertexBufferInterface() +{ + delete mVertexBuffer; +} + +unsigned int VertexBufferInterface::getSerial() const +{ + return mVertexBuffer->getSerial(); +} + +unsigned int VertexBufferInterface::getBufferSize() const +{ + return mVertexBuffer->getBufferSize(); +} + +gl::Error 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; +} + +gl::Error VertexBufferInterface::discard() +{ + return mVertexBuffer->discard(); +} + +gl::Error VertexBufferInterface::storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData ¤tValue, + GLint start, GLsizei count, GLsizei instances, unsigned int *outStreamOffset) +{ + gl::Error error(GL_NO_ERROR); + + unsigned int spaceRequired; + error = mVertexBuffer->getSpaceRequired(attrib, count, instances, &spaceRequired); + if (error.isError()) + { + return error; + } + + if (mWritePosition + spaceRequired < mWritePosition) + { + return gl::Error(GL_OUT_OF_MEMORY, "Internal error, new vertex buffer write position would overflow."); + } + + error = reserveSpace(mReservedSpace); + if (error.isError()) + { + return error; + } + mReservedSpace = 0; + + error = mVertexBuffer->storeVertexAttributes(attrib, currentValue, start, count, instances, mWritePosition); + if (error.isError()) + { + return error; + } + + if (outStreamOffset) + { + *outStreamOffset = mWritePosition; + } + + mWritePosition += spaceRequired; + + // Align to 16-byte boundary + mWritePosition = roundUp(mWritePosition, 16u); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error VertexBufferInterface::reserveVertexSpace(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances) +{ + gl::Error error(GL_NO_ERROR); + + unsigned int requiredSpace; + error = mVertexBuffer->getSpaceRequired(attrib, count, instances, &requiredSpace); + if (error.isError()) + { + return error; + } + + // Protect against integer overflow + if (mReservedSpace + requiredSpace < mReservedSpace) + { + return gl::Error(GL_OUT_OF_MEMORY, "Unable to reserve %u extra bytes in internal vertex buffer, " + "it would result in an overflow.", requiredSpace); + } + + mReservedSpace += requiredSpace; + + // Align to 16-byte boundary + mReservedSpace = roundUp(mReservedSpace, 16u); + + return gl::Error(GL_NO_ERROR); +} + +VertexBuffer* VertexBufferInterface::getVertexBuffer() const +{ + return mVertexBuffer; +} + +bool VertexBufferInterface::directStoragePossible(const gl::VertexAttribute &attrib, + const gl::VertexAttribCurrentValueData ¤tValue) const +{ + gl::Buffer *buffer = attrib.buffer.get(); + BufferD3D *storage = buffer ? GetImplAs(buffer) : NULL; + + if (!storage || !storage->supportsDirectBinding()) + { + return false; + } + + // Alignment restrictions: In D3D, vertex data must be aligned to + // the format stride, or to a 4-byte boundary, whichever is smaller. + // (Undocumented, and experimentally confirmed) + size_t alignment = 4; + bool requiresConversion = false; + + if (attrib.type != GL_FLOAT) + { + gl::VertexFormat vertexFormat(attrib, currentValue.Type); + + unsigned int outputElementSize; + getVertexBuffer()->getSpaceRequired(attrib, 1, 0, &outputElementSize); + alignment = std::min(outputElementSize, 4); + + // TODO(jmadill): add VertexFormatCaps + requiresConversion = (mFactory->getVertexConversionType(vertexFormat) & VERTEX_CONVERT_CPU) != 0; + } + + bool isAligned = (static_cast(ComputeVertexAttributeStride(attrib)) % alignment == 0) && + (static_cast(attrib.offset) % alignment == 0); + + return !requiresConversion && isAligned; +} + +StreamingVertexBufferInterface::StreamingVertexBufferInterface(BufferFactoryD3D *factory, std::size_t initialSize) + : VertexBufferInterface(factory, true) +{ + setBufferSize(initialSize); +} + +StreamingVertexBufferInterface::~StreamingVertexBufferInterface() +{ +} + +gl::Error StreamingVertexBufferInterface::reserveSpace(unsigned int size) +{ + unsigned int curBufferSize = getBufferSize(); + if (size > curBufferSize) + { + gl::Error error = setBufferSize(std::max(size, 3 * curBufferSize / 2)); + if (error.isError()) + { + return error; + } + setWritePosition(0); + } + else if (getWritePosition() + size > curBufferSize) + { + gl::Error error = discard(); + if (error.isError()) + { + return error; + } + setWritePosition(0); + } + + return gl::Error(GL_NO_ERROR); +} + +StaticVertexBufferInterface::StaticVertexBufferInterface(BufferFactoryD3D *factory) + : VertexBufferInterface(factory, false) +{ +} + +StaticVertexBufferInterface::~StaticVertexBufferInterface() +{ +} + +bool StaticVertexBufferInterface::lookupAttribute(const gl::VertexAttribute &attrib, unsigned int *outStreamOffset) +{ + for (unsigned int element = 0; element < mCache.size(); element++) + { + if (mCache[element].type == attrib.type && + mCache[element].size == attrib.size && + mCache[element].stride == ComputeVertexAttributeStride(attrib) && + mCache[element].normalized == attrib.normalized && + mCache[element].pureInteger == attrib.pureInteger) + { + size_t offset = (static_cast(attrib.offset) % ComputeVertexAttributeStride(attrib)); + if (mCache[element].attributeOffset == offset) + { + if (outStreamOffset) + { + *outStreamOffset = mCache[element].streamOffset; + } + return true; + } + } + } + + return false; +} + +gl::Error StaticVertexBufferInterface::reserveSpace(unsigned int size) +{ + unsigned int curSize = getBufferSize(); + if (curSize == 0) + { + return setBufferSize(size); + } + else if (curSize >= size) + { + return gl::Error(GL_NO_ERROR); + } + else + { + UNREACHABLE(); + return gl::Error(GL_INVALID_OPERATION, "Internal error, Static vertex buffers can't be resized."); + } +} + +gl::Error StaticVertexBufferInterface::storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData ¤tValue, + GLint start, GLsizei count, GLsizei instances, unsigned int *outStreamOffset) +{ + unsigned int streamOffset; + gl::Error error = VertexBufferInterface::storeVertexAttributes(attrib, currentValue, start, count, instances, &streamOffset); + if (error.isError()) + { + return error; + } + + size_t attributeOffset = static_cast(attrib.offset) % ComputeVertexAttributeStride(attrib); + VertexElement element = { attrib.type, attrib.size, static_cast(ComputeVertexAttributeStride(attrib)), attrib.normalized, attrib.pureInteger, attributeOffset, streamOffset }; + mCache.push_back(element); + + if (outStreamOffset) + { + *outStreamOffset = streamOffset; + } + + return gl::Error(GL_NO_ERROR); +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexBuffer.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexBuffer.h new file mode 100644 index 0000000000..5cb03fe3a1 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexBuffer.h @@ -0,0 +1,143 @@ +// +// 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 LIBANGLE_RENDERER_D3D_VERTEXBUFFER_H_ +#define LIBANGLE_RENDERER_D3D_VERTEXBUFFER_H_ + +#include "common/angleutils.h" +#include "libANGLE/Error.h" + +#include + +#include +#include + +namespace gl +{ +struct VertexAttribute; +struct VertexAttribCurrentValueData; +} + +namespace rx +{ +class BufferFactoryD3D; + +class VertexBuffer : angle::NonCopyable +{ + public: + VertexBuffer(); + virtual ~VertexBuffer(); + + virtual gl::Error initialize(unsigned int size, bool dynamicUsage) = 0; + + virtual gl::Error storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData ¤tValue, + GLint start, GLsizei count, GLsizei instances, unsigned int offset) = 0; + virtual gl::Error getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances, + unsigned int *outSpaceRequired) const = 0; + + virtual unsigned int getBufferSize() const = 0; + virtual gl::Error setBufferSize(unsigned int size) = 0; + virtual gl::Error discard() = 0; + + unsigned int getSerial() const; + + // This may be overridden (e.g. by VertexBuffer11) if necessary. + virtual void hintUnmapResource() { }; + + protected: + void updateSerial(); + + private: + unsigned int mSerial; + static unsigned int mNextSerial; +}; + +class VertexBufferInterface : angle::NonCopyable +{ + public: + VertexBufferInterface(BufferFactoryD3D *factory, bool dynamic); + virtual ~VertexBufferInterface(); + + gl::Error reserveVertexSpace(const gl::VertexAttribute &attribute, GLsizei count, GLsizei instances); + + unsigned int getBufferSize() const; + + unsigned int getSerial() const; + + virtual gl::Error storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData ¤tValue, + GLint start, GLsizei count, GLsizei instances, unsigned int *outStreamOffset); + + bool directStoragePossible(const gl::VertexAttribute &attrib, + const gl::VertexAttribCurrentValueData ¤tValue) const; + + VertexBuffer* getVertexBuffer() const; + + protected: + virtual gl::Error reserveSpace(unsigned int size) = 0; + + unsigned int getWritePosition() const; + void setWritePosition(unsigned int writePosition); + + gl::Error discard(); + + gl::Error setBufferSize(unsigned int size); + + private: + BufferFactoryD3D *const mFactory; + + VertexBuffer* mVertexBuffer; + + unsigned int mWritePosition; + unsigned int mReservedSpace; + bool mDynamic; +}; + +class StreamingVertexBufferInterface : public VertexBufferInterface +{ + public: + StreamingVertexBufferInterface(BufferFactoryD3D *factory, std::size_t initialSize); + ~StreamingVertexBufferInterface(); + + protected: + gl::Error reserveSpace(unsigned int size); +}; + +class StaticVertexBufferInterface : public VertexBufferInterface +{ + public: + explicit StaticVertexBufferInterface(BufferFactoryD3D *factory); + ~StaticVertexBufferInterface(); + + gl::Error storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData ¤tValue, + GLint start, GLsizei count, GLsizei instances, unsigned int *outStreamOffset); + + bool lookupAttribute(const gl::VertexAttribute &attribute, unsigned int* outStreamFffset); + + protected: + gl::Error reserveSpace(unsigned int size); + + private: + struct VertexElement + { + GLenum type; + GLuint size; + GLuint stride; + bool normalized; + bool pureInteger; + size_t attributeOffset; + + unsigned int streamOffset; + }; + + std::vector mCache; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_VERTEXBUFFER_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexDataManager.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexDataManager.cpp new file mode 100644 index 0000000000..cb70b9e4ef --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexDataManager.cpp @@ -0,0 +1,396 @@ +// +// 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 "libANGLE/renderer/d3d/VertexDataManager.h" + +#include "libANGLE/Buffer.h" +#include "libANGLE/Program.h" +#include "libANGLE/State.h" +#include "libANGLE/VertexAttribute.h" +#include "libANGLE/VertexArray.h" +#include "libANGLE/renderer/d3d/BufferD3D.h" +#include "libANGLE/renderer/d3d/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 &attrib, unsigned int size) +{ + // Size cannot be larger than a GLsizei + if (size > static_cast(std::numeric_limits::max())) + { + size = static_cast(std::numeric_limits::max()); + } + + GLsizei stride = ComputeVertexAttributeStride(attrib); + return (size - attrib.offset % stride + (stride - ComputeVertexAttributeTypeSize(attrib))) / stride; +} + +static int StreamingBufferElementCount(const gl::VertexAttribute &attrib, int vertexDrawCount, int instanceDrawCount) +{ + // For instanced rendering, we draw "instanceDrawCount" sets of "vertexDrawCount" vertices. + // + // A vertex attribute with a positive divisor loads one instanced vertex for every set of + // non-instanced vertices, and the instanced vertex index advances once every "mDivisor" instances. + if (instanceDrawCount > 0 && attrib.divisor > 0) + { + // When instanceDrawCount is not a multiple attrib.divisor, the division must round up. + // For instance, with 5 non-instanced vertices and a divisor equal to 3, we need 2 instanced vertices. + return (instanceDrawCount + attrib.divisor - 1) / attrib.divisor; + } + + return vertexDrawCount; +} + +VertexDataManager::VertexDataManager(BufferFactoryD3D *factory) + : mFactory(factory) +{ + for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + mCurrentValue[i].FloatValues[0] = std::numeric_limits::quiet_NaN(); + mCurrentValue[i].FloatValues[1] = std::numeric_limits::quiet_NaN(); + mCurrentValue[i].FloatValues[2] = std::numeric_limits::quiet_NaN(); + mCurrentValue[i].FloatValues[3] = std::numeric_limits::quiet_NaN(); + mCurrentValue[i].Type = GL_FLOAT; + mCurrentValueBuffer[i] = NULL; + mCurrentValueOffsets[i] = 0; + } + + mStreamingBuffer = new StreamingVertexBufferInterface(factory, 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]; + } +} + +void VertexDataManager::hintUnmapAllResources(const std::vector &vertexAttributes) +{ + mStreamingBuffer->getVertexBuffer()->hintUnmapResource(); + + for (size_t i = 0; i < vertexAttributes.size(); i++) + { + const gl::VertexAttribute &attrib = vertexAttributes[i]; + if (attrib.enabled) + { + gl::Buffer *buffer = attrib.buffer.get(); + BufferD3D *storage = buffer ? GetImplAs(buffer) : NULL; + StaticVertexBufferInterface *staticBuffer = storage ? storage->getStaticVertexBuffer() : NULL; + + if (staticBuffer) + { + staticBuffer->getVertexBuffer()->hintUnmapResource(); + } + } + } + + for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + if (mCurrentValueBuffer[i] != NULL) + { + mCurrentValueBuffer[i]->getVertexBuffer()->hintUnmapResource(); + } + } +} + +gl::Error VertexDataManager::prepareVertexData(const gl::State &state, GLint start, GLsizei count, + TranslatedAttribute *translated, GLsizei instances) +{ + if (!mStreamingBuffer) + { + return gl::Error(GL_OUT_OF_MEMORY, "Internal streaming vertex buffer is unexpectedly NULL."); + } + + const gl::VertexArray *vertexArray = state.getVertexArray(); + const std::vector &vertexAttributes = vertexArray->getVertexAttributes(); + + // Invalidate static buffers that don't contain matching attributes + for (int attributeIndex = 0; attributeIndex < gl::MAX_VERTEX_ATTRIBS; attributeIndex++) + { + translated[attributeIndex].active = (state.getProgram()->getSemanticIndex(attributeIndex) != -1); + if (translated[attributeIndex].active && vertexAttributes[attributeIndex].enabled) + { + invalidateMatchingStaticData(vertexAttributes[attributeIndex], state.getVertexAttribCurrentValue(attributeIndex)); + } + } + + // Reserve the required space in the buffers + for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + if (translated[i].active && vertexAttributes[i].enabled) + { + gl::Error error = reserveSpaceForAttrib(vertexAttributes[i], state.getVertexAttribCurrentValue(i), count, instances); + if (error.isError()) + { + return error; + } + } + } + + // Perform the vertex data translations + for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + const gl::VertexAttribute &curAttrib = vertexAttributes[i]; + if (translated[i].active) + { + if (curAttrib.enabled) + { + gl::Error error = storeAttribute(curAttrib, state.getVertexAttribCurrentValue(i), + &translated[i], start, count, instances); + + if (error.isError()) + { + hintUnmapAllResources(vertexAttributes); + return error; + } + } + else + { + if (!mCurrentValueBuffer[i]) + { + mCurrentValueBuffer[i] = new StreamingVertexBufferInterface(mFactory, CONSTANT_VERTEX_BUFFER_SIZE); + } + + gl::Error error = storeCurrentValue(curAttrib, state.getVertexAttribCurrentValue(i), &translated[i], + &mCurrentValue[i], &mCurrentValueOffsets[i], + mCurrentValueBuffer[i]); + if (error.isError()) + { + hintUnmapAllResources(vertexAttributes); + return error; + } + } + } + } + + // Hint to unmap all the resources + hintUnmapAllResources(vertexAttributes); + + for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + const gl::VertexAttribute &curAttrib = vertexAttributes[i]; + if (translated[i].active && curAttrib.enabled) + { + gl::Buffer *buffer = curAttrib.buffer.get(); + + if (buffer) + { + BufferD3D *bufferImpl = GetImplAs(buffer); + bufferImpl->promoteStaticUsage(count * ComputeVertexAttributeTypeSize(curAttrib)); + } + } + } + + return gl::Error(GL_NO_ERROR); +} + +void VertexDataManager::invalidateMatchingStaticData(const gl::VertexAttribute &attrib, + const gl::VertexAttribCurrentValueData ¤tValue) const +{ + gl::Buffer *buffer = attrib.buffer.get(); + + if (buffer) + { + BufferD3D *bufferImpl = GetImplAs(buffer); + StaticVertexBufferInterface *staticBuffer = bufferImpl->getStaticVertexBuffer(); + + if (staticBuffer && + staticBuffer->getBufferSize() > 0 && + !staticBuffer->lookupAttribute(attrib, NULL) && + !staticBuffer->directStoragePossible(attrib, currentValue)) + { + bufferImpl->invalidateStaticData(); + } + } +} + +gl::Error VertexDataManager::reserveSpaceForAttrib(const gl::VertexAttribute &attrib, + const gl::VertexAttribCurrentValueData ¤tValue, + GLsizei count, + GLsizei instances) const +{ + gl::Buffer *buffer = attrib.buffer.get(); + BufferD3D *bufferImpl = buffer ? GetImplAs(buffer) : NULL; + StaticVertexBufferInterface *staticBuffer = bufferImpl ? bufferImpl->getStaticVertexBuffer() : NULL; + VertexBufferInterface *vertexBuffer = staticBuffer ? staticBuffer : static_cast(mStreamingBuffer); + + if (!vertexBuffer->directStoragePossible(attrib, currentValue)) + { + if (staticBuffer) + { + if (staticBuffer->getBufferSize() == 0) + { + int totalCount = ElementsInBuffer(attrib, bufferImpl->getSize()); + gl::Error error = staticBuffer->reserveVertexSpace(attrib, totalCount, 0); + if (error.isError()) + { + return error; + } + } + } + else + { + int totalCount = StreamingBufferElementCount(attrib, count, instances); + ASSERT(!bufferImpl || ElementsInBuffer(attrib, bufferImpl->getSize()) >= totalCount); + + gl::Error error = mStreamingBuffer->reserveVertexSpace(attrib, totalCount, instances); + if (error.isError()) + { + return error; + } + } + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error VertexDataManager::storeAttribute(const gl::VertexAttribute &attrib, + const gl::VertexAttribCurrentValueData ¤tValue, + TranslatedAttribute *translated, + GLint start, + GLsizei count, + GLsizei instances) +{ + gl::Buffer *buffer = attrib.buffer.get(); + ASSERT(buffer || attrib.pointer); + + BufferD3D *storage = buffer ? GetImplAs(buffer) : NULL; + StaticVertexBufferInterface *staticBuffer = storage ? storage->getStaticVertexBuffer() : NULL; + VertexBufferInterface *vertexBuffer = staticBuffer ? staticBuffer : static_cast(mStreamingBuffer); + bool directStorage = vertexBuffer->directStoragePossible(attrib, currentValue); + + unsigned int streamOffset = 0; + unsigned int outputElementSize = 0; + + // Instanced vertices do not apply the 'start' offset + GLint firstVertexIndex = (instances > 0 && attrib.divisor > 0 ? 0 : start); + + if (directStorage) + { + outputElementSize = ComputeVertexAttributeStride(attrib); + streamOffset = attrib.offset + outputElementSize * firstVertexIndex; + } + else if (staticBuffer) + { + gl::Error error = staticBuffer->getVertexBuffer()->getSpaceRequired(attrib, 1, 0, &outputElementSize); + if (error.isError()) + { + return error; + } + + if (!staticBuffer->lookupAttribute(attrib, &streamOffset)) + { + // Convert the entire buffer + int totalCount = ElementsInBuffer(attrib, storage->getSize()); + int startIndex = attrib.offset / ComputeVertexAttributeStride(attrib); + + error = staticBuffer->storeVertexAttributes(attrib, currentValue, -startIndex, totalCount, + 0, &streamOffset); + if (error.isError()) + { + return error; + } + } + + unsigned int firstElementOffset = (attrib.offset / ComputeVertexAttributeStride(attrib)) * outputElementSize; + unsigned int startOffset = (instances == 0 || attrib.divisor == 0) ? firstVertexIndex * outputElementSize : 0; + if (streamOffset + firstElementOffset + startOffset < streamOffset) + { + return gl::Error(GL_OUT_OF_MEMORY); + } + + streamOffset += firstElementOffset + startOffset; + } + else + { + int totalCount = StreamingBufferElementCount(attrib, count, instances); + gl::Error error = mStreamingBuffer->getVertexBuffer()->getSpaceRequired(attrib, 1, 0, &outputElementSize); + if (error.isError()) + { + return error; + } + + error = mStreamingBuffer->storeVertexAttributes(attrib, currentValue, firstVertexIndex, + totalCount, instances, &streamOffset); + if (error.isError()) + { + return error; + } + } + + translated->storage = directStorage ? storage : NULL; + translated->vertexBuffer = vertexBuffer->getVertexBuffer(); + translated->serial = directStorage ? storage->getSerial() : vertexBuffer->getSerial(); + translated->divisor = attrib.divisor; + + translated->attribute = &attrib; + translated->currentValueType = currentValue.Type; + translated->stride = outputElementSize; + translated->offset = streamOffset; + + return gl::Error(GL_NO_ERROR); +} + +gl::Error VertexDataManager::storeCurrentValue(const gl::VertexAttribute &attrib, + const gl::VertexAttribCurrentValueData ¤tValue, + TranslatedAttribute *translated, + gl::VertexAttribCurrentValueData *cachedValue, + size_t *cachedOffset, + StreamingVertexBufferInterface *buffer) +{ + if (*cachedValue != currentValue) + { + gl::Error error = buffer->reserveVertexSpace(attrib, 1, 0); + if (error.isError()) + { + return error; + } + + unsigned int streamOffset; + error = buffer->storeVertexAttributes(attrib, currentValue, 0, 1, 0, &streamOffset); + if (error.isError()) + { + return error; + } + + *cachedValue = currentValue; + *cachedOffset = streamOffset; + } + + translated->storage = NULL; + translated->vertexBuffer = buffer->getVertexBuffer(); + translated->serial = buffer->getSerial(); + translated->divisor = 0; + + translated->attribute = &attrib; + translated->currentValueType = currentValue.Type; + translated->stride = 0; + translated->offset = *cachedOffset; + + return gl::Error(GL_NO_ERROR); +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexDataManager.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexDataManager.h new file mode 100644 index 0000000000..898ed340b8 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexDataManager.h @@ -0,0 +1,95 @@ +// +// 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 LIBANGLE_RENDERER_D3D_VERTEXDATAMANAGER_H_ +#define LIBANGLE_RENDERER_D3D_VERTEXDATAMANAGER_H_ + +#include "libANGLE/Constants.h" +#include "libANGLE/VertexAttribute.h" +#include "common/angleutils.h" + +namespace gl +{ +class State; +struct VertexAttribute; +struct VertexAttribCurrentValueData; +} + +namespace rx +{ +class BufferD3D; +class BufferFactoryD3D; +class StreamingVertexBufferInterface; +class VertexBuffer; + +struct TranslatedAttribute +{ + TranslatedAttribute() : active(false), attribute(NULL), currentValueType(GL_NONE), + offset(0), stride(0), vertexBuffer(NULL), storage(NULL), + serial(0), divisor(0) {}; + bool active; + + const gl::VertexAttribute *attribute; + GLenum currentValueType; + unsigned int offset; + unsigned int stride; // 0 means not to advance the read pointer at all + + VertexBuffer *vertexBuffer; + BufferD3D *storage; + unsigned int serial; + unsigned int divisor; +}; + +class VertexDataManager : angle::NonCopyable +{ + public: + VertexDataManager(BufferFactoryD3D *factory); + virtual ~VertexDataManager(); + + gl::Error prepareVertexData(const gl::State &state, GLint start, GLsizei count, + TranslatedAttribute *outAttribs, GLsizei instances); + + private: + gl::Error reserveSpaceForAttrib(const gl::VertexAttribute &attrib, + const gl::VertexAttribCurrentValueData ¤tValue, + GLsizei count, + GLsizei instances) const; + + void invalidateMatchingStaticData(const gl::VertexAttribute &attrib, + const gl::VertexAttribCurrentValueData ¤tValue) const; + + gl::Error storeAttribute(const gl::VertexAttribute &attrib, + const gl::VertexAttribCurrentValueData ¤tValue, + TranslatedAttribute *translated, + GLint start, + GLsizei count, + GLsizei instances); + + gl::Error storeCurrentValue(const gl::VertexAttribute &attrib, + const gl::VertexAttribCurrentValueData ¤tValue, + TranslatedAttribute *translated, + gl::VertexAttribCurrentValueData *cachedValue, + size_t *cachedOffset, + StreamingVertexBufferInterface *buffer); + + void hintUnmapAllResources(const std::vector &vertexAttributes); + + BufferFactoryD3D *const mFactory; + + StreamingVertexBufferInterface *mStreamingBuffer; + + gl::VertexAttribCurrentValueData mCurrentValue[gl::MAX_VERTEX_ATTRIBS]; + + StreamingVertexBufferInterface *mCurrentValueBuffer[gl::MAX_VERTEX_ATTRIBS]; + std::size_t mCurrentValueOffsets[gl::MAX_VERTEX_ATTRIBS]; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_VERTEXDATAMANAGER_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/copyimage.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/copyimage.cpp new file mode 100644 index 0000000000..b1798454ca --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/copyimage.cpp @@ -0,0 +1,22 @@ +// +// 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. +// + +// copyimage.cpp: Defines image copying functions + +#include "libANGLE/renderer/d3d/copyimage.h" + +namespace rx +{ + +void CopyBGRA8ToRGBA8(const uint8_t *source, uint8_t *dest) +{ + uint32_t argb = *reinterpret_cast(source); + *reinterpret_cast(dest) = (argb & 0xFF00FF00) | // Keep alpha and green + (argb & 0x00FF0000) >> 16 | // Move red to blue + (argb & 0x000000FF) << 16; // Move blue to red +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/copyimage.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/copyimage.h new file mode 100644 index 0000000000..189654ca39 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/copyimage.h @@ -0,0 +1,35 @@ +// +// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// copyimage.h: Defines image copying functions + +#ifndef LIBANGLE_RENDERER_D3D_COPYIMAGE_H_ +#define LIBANGLE_RENDERER_D3D_COPYIMAGE_H_ + +#include "common/mathutil.h" +#include "libANGLE/angletypes.h" + +#include + +namespace rx +{ + +template +void ReadColor(const uint8_t *source, uint8_t *dest); + +template +void WriteColor(const uint8_t *source, uint8_t *dest); + +template +void CopyPixel(const uint8_t *source, uint8_t *dest); + +void CopyBGRA8ToRGBA8(const uint8_t *source, uint8_t *dest); + +} + +#include "copyimage.inl" + +#endif // LIBANGLE_RENDERER_D3D_COPYIMAGE_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/copyimage.inl b/src/3rdparty/angle/src/libANGLE/renderer/d3d/copyimage.inl new file mode 100644 index 0000000000..0498cf7750 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/copyimage.inl @@ -0,0 +1,32 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// copyimage.inl: Defines image copying functions + +namespace rx +{ + +template +inline void ReadColor(const uint8_t *source, uint8_t *dest) +{ + sourceType::readColor(reinterpret_cast*>(dest), reinterpret_cast(source)); +} + +template +inline void WriteColor(const uint8_t *source, uint8_t *dest) +{ + destType::writeColor(reinterpret_cast(dest), reinterpret_cast*>(source)); +} + +template +inline void CopyPixel(const uint8_t *source, uint8_t *dest) +{ + colorDataType temp; + ReadColor(source, &temp); + WriteColor(&temp, dest); +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.cpp new file mode 100644 index 0000000000..e38b61709f --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.cpp @@ -0,0 +1,1059 @@ +// +// 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. +// + +// Blit11.cpp: Texture copy utility class. + +#include "libANGLE/renderer/d3d/d3d11/Blit11.h" + +#include + +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" +#include "libANGLE/renderer/d3d/d3d11/formatutils11.h" +#include "libANGLE/formatutils.h" + +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough2d11vs.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughdepth2d11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2d11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dui11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2di11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2d11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2dui11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2di11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2d11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2dui11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2di11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2d11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2dui11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2di11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlum2d11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha2d11ps.h" + +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough3d11vs.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough3d11gs.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3d11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3dui11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3di11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3d11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3dui11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3di11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3d11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3dui11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3di11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3d11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3dui11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3di11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlum3d11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha3d11ps.h" + +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef2dps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei2dps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui2dps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef3dps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei3dps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui3dps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef2darrayps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei2darrayps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui2darrayps.h" + +namespace rx +{ + +static DXGI_FORMAT GetTextureFormat(ID3D11Resource *resource) +{ + ID3D11Texture2D *texture = d3d11::DynamicCastComObject(resource); + if (!texture) + { + return DXGI_FORMAT_UNKNOWN; + } + + D3D11_TEXTURE2D_DESC desc; + texture->GetDesc(&desc); + + SafeRelease(texture); + + return desc.Format; +} + +static ID3D11Resource *CreateStagingTexture(ID3D11Device *device, ID3D11DeviceContext *context, + ID3D11Resource *source, unsigned int subresource, + const gl::Extents &size, unsigned int cpuAccessFlags) +{ + D3D11_TEXTURE2D_DESC stagingDesc; + stagingDesc.Width = size.width; + stagingDesc.Height = size.height; + stagingDesc.MipLevels = 1; + stagingDesc.ArraySize = 1; + stagingDesc.Format = GetTextureFormat(source); + stagingDesc.SampleDesc.Count = 1; + stagingDesc.SampleDesc.Quality = 0; + stagingDesc.Usage = D3D11_USAGE_STAGING; + stagingDesc.CPUAccessFlags = cpuAccessFlags; + stagingDesc.MiscFlags = 0; + stagingDesc.BindFlags = 0; + + ID3D11Texture2D *stagingTexture = NULL; + HRESULT result = device->CreateTexture2D(&stagingDesc, NULL, &stagingTexture); + if (FAILED(result)) + { + ERR("Failed to create staging texture for depth stencil blit. HRESULT: 0x%X.", result); + return NULL; + } + + context->CopySubresourceRegion(stagingTexture, 0, 0, 0, 0, source, subresource, NULL); + + return stagingTexture; +} + +inline static void GenerateVertexCoords(const gl::Box &sourceArea, const gl::Extents &sourceSize, + const gl::Box &destArea, const gl::Extents &destSize, + float *x1, float *y1, float *x2, float *y2, + float *u1, float *v1, float *u2, float *v2) +{ + *x1 = (destArea.x / float(destSize.width)) * 2.0f - 1.0f; + *y1 = ((destSize.height - destArea.y - destArea.height) / float(destSize.height)) * 2.0f - 1.0f; + *x2 = ((destArea.x + destArea.width) / float(destSize.width)) * 2.0f - 1.0f; + *y2 = ((destSize.height - destArea.y) / float(destSize.height)) * 2.0f - 1.0f; + + *u1 = sourceArea.x / float(sourceSize.width); + *v1 = sourceArea.y / float(sourceSize.height); + *u2 = (sourceArea.x + sourceArea.width) / float(sourceSize.width); + *v2 = (sourceArea.y + sourceArea.height) / float(sourceSize.height); +} + +static void Write2DVertices(const gl::Box &sourceArea, const gl::Extents &sourceSize, + const gl::Box &destArea, const gl::Extents &destSize, + void *outVertices, unsigned int *outStride, unsigned int *outVertexCount, + D3D11_PRIMITIVE_TOPOLOGY *outTopology) +{ + float x1, y1, x2, y2, u1, v1, u2, v2; + GenerateVertexCoords(sourceArea, sourceSize, destArea, destSize, &x1, &y1, &x2, &y2, &u1, &v1, &u2, &v2); + + d3d11::PositionTexCoordVertex *vertices = static_cast(outVertices); + + 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); + + *outStride = sizeof(d3d11::PositionTexCoordVertex); + *outVertexCount = 4; + *outTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP; +} + +static void Write3DVertices(const gl::Box &sourceArea, const gl::Extents &sourceSize, + const gl::Box &destArea, const gl::Extents &destSize, + void *outVertices, unsigned int *outStride, unsigned int *outVertexCount, + D3D11_PRIMITIVE_TOPOLOGY *outTopology) +{ + ASSERT(sourceSize.depth > 0 && destSize.depth > 0); + + float x1, y1, x2, y2, u1, v1, u2, v2; + GenerateVertexCoords(sourceArea, sourceSize, destArea, destSize, &x1, &y1, &x2, &y2, &u1, &v1, &u2, &v2); + + d3d11::PositionLayerTexCoord3DVertex *vertices = static_cast(outVertices); + + for (int i = 0; i < destSize.depth; i++) + { + float readDepth = (float)i / std::max(destSize.depth - 1, 1); + + d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 0], x1, y1, i, u1, v2, readDepth); + d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 1], x1, y2, i, u1, v1, readDepth); + d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 2], x2, y1, i, u2, v2, readDepth); + + d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 3], x1, y2, i, u1, v1, readDepth); + d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 4], x2, y2, i, u2, v1, readDepth); + d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 5], x2, y1, i, u2, v2, readDepth); + } + + *outStride = sizeof(d3d11::PositionLayerTexCoord3DVertex); + *outVertexCount = destSize.depth * 6; + *outTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; +} + +Blit11::Blit11(Renderer11 *renderer) + : mRenderer(renderer), mBlitShaderMap(compareBlitParameters), mSwizzleShaderMap(compareSwizzleParameters), + mVertexBuffer(NULL), mPointSampler(NULL), mLinearSampler(NULL), mScissorEnabledRasterizerState(NULL), + mScissorDisabledRasterizerState(NULL), mDepthStencilState(NULL), + mQuad2DIL(NULL), mQuad2DVS(NULL), mDepthPS(NULL), + mQuad3DIL(NULL), mQuad3DVS(NULL), mQuad3DGS(NULL), + mSwizzleCB(NULL) +{ + HRESULT result; + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_BUFFER_DESC vbDesc; + vbDesc.ByteWidth = std::max(sizeof(d3d11::PositionLayerTexCoord3DVertex), sizeof(d3d11::PositionTexCoordVertex)) * + 6 * renderer->getRendererCaps().max3DTextureSize; + vbDesc.Usage = D3D11_USAGE_DYNAMIC; + vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + vbDesc.MiscFlags = 0; + vbDesc.StructureByteStride = 0; + + result = device->CreateBuffer(&vbDesc, NULL, &mVertexBuffer); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mVertexBuffer, "Blit11 vertex buffer"); + + D3D11_SAMPLER_DESC pointSamplerDesc; + pointSamplerDesc.Filter = D3D11_FILTER_MIN_MAG_POINT_MIP_LINEAR; + pointSamplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP; + pointSamplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; + pointSamplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; + pointSamplerDesc.MipLODBias = 0.0f; + pointSamplerDesc.MaxAnisotropy = 0; + pointSamplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER; + pointSamplerDesc.BorderColor[0] = 0.0f; + pointSamplerDesc.BorderColor[1] = 0.0f; + pointSamplerDesc.BorderColor[2] = 0.0f; + pointSamplerDesc.BorderColor[3] = 0.0f; + pointSamplerDesc.MinLOD = 0.0f; + pointSamplerDesc.MaxLOD = FLT_MAX; + + result = device->CreateSamplerState(&pointSamplerDesc, &mPointSampler); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mPointSampler, "Blit11 point sampler"); + + D3D11_SAMPLER_DESC linearSamplerDesc; + linearSamplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + linearSamplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP; + linearSamplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; + linearSamplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; + linearSamplerDesc.MipLODBias = 0.0f; + linearSamplerDesc.MaxAnisotropy = 0; + linearSamplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER; + linearSamplerDesc.BorderColor[0] = 0.0f; + linearSamplerDesc.BorderColor[1] = 0.0f; + linearSamplerDesc.BorderColor[2] = 0.0f; + linearSamplerDesc.BorderColor[3] = 0.0f; + linearSamplerDesc.MinLOD = 0.0f; + linearSamplerDesc.MaxLOD = FLT_MAX; + + result = device->CreateSamplerState(&linearSamplerDesc, &mLinearSampler); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mLinearSampler, "Blit11 linear sampler"); + + // Use a rasterizer state that will not cull so that inverted quads will not be culled + D3D11_RASTERIZER_DESC rasterDesc; + rasterDesc.FillMode = D3D11_FILL_SOLID; + rasterDesc.CullMode = D3D11_CULL_NONE; + rasterDesc.FrontCounterClockwise = FALSE; + rasterDesc.DepthBias = 0; + rasterDesc.SlopeScaledDepthBias = 0.0f; + rasterDesc.DepthBiasClamp = 0.0f; + rasterDesc.DepthClipEnable = TRUE; + rasterDesc.MultisampleEnable = FALSE; + rasterDesc.AntialiasedLineEnable = FALSE; + + rasterDesc.ScissorEnable = TRUE; + result = device->CreateRasterizerState(&rasterDesc, &mScissorEnabledRasterizerState); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mScissorEnabledRasterizerState, "Blit11 scissoring rasterizer state"); + + rasterDesc.ScissorEnable = FALSE; + result = device->CreateRasterizerState(&rasterDesc, &mScissorDisabledRasterizerState); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mScissorDisabledRasterizerState, "Blit11 no scissoring rasterizer state"); + + D3D11_DEPTH_STENCIL_DESC depthStencilDesc; + depthStencilDesc.DepthEnable = true; + depthStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; + depthStencilDesc.DepthFunc = D3D11_COMPARISON_ALWAYS; + depthStencilDesc.StencilEnable = FALSE; + depthStencilDesc.StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK; + depthStencilDesc.StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK; + depthStencilDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; + depthStencilDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP; + depthStencilDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; + depthStencilDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS; + depthStencilDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; + depthStencilDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP; + depthStencilDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; + depthStencilDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS; + + result = device->CreateDepthStencilState(&depthStencilDesc, &mDepthStencilState); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mDepthStencilState, "Blit11 depth stencil state"); + + D3D11_INPUT_ELEMENT_DESC quad2DLayout[] = + { + { "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(quad2DLayout, ArraySize(quad2DLayout), g_VS_Passthrough2D, ArraySize(g_VS_Passthrough2D), &mQuad2DIL); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mQuad2DIL, "Blit11 2D input layout"); + + result = device->CreateVertexShader(g_VS_Passthrough2D, ArraySize(g_VS_Passthrough2D), NULL, &mQuad2DVS); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mQuad2DVS, "Blit11 2D vertex shader"); + + if (renderer->isES3Capable()) + { + result = device->CreatePixelShader(g_PS_PassthroughDepth2D, ArraySize(g_PS_PassthroughDepth2D), NULL, &mDepthPS); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mDepthPS, "Blit11 2D depth pixel shader"); + + D3D11_INPUT_ELEMENT_DESC quad3DLayout[] = + { + { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "LAYER", 0, DXGI_FORMAT_R32_UINT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "TEXCOORD", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + }; + + result = device->CreateInputLayout(quad3DLayout, ArraySize(quad3DLayout), g_VS_Passthrough3D, ArraySize(g_VS_Passthrough3D), &mQuad3DIL); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mQuad3DIL, "Blit11 3D input layout"); + + result = device->CreateVertexShader(g_VS_Passthrough3D, ArraySize(g_VS_Passthrough3D), NULL, &mQuad3DVS); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mQuad3DVS, "Blit11 3D vertex shader"); + + result = device->CreateGeometryShader(g_GS_Passthrough3D, ArraySize(g_GS_Passthrough3D), NULL, &mQuad3DGS); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mQuad3DGS, "Renderer11 copy 3D texture geometry shader"); + } + + buildShaderMap(); + + D3D11_BUFFER_DESC swizzleBufferDesc; + swizzleBufferDesc.ByteWidth = sizeof(unsigned int) * 4; + swizzleBufferDesc.Usage = D3D11_USAGE_DYNAMIC; + swizzleBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + swizzleBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + swizzleBufferDesc.MiscFlags = 0; + swizzleBufferDesc.StructureByteStride = 0; + + result = device->CreateBuffer(&swizzleBufferDesc, NULL, &mSwizzleCB); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mSwizzleCB, "Blit11 swizzle constant buffer"); +} + +Blit11::~Blit11() +{ + SafeRelease(mVertexBuffer); + SafeRelease(mPointSampler); + SafeRelease(mLinearSampler); + SafeRelease(mScissorEnabledRasterizerState); + SafeRelease(mScissorDisabledRasterizerState); + SafeRelease(mDepthStencilState); + + SafeRelease(mQuad2DIL); + SafeRelease(mQuad2DVS); + SafeRelease(mDepthPS); + + SafeRelease(mQuad3DIL); + SafeRelease(mQuad3DVS); + SafeRelease(mQuad3DGS); + + SafeRelease(mSwizzleCB); + + clearShaderMap(); +} + +static inline unsigned int GetSwizzleIndex(GLenum swizzle) +{ + unsigned int colorIndex = 0; + + switch (swizzle) + { + case GL_RED: colorIndex = 0; break; + case GL_GREEN: colorIndex = 1; break; + case GL_BLUE: colorIndex = 2; break; + case GL_ALPHA: colorIndex = 3; break; + case GL_ZERO: colorIndex = 4; break; + case GL_ONE: colorIndex = 5; break; + default: UNREACHABLE(); break; + } + + return colorIndex; +} + +gl::Error Blit11::swizzleTexture(ID3D11ShaderResourceView *source, ID3D11RenderTargetView *dest, const gl::Extents &size, + GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha) +{ + HRESULT result; + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + + D3D11_SHADER_RESOURCE_VIEW_DESC sourceSRVDesc; + source->GetDesc(&sourceSRVDesc); + + const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(sourceSRVDesc.Format); + const gl::InternalFormat &sourceFormatInfo = gl::GetInternalFormatInfo(dxgiFormatInfo.internalFormat); + + GLenum shaderType = GL_NONE; + switch (sourceFormatInfo.componentType) + { + case GL_UNSIGNED_NORMALIZED: + case GL_SIGNED_NORMALIZED: + case GL_FLOAT: + shaderType = GL_FLOAT; + break; + case GL_INT: + shaderType = GL_INT; + break; + case GL_UNSIGNED_INT: + shaderType = GL_UNSIGNED_INT; + break; + default: + UNREACHABLE(); + break; + } + + SwizzleParameters parameters = { 0 }; + parameters.mDestinationType = shaderType; + parameters.mViewDimension = sourceSRVDesc.ViewDimension; + + SwizzleShaderMap::const_iterator i = mSwizzleShaderMap.find(parameters); + if (i == mSwizzleShaderMap.end()) + { + UNREACHABLE(); + return gl::Error(GL_INVALID_OPERATION, "Internal error, missing swizzle shader."); + } + + const Shader &shader = i->second; + + // Set vertices + D3D11_MAPPED_SUBRESOURCE mappedResource; + result = deviceContext->Map(mVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal vertex buffer for swizzle, HRESULT: 0x%X.", result); + } + + UINT stride = 0; + UINT startIdx = 0; + UINT drawCount = 0; + D3D11_PRIMITIVE_TOPOLOGY topology; + + gl::Box area(0, 0, 0, size.width, size.height, size.depth); + shader.mVertexWriteFunction(area, size, area, size, mappedResource.pData, &stride, &drawCount, &topology); + + deviceContext->Unmap(mVertexBuffer, 0); + + // Set constant buffer + result = deviceContext->Map(mSwizzleCB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal constant buffer for swizzle, HRESULT: 0x%X.", result); + } + + unsigned int *swizzleIndices = reinterpret_cast(mappedResource.pData); + swizzleIndices[0] = GetSwizzleIndex(swizzleRed); + swizzleIndices[1] = GetSwizzleIndex(swizzleGreen); + swizzleIndices[2] = GetSwizzleIndex(swizzleBlue); + swizzleIndices[3] = GetSwizzleIndex(swizzleAlpha); + + deviceContext->Unmap(mSwizzleCB, 0); + + // Apply vertex buffer + deviceContext->IASetVertexBuffers(0, 1, &mVertexBuffer, &stride, &startIdx); + + // Apply constant buffer + deviceContext->PSSetConstantBuffers(0, 1, &mSwizzleCB); + + // Apply state + deviceContext->OMSetBlendState(NULL, NULL, 0xFFFFFFF); + deviceContext->OMSetDepthStencilState(NULL, 0xFFFFFFFF); + deviceContext->RSSetState(mScissorDisabledRasterizerState); + + // Apply shaders + deviceContext->IASetInputLayout(shader.mInputLayout); + deviceContext->IASetPrimitiveTopology(topology); + deviceContext->VSSetShader(shader.mVertexShader, NULL, 0); + + deviceContext->PSSetShader(shader.mPixelShader, NULL, 0); + deviceContext->GSSetShader(shader.mGeometryShader, NULL, 0); + + // Unset the currently bound shader resource to avoid conflicts + mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, NULL); + + // Apply render target + mRenderer->setOneTimeRenderTarget(dest); + + // Set the viewport + D3D11_VIEWPORT viewport; + viewport.TopLeftX = 0; + viewport.TopLeftY = 0; + viewport.Width = size.width; + viewport.Height = size.height; + viewport.MinDepth = 0.0f; + viewport.MaxDepth = 1.0f; + deviceContext->RSSetViewports(1, &viewport); + + // Apply textures + mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, source); + + // Apply samplers + deviceContext->PSSetSamplers(0, 1, &mPointSampler); + + // Draw the quad + deviceContext->Draw(drawCount, 0); + + // Unbind textures and render targets and vertex buffer + mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, NULL); + + mRenderer->unapplyRenderTargets(); + + UINT zero = 0; + ID3D11Buffer *const nullBuffer = NULL; + deviceContext->IASetVertexBuffers(0, 1, &nullBuffer, &zero, &zero); + + mRenderer->markAllStateDirty(); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Blit11::copyTexture(ID3D11ShaderResourceView *source, const gl::Box &sourceArea, const gl::Extents &sourceSize, + ID3D11RenderTargetView *dest, const gl::Box &destArea, const gl::Extents &destSize, + const gl::Rectangle *scissor, GLenum destFormat, GLenum filter) +{ + HRESULT result; + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + + // Determine if the source format is a signed integer format, the destFormat will already + // be GL_XXXX_INTEGER but it does not tell us if it is signed or unsigned. + D3D11_SHADER_RESOURCE_VIEW_DESC sourceSRVDesc; + source->GetDesc(&sourceSRVDesc); + + const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(sourceSRVDesc.Format); + const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(dxgiFormatInfo.internalFormat); + + BlitParameters parameters = { 0 }; + parameters.mDestinationFormat = destFormat; + parameters.mSignedInteger = (internalFormatInfo.componentType == GL_INT); + parameters.m3DBlit = sourceSRVDesc.ViewDimension == D3D11_SRV_DIMENSION_TEXTURE3D; + + BlitShaderMap::const_iterator i = mBlitShaderMap.find(parameters); + if (i == mBlitShaderMap.end()) + { + UNREACHABLE(); + return gl::Error(GL_OUT_OF_MEMORY, "Could not find appropriate shader for internal texture blit."); + } + + const Shader& shader = i->second; + + // Set vertices + D3D11_MAPPED_SUBRESOURCE mappedResource; + result = deviceContext->Map(mVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal vertex buffer for texture copy, HRESULT: 0x%X.", result); + } + + UINT stride = 0; + UINT startIdx = 0; + UINT drawCount = 0; + D3D11_PRIMITIVE_TOPOLOGY topology; + + shader.mVertexWriteFunction(sourceArea, sourceSize, destArea, destSize, mappedResource.pData, + &stride, &drawCount, &topology); + + deviceContext->Unmap(mVertexBuffer, 0); + + // Apply vertex buffer + deviceContext->IASetVertexBuffers(0, 1, &mVertexBuffer, &stride, &startIdx); + + // Apply state + deviceContext->OMSetBlendState(NULL, NULL, 0xFFFFFFF); + deviceContext->OMSetDepthStencilState(NULL, 0xFFFFFFFF); + + if (scissor) + { + D3D11_RECT scissorRect; + scissorRect.left = scissor->x; + scissorRect.right = scissor->x + scissor->width; + scissorRect.top = scissor->y; + scissorRect.bottom = scissor->y + scissor->height; + + deviceContext->RSSetScissorRects(1, &scissorRect); + deviceContext->RSSetState(mScissorEnabledRasterizerState); + } + else + { + deviceContext->RSSetState(mScissorDisabledRasterizerState); + } + + // Apply shaders + deviceContext->IASetInputLayout(shader.mInputLayout); + deviceContext->IASetPrimitiveTopology(topology); + deviceContext->VSSetShader(shader.mVertexShader, NULL, 0); + + deviceContext->PSSetShader(shader.mPixelShader, NULL, 0); + deviceContext->GSSetShader(shader.mGeometryShader, NULL, 0); + + // Unset the currently bound shader resource to avoid conflicts + mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, NULL); + + // Apply render target + mRenderer->setOneTimeRenderTarget(dest); + + // Set the viewport + D3D11_VIEWPORT viewport; + viewport.TopLeftX = 0; + viewport.TopLeftY = 0; + viewport.Width = destSize.width; + viewport.Height = destSize.height; + viewport.MinDepth = 0.0f; + viewport.MaxDepth = 1.0f; + deviceContext->RSSetViewports(1, &viewport); + + // Apply textures + mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, source); + + // Apply samplers + ID3D11SamplerState *sampler = NULL; + switch (filter) + { + case GL_NEAREST: sampler = mPointSampler; break; + case GL_LINEAR: sampler = mLinearSampler; break; + + default: + UNREACHABLE(); + return gl::Error(GL_OUT_OF_MEMORY, "Internal error, unknown blit filter mode."); + } + deviceContext->PSSetSamplers(0, 1, &sampler); + + // Draw the quad + deviceContext->Draw(drawCount, 0); + + // Unbind textures and render targets and vertex buffer + mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, NULL); + + mRenderer->unapplyRenderTargets(); + + UINT zero = 0; + ID3D11Buffer *const nullBuffer = NULL; + deviceContext->IASetVertexBuffers(0, 1, &nullBuffer, &zero, &zero); + + mRenderer->markAllStateDirty(); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Blit11::copyStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize, + ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize, + const gl::Rectangle *scissor) +{ + return copyDepthStencil(source, sourceSubresource, sourceArea, sourceSize, + dest, destSubresource, destArea, destSize, + scissor, true); +} + +gl::Error Blit11::copyDepth(ID3D11ShaderResourceView *source, const gl::Box &sourceArea, const gl::Extents &sourceSize, + ID3D11DepthStencilView *dest, const gl::Box &destArea, const gl::Extents &destSize, + const gl::Rectangle *scissor) +{ + HRESULT result; + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + + // Set vertices + D3D11_MAPPED_SUBRESOURCE mappedResource; + result = deviceContext->Map(mVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal vertex buffer for texture copy, HRESULT: 0x%X.", result); + } + + UINT stride = 0; + UINT startIdx = 0; + UINT drawCount = 0; + D3D11_PRIMITIVE_TOPOLOGY topology; + + Write2DVertices(sourceArea, sourceSize, destArea, destSize, mappedResource.pData, + &stride, &drawCount, &topology); + + deviceContext->Unmap(mVertexBuffer, 0); + + // Apply vertex buffer + deviceContext->IASetVertexBuffers(0, 1, &mVertexBuffer, &stride, &startIdx); + + // Apply state + deviceContext->OMSetBlendState(NULL, NULL, 0xFFFFFFF); + deviceContext->OMSetDepthStencilState(mDepthStencilState, 0xFFFFFFFF); + + if (scissor) + { + D3D11_RECT scissorRect; + scissorRect.left = scissor->x; + scissorRect.right = scissor->x + scissor->width; + scissorRect.top = scissor->y; + scissorRect.bottom = scissor->y + scissor->height; + + deviceContext->RSSetScissorRects(1, &scissorRect); + deviceContext->RSSetState(mScissorEnabledRasterizerState); + } + else + { + deviceContext->RSSetState(mScissorDisabledRasterizerState); + } + + // Apply shaders + deviceContext->IASetInputLayout(mQuad2DIL); + deviceContext->IASetPrimitiveTopology(topology); + deviceContext->VSSetShader(mQuad2DVS, NULL, 0); + + deviceContext->PSSetShader(mDepthPS, NULL, 0); + deviceContext->GSSetShader(NULL, NULL, 0); + + // Unset the currently bound shader resource to avoid conflicts + mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, NULL); + + // Apply render target + deviceContext->OMSetRenderTargets(0, NULL, dest); + + // Set the viewport + D3D11_VIEWPORT viewport; + viewport.TopLeftX = 0; + viewport.TopLeftY = 0; + viewport.Width = destSize.width; + viewport.Height = destSize.height; + viewport.MinDepth = 0.0f; + viewport.MaxDepth = 1.0f; + deviceContext->RSSetViewports(1, &viewport); + + // Apply textures + mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, source); + + // Apply samplers + deviceContext->PSSetSamplers(0, 1, &mPointSampler); + + // Draw the quad + deviceContext->Draw(drawCount, 0); + + // Unbind textures and render targets and vertex buffer + mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, NULL); + + mRenderer->unapplyRenderTargets(); + + UINT zero = 0; + ID3D11Buffer *const nullBuffer = NULL; + deviceContext->IASetVertexBuffers(0, 1, &nullBuffer, &zero, &zero); + + mRenderer->markAllStateDirty(); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Blit11::copyDepthStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize, + ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize, + const gl::Rectangle *scissor) +{ + return copyDepthStencil(source, sourceSubresource, sourceArea, sourceSize, + dest, destSubresource, destArea, destSize, + scissor, false); +} + +gl::Error Blit11::copyDepthStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize, + ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize, + const gl::Rectangle *scissor, bool stencilOnly) +{ + ID3D11Device *device = mRenderer->getDevice(); + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + + ID3D11Resource *sourceStaging = CreateStagingTexture(device, deviceContext, source, sourceSubresource, sourceSize, D3D11_CPU_ACCESS_READ); + // HACK: Create the destination staging buffer as a read/write texture so ID3D11DevicContext::UpdateSubresource can be called + // using it's mapped data as a source + ID3D11Resource *destStaging = CreateStagingTexture(device, deviceContext, dest, destSubresource, destSize, D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE); + + if (!sourceStaging || !destStaging) + { + SafeRelease(sourceStaging); + SafeRelease(destStaging); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal staging textures for depth stencil blit."); + } + + DXGI_FORMAT format = GetTextureFormat(source); + ASSERT(format == GetTextureFormat(dest)); + + const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(format); + unsigned int pixelSize = dxgiFormatInfo.pixelBytes; + unsigned int copyOffset = 0; + unsigned int copySize = pixelSize; + if (stencilOnly) + { + copyOffset = dxgiFormatInfo.depthBits / 8; + copySize = dxgiFormatInfo.stencilBits / 8; + + // It would be expensive to have non-byte sized stencil sizes since it would + // require reading from the destination, currently there aren't any though. + ASSERT(dxgiFormatInfo.stencilBits % 8 == 0 && + dxgiFormatInfo.depthBits % 8 == 0); + } + + D3D11_MAPPED_SUBRESOURCE sourceMapping; + HRESULT result = deviceContext->Map(sourceStaging, 0, D3D11_MAP_READ, 0, &sourceMapping); + if (FAILED(result)) + { + SafeRelease(sourceStaging); + SafeRelease(destStaging); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal source staging texture for depth stencil blit, HRESULT: 0x%X.", result); + } + + D3D11_MAPPED_SUBRESOURCE destMapping; + result = deviceContext->Map(destStaging, 0, D3D11_MAP_WRITE, 0, &destMapping); + if (FAILED(result)) + { + deviceContext->Unmap(sourceStaging, 0); + SafeRelease(sourceStaging); + SafeRelease(destStaging); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal destination staging texture for depth stencil blit, HRESULT: 0x%X.", result); + } + + gl::Rectangle clippedDestArea(destArea.x, destArea.y, destArea.width, destArea.height); + + // Clip dest area to the destination size + gl::ClipRectangle(clippedDestArea, gl::Rectangle(0, 0, destSize.width, destSize.height), &clippedDestArea); + + // Clip dest area to the scissor + if (scissor) + { + gl::ClipRectangle(clippedDestArea, *scissor, &clippedDestArea); + } + + // Determine if entire rows can be copied at once instead of each individual pixel, requires that there is + // no out of bounds lookups required, the entire pixel is copied and no stretching + bool wholeRowCopy = sourceArea.width == clippedDestArea.width && + sourceArea.x >= 0 && sourceArea.x + sourceArea.width <= sourceSize.width && + copySize == pixelSize; + + for (int y = clippedDestArea.y; y < clippedDestArea.y + clippedDestArea.height; y++) + { + float yPerc = static_cast(y - destArea.y) / (destArea.height - 1); + + // Interpolate using the original source rectangle to determine which row to sample from while clamping to the edges + unsigned int readRow = gl::clamp(sourceArea.y + floor(yPerc * (sourceArea.height - 1) + 0.5f), 0, sourceSize.height - 1); + unsigned int writeRow = y; + + if (wholeRowCopy) + { + void *sourceRow = reinterpret_cast(sourceMapping.pData) + + readRow * sourceMapping.RowPitch + + sourceArea.x * pixelSize; + + void *destRow = reinterpret_cast(destMapping.pData) + + writeRow * destMapping.RowPitch + + destArea.x * pixelSize; + + memcpy(destRow, sourceRow, pixelSize * destArea.width); + } + else + { + for (int x = clippedDestArea.x; x < clippedDestArea.x + clippedDestArea.width; x++) + { + float xPerc = static_cast(x - destArea.x) / (destArea.width - 1); + + // Interpolate the original source rectangle to determine which column to sample from while clamping to the edges + unsigned int readColumn = gl::clamp(sourceArea.x + floor(xPerc * (sourceArea.width - 1) + 0.5f), 0, sourceSize.width - 1); + unsigned int writeColumn = x; + + void *sourcePixel = reinterpret_cast(sourceMapping.pData) + + readRow * sourceMapping.RowPitch + + readColumn * pixelSize + + copyOffset; + + void *destPixel = reinterpret_cast(destMapping.pData) + + writeRow * destMapping.RowPitch + + writeColumn * pixelSize + + copyOffset; + + memcpy(destPixel, sourcePixel, copySize); + } + } + } + + // HACK: Use ID3D11DevicContext::UpdateSubresource which causes an extra copy compared to ID3D11DevicContext::CopySubresourceRegion + // according to MSDN. + deviceContext->UpdateSubresource(dest, destSubresource, NULL, destMapping.pData, destMapping.RowPitch, destMapping.DepthPitch); + + deviceContext->Unmap(sourceStaging, 0); + deviceContext->Unmap(destStaging, 0); + + // TODO: Determine why this call to ID3D11DevicContext::CopySubresourceRegion causes a TDR timeout on some + // systems when called repeatedly. + // deviceContext->CopySubresourceRegion(dest, destSubresource, 0, 0, 0, destStaging, 0, NULL); + + SafeRelease(sourceStaging); + SafeRelease(destStaging); + + return gl::Error(GL_NO_ERROR); +} + +bool Blit11::compareBlitParameters(const Blit11::BlitParameters &a, const Blit11::BlitParameters &b) +{ + return memcmp(&a, &b, sizeof(Blit11::BlitParameters)) < 0; +} + +bool Blit11::compareSwizzleParameters(const SwizzleParameters &a, const SwizzleParameters &b) +{ + return memcmp(&a, &b, sizeof(Blit11::SwizzleParameters)) < 0; +} + +void Blit11::add2DBlitShaderToMap(GLenum destFormat, bool signedInteger, ID3D11PixelShader *ps) +{ + BlitParameters params = { 0 }; + params.mDestinationFormat = destFormat; + params.mSignedInteger = signedInteger; + params.m3DBlit = false; + + ASSERT(mBlitShaderMap.find(params) == mBlitShaderMap.end()); + ASSERT(ps); + + Shader shader; + shader.mVertexWriteFunction = Write2DVertices; + shader.mInputLayout = mQuad2DIL; + shader.mVertexShader = mQuad2DVS; + shader.mGeometryShader = NULL; + shader.mPixelShader = ps; + + mBlitShaderMap[params] = shader; +} + +void Blit11::add3DBlitShaderToMap(GLenum destFormat, bool signedInteger, ID3D11PixelShader *ps) +{ + BlitParameters params = { 0 }; + params.mDestinationFormat = destFormat; + params.mSignedInteger = signedInteger; + params.m3DBlit = true; + + ASSERT(mBlitShaderMap.find(params) == mBlitShaderMap.end()); + ASSERT(ps); + + Shader shader; + shader.mVertexWriteFunction = Write3DVertices; + shader.mInputLayout = mQuad3DIL; + shader.mVertexShader = mQuad3DVS; + shader.mGeometryShader = mQuad3DGS; + shader.mPixelShader = ps; + + mBlitShaderMap[params] = shader; +} + +void Blit11::addSwizzleShaderToMap(GLenum destType, D3D11_SRV_DIMENSION viewDimension, ID3D11PixelShader *ps) +{ + SwizzleParameters params = { 0 }; + params.mDestinationType = destType; + params.mViewDimension = viewDimension; + + ASSERT(mSwizzleShaderMap.find(params) == mSwizzleShaderMap.end()); + ASSERT(ps); + + Shader shader; + switch (viewDimension) + { + case D3D_SRV_DIMENSION_TEXTURE2D: + shader.mVertexWriteFunction = Write2DVertices; + shader.mInputLayout = mQuad2DIL; + shader.mVertexShader = mQuad2DVS; + shader.mGeometryShader = NULL; + break; + + case D3D_SRV_DIMENSION_TEXTURE3D: + case D3D_SRV_DIMENSION_TEXTURE2DARRAY: + case D3D_SRV_DIMENSION_TEXTURECUBE: + shader.mVertexWriteFunction = Write3DVertices; + shader.mInputLayout = mQuad3DIL; + shader.mVertexShader = mQuad3DVS; + shader.mGeometryShader = mQuad3DGS; + break; + + default: + UNREACHABLE(); + break; + } + shader.mPixelShader = ps; + + mSwizzleShaderMap[params] = shader; +} + +void Blit11::buildShaderMap() +{ + ID3D11Device *device = mRenderer->getDevice(); + + // 2D shaders (OpenGL ES 2+) + add2DBlitShaderToMap(GL_RGBA, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA2D, "Blit11 2D RGBA pixel shader" )); + add2DBlitShaderToMap(GL_BGRA_EXT, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA2D, "Blit11 2D BGRA pixel shader" )); + add2DBlitShaderToMap(GL_RGB, false, d3d11::CompilePS(device, g_PS_PassthroughRGB2D, "Blit11 2D RGB pixel shader" )); + add2DBlitShaderToMap(GL_RG, false, d3d11::CompilePS(device, g_PS_PassthroughRG2D, "Blit11 2D RG pixel shader" )); + add2DBlitShaderToMap(GL_RED, false, d3d11::CompilePS(device, g_PS_PassthroughR2D, "Blit11 2D R pixel shader" )); + add2DBlitShaderToMap(GL_ALPHA, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA2D, "Blit11 2D alpha pixel shader" )); + add2DBlitShaderToMap(GL_LUMINANCE, false, d3d11::CompilePS(device, g_PS_PassthroughLum2D, "Blit11 2D lum pixel shader" )); + add2DBlitShaderToMap(GL_LUMINANCE_ALPHA, false, d3d11::CompilePS(device, g_PS_PassthroughLumAlpha2D, "Blit11 2D luminance alpha pixel shader")); + + // 2D shaders (OpenGL ES 3+) + if (mRenderer->isES3Capable()) + { + add2DBlitShaderToMap(GL_RGBA_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA2DUI, "Blit11 2D RGBA UI pixel shader" )); + add2DBlitShaderToMap(GL_RGBA_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughRGBA2DI, "Blit11 2D RGBA I pixel shader" )); + add2DBlitShaderToMap(GL_RGB_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughRGB2DUI, "Blit11 2D RGB UI pixel shader" )); + add2DBlitShaderToMap(GL_RGB_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughRGB2DI, "Blit11 2D RGB I pixel shader" )); + add2DBlitShaderToMap(GL_RG_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughRG2DUI, "Blit11 2D RG UI pixel shader" )); + add2DBlitShaderToMap(GL_RG_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughRG2DI, "Blit11 2D RG I pixel shader" )); + add2DBlitShaderToMap(GL_RED_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughR2DUI, "Blit11 2D R UI pixel shader" )); + add2DBlitShaderToMap(GL_RED_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughR2DI, "Blit11 2D R I pixel shader" )); + } + + // 3D shaders (OpenGL ES 3+) + if (mRenderer->isES3Capable()) + { + add3DBlitShaderToMap(GL_RGBA, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA3D, "Blit11 3D RGBA pixel shader" )); + add3DBlitShaderToMap(GL_RGBA_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA3DUI, "Blit11 3D UI RGBA pixel shader" )); + add3DBlitShaderToMap(GL_RGBA_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughRGBA3DI, "Blit11 3D I RGBA pixel shader" )); + add3DBlitShaderToMap(GL_BGRA_EXT, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA3D, "Blit11 3D BGRA pixel shader" )); + add3DBlitShaderToMap(GL_RGB, false, d3d11::CompilePS(device, g_PS_PassthroughRGB3D, "Blit11 3D RGB pixel shader" )); + add3DBlitShaderToMap(GL_RGB_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughRGB3DUI, "Blit11 3D RGB UI pixel shader" )); + add3DBlitShaderToMap(GL_RGB_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughRGB3DI, "Blit11 3D RGB I pixel shader" )); + add3DBlitShaderToMap(GL_RG, false, d3d11::CompilePS(device, g_PS_PassthroughRG3D, "Blit11 3D RG pixel shader" )); + add3DBlitShaderToMap(GL_RG_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughRG3DUI, "Blit11 3D RG UI pixel shader" )); + add3DBlitShaderToMap(GL_RG_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughRG3DI, "Blit11 3D RG I pixel shader" )); + add3DBlitShaderToMap(GL_RED, false, d3d11::CompilePS(device, g_PS_PassthroughR3D, "Blit11 3D R pixel shader" )); + add3DBlitShaderToMap(GL_RED_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughR3DUI, "Blit11 3D R UI pixel shader" )); + add3DBlitShaderToMap(GL_RED_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughR3DI, "Blit11 3D R I pixel shader" )); + add3DBlitShaderToMap(GL_ALPHA, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA3D, "Blit11 3D alpha pixel shader" )); + add3DBlitShaderToMap(GL_LUMINANCE, false, d3d11::CompilePS(device, g_PS_PassthroughLum3D, "Blit11 3D luminance pixel shader" )); + add3DBlitShaderToMap(GL_LUMINANCE_ALPHA, false, d3d11::CompilePS(device, g_PS_PassthroughLumAlpha3D, "Blit11 3D luminance alpha pixel shader")); + } + + // Swizzling shaders (OpenGL ES 3+) + if (mRenderer->isES3Capable()) + { + addSwizzleShaderToMap(GL_FLOAT, D3D_SRV_DIMENSION_TEXTURE2D, d3d11::CompilePS(device, g_PS_SwizzleF2D, "Blit11 2D F swizzle pixel shader" )); + addSwizzleShaderToMap(GL_UNSIGNED_INT, D3D_SRV_DIMENSION_TEXTURE2D, d3d11::CompilePS(device, g_PS_SwizzleUI2D, "Blit11 2D UI swizzle pixel shader")); + addSwizzleShaderToMap(GL_INT, D3D_SRV_DIMENSION_TEXTURE2D, d3d11::CompilePS(device, g_PS_SwizzleI2D, "Blit11 2D I swizzle pixel shader" )); + + addSwizzleShaderToMap(GL_FLOAT, D3D_SRV_DIMENSION_TEXTURECUBE, d3d11::CompilePS(device, g_PS_SwizzleF2DArray, "Blit11 2D Cube F swizzle pixel shader" )); + addSwizzleShaderToMap(GL_UNSIGNED_INT, D3D_SRV_DIMENSION_TEXTURECUBE, d3d11::CompilePS(device, g_PS_SwizzleUI2DArray, "Blit11 2D Cube UI swizzle pixel shader")); + addSwizzleShaderToMap(GL_INT, D3D_SRV_DIMENSION_TEXTURECUBE, d3d11::CompilePS(device, g_PS_SwizzleI2DArray, "Blit11 2D Cube I swizzle pixel shader" )); + + addSwizzleShaderToMap(GL_FLOAT, D3D_SRV_DIMENSION_TEXTURE3D, d3d11::CompilePS(device, g_PS_SwizzleF3D, "Blit11 3D F swizzle pixel shader" )); + addSwizzleShaderToMap(GL_UNSIGNED_INT, D3D_SRV_DIMENSION_TEXTURE3D, d3d11::CompilePS(device, g_PS_SwizzleUI3D, "Blit11 3D UI swizzle pixel shader")); + addSwizzleShaderToMap(GL_INT, D3D_SRV_DIMENSION_TEXTURE3D, d3d11::CompilePS(device, g_PS_SwizzleI3D, "Blit11 3D I swizzle pixel shader" )); + + addSwizzleShaderToMap(GL_FLOAT, D3D_SRV_DIMENSION_TEXTURE2DARRAY, d3d11::CompilePS(device, g_PS_SwizzleF2DArray, "Blit11 2D Array F swizzle pixel shader" )); + addSwizzleShaderToMap(GL_UNSIGNED_INT, D3D_SRV_DIMENSION_TEXTURE2DARRAY, d3d11::CompilePS(device, g_PS_SwizzleUI2DArray, "Blit11 2D Array UI swizzle pixel shader")); + addSwizzleShaderToMap(GL_INT, D3D_SRV_DIMENSION_TEXTURE2DARRAY, d3d11::CompilePS(device, g_PS_SwizzleI2DArray, "Blit11 2D Array I swizzle pixel shader" )); + } +} + +void Blit11::clearShaderMap() +{ + for (BlitShaderMap::iterator i = mBlitShaderMap.begin(); i != mBlitShaderMap.end(); ++i) + { + Shader &shader = i->second; + SafeRelease(shader.mPixelShader); + } + mBlitShaderMap.clear(); + + for (SwizzleShaderMap::iterator i = mSwizzleShaderMap.begin(); i != mSwizzleShaderMap.end(); ++i) + { + Shader &shader = i->second; + SafeRelease(shader.mPixelShader); + } + mSwizzleShaderMap.clear(); +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.h new file mode 100644 index 0000000000..d3a8c2c8a3 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.h @@ -0,0 +1,121 @@ +// +// 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. +// + +// Blit11.cpp: Texture copy utility class. + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_BLIT11_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_BLIT11_H_ + +#include "common/angleutils.h" +#include "libANGLE/angletypes.h" +#include "libANGLE/Error.h" + +#include + +namespace rx +{ +class Renderer11; + +class Blit11 : angle::NonCopyable +{ + public: + explicit Blit11(Renderer11 *renderer); + ~Blit11(); + + gl::Error swizzleTexture(ID3D11ShaderResourceView *source, ID3D11RenderTargetView *dest, const gl::Extents &size, + GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha); + + gl::Error copyTexture(ID3D11ShaderResourceView *source, const gl::Box &sourceArea, const gl::Extents &sourceSize, + ID3D11RenderTargetView *dest, const gl::Box &destArea, const gl::Extents &destSize, + const gl::Rectangle *scissor, GLenum destFormat, GLenum filter); + + gl::Error copyStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize, + ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize, + const gl::Rectangle *scissor); + + gl::Error copyDepth(ID3D11ShaderResourceView *source, const gl::Box &sourceArea, const gl::Extents &sourceSize, + ID3D11DepthStencilView *dest, const gl::Box &destArea, const gl::Extents &destSize, + const gl::Rectangle *scissor); + + gl::Error copyDepthStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize, + ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize, + const gl::Rectangle *scissor); + + private: + Renderer11 *mRenderer; + + struct BlitParameters + { + GLenum mDestinationFormat; + bool mSignedInteger; + bool m3DBlit; + }; + + gl::Error copyDepthStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize, + ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize, + const gl::Rectangle *scissor, bool stencilOnly); + + static bool compareBlitParameters(const BlitParameters &a, const BlitParameters &b); + + typedef void (*WriteVertexFunction)(const gl::Box &sourceArea, const gl::Extents &sourceSize, + const gl::Box &destArea, const gl::Extents &destSize, + void *outVertices, unsigned int *outStride, unsigned int *outVertexCount, + D3D11_PRIMITIVE_TOPOLOGY *outTopology); + + struct Shader + { + WriteVertexFunction mVertexWriteFunction; + ID3D11InputLayout *mInputLayout; + ID3D11VertexShader *mVertexShader; + ID3D11GeometryShader *mGeometryShader; + ID3D11PixelShader *mPixelShader; + }; + + typedef bool (*BlitParametersComparisonFunction)(const BlitParameters&, const BlitParameters &); + typedef std::map BlitShaderMap; + BlitShaderMap mBlitShaderMap; + + void add2DBlitShaderToMap(GLenum destFormat, bool signedInteger, ID3D11PixelShader *ps); + void add3DBlitShaderToMap(GLenum destFormat, bool signedInteger, ID3D11PixelShader *ps); + + struct SwizzleParameters + { + GLenum mDestinationType; + D3D11_SRV_DIMENSION mViewDimension; + }; + + static bool compareSwizzleParameters(const SwizzleParameters &a, const SwizzleParameters &b); + + typedef bool (*SwizzleParametersComparisonFunction)(const SwizzleParameters&, const SwizzleParameters &); + typedef std::map SwizzleShaderMap; + SwizzleShaderMap mSwizzleShaderMap; + + void addSwizzleShaderToMap(GLenum destType, D3D11_SRV_DIMENSION viewDimension, ID3D11PixelShader *ps); + + void buildShaderMap(); + void clearShaderMap(); + + ID3D11Buffer *mVertexBuffer; + ID3D11SamplerState *mPointSampler; + ID3D11SamplerState *mLinearSampler; + ID3D11RasterizerState *mScissorEnabledRasterizerState; + ID3D11RasterizerState *mScissorDisabledRasterizerState; + ID3D11DepthStencilState *mDepthStencilState; + + ID3D11InputLayout *mQuad2DIL; + ID3D11VertexShader *mQuad2DVS; + ID3D11PixelShader *mDepthPS; + + ID3D11InputLayout *mQuad3DIL; + ID3D11VertexShader *mQuad3DVS; + ID3D11GeometryShader *mQuad3DGS; + + ID3D11Buffer *mSwizzleCB; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_D3D11_BLIT11_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp new file mode 100644 index 0000000000..d56b0ea7ad --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp @@ -0,0 +1,1070 @@ +// +// Copyright 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Buffer11.cpp Defines the Buffer11 class. + +#include "libANGLE/renderer/d3d/d3d11/Buffer11.h" + +#include "common/MemoryBuffer.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" +#include "libANGLE/renderer/d3d/d3d11/formatutils11.h" + +#if defined(ANGLE_MINGW32_COMPAT) +typedef enum D3D11_MAP_FLAG { + D3D11_MAP_FLAG_DO_NOT_WAIT = 0x100000 +} D3D11_MAP_FLAG; +#endif + +namespace rx +{ + +PackPixelsParams::PackPixelsParams() + : format(GL_NONE), + type(GL_NONE), + outputPitch(0), + packBuffer(NULL), + offset(0) +{} + +PackPixelsParams::PackPixelsParams(const gl::Rectangle &areaIn, GLenum formatIn, GLenum typeIn, GLuint outputPitchIn, + const gl::PixelPackState &packIn, ptrdiff_t offsetIn) + : area(areaIn), + format(formatIn), + type(typeIn), + outputPitch(outputPitchIn), + packBuffer(packIn.pixelBuffer.get()), + pack(packIn.alignment, packIn.reverseRowOrder), + offset(offsetIn) +{} + +namespace gl_d3d11 +{ + +D3D11_MAP GetD3DMapTypeFromBits(GLbitfield access) +{ + bool readBit = ((access & GL_MAP_READ_BIT) != 0); + bool writeBit = ((access & GL_MAP_WRITE_BIT) != 0); + + ASSERT(readBit || writeBit); + + // Note : we ignore the discard bit, because in D3D11, staging buffers + // don't accept the map-discard flag (discard only works for DYNAMIC usage) + + if (readBit && !writeBit) + { + return D3D11_MAP_READ; + } + else if (writeBit && !readBit) + { + return D3D11_MAP_WRITE; + } + else if (writeBit && readBit) + { + return D3D11_MAP_READ_WRITE; + } + else + { + UNREACHABLE(); + return D3D11_MAP_READ; + } +} + +} + +// Each instance of Buffer11::BufferStorage is specialized for a class of D3D binding points +// - vertex/transform feedback buffers +// - index buffers +// - pixel unpack buffers +// - uniform buffers +class Buffer11::BufferStorage : angle::NonCopyable +{ + public: + virtual ~BufferStorage() {} + + DataRevision getDataRevision() const { return mRevision; } + BufferUsage getUsage() const { return mUsage; } + size_t getSize() const { return mBufferSize; } + void setDataRevision(DataRevision rev) { mRevision = rev; } + + virtual bool isMappable() const = 0; + + virtual bool copyFromStorage(BufferStorage *source, size_t sourceOffset, + size_t size, size_t destOffset) = 0; + virtual gl::Error resize(size_t size, bool preserveData) = 0; + + virtual uint8_t *map(size_t offset, size_t length, GLbitfield access) = 0; + virtual void unmap() = 0; + + gl::Error setData(const uint8_t *data, size_t offset, size_t size); + + protected: + BufferStorage(Renderer11 *renderer, BufferUsage usage); + + Renderer11 *mRenderer; + DataRevision mRevision; + const BufferUsage mUsage; + size_t mBufferSize; +}; + +// A native buffer storage represents an underlying D3D11 buffer for a particular +// type of storage. +class Buffer11::NativeStorage : public Buffer11::BufferStorage +{ + public: + NativeStorage(Renderer11 *renderer, BufferUsage usage); + ~NativeStorage() override; + + bool isMappable() const override { return mUsage == BUFFER_USAGE_STAGING; } + + ID3D11Buffer *getNativeStorage() const { return mNativeStorage; } + + bool copyFromStorage(BufferStorage *source, size_t sourceOffset, + size_t size, size_t destOffset) override; + gl::Error resize(size_t size, bool preserveData) override; + + uint8_t *map(size_t offset, size_t length, GLbitfield access) override; + void unmap() override; + + private: + static void fillBufferDesc(D3D11_BUFFER_DESC* bufferDesc, Renderer11 *renderer, BufferUsage usage, unsigned int bufferSize); + + ID3D11Buffer *mNativeStorage; +}; + +// Pack storage represents internal storage for pack buffers. We implement pack buffers +// as CPU memory, tied to a staging texture, for asynchronous texture readback. +class Buffer11::PackStorage : public Buffer11::BufferStorage +{ + public: + explicit PackStorage(Renderer11 *renderer); + ~PackStorage() override; + + bool isMappable() const override { return true; } + + bool copyFromStorage(BufferStorage *source, size_t sourceOffset, + size_t size, size_t destOffset) override; + gl::Error resize(size_t size, bool preserveData) override; + + uint8_t *map(size_t offset, size_t length, GLbitfield access) override; + void unmap() override; + + gl::Error packPixels(ID3D11Texture2D *srcTexure, UINT srcSubresource, const PackPixelsParams ¶ms); + + private: + gl::Error flushQueuedPackCommand(); + + ID3D11Texture2D *mStagingTexture; + DXGI_FORMAT mTextureFormat; + gl::Extents mTextureSize; + MemoryBuffer mMemoryBuffer; + PackPixelsParams *mQueuedPackCommand; + PackPixelsParams mPackParams; + bool mDataModified; +}; + +// System memory storage stores a CPU memory buffer with our buffer data. +// For dynamic data, it's much faster to update the CPU memory buffer than +// it is to update a D3D staging buffer and read it back later. +class Buffer11::SystemMemoryStorage : public Buffer11::BufferStorage +{ + public: + explicit SystemMemoryStorage(Renderer11 *renderer); + ~SystemMemoryStorage() override {} + + bool isMappable() const override { return true; } + + bool copyFromStorage(BufferStorage *source, size_t sourceOffset, + size_t size, size_t destOffset) override; + gl::Error resize(size_t size, bool preserveData) override; + + uint8_t *map(size_t offset, size_t length, GLbitfield access) override; + void unmap() override; + + MemoryBuffer *getSystemCopy() { return &mSystemCopy; } + + protected: + MemoryBuffer mSystemCopy; +}; + +Buffer11::Buffer11(Renderer11 *renderer) + : BufferD3D(renderer), + mRenderer(renderer), + mSize(0), + mMappedStorage(NULL), + mReadUsageCount(0), + mHasSystemMemoryStorage(false) +{} + +Buffer11::~Buffer11() +{ + for (auto it = mBufferStorages.begin(); it != mBufferStorages.end(); it++) + { + SafeDelete(it->second); + } +} + +Buffer11 *Buffer11::makeBuffer11(BufferImpl *buffer) +{ + ASSERT(HAS_DYNAMIC_TYPE(Buffer11*, buffer)); + return static_cast(buffer); +} + +gl::Error Buffer11::setData(const void *data, size_t size, GLenum usage) +{ + gl::Error error = setSubData(data, size, 0); + if (error.isError()) + { + return error; + } + + if (usage == GL_STATIC_DRAW) + { + initializeStaticData(); + } + + return error; +} + +gl::Error Buffer11::getData(const uint8_t **outData) +{ + SystemMemoryStorage *systemMemoryStorage = nullptr; + gl::Error error = getSystemMemoryStorage(&systemMemoryStorage); + + if (error.isError()) + { + *outData = nullptr; + return error; + } + + mReadUsageCount = 0; + + ASSERT(systemMemoryStorage->getSize() >= mSize); + + *outData = systemMemoryStorage->getSystemCopy()->data(); + return gl::Error(GL_NO_ERROR); +} + +gl::Error Buffer11::getSystemMemoryStorage(SystemMemoryStorage **storageOut) +{ + BufferStorage *memStorageUntyped = getBufferStorage(BUFFER_USAGE_SYSTEM_MEMORY); + + if (memStorageUntyped == nullptr) + { + // TODO(jmadill): convert all to errors + return gl::Error(GL_OUT_OF_MEMORY); + } + + *storageOut = GetAs(memStorageUntyped); + return gl::Error(GL_NO_ERROR); +} + +gl::Error Buffer11::setSubData(const void *data, size_t size, size_t offset) +{ + size_t requiredSize = size + offset; + + if (data && size > 0) + { + // Use system memory storage for dynamic buffers. + + BufferStorage *writeBuffer = nullptr; + if (supportsDirectBinding()) + { + writeBuffer = getStagingStorage(); + + if (!writeBuffer) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal buffer."); + } + } + else + { + SystemMemoryStorage *systemMemoryStorage = nullptr; + gl::Error error = getSystemMemoryStorage(&systemMemoryStorage); + if (error.isError()) + { + return error; + } + + writeBuffer = systemMemoryStorage; + } + + ASSERT(writeBuffer); + + // Explicitly resize the staging buffer, preserving data if the new data will not + // completely fill the buffer + if (writeBuffer->getSize() < requiredSize) + { + bool preserveData = (offset > 0); + gl::Error error = writeBuffer->resize(requiredSize, preserveData); + if (error.isError()) + { + return error; + } + } + + writeBuffer->setData(static_cast(data), offset, size); + writeBuffer->setDataRevision(writeBuffer->getDataRevision() + 1); + } + + mSize = std::max(mSize, requiredSize); + invalidateStaticData(); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Buffer11::copySubData(BufferImpl* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size) +{ + Buffer11 *sourceBuffer = makeBuffer11(source); + ASSERT(sourceBuffer != NULL); + + BufferStorage *copyDest = getLatestBufferStorage(); + if (!copyDest) + { + copyDest = getStagingStorage(); + } + + BufferStorage *copySource = sourceBuffer->getLatestBufferStorage(); + + if (!copySource || !copyDest) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal staging buffer."); + } + + // If copying to/from a pixel pack buffer, we must have a staging or + // pack buffer partner, because other native buffers can't be mapped + if (copyDest->getUsage() == BUFFER_USAGE_PIXEL_PACK && !copySource->isMappable()) + { + copySource = sourceBuffer->getStagingStorage(); + } + else if (copySource->getUsage() == BUFFER_USAGE_PIXEL_PACK && !copyDest->isMappable()) + { + copyDest = getStagingStorage(); + } + + // D3D11 does not allow overlapped copies until 11.1, and only if the + // device supports D3D11_FEATURE_DATA_D3D11_OPTIONS::CopyWithOverlap + // Get around this via a different source buffer + if (copySource == copyDest) + { + if (copySource->getUsage() == BUFFER_USAGE_STAGING) + { + copySource = getBufferStorage(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK); + } + else + { + copySource = getStagingStorage(); + } + } + + copyDest->copyFromStorage(copySource, sourceOffset, size, destOffset); + copyDest->setDataRevision(copyDest->getDataRevision() + 1); + + mSize = std::max(mSize, destOffset + size); + invalidateStaticData(); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Buffer11::map(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr) +{ + ASSERT(!mMappedStorage); + + BufferStorage *latestStorage = getLatestBufferStorage(); + if (latestStorage && + (latestStorage->getUsage() == BUFFER_USAGE_PIXEL_PACK || + latestStorage->getUsage() == BUFFER_USAGE_STAGING)) + { + // Latest storage is mappable. + mMappedStorage = latestStorage; + } + else + { + // Fall back to using the staging buffer if the latest storage does + // not exist or is not CPU-accessible. + mMappedStorage = getStagingStorage(); + } + + if (!mMappedStorage) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate mappable internal buffer."); + } + + if ((access & GL_MAP_WRITE_BIT) > 0) + { + // Update the data revision immediately, since the data might be changed at any time + mMappedStorage->setDataRevision(mMappedStorage->getDataRevision() + 1); + } + + uint8_t *mappedBuffer = mMappedStorage->map(offset, length, access); + if (!mappedBuffer) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal buffer."); + } + + *mapPtr = static_cast(mappedBuffer); + return gl::Error(GL_NO_ERROR); +} + +gl::Error Buffer11::unmap() +{ + ASSERT(mMappedStorage); + mMappedStorage->unmap(); + mMappedStorage = NULL; + return gl::Error(GL_NO_ERROR); +} + +void Buffer11::markTransformFeedbackUsage() +{ + BufferStorage *transformFeedbackStorage = getBufferStorage(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK); + + if (transformFeedbackStorage) + { + transformFeedbackStorage->setDataRevision(transformFeedbackStorage->getDataRevision() + 1); + } + + invalidateStaticData(); +} + +void Buffer11::markBufferUsage() +{ + mReadUsageCount++; + + // Free the system memory storage if we decide it isn't being used very often. + const unsigned int usageLimit = 5; + + if (mReadUsageCount > usageLimit && mHasSystemMemoryStorage) + { + auto systemMemoryStorageIt = mBufferStorages.find(BUFFER_USAGE_SYSTEM_MEMORY); + ASSERT(systemMemoryStorageIt != mBufferStorages.end()); + + SafeDelete(systemMemoryStorageIt->second); + mBufferStorages.erase(systemMemoryStorageIt); + mHasSystemMemoryStorage = false; + } +} + +ID3D11Buffer *Buffer11::getBuffer(BufferUsage usage) +{ + markBufferUsage(); + + BufferStorage *bufferStorage = getBufferStorage(usage); + + if (!bufferStorage) + { + // Storage out-of-memory + return NULL; + } + + ASSERT(HAS_DYNAMIC_TYPE(NativeStorage*, bufferStorage)); + + return static_cast(bufferStorage)->getNativeStorage(); +} + +ID3D11ShaderResourceView *Buffer11::getSRV(DXGI_FORMAT srvFormat) +{ + BufferStorage *storage = getBufferStorage(BUFFER_USAGE_PIXEL_UNPACK); + + if (!storage) + { + // Storage out-of-memory + return NULL; + } + + ASSERT(HAS_DYNAMIC_TYPE(NativeStorage*, storage)); + ID3D11Buffer *buffer = static_cast(storage)->getNativeStorage(); + + auto bufferSRVIt = mBufferResourceViews.find(srvFormat); + + if (bufferSRVIt != mBufferResourceViews.end()) + { + if (bufferSRVIt->second.first == buffer) + { + return bufferSRVIt->second.second; + } + else + { + // The underlying buffer has changed since the SRV was created: recreate the SRV. + SafeRelease(bufferSRVIt->second.second); + } + } + + ID3D11Device *device = mRenderer->getDevice(); + ID3D11ShaderResourceView *bufferSRV = NULL; + + const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(srvFormat); + + D3D11_SHADER_RESOURCE_VIEW_DESC bufferSRVDesc; + bufferSRVDesc.Buffer.ElementOffset = 0; + bufferSRVDesc.Buffer.ElementWidth = mSize / dxgiFormatInfo.pixelBytes; + bufferSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER; + bufferSRVDesc.Format = srvFormat; + + HRESULT result = device->CreateShaderResourceView(buffer, &bufferSRVDesc, &bufferSRV); + UNUSED_ASSERTION_VARIABLE(result); + ASSERT(SUCCEEDED(result)); + + mBufferResourceViews[srvFormat] = BufferSRVPair(buffer, bufferSRV); + + return bufferSRV; +} + +gl::Error Buffer11::packPixels(ID3D11Texture2D *srcTexture, UINT srcSubresource, const PackPixelsParams ¶ms) +{ + PackStorage *packStorage = getPackStorage(); + BufferStorage *latestStorage = getLatestBufferStorage(); + + if (packStorage) + { + gl::Error error = packStorage->packPixels(srcTexture, srcSubresource, params); + if (error.isError()) + { + return error; + } + packStorage->setDataRevision(latestStorage ? latestStorage->getDataRevision() + 1 : 1); + } + + return gl::Error(GL_NO_ERROR); +} + +Buffer11::BufferStorage *Buffer11::getBufferStorage(BufferUsage usage) +{ + BufferStorage *newStorage = NULL; + auto directBufferIt = mBufferStorages.find(usage); + if (directBufferIt != mBufferStorages.end()) + { + newStorage = directBufferIt->second; + } + + if (!newStorage) + { + if (usage == BUFFER_USAGE_PIXEL_PACK) + { + newStorage = new PackStorage(mRenderer); + } + else if (usage == BUFFER_USAGE_SYSTEM_MEMORY) + { + newStorage = new SystemMemoryStorage(mRenderer); + mHasSystemMemoryStorage = true; + } + else + { + // buffer is not allocated, create it + newStorage = new NativeStorage(mRenderer, usage); + } + + mBufferStorages.insert(std::make_pair(usage, newStorage)); + } + + // resize buffer + if (newStorage->getSize() < mSize) + { + if (newStorage->resize(mSize, true).isError()) + { + // Out of memory error + return NULL; + } + } + + BufferStorage *latestBuffer = getLatestBufferStorage(); + if (latestBuffer && latestBuffer->getDataRevision() > newStorage->getDataRevision()) + { + // Copy through a staging buffer if we're copying from or to a non-staging, mappable + // buffer storage. This is because we can't map a GPU buffer, and copy CPU + // data directly. If we're already using a staging buffer we're fine. + if (latestBuffer->getUsage() != BUFFER_USAGE_STAGING && + newStorage->getUsage() != BUFFER_USAGE_STAGING && + (!latestBuffer->isMappable() || !newStorage->isMappable())) + { + NativeStorage *stagingBuffer = getStagingStorage(); + + stagingBuffer->copyFromStorage(latestBuffer, 0, latestBuffer->getSize(), 0); + stagingBuffer->setDataRevision(latestBuffer->getDataRevision()); + + latestBuffer = stagingBuffer; + } + + // if copyFromStorage returns true, the D3D buffer has been recreated + // and we should update our serial + if (newStorage->copyFromStorage(latestBuffer, 0, latestBuffer->getSize(), 0)) + { + updateSerial(); + } + newStorage->setDataRevision(latestBuffer->getDataRevision()); + } + + return newStorage; +} + +Buffer11::BufferStorage *Buffer11::getLatestBufferStorage() const +{ + // Even though we iterate over all the direct buffers, it is expected that only + // 1 or 2 will be present. + BufferStorage *latestStorage = NULL; + DataRevision latestRevision = 0; + for (auto it = mBufferStorages.begin(); it != mBufferStorages.end(); it++) + { + BufferStorage *storage = it->second; + if (!latestStorage || storage->getDataRevision() > latestRevision) + { + latestStorage = storage; + latestRevision = storage->getDataRevision(); + } + } + + // resize buffer + if (latestStorage && latestStorage->getSize() < mSize) + { + if (latestStorage->resize(mSize, true).isError()) + { + // Out of memory error + return NULL; + } + } + + return latestStorage; +} + +Buffer11::NativeStorage *Buffer11::getStagingStorage() +{ + BufferStorage *stagingStorage = getBufferStorage(BUFFER_USAGE_STAGING); + + if (!stagingStorage) + { + // Out-of-memory + return NULL; + } + + ASSERT(HAS_DYNAMIC_TYPE(NativeStorage*, stagingStorage)); + return static_cast(stagingStorage); +} + +Buffer11::PackStorage *Buffer11::getPackStorage() +{ + BufferStorage *packStorage = getBufferStorage(BUFFER_USAGE_PIXEL_PACK); + + if (!packStorage) + { + // Out-of-memory + return NULL; + } + + ASSERT(HAS_DYNAMIC_TYPE(PackStorage*, packStorage)); + return static_cast(packStorage); +} + +bool Buffer11::supportsDirectBinding() const +{ + // Do not support direct buffers for dynamic data. The streaming buffer + // offers better performance for data which changes every frame. + // Check for absence of static buffer interfaces to detect dynamic data. + return (mStaticVertexBuffer && mStaticIndexBuffer); +} + +Buffer11::BufferStorage::BufferStorage(Renderer11 *renderer, BufferUsage usage) + : mRenderer(renderer), + mUsage(usage), + mRevision(0), + mBufferSize(0) +{ +} + +gl::Error Buffer11::BufferStorage::setData(const uint8_t *data, size_t offset, size_t size) +{ + ASSERT(isMappable()); + + uint8_t *writePointer = map(offset, size, GL_MAP_WRITE_BIT); + if (!writePointer) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal buffer."); + } + + memcpy(writePointer, data, size); + + unmap(); + + return gl::Error(GL_NO_ERROR); +} + +Buffer11::NativeStorage::NativeStorage(Renderer11 *renderer, BufferUsage usage) + : BufferStorage(renderer, usage), + mNativeStorage(NULL) +{ +} + +Buffer11::NativeStorage::~NativeStorage() +{ + SafeRelease(mNativeStorage); +} + +// Returns true if it recreates the direct buffer +bool Buffer11::NativeStorage::copyFromStorage(BufferStorage *source, size_t sourceOffset, + size_t size, size_t destOffset) +{ + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + + size_t requiredSize = sourceOffset + size; + bool createBuffer = !mNativeStorage || mBufferSize < requiredSize; + + // (Re)initialize D3D buffer if needed + if (createBuffer) + { + bool preserveData = (destOffset > 0); + resize(source->getSize(), preserveData); + } + + if (source->getUsage() == BUFFER_USAGE_PIXEL_PACK || + source->getUsage() == BUFFER_USAGE_SYSTEM_MEMORY) + { + ASSERT(source->isMappable()); + + uint8_t *sourcePointer = source->map(sourceOffset, size, GL_MAP_READ_BIT); + + D3D11_MAPPED_SUBRESOURCE mappedResource; + HRESULT hr = context->Map(mNativeStorage, 0, D3D11_MAP_WRITE, 0, &mappedResource); + UNUSED_ASSERTION_VARIABLE(hr); + ASSERT(SUCCEEDED(hr)); + + uint8_t *destPointer = static_cast(mappedResource.pData) + destOffset; + + // Offset bounds are validated at the API layer + ASSERT(sourceOffset + size <= destOffset + mBufferSize); + memcpy(destPointer, sourcePointer, size); + + context->Unmap(mNativeStorage, 0); + source->unmap(); + } + else + { + ASSERT(HAS_DYNAMIC_TYPE(NativeStorage*, source)); + + D3D11_BOX srcBox; + srcBox.left = sourceOffset; + srcBox.right = sourceOffset + size; + srcBox.top = 0; + srcBox.bottom = 1; + srcBox.front = 0; + srcBox.back = 1; + + ASSERT(HAS_DYNAMIC_TYPE(NativeStorage*, source)); + ID3D11Buffer *sourceBuffer = static_cast(source)->getNativeStorage(); + + context->CopySubresourceRegion(mNativeStorage, 0, destOffset, 0, 0, sourceBuffer, 0, &srcBox); + } + + return createBuffer; +} + +gl::Error Buffer11::NativeStorage::resize(size_t size, bool preserveData) +{ + ID3D11Device *device = mRenderer->getDevice(); + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + + D3D11_BUFFER_DESC bufferDesc; + fillBufferDesc(&bufferDesc, mRenderer, mUsage, size); + + ID3D11Buffer *newBuffer; + HRESULT result = device->CreateBuffer(&bufferDesc, NULL, &newBuffer); + + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal buffer, result: 0x%X.", result); + } + + if (mNativeStorage && preserveData) + { + // We don't call resize if the buffer is big enough already. + ASSERT(mBufferSize <= size); + + D3D11_BOX srcBox; + srcBox.left = 0; + srcBox.right = mBufferSize; + srcBox.top = 0; + srcBox.bottom = 1; + srcBox.front = 0; + srcBox.back = 1; + + context->CopySubresourceRegion(newBuffer, 0, 0, 0, 0, mNativeStorage, 0, &srcBox); + } + + // No longer need the old buffer + SafeRelease(mNativeStorage); + mNativeStorage = newBuffer; + + mBufferSize = bufferDesc.ByteWidth; + + return gl::Error(GL_NO_ERROR); +} + +void Buffer11::NativeStorage::fillBufferDesc(D3D11_BUFFER_DESC* bufferDesc, Renderer11 *renderer, + BufferUsage usage, unsigned int bufferSize) +{ + bufferDesc->ByteWidth = bufferSize; + bufferDesc->MiscFlags = 0; + bufferDesc->StructureByteStride = 0; + + switch (usage) + { + case BUFFER_USAGE_STAGING: + bufferDesc->Usage = D3D11_USAGE_STAGING; + bufferDesc->BindFlags = 0; + bufferDesc->CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; + break; + + case BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK: + bufferDesc->Usage = D3D11_USAGE_DEFAULT; + bufferDesc->BindFlags = D3D11_BIND_VERTEX_BUFFER; + + if (renderer->isES3Capable()) + { + bufferDesc->BindFlags |= D3D11_BIND_STREAM_OUTPUT; + } + + bufferDesc->CPUAccessFlags = 0; + break; + + case BUFFER_USAGE_INDEX: + bufferDesc->Usage = D3D11_USAGE_DEFAULT; + bufferDesc->BindFlags = D3D11_BIND_INDEX_BUFFER; + bufferDesc->CPUAccessFlags = 0; + break; + + case BUFFER_USAGE_PIXEL_UNPACK: + bufferDesc->Usage = D3D11_USAGE_DEFAULT; + bufferDesc->BindFlags = D3D11_BIND_SHADER_RESOURCE; + bufferDesc->CPUAccessFlags = 0; + break; + + case BUFFER_USAGE_UNIFORM: + bufferDesc->Usage = D3D11_USAGE_DYNAMIC; + bufferDesc->BindFlags = D3D11_BIND_CONSTANT_BUFFER; + bufferDesc->CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + + // Constant buffers must be of a limited size, and aligned to 16 byte boundaries + // For our purposes we ignore any buffer data past the maximum constant buffer size + bufferDesc->ByteWidth = roundUp(bufferDesc->ByteWidth, 16u); + bufferDesc->ByteWidth = std::min(bufferDesc->ByteWidth, renderer->getRendererCaps().maxUniformBlockSize); + break; + + default: + UNREACHABLE(); + } +} + +uint8_t *Buffer11::NativeStorage::map(size_t offset, size_t length, GLbitfield access) +{ + ASSERT(mUsage == BUFFER_USAGE_STAGING); + + D3D11_MAPPED_SUBRESOURCE mappedResource; + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + D3D11_MAP d3dMapType = gl_d3d11::GetD3DMapTypeFromBits(access); + UINT d3dMapFlag = ((access & GL_MAP_UNSYNCHRONIZED_BIT) != 0 ? D3D11_MAP_FLAG_DO_NOT_WAIT : 0); + + HRESULT result = context->Map(mNativeStorage, 0, d3dMapType, d3dMapFlag, &mappedResource); + UNUSED_ASSERTION_VARIABLE(result); + ASSERT(SUCCEEDED(result)); + + return static_cast(mappedResource.pData) + offset; +} + +void Buffer11::NativeStorage::unmap() +{ + ASSERT(mUsage == BUFFER_USAGE_STAGING); + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + context->Unmap(mNativeStorage, 0); +} + +Buffer11::PackStorage::PackStorage(Renderer11 *renderer) + : BufferStorage(renderer, BUFFER_USAGE_PIXEL_PACK), + mStagingTexture(NULL), + mTextureFormat(DXGI_FORMAT_UNKNOWN), + mQueuedPackCommand(NULL), + mDataModified(false) +{ +} + +Buffer11::PackStorage::~PackStorage() +{ + SafeRelease(mStagingTexture); + SafeDelete(mQueuedPackCommand); +} + +bool Buffer11::PackStorage::copyFromStorage(BufferStorage *source, size_t sourceOffset, + size_t size, size_t destOffset) +{ + // We copy through a staging buffer when drawing with a pack buffer, + // or for other cases where we access the pack buffer + UNREACHABLE(); + return false; +} + +gl::Error Buffer11::PackStorage::resize(size_t size, bool preserveData) +{ + if (size != mBufferSize) + { + if (!mMemoryBuffer.resize(size)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to resize internal buffer storage."); + } + mBufferSize = size; + } + + return gl::Error(GL_NO_ERROR); +} + +uint8_t *Buffer11::PackStorage::map(size_t offset, size_t length, GLbitfield access) +{ + ASSERT(offset + length <= getSize()); + // TODO: fast path + // We might be able to optimize out one or more memcpy calls by detecting when + // and if D3D packs the staging texture memory identically to how we would fill + // the pack buffer according to the current pack state. + + gl::Error error = flushQueuedPackCommand(); + if (error.isError()) + { + return NULL; + } + + mDataModified = (mDataModified || (access & GL_MAP_WRITE_BIT) != 0); + + return mMemoryBuffer.data() + offset; +} + +void Buffer11::PackStorage::unmap() +{ + // No-op +} + +gl::Error Buffer11::PackStorage::packPixels(ID3D11Texture2D *srcTexure, UINT srcSubresource, const PackPixelsParams ¶ms) +{ + gl::Error error = flushQueuedPackCommand(); + if (error.isError()) + { + return error; + } + + mQueuedPackCommand = new PackPixelsParams(params); + + D3D11_TEXTURE2D_DESC textureDesc; + srcTexure->GetDesc(&textureDesc); + + if (mStagingTexture != NULL && + (mTextureFormat != textureDesc.Format || + mTextureSize.width != params.area.width || + mTextureSize.height != params.area.height)) + { + SafeRelease(mStagingTexture); + mTextureSize.width = 0; + mTextureSize.height = 0; + mTextureFormat = DXGI_FORMAT_UNKNOWN; + } + + if (mStagingTexture == NULL) + { + ID3D11Device *device = mRenderer->getDevice(); + HRESULT hr; + + mTextureSize.width = params.area.width; + mTextureSize.height = params.area.height; + mTextureFormat = textureDesc.Format; + + D3D11_TEXTURE2D_DESC stagingDesc; + stagingDesc.Width = params.area.width; + stagingDesc.Height = params.area.height; + stagingDesc.MipLevels = 1; + stagingDesc.ArraySize = 1; + stagingDesc.Format = mTextureFormat; + 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; + + hr = device->CreateTexture2D(&stagingDesc, NULL, &mStagingTexture); + if (FAILED(hr)) + { + ASSERT(hr == E_OUTOFMEMORY); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal staging texture."); + } + } + + // ReadPixels from multisampled FBOs isn't supported in current GL + ASSERT(textureDesc.SampleDesc.Count <= 1); + + ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext(); + D3D11_BOX srcBox; + srcBox.left = params.area.x; + srcBox.right = params.area.x + params.area.width; + srcBox.top = params.area.y; + srcBox.bottom = params.area.y + params.area.height; + srcBox.front = 0; + srcBox.back = 1; + + // Asynchronous copy + immediateContext->CopySubresourceRegion(mStagingTexture, 0, 0, 0, 0, srcTexure, srcSubresource, &srcBox); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Buffer11::PackStorage::flushQueuedPackCommand() +{ + ASSERT(mMemoryBuffer.size() > 0); + + if (mQueuedPackCommand) + { + gl::Error error = mRenderer->packPixels(mStagingTexture, *mQueuedPackCommand, mMemoryBuffer.data()); + SafeDelete(mQueuedPackCommand); + if (error.isError()) + { + return error; + } + } + + return gl::Error(GL_NO_ERROR); +} + +Buffer11::SystemMemoryStorage::SystemMemoryStorage(Renderer11 *renderer) + : Buffer11::BufferStorage(renderer, BUFFER_USAGE_SYSTEM_MEMORY) +{} + +bool Buffer11::SystemMemoryStorage::copyFromStorage(BufferStorage *source, size_t sourceOffset, + size_t size, size_t destOffset) +{ + ASSERT(source->isMappable()); + const uint8_t *sourceData = source->map(sourceOffset, size, GL_MAP_READ_BIT); + ASSERT(destOffset + size <= mSystemCopy.size()); + memcpy(mSystemCopy.data() + destOffset, sourceData, size); + source->unmap(); + return true; +} + +gl::Error Buffer11::SystemMemoryStorage::resize(size_t size, bool preserveData) +{ + if (mSystemCopy.size() < size) + { + if (!mSystemCopy.resize(size)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to resize SystemMemoryStorage"); + } + mBufferSize = size; + } + + return gl::Error(GL_NO_ERROR); +} + +uint8_t *Buffer11::SystemMemoryStorage::map(size_t offset, size_t length, GLbitfield access) +{ + ASSERT(!mSystemCopy.empty() && offset + length <= mSystemCopy.size()); + return mSystemCopy.data() + offset; +} + +void Buffer11::SystemMemoryStorage::unmap() +{ + // No-op +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.h new file mode 100644 index 0000000000..39bafe880e --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.h @@ -0,0 +1,103 @@ +// +// Copyright 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Buffer11.h: Defines the rx::Buffer11 class which implements rx::BufferImpl via rx::BufferD3D. + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_BUFFER11_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_BUFFER11_H_ + +#include "libANGLE/angletypes.h" +#include "libANGLE/renderer/d3d/BufferD3D.h" + +namespace rx +{ +class Renderer11; + +enum BufferUsage +{ + BUFFER_USAGE_STAGING, + BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK, + BUFFER_USAGE_INDEX, + BUFFER_USAGE_PIXEL_UNPACK, + BUFFER_USAGE_PIXEL_PACK, + BUFFER_USAGE_UNIFORM, + BUFFER_USAGE_SYSTEM_MEMORY, +}; + +struct PackPixelsParams +{ + PackPixelsParams(); + PackPixelsParams(const gl::Rectangle &area, GLenum format, GLenum type, GLuint outputPitch, + const gl::PixelPackState &pack, ptrdiff_t offset); + + gl::Rectangle area; + GLenum format; + GLenum type; + GLuint outputPitch; + gl::Buffer *packBuffer; + gl::PixelPackState pack; + ptrdiff_t offset; +}; + +typedef size_t DataRevision; + +class Buffer11 : public BufferD3D +{ + public: + Buffer11(Renderer11 *renderer); + virtual ~Buffer11(); + + static Buffer11 *makeBuffer11(BufferImpl *buffer); + + ID3D11Buffer *getBuffer(BufferUsage usage); + ID3D11ShaderResourceView *getSRV(DXGI_FORMAT srvFormat); + bool isMapped() const { return mMappedStorage != NULL; } + gl::Error packPixels(ID3D11Texture2D *srcTexure, UINT srcSubresource, const PackPixelsParams ¶ms); + + // BufferD3D implementation + virtual size_t getSize() const { return mSize; } + virtual bool supportsDirectBinding() const; + + // BufferImpl implementation + virtual gl::Error setData(const void* data, size_t size, GLenum usage); + gl::Error getData(const uint8_t **outData) override; + virtual gl::Error setSubData(const void* data, size_t size, size_t offset); + virtual gl::Error copySubData(BufferImpl* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size); + virtual gl::Error map(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr); + virtual gl::Error unmap(); + virtual void markTransformFeedbackUsage(); + + private: + class BufferStorage; + class NativeStorage; + class PackStorage; + class SystemMemoryStorage; + + Renderer11 *mRenderer; + size_t mSize; + + BufferStorage *mMappedStorage; + + std::map mBufferStorages; + + typedef std::pair BufferSRVPair; + std::map mBufferResourceViews; + + unsigned int mReadUsageCount; + bool mHasSystemMemoryStorage; + + void markBufferUsage(); + NativeStorage *getStagingStorage(); + PackStorage *getPackStorage(); + gl::Error getSystemMemoryStorage(SystemMemoryStorage **storageOut); + + BufferStorage *getBufferStorage(BufferUsage usage); + BufferStorage *getLatestBufferStorage() const; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_D3D11_BUFFER11_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp new file mode 100644 index 0000000000..057c3bed42 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp @@ -0,0 +1,614 @@ +// +// 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. +// + +// Clear11.cpp: Framebuffer clear utility class. + +#include "libANGLE/renderer/d3d/d3d11/Clear11.h" + +#include + +#include "libANGLE/FramebufferAttachment.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/renderer/d3d/FramebufferD3D.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" +#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h" +#include "libANGLE/renderer/d3d/d3d11/formatutils11.h" + +// Precompiled shaders +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11vs.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11_fl9ps.h" + +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11vs.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps.h" + +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11vs.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps.h" + +namespace rx +{ + +template +static void ApplyVertices(const gl::Extents &framebufferSize, const gl::Rectangle *scissor, const gl::Color &color, float depth, void *buffer) +{ + d3d11::PositionDepthColorVertex *vertices = reinterpret_cast*>(buffer); + + float depthClear = gl::clamp01(depth); + float left = -1.0f; + float right = 1.0f; + float top = -1.0f; + float bottom = 1.0f; + + // Clip the quad coordinates to the scissor if needed + if (scissor != NULL) + { + left = std::max(left, (scissor->x / float(framebufferSize.width)) * 2.0f - 1.0f); + right = std::min(right, ((scissor->x + scissor->width) / float(framebufferSize.width)) * 2.0f - 1.0f); + top = std::max(top, ((framebufferSize.height - scissor->y - scissor->height) / float(framebufferSize.height)) * 2.0f - 1.0f); + bottom = std::min(bottom, ((framebufferSize.height - scissor->y) / float(framebufferSize.height)) * 2.0f - 1.0f); + } + + d3d11::SetPositionDepthColorVertex(vertices + 0, left, bottom, depthClear, color); + d3d11::SetPositionDepthColorVertex(vertices + 1, left, top, depthClear, color); + d3d11::SetPositionDepthColorVertex(vertices + 2, right, bottom, depthClear, color); + d3d11::SetPositionDepthColorVertex(vertices + 3, right, top, depthClear, color); +} + +template +Clear11::ClearShader Clear11::CreateClearShader(ID3D11Device *device, DXGI_FORMAT colorType, const BYTE (&vsByteCode)[vsSize], const BYTE (&psByteCode)[psSize]) +{ + HRESULT result; + + ClearShader shader = { 0 }; + + D3D11_INPUT_ELEMENT_DESC quadLayout[] = + { + { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "COLOR", 0, colorType, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + }; + + result = device->CreateInputLayout(quadLayout, ArraySize(quadLayout), vsByteCode, vsSize, &shader.inputLayout); + ASSERT(SUCCEEDED(result)); + + result = device->CreateVertexShader(vsByteCode, vsSize, NULL, &shader.vertexShader); + ASSERT(SUCCEEDED(result)); + + result = device->CreatePixelShader(psByteCode, psSize, NULL, &shader.pixelShader); + ASSERT(SUCCEEDED(result)); + + return shader; +} + +Clear11::Clear11(Renderer11 *renderer) + : mRenderer(renderer), mClearBlendStates(StructLessThan), mClearDepthStencilStates(StructLessThan), + mVertexBuffer(NULL), mRasterizerState(NULL), mSupportsClearView(false) +{ + HRESULT result; + ID3D11Device *device = renderer->getDevice(); + + 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 = device->CreateBuffer(&vbDesc, NULL, &mVertexBuffer); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mVertexBuffer, "Clear11 masked clear vertex buffer"); + + D3D11_RASTERIZER_DESC rsDesc; + rsDesc.FillMode = D3D11_FILL_SOLID; + rsDesc.CullMode = D3D11_CULL_NONE; + rsDesc.FrontCounterClockwise = FALSE; + rsDesc.DepthBias = 0; + rsDesc.DepthBiasClamp = 0.0f; + rsDesc.SlopeScaledDepthBias = 0.0f; + rsDesc.DepthClipEnable = TRUE; + rsDesc.ScissorEnable = FALSE; + rsDesc.MultisampleEnable = FALSE; + rsDesc.AntialiasedLineEnable = FALSE; + + result = device->CreateRasterizerState(&rsDesc, &mRasterizerState); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mRasterizerState, "Clear11 masked clear rasterizer state"); + + if (renderer->getFeatureLevel() <= D3D_FEATURE_LEVEL_9_3) + { + mFloatClearShader = CreateClearShader(device, DXGI_FORMAT_R32G32B32A32_FLOAT, g_VS_ClearFloat, g_PS_ClearFloat_FL9); + } + else + { + mFloatClearShader = CreateClearShader(device, DXGI_FORMAT_R32G32B32A32_FLOAT, g_VS_ClearFloat, g_PS_ClearFloat); + } + + if (renderer->isES3Capable()) + { + mUintClearShader = CreateClearShader(device, DXGI_FORMAT_R32G32B32A32_UINT, g_VS_ClearUint, g_PS_ClearUint ); + mIntClearShader = CreateClearShader(device, DXGI_FORMAT_R32G32B32A32_SINT, g_VS_ClearSint, g_PS_ClearSint ); + } + +#if defined(ANGLE_ENABLE_D3D11_1) + if (renderer->getDeviceContext1IfSupported()) + { + D3D11_FEATURE_DATA_D3D11_OPTIONS d3d11Options; + device->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS, &d3d11Options, sizeof(D3D11_FEATURE_DATA_D3D11_OPTIONS)); + mSupportsClearView = (d3d11Options.ClearView != FALSE); + } +#endif +} + +Clear11::~Clear11() +{ + for (ClearBlendStateMap::iterator i = mClearBlendStates.begin(); i != mClearBlendStates.end(); i++) + { + SafeRelease(i->second); + } + mClearBlendStates.clear(); + + SafeRelease(mFloatClearShader.inputLayout); + SafeRelease(mFloatClearShader.vertexShader); + SafeRelease(mFloatClearShader.pixelShader); + + if (mRenderer->isES3Capable()) + { + SafeRelease(mUintClearShader.inputLayout); + SafeRelease(mUintClearShader.vertexShader); + SafeRelease(mUintClearShader.pixelShader); + + SafeRelease(mIntClearShader.inputLayout); + SafeRelease(mIntClearShader.vertexShader); + SafeRelease(mIntClearShader.pixelShader); + } + + for (ClearDepthStencilStateMap::iterator i = mClearDepthStencilStates.begin(); i != mClearDepthStencilStates.end(); i++) + { + SafeRelease(i->second); + } + mClearDepthStencilStates.clear(); + + SafeRelease(mVertexBuffer); + SafeRelease(mRasterizerState); +} + +gl::Error Clear11::clearFramebuffer(const ClearParameters &clearParams, const gl::Framebuffer::Data &fboData) +{ + const auto &colorAttachments = fboData.mColorAttachments; + const auto &drawBufferStates = fboData.mDrawBufferStates; + const auto *depthAttachment = fboData.mDepthAttachment; + const auto *stencilAttachment = fboData.mStencilAttachment; + + ASSERT(colorAttachments.size() == drawBufferStates.size()); + + // Iterate over the color buffers which require clearing and determine if they can be + // cleared with ID3D11DeviceContext::ClearRenderTargetView or ID3D11DeviceContext1::ClearView. + // This requires: + // 1) The render target is being cleared to a float value (will be cast to integer when clearing integer + // render targets as expected but does not work the other way around) + // 2) The format of the render target has no color channels that are currently masked out. + // Clear the easy-to-clear buffers on the spot and accumulate the ones that require special work. + // + // If these conditions are met, and: + // - No scissored clear is needed, then clear using ID3D11DeviceContext::ClearRenderTargetView. + // - A scissored clear is needed then clear using ID3D11DeviceContext1::ClearView if available. + // Otherwise draw a quad. + // + // Also determine if the depth stencil can be cleared with ID3D11DeviceContext::ClearDepthStencilView + // by checking if the stencil write mask covers the entire stencil. + // + // To clear the remaining buffers, quads must be drawn containing an int, uint or float vertex color + // attribute. + + gl::Extents framebufferSize; + + auto iter = std::find_if(colorAttachments.begin(), colorAttachments.end(), [](const gl::FramebufferAttachment *attachment) { return attachment != nullptr; }); + if (iter != colorAttachments.end()) + { + framebufferSize.width = (*iter)->getWidth(); + framebufferSize.height = (*iter)->getHeight(); + framebufferSize.depth = 1; + } + else if (depthAttachment != nullptr) + { + framebufferSize.width = depthAttachment->getWidth(); + framebufferSize.height = depthAttachment->getHeight(); + framebufferSize.depth = 1; + } + else if (stencilAttachment != nullptr) + { + framebufferSize.width = stencilAttachment->getWidth(); + framebufferSize.height = stencilAttachment->getHeight(); + framebufferSize.depth = 1; + } + else + { + UNREACHABLE(); + return gl::Error(GL_INVALID_OPERATION); + } + + if (clearParams.scissorEnabled && (clearParams.scissor.x >= framebufferSize.width || + clearParams.scissor.y >= framebufferSize.height || + clearParams.scissor.x + clearParams.scissor.width <= 0 || + clearParams.scissor.y + clearParams.scissor.height <= 0)) + { + // Scissor is enabled and the scissor rectangle is outside the renderbuffer + return gl::Error(GL_NO_ERROR); + } + + bool needScissoredClear = clearParams.scissorEnabled && (clearParams.scissor.x > 0 || clearParams.scissor.y > 0 || + clearParams.scissor.x + clearParams.scissor.width < framebufferSize.width || + clearParams.scissor.y + clearParams.scissor.height < framebufferSize.height); + + std::vector maskedClearRenderTargets; + RenderTarget11* maskedClearDepthStencil = NULL; + + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + ID3D11DeviceContext1 *deviceContext1 = mRenderer->getDeviceContext1IfSupported(); + + for (size_t colorAttachment = 0; colorAttachment < colorAttachments.size(); colorAttachment++) + { + if (clearParams.clearColor[colorAttachment] && + colorAttachments[colorAttachment] != nullptr && + drawBufferStates[colorAttachment] != GL_NONE) + { + const gl::FramebufferAttachment *attachment = colorAttachments[colorAttachment]; + + RenderTarget11 *renderTarget = NULL; + gl::Error error = d3d11::GetAttachmentRenderTarget(attachment, &renderTarget); + if (error.isError()) + { + return error; + } + + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(attachment->getInternalFormat()); + + if (clearParams.colorClearType == GL_FLOAT && + !(formatInfo.componentType == GL_FLOAT || formatInfo.componentType == GL_UNSIGNED_NORMALIZED || formatInfo.componentType == GL_SIGNED_NORMALIZED)) + { + ERR("It is undefined behaviour to clear a render buffer which is not normalized fixed point or floating-" + "point to floating point values (color attachment %u has internal format 0x%X).", colorAttachment, + attachment->getInternalFormat()); + } + + if ((formatInfo.redBits == 0 || !clearParams.colorMaskRed) && + (formatInfo.greenBits == 0 || !clearParams.colorMaskGreen) && + (formatInfo.blueBits == 0 || !clearParams.colorMaskBlue) && + (formatInfo.alphaBits == 0 || !clearParams.colorMaskAlpha)) + { + // Every channel either does not exist in the render target or is masked out + continue; + } + else if ((!mSupportsClearView && needScissoredClear) || clearParams.colorClearType != GL_FLOAT || + (formatInfo.redBits > 0 && !clearParams.colorMaskRed) || + (formatInfo.greenBits > 0 && !clearParams.colorMaskGreen) || + (formatInfo.blueBits > 0 && !clearParams.colorMaskBlue) || + (formatInfo.alphaBits > 0 && !clearParams.colorMaskAlpha)) + { + // A masked clear is required, or a scissored clear is required and ID3D11DeviceContext1::ClearView is unavailable + MaskedRenderTarget maskAndRt; + bool clearColor = clearParams.clearColor[colorAttachment]; + maskAndRt.colorMask[0] = (clearColor && clearParams.colorMaskRed); + maskAndRt.colorMask[1] = (clearColor && clearParams.colorMaskGreen); + maskAndRt.colorMask[2] = (clearColor && clearParams.colorMaskBlue); + maskAndRt.colorMask[3] = (clearColor && clearParams.colorMaskAlpha); + maskAndRt.renderTarget = renderTarget; + maskedClearRenderTargets.push_back(maskAndRt); + } + else + { + // ID3D11DeviceContext::ClearRenderTargetView or ID3D11DeviceContext1::ClearView is possible + + ID3D11RenderTargetView *framebufferRTV = renderTarget->getRenderTargetView(); + if (!framebufferRTV) + { + return gl::Error(GL_OUT_OF_MEMORY, "Internal render target view pointer unexpectedly null."); + } + + const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(renderTarget->getDXGIFormat()); + + // Check if the actual format has a channel that the internal format does not and set them to the + // default values + const float clearValues[4] = + { + ((formatInfo.redBits == 0 && dxgiFormatInfo.redBits > 0) ? 0.0f : clearParams.colorFClearValue.red), + ((formatInfo.greenBits == 0 && dxgiFormatInfo.greenBits > 0) ? 0.0f : clearParams.colorFClearValue.green), + ((formatInfo.blueBits == 0 && dxgiFormatInfo.blueBits > 0) ? 0.0f : clearParams.colorFClearValue.blue), + ((formatInfo.alphaBits == 0 && dxgiFormatInfo.alphaBits > 0) ? 1.0f : clearParams.colorFClearValue.alpha), + }; + + if (needScissoredClear) + { +#if defined(ANGLE_ENABLE_D3D11_1) + // We shouldn't reach here if deviceContext1 is unavailable. + ASSERT(deviceContext1); + + D3D11_RECT rect; + rect.left = clearParams.scissor.x; + rect.right = clearParams.scissor.x + clearParams.scissor.width; + rect.top = clearParams.scissor.y; + rect.bottom = clearParams.scissor.y + clearParams.scissor.height; + + deviceContext1->ClearView(framebufferRTV, clearValues, &rect, 1); +#endif + } + else + { + deviceContext->ClearRenderTargetView(framebufferRTV, clearValues); + } + } + } + } + + if (clearParams.clearDepth || clearParams.clearStencil) + { + const gl::FramebufferAttachment *attachment = (depthAttachment != nullptr) ? depthAttachment : stencilAttachment; + ASSERT(attachment != nullptr); + + RenderTarget11 *renderTarget = NULL; + gl::Error error = d3d11::GetAttachmentRenderTarget(attachment, &renderTarget); + if (error.isError()) + { + return error; + } + + const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(renderTarget->getDXGIFormat()); + + unsigned int stencilUnmasked = (stencilAttachment != nullptr) ? (1 << dxgiFormatInfo.stencilBits) - 1 : 0; + bool needMaskedStencilClear = clearParams.clearStencil && (clearParams.stencilWriteMask & stencilUnmasked) != stencilUnmasked; + + if (needScissoredClear || needMaskedStencilClear) + { + maskedClearDepthStencil = renderTarget; + } + else + { + ID3D11DepthStencilView *framebufferDSV = renderTarget->getDepthStencilView(); + if (!framebufferDSV) + { + return gl::Error(GL_OUT_OF_MEMORY, "Internal depth stencil view pointer unexpectedly null."); + } + + UINT clearFlags = (clearParams.clearDepth ? D3D11_CLEAR_DEPTH : 0) | + (clearParams.clearStencil ? D3D11_CLEAR_STENCIL : 0); + FLOAT depthClear = gl::clamp01(clearParams.depthClearValue); + UINT8 stencilClear = clearParams.stencilClearValue & 0xFF; + + deviceContext->ClearDepthStencilView(framebufferDSV, clearFlags, depthClear, stencilClear); + } + } + + if (maskedClearRenderTargets.size() > 0 || maskedClearDepthStencil) + { + // To clear the render targets and depth stencil in one pass: + // + // Render a quad clipped to the scissor rectangle which draws the clear color and a blend + // state that will perform the required color masking. + // + // The quad's depth is equal to the depth clear value with a depth stencil state that + // will enable or disable depth test/writes if the depth buffer should be cleared or not. + // + // The rasterizer state's stencil is set to always pass or fail based on if the stencil + // should be cleared or not with a stencil write mask of the stencil clear value. + // + // ====================================================================================== + // + // Luckily, the gl spec (ES 3.0.2 pg 183) states that the results of clearing a render- + // buffer that is not normalized fixed point or floating point with floating point values + // are undefined so we can just write floats to them and D3D11 will bit cast them to + // integers. + // + // Also, we don't have to worry about attempting to clear a normalized fixed/floating point + // buffer with integer values because there is no gl API call which would allow it, + // glClearBuffer* calls only clear a single renderbuffer at a time which is verified to + // be a compatible clear type. + + // Bind all the render targets which need clearing + ASSERT(maskedClearRenderTargets.size() <= mRenderer->getRendererCaps().maxDrawBuffers); + std::vector rtvs(maskedClearRenderTargets.size()); + for (unsigned int i = 0; i < maskedClearRenderTargets.size(); i++) + { + RenderTarget11 *renderTarget = maskedClearRenderTargets[i].renderTarget; + ID3D11RenderTargetView *rtv = renderTarget->getRenderTargetView(); + if (!rtv) + { + return gl::Error(GL_OUT_OF_MEMORY, "Internal render target view pointer unexpectedly null."); + } + + rtvs[i] = rtv; + } + ID3D11DepthStencilView *dsv = maskedClearDepthStencil ? maskedClearDepthStencil->getDepthStencilView() : NULL; + + ID3D11BlendState *blendState = getBlendState(maskedClearRenderTargets); + const FLOAT blendFactors[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; + const UINT sampleMask = 0xFFFFFFFF; + + ID3D11DepthStencilState *dsState = getDepthStencilState(clearParams); + const UINT stencilClear = clearParams.stencilClearValue & 0xFF; + + // Set the vertices + UINT vertexStride = 0; + const UINT startIdx = 0; + const ClearShader* shader = NULL; + D3D11_MAPPED_SUBRESOURCE mappedResource; + HRESULT result = deviceContext->Map(mVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal masked clear vertex buffer, HRESULT: 0x%X.", result); + } + + const gl::Rectangle *scissorPtr = clearParams.scissorEnabled ? &clearParams.scissor : NULL; + switch (clearParams.colorClearType) + { + case GL_FLOAT: + ApplyVertices(framebufferSize, scissorPtr, clearParams.colorFClearValue, clearParams.depthClearValue, mappedResource.pData); + vertexStride = sizeof(d3d11::PositionDepthColorVertex); + shader = &mFloatClearShader; + break; + + case GL_UNSIGNED_INT: + ApplyVertices(framebufferSize, scissorPtr, clearParams.colorUIClearValue, clearParams.depthClearValue, mappedResource.pData); + vertexStride = sizeof(d3d11::PositionDepthColorVertex); + shader = &mUintClearShader; + break; + + case GL_INT: + ApplyVertices(framebufferSize, scissorPtr, clearParams.colorIClearValue, clearParams.depthClearValue, mappedResource.pData); + vertexStride = sizeof(d3d11::PositionDepthColorVertex); + shader = &mIntClearShader; + break; + + default: + UNREACHABLE(); + break; + } + + deviceContext->Unmap(mVertexBuffer, 0); + + // Set the viewport to be the same size as the framebuffer + D3D11_VIEWPORT viewport; + viewport.TopLeftX = 0; + viewport.TopLeftY = 0; + viewport.Width = framebufferSize.width; + viewport.Height = framebufferSize.height; + viewport.MinDepth = 0; + viewport.MaxDepth = 1; + deviceContext->RSSetViewports(1, &viewport); + + // Apply state + deviceContext->OMSetBlendState(blendState, blendFactors, sampleMask); + deviceContext->OMSetDepthStencilState(dsState, stencilClear); + deviceContext->RSSetState(mRasterizerState); + + // Apply shaders + deviceContext->IASetInputLayout(shader->inputLayout); + deviceContext->VSSetShader(shader->vertexShader, NULL, 0); + deviceContext->PSSetShader(shader->pixelShader, NULL, 0); + deviceContext->GSSetShader(NULL, NULL, 0); + + // Apply vertex buffer + deviceContext->IASetVertexBuffers(0, 1, &mVertexBuffer, &vertexStride, &startIdx); + deviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); + + // Apply render targets + deviceContext->OMSetRenderTargets(rtvs.size(), (rtvs.empty() ? NULL : &rtvs[0]), dsv); + + // Draw the clear quad + deviceContext->Draw(4, 0); + + // Clean up + mRenderer->markAllStateDirty(); + } + + return gl::Error(GL_NO_ERROR); +} + +ID3D11BlendState *Clear11::getBlendState(const std::vector& rts) +{ + ClearBlendInfo blendKey = { 0 }; + for (unsigned int i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++) + { + if (i < rts.size()) + { + RenderTarget11 *rt = rts[i].renderTarget; + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(rt->getInternalFormat()); + + blendKey.maskChannels[i][0] = (rts[i].colorMask[0] && formatInfo.redBits > 0); + blendKey.maskChannels[i][1] = (rts[i].colorMask[1] && formatInfo.greenBits > 0); + blendKey.maskChannels[i][2] = (rts[i].colorMask[2] && formatInfo.blueBits > 0); + blendKey.maskChannels[i][3] = (rts[i].colorMask[3] && formatInfo.alphaBits > 0); + } + else + { + blendKey.maskChannels[i][0] = false; + blendKey.maskChannels[i][1] = false; + blendKey.maskChannels[i][2] = false; + blendKey.maskChannels[i][3] = false; + } + } + + ClearBlendStateMap::const_iterator i = mClearBlendStates.find(blendKey); + if (i != mClearBlendStates.end()) + { + return i->second; + } + else + { + D3D11_BLEND_DESC blendDesc = { 0 }; + blendDesc.AlphaToCoverageEnable = FALSE; + blendDesc.IndependentBlendEnable = (rts.size() > 1) ? TRUE : FALSE; + + for (unsigned int j = 0; j < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; j++) + { + blendDesc.RenderTarget[j].BlendEnable = FALSE; + blendDesc.RenderTarget[j].RenderTargetWriteMask = gl_d3d11::ConvertColorMask(blendKey.maskChannels[j][0], + blendKey.maskChannels[j][1], + blendKey.maskChannels[j][2], + blendKey.maskChannels[j][3]); + } + + ID3D11Device *device = mRenderer->getDevice(); + ID3D11BlendState* blendState = NULL; + HRESULT result = device->CreateBlendState(&blendDesc, &blendState); + if (FAILED(result) || !blendState) + { + ERR("Unable to create a ID3D11BlendState, HRESULT: 0x%X.", result); + return NULL; + } + + mClearBlendStates[blendKey] = blendState; + + return blendState; + } +} + +ID3D11DepthStencilState *Clear11::getDepthStencilState(const ClearParameters &clearParams) +{ + ClearDepthStencilInfo dsKey = { 0 }; + dsKey.clearDepth = clearParams.clearDepth; + dsKey.clearStencil = clearParams.clearStencil; + dsKey.stencilWriteMask = clearParams.stencilWriteMask & 0xFF; + + ClearDepthStencilStateMap::const_iterator i = mClearDepthStencilStates.find(dsKey); + if (i != mClearDepthStencilStates.end()) + { + return i->second; + } + else + { + D3D11_DEPTH_STENCIL_DESC dsDesc = { 0 }; + dsDesc.DepthEnable = dsKey.clearDepth ? TRUE : FALSE; + dsDesc.DepthWriteMask = dsKey.clearDepth ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO; + dsDesc.DepthFunc = D3D11_COMPARISON_ALWAYS; + dsDesc.StencilEnable = dsKey.clearStencil ? TRUE : FALSE; + dsDesc.StencilReadMask = 0; + dsDesc.StencilWriteMask = dsKey.stencilWriteMask; + dsDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_REPLACE; + dsDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_REPLACE; + dsDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_REPLACE; + dsDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS; + dsDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_REPLACE; + dsDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_REPLACE; + dsDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_REPLACE; + dsDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS; + + ID3D11Device *device = mRenderer->getDevice(); + ID3D11DepthStencilState* dsState = NULL; + HRESULT result = device->CreateDepthStencilState(&dsDesc, &dsState); + if (FAILED(result) || !dsState) + { + ERR("Unable to create a ID3D11DepthStencilState, HRESULT: 0x%X.", result); + return NULL; + } + + mClearDepthStencilStates[dsKey] = dsState; + + return dsState; + } +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.h new file mode 100644 index 0000000000..4797ca1aa0 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.h @@ -0,0 +1,86 @@ +// +// 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. +// + +// Clear11.h: Framebuffer clear utility class. + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_CLEAR11_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_CLEAR11_H_ + +#include +#include + +#include "libANGLE/angletypes.h" +#include "libANGLE/Error.h" +#include "libANGLE/Framebuffer.h" + +namespace rx +{ +class Renderer11; +class RenderTarget11; +struct ClearParameters; + +class Clear11 : angle::NonCopyable +{ + public: + explicit Clear11(Renderer11 *renderer); + ~Clear11(); + + // Clears the framebuffer with the supplied clear parameters, assumes that the framebuffer is currently applied. + gl::Error clearFramebuffer(const ClearParameters &clearParams, const gl::Framebuffer::Data &fboData); + + private: + struct MaskedRenderTarget + { + bool colorMask[4]; + RenderTarget11 *renderTarget; + }; + + ID3D11BlendState *getBlendState(const std::vector &rts); + ID3D11DepthStencilState *getDepthStencilState(const ClearParameters &clearParams); + + struct ClearShader + { + ID3D11InputLayout *inputLayout; + ID3D11VertexShader *vertexShader; + ID3D11PixelShader *pixelShader; + }; + + template + static ClearShader CreateClearShader(ID3D11Device *device, DXGI_FORMAT colorType, const BYTE(&vsByteCode)[vsSize], const BYTE(&psByteCode)[psSize]); + + Renderer11 *mRenderer; + + struct ClearBlendInfo + { + bool maskChannels[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT][4]; + }; + typedef bool(*ClearBlendInfoComparisonFunction)(const ClearBlendInfo&, const ClearBlendInfo &); + typedef std::map ClearBlendStateMap; + ClearBlendStateMap mClearBlendStates; + + ClearShader mFloatClearShader; + ClearShader mUintClearShader; + ClearShader mIntClearShader; + + struct ClearDepthStencilInfo + { + bool clearDepth; + bool clearStencil; + UINT8 stencilWriteMask; + }; + typedef bool (*ClearDepthStencilInfoComparisonFunction)(const ClearDepthStencilInfo&, const ClearDepthStencilInfo &); + typedef std::map ClearDepthStencilStateMap; + ClearDepthStencilStateMap mClearDepthStencilStates; + + ID3D11Buffer *mVertexBuffer; + ID3D11RasterizerState *mRasterizerState; + + bool mSupportsClearView; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_D3D11_CLEAR11_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp new file mode 100644 index 0000000000..f1fe2bb2c7 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp @@ -0,0 +1,119 @@ +// +// Copyright 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// DebugAnnotator11.cpp: D3D11 helpers for adding trace annotations. +// + +#include "libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h" + +#include "common/debug.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" + +namespace rx +{ + +DebugAnnotator11::DebugAnnotator11() + : mInitialized(false), + mD3d11Module(nullptr), + mUserDefinedAnnotation(nullptr) +{ + // D3D11 devices can't be created during DllMain. + // We defer device creation until the object is actually used. +} + +DebugAnnotator11::~DebugAnnotator11() +{ + if (mInitialized) + { +#if defined(ANGLE_ENABLE_D3D11_1) + SafeRelease(mUserDefinedAnnotation); +#endif + +#if !defined(ANGLE_ENABLE_WINDOWS_STORE) + FreeLibrary(mD3d11Module); +#endif // !ANGLE_ENABLE_WINDOWS_STORE + } +} + +void DebugAnnotator11::beginEvent(const std::wstring &eventName) +{ + initializeDevice(); + +#if defined(ANGLE_ENABLE_D3D11_1) + mUserDefinedAnnotation->BeginEvent(eventName.c_str()); +#endif +} + +void DebugAnnotator11::endEvent() +{ + initializeDevice(); + +#if defined(ANGLE_ENABLE_D3D11_1) + mUserDefinedAnnotation->EndEvent(); +#endif +} + +void DebugAnnotator11::setMarker(const std::wstring &markerName) +{ + initializeDevice(); + +#if defined(ANGLE_ENABLE_D3D11_1) + mUserDefinedAnnotation->SetMarker(markerName.c_str()); +#endif +} + +bool DebugAnnotator11::getStatus() +{ + // ID3DUserDefinedAnnotation::GetStatus doesn't work with the Graphics Diagnostics tools in Visual Studio 2013. + +#if defined(_DEBUG) && defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP) + // In the Windows Store, we can use IDXGraphicsAnalysis. The call to GetDebugInterface1 only succeeds if the app is under capture. + // This should only be called in DEBUG mode. + // If an app links against DXGIGetDebugInterface1 in release mode then it will fail Windows Store ingestion checks. + IDXGraphicsAnalysis *graphicsAnalysis; + DXGIGetDebugInterface1(0, IID_PPV_ARGS(&graphicsAnalysis)); + bool underCapture = (graphicsAnalysis != nullptr); + SafeRelease(graphicsAnalysis); + return underCapture; +#endif // _DEBUG && !ANGLE_ENABLE_WINDOWS_STORE + + // Otherwise, we have to return true here. + return true; +} + +void DebugAnnotator11::initializeDevice() +{ + if (!mInitialized) + { +#if !defined(ANGLE_ENABLE_WINDOWS_STORE) + mD3d11Module = LoadLibrary(TEXT("d3d11.dll")); + ASSERT(mD3d11Module); + + PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE)GetProcAddress(mD3d11Module, "D3D11CreateDevice"); + ASSERT(D3D11CreateDevice != nullptr); +#endif // !ANGLE_ENABLE_WINDOWS_STORE + + ID3D11Device *device = nullptr; + ID3D11DeviceContext *context = nullptr; + + HRESULT hr = E_FAIL; + + // Create a D3D_DRIVER_TYPE_NULL device, which is much cheaper than other types of device. + hr = D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_NULL, nullptr, 0, nullptr, 0, D3D11_SDK_VERSION, &device, nullptr, &context); + ASSERT(SUCCEEDED(hr)); + +#if defined(ANGLE_ENABLE_D3D11_1) + mUserDefinedAnnotation = d3d11::DynamicCastComObject(context); + ASSERT(mUserDefinedAnnotation != nullptr); +#endif + + SafeRelease(device); + SafeRelease(context); + + mInitialized = true; + } +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h new file mode 100644 index 0000000000..3df62b015c --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h @@ -0,0 +1,39 @@ +// +// Copyright 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// DebugAnnotator11.h: D3D11 helpers for adding trace annotations. +// + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_DEBUGANNOTATOR11_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_DEBUGANNOTATOR11_H_ + +#include "common/debug.h" + +struct ID3DUserDefinedAnnotation; + +namespace rx +{ + +class DebugAnnotator11 : public gl::DebugAnnotator +{ + public: + DebugAnnotator11(); + ~DebugAnnotator11() override; + void beginEvent(const std::wstring &eventName) override; + void endEvent() override; + void setMarker(const std::wstring &markerName) override; + bool getStatus() override; + + private: + void initializeDevice(); + + bool mInitialized; + HMODULE mD3d11Module; + ID3DUserDefinedAnnotation *mUserDefinedAnnotation; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_D3D11_DEBUGANNOTATOR11_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Fence11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Fence11.cpp new file mode 100644 index 0000000000..8552bc2beb --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Fence11.cpp @@ -0,0 +1,231 @@ +// +// 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::FenceNV11 and rx::FenceSync11 classes which implement rx::FenceNVImpl and rx::FenceSyncImpl. + +#include "libANGLE/renderer/d3d/d3d11/Fence11.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" + +#include "common/utilities.h" + +namespace rx +{ + +// +// Template helpers for set and test operations. +// + +template +gl::Error FenceSetHelper(FenceClass *fence) +{ + if (!fence->mQuery) + { + D3D11_QUERY_DESC queryDesc; + queryDesc.Query = D3D11_QUERY_EVENT; + queryDesc.MiscFlags = 0; + + HRESULT result = fence->mRenderer->getDevice()->CreateQuery(&queryDesc, &fence->mQuery); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create event query, result: 0x%X.", result); + } + } + + fence->mRenderer->getDeviceContext()->End(fence->mQuery); + return gl::Error(GL_NO_ERROR); +} + +template +gl::Error FenceTestHelper(FenceClass *fence, bool flushCommandBuffer, GLboolean *outFinished) +{ + ASSERT(fence->mQuery); + + UINT getDataFlags = (flushCommandBuffer ? 0 : D3D11_ASYNC_GETDATA_DONOTFLUSH); + HRESULT result = fence->mRenderer->getDeviceContext()->GetData(fence->mQuery, NULL, 0, getDataFlags); + + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to get query data, result: 0x%X.", result); + } + else if (fence->mRenderer->isDeviceLost()) + { + return gl::Error(GL_OUT_OF_MEMORY, "Device was lost while querying result of an event query."); + } + + ASSERT(result == S_OK || result == S_FALSE); + *outFinished = ((result == S_OK) ? GL_TRUE : GL_FALSE); + return gl::Error(GL_NO_ERROR); +} + +// +// FenceNV11 +// + +FenceNV11::FenceNV11(Renderer11 *renderer) + : FenceNVImpl(), + mRenderer(renderer), + mQuery(NULL) +{ +} + +FenceNV11::~FenceNV11() +{ + SafeRelease(mQuery); +} + +gl::Error FenceNV11::set() +{ + return FenceSetHelper(this); +} + +gl::Error FenceNV11::test(bool flushCommandBuffer, GLboolean *outFinished) +{ + return FenceTestHelper(this, flushCommandBuffer, outFinished); +} + +gl::Error FenceNV11::finishFence(GLboolean *outFinished) +{ + ASSERT(outFinished); + + while (*outFinished != GL_TRUE) + { + gl::Error error = test(true, outFinished); + if (error.isError()) + { + return error; + } + + ScheduleYield(); + } + + return gl::Error(GL_NO_ERROR); +} + +// +// FenceSync11 +// + +// Important note on accurate timers in Windows: +// +// QueryPerformanceCounter has a few major issues, including being 10x as expensive to call +// as timeGetTime on laptops and "jumping" during certain hardware events. +// +// See the comments at the top of the Chromium source file "chromium/src/base/time/time_win.cc" +// https://code.google.com/p/chromium/codesearch#chromium/src/base/time/time_win.cc +// +// We still opt to use QPC. In the present and moving forward, most newer systems will not suffer +// from buggy implementations. + +FenceSync11::FenceSync11(Renderer11 *renderer) + : FenceSyncImpl(), + mRenderer(renderer), + mQuery(NULL) +{ + LARGE_INTEGER counterFreqency = { 0 }; + BOOL success = QueryPerformanceFrequency(&counterFreqency); + UNUSED_ASSERTION_VARIABLE(success); + ASSERT(success); + + mCounterFrequency = counterFreqency.QuadPart; +} + +FenceSync11::~FenceSync11() +{ + SafeRelease(mQuery); +} + +gl::Error FenceSync11::set() +{ + return FenceSetHelper(this); +} + +gl::Error FenceSync11::clientWait(GLbitfield flags, GLuint64 timeout, GLenum *outResult) +{ + ASSERT(outResult); + + bool flushCommandBuffer = ((flags & GL_SYNC_FLUSH_COMMANDS_BIT) != 0); + + GLboolean result = GL_FALSE; + gl::Error error = FenceTestHelper(this, flushCommandBuffer, &result); + if (error.isError()) + { + *outResult = GL_WAIT_FAILED; + return error; + } + + if (result == GL_TRUE) + { + *outResult = GL_ALREADY_SIGNALED; + return gl::Error(GL_NO_ERROR); + } + + if (timeout == 0) + { + *outResult = GL_TIMEOUT_EXPIRED; + return gl::Error(GL_NO_ERROR); + } + + LARGE_INTEGER currentCounter = { 0 }; + BOOL success = QueryPerformanceCounter(¤tCounter); + UNUSED_ASSERTION_VARIABLE(success); + ASSERT(success); + + LONGLONG timeoutInSeconds = static_cast(timeout) * static_cast(1000000ll); + LONGLONG endCounter = currentCounter.QuadPart + mCounterFrequency * timeoutInSeconds; + + while (currentCounter.QuadPart < endCounter && !result) + { + ScheduleYield(); + success = QueryPerformanceCounter(¤tCounter); + UNUSED_ASSERTION_VARIABLE(success); + ASSERT(success); + + error = FenceTestHelper(this, flushCommandBuffer, &result); + if (error.isError()) + { + *outResult = GL_WAIT_FAILED; + return error; + } + } + + if (currentCounter.QuadPart >= endCounter) + { + *outResult = GL_TIMEOUT_EXPIRED; + } + else + { + *outResult = GL_CONDITION_SATISFIED; + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error FenceSync11::serverWait(GLbitfield flags, GLuint64 timeout) +{ + // Because our API is currently designed to be called from a single thread, we don't need to do + // extra work for a server-side fence. GPU commands issued after the fence is created will always + // be processed after the fence is signaled. + return gl::Error(GL_NO_ERROR); +} + +gl::Error FenceSync11::getStatus(GLint *outResult) +{ + GLboolean result = GL_FALSE; + gl::Error error = FenceTestHelper(this, false, &result); + if (error.isError()) + { + // The spec does not specify any way to report errors during the status test (e.g. device lost) + // so we report the fence is unblocked in case of error or signaled. + *outResult = GL_SIGNALED; + + return error; + } + + *outResult = (result ? GL_SIGNALED : GL_UNSIGNALED); + return gl::Error(GL_NO_ERROR); +} + +} // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Fence11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Fence11.h new file mode 100644 index 0000000000..2d87f43e76 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Fence11.h @@ -0,0 +1,59 @@ +// +// 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::FenceNV11 and rx::FenceSync11 classes which implement rx::FenceNVImpl and rx::FenceSyncImpl. + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_FENCE11_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_FENCE11_H_ + +#include "libANGLE/renderer/FenceNVImpl.h" +#include "libANGLE/renderer/FenceSyncImpl.h" + +namespace rx +{ +class Renderer11; + +class FenceNV11 : public FenceNVImpl +{ + public: + explicit FenceNV11(Renderer11 *renderer); + virtual ~FenceNV11(); + + gl::Error set(); + gl::Error test(bool flushCommandBuffer, GLboolean *outFinished); + gl::Error finishFence(GLboolean *outFinished); + + private: + template friend gl::Error FenceSetHelper(T *fence); + template friend gl::Error FenceTestHelper(T *fence, bool flushCommandBuffer, GLboolean *outFinished); + + Renderer11 *mRenderer; + ID3D11Query *mQuery; +}; + +class FenceSync11 : public FenceSyncImpl +{ + public: + explicit FenceSync11(Renderer11 *renderer); + virtual ~FenceSync11(); + + gl::Error set(); + gl::Error clientWait(GLbitfield flags, GLuint64 timeout, GLenum *outResult); + gl::Error serverWait(GLbitfield flags, GLuint64 timeout); + gl::Error getStatus(GLint *outResult); + + private: + template friend gl::Error FenceSetHelper(T *fence); + template friend gl::Error FenceTestHelper(T *fence, bool flushCommandBuffer, GLboolean *outFinished); + + Renderer11 *mRenderer; + ID3D11Query *mQuery; + LONGLONG mCounterFrequency; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_D3D11_FENCE11_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp new file mode 100644 index 0000000000..da01f320c0 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp @@ -0,0 +1,270 @@ +// +// Copyright 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Framebuffer11.cpp: Implements the Framebuffer11 class. + +#include "libANGLE/renderer/d3d/d3d11/Framebuffer11.h" + +#include "common/debug.h" +#include "libANGLE/renderer/d3d/d3d11/Buffer11.h" +#include "libANGLE/renderer/d3d/d3d11/Clear11.h" +#include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" +#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h" +#include "libANGLE/renderer/d3d/d3d11/formatutils11.h" +#include "libANGLE/renderer/d3d/TextureD3D.h" +#include "libANGLE/Framebuffer.h" +#include "libANGLE/FramebufferAttachment.h" +#include "libANGLE/Texture.h" + +namespace rx +{ + +Framebuffer11::Framebuffer11(const gl::Framebuffer::Data &data, Renderer11 *renderer) + : FramebufferD3D(data, renderer), + mRenderer(renderer) +{ + ASSERT(mRenderer != nullptr); +} + +Framebuffer11::~Framebuffer11() +{ +} + +static gl::Error InvalidateAttachmentSwizzles(const gl::FramebufferAttachment *attachment) +{ + if (attachment && attachment->type() == GL_TEXTURE) + { + gl::Texture *texture = attachment->getTexture(); + + TextureD3D *textureD3D = GetImplAs(texture); + + TextureStorage *texStorage = NULL; + gl::Error error = textureD3D->getNativeTexture(&texStorage); + if (error.isError()) + { + return error; + } + + if (texStorage) + { + TextureStorage11 *texStorage11 = TextureStorage11::makeTextureStorage11(texStorage); + ASSERT(texStorage11); + + texStorage11->invalidateSwizzleCacheLevel(attachment->mipLevel()); + } + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Framebuffer11::invalidateSwizzles() const +{ + for (auto it = mData.mColorAttachments.cbegin(); it != mData.mColorAttachments.cend(); ++it) + { + gl::FramebufferAttachment *colorAttachment = *it; + gl::Error error = InvalidateAttachmentSwizzles(colorAttachment); + if (error.isError()) + { + return error; + } + } + + gl::Error error = InvalidateAttachmentSwizzles(mData.mDepthAttachment); + if (error.isError()) + { + return error; + } + + error = InvalidateAttachmentSwizzles(mData.mStencilAttachment); + if (error.isError()) + { + return error; + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Framebuffer11::clear(const gl::State &state, const ClearParameters &clearParams) +{ + Clear11 *clearer = mRenderer->getClearer(); + gl::Error error = clearer->clearFramebuffer(clearParams, mData); + if (error.isError()) + { + return error; + } + + error = invalidateSwizzles(); + if (error.isError()) + { + return error; + } + + return gl::Error(GL_NO_ERROR); +} + +static gl::Error getRenderTargetResource(const gl::FramebufferAttachment *colorbuffer, unsigned int *subresourceIndexOut, + ID3D11Texture2D **texture2DOut) +{ + ASSERT(colorbuffer); + + RenderTarget11 *renderTarget = NULL; + gl::Error error = d3d11::GetAttachmentRenderTarget(colorbuffer, &renderTarget); + if (error.isError()) + { + return error; + } + + ID3D11Resource *renderTargetResource = renderTarget->getTexture(); + ASSERT(renderTargetResource); + + *subresourceIndexOut = renderTarget->getSubresourceIndex(); + *texture2DOut = d3d11::DynamicCastComObject(renderTargetResource); + + if (!(*texture2DOut)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to query the ID3D11Texture2D from a RenderTarget"); + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Framebuffer11::readPixels(const gl::Rectangle &area, GLenum format, GLenum type, size_t outputPitch, const gl::PixelPackState &pack, uint8_t *pixels) const +{ + ID3D11Texture2D *colorBufferTexture = NULL; + unsigned int subresourceIndex = 0; + + const gl::FramebufferAttachment *colorbuffer = mData.getReadAttachment(); + ASSERT(colorbuffer); + + gl::Error error = getRenderTargetResource(colorbuffer, &subresourceIndex, &colorBufferTexture); + if (error.isError()) + { + return error; + } + + gl::Buffer *packBuffer = pack.pixelBuffer.get(); + if (packBuffer != NULL) + { + Buffer11 *packBufferStorage = Buffer11::makeBuffer11(packBuffer->getImplementation()); + PackPixelsParams packParams(area, format, type, outputPitch, pack, reinterpret_cast(pixels)); + + error = packBufferStorage->packPixels(colorBufferTexture, subresourceIndex, packParams); + if (error.isError()) + { + SafeRelease(colorBufferTexture); + return error; + } + + packBuffer->getIndexRangeCache()->clear(); + } + else + { + error = mRenderer->readTextureData(colorBufferTexture, subresourceIndex, area, format, type, outputPitch, pack, pixels); + if (error.isError()) + { + SafeRelease(colorBufferTexture); + return error; + } + } + + SafeRelease(colorBufferTexture); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Framebuffer11::blit(const gl::Rectangle &sourceArea, const gl::Rectangle &destArea, const gl::Rectangle *scissor, + bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter, + const gl::Framebuffer *sourceFramebuffer) +{ + if (blitRenderTarget) + { + const gl::FramebufferAttachment *readBuffer = sourceFramebuffer->getReadColorbuffer(); + ASSERT(readBuffer); + + RenderTargetD3D *readRenderTarget = NULL; + gl::Error error = GetAttachmentRenderTarget(readBuffer, &readRenderTarget); + if (error.isError()) + { + return error; + } + ASSERT(readRenderTarget); + + for (size_t colorAttachment = 0; colorAttachment < mData.mColorAttachments.size(); colorAttachment++) + { + if (mData.mColorAttachments[colorAttachment] != nullptr && + mData.mDrawBufferStates[colorAttachment] != GL_NONE) + { + const gl::FramebufferAttachment *drawBuffer = mData.mColorAttachments[colorAttachment]; + + RenderTargetD3D *drawRenderTarget = NULL; + error = GetAttachmentRenderTarget(drawBuffer, &drawRenderTarget); + if (error.isError()) + { + return error; + } + ASSERT(drawRenderTarget); + + error = mRenderer->blitRenderbufferRect(sourceArea, destArea, readRenderTarget, drawRenderTarget, + filter, scissor, blitRenderTarget, false, false); + if (error.isError()) + { + return error; + } + } + } + } + + if (blitDepth || blitStencil) + { + gl::FramebufferAttachment *readBuffer = sourceFramebuffer->getDepthOrStencilbuffer(); + ASSERT(readBuffer); + + RenderTargetD3D *readRenderTarget = NULL; + gl::Error error = GetAttachmentRenderTarget(readBuffer, &readRenderTarget); + if (error.isError()) + { + return error; + } + ASSERT(readRenderTarget); + + const gl::FramebufferAttachment *drawBuffer = mData.getDepthOrStencilAttachment(); + ASSERT(drawBuffer); + + RenderTargetD3D *drawRenderTarget = NULL; + error = GetAttachmentRenderTarget(drawBuffer, &drawRenderTarget); + if (error.isError()) + { + return error; + } + ASSERT(drawRenderTarget); + + error = mRenderer->blitRenderbufferRect(sourceArea, destArea, readRenderTarget, drawRenderTarget, filter, scissor, + false, blitDepth, blitStencil); + if (error.isError()) + { + return error; + } + } + + gl::Error error = invalidateSwizzles(); + if (error.isError()) + { + return error; + } + + return gl::Error(GL_NO_ERROR); +} + +GLenum Framebuffer11::getRenderTargetImplementationFormat(RenderTargetD3D *renderTarget) const +{ + RenderTarget11 *renderTarget11 = RenderTarget11::makeRenderTarget11(renderTarget); + const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(renderTarget11->getDXGIFormat()); + return dxgiFormatInfo.internalFormat; +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.h new file mode 100644 index 0000000000..07fa480fa2 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.h @@ -0,0 +1,45 @@ +// +// Copyright 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Framebuffer11.h: Defines the Framebuffer11 class. + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_FRAMBUFFER11_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_FRAMBUFFER11_H_ + +#include "libANGLE/renderer/d3d/FramebufferD3D.h" + +namespace rx +{ +class Renderer11; + +class Framebuffer11 : public FramebufferD3D +{ + public: + Framebuffer11(const gl::Framebuffer::Data &data, Renderer11 *renderer); + virtual ~Framebuffer11(); + + // Invalidate the cached swizzles of all bound texture attachments. + gl::Error invalidateSwizzles() const; + + private: + gl::Error clear(const gl::State &state, const ClearParameters &clearParams) override; + + gl::Error readPixels(const gl::Rectangle &area, GLenum format, GLenum type, size_t outputPitch, + const gl::PixelPackState &pack, uint8_t *pixels) const override; + + gl::Error blit(const gl::Rectangle &sourceArea, const gl::Rectangle &destArea, const gl::Rectangle *scissor, + bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter, + const gl::Framebuffer *sourceFramebuffer) override; + + + GLenum getRenderTargetImplementationFormat(RenderTargetD3D *renderTarget) const override; + + Renderer11 *const mRenderer; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_D3D11_FRAMBUFFER11_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Image11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Image11.cpp new file mode 100644 index 0000000000..956b78b5a6 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Image11.cpp @@ -0,0 +1,664 @@ +// +// 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 "libANGLE/renderer/d3d/d3d11/Renderer11.h" +#include "libANGLE/renderer/d3d/d3d11/Image11.h" +#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h" +#include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h" +#include "libANGLE/renderer/d3d/d3d11/formatutils11.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" +#include "libANGLE/Framebuffer.h" +#include "libANGLE/FramebufferAttachment.h" +#include "libANGLE/formatutils.h" + +#include "common/utilities.h" + +namespace rx +{ + +Image11::Image11(Renderer11 *renderer) + : mRenderer(renderer), + mDXGIFormat(DXGI_FORMAT_UNKNOWN), + mStagingTexture(NULL), + mStagingSubresource(0), + mRecoverFromStorage(false), + mAssociatedStorage(NULL), + mAssociatedImageIndex(gl::ImageIndex::MakeInvalid()), + mRecoveredFromStorageCount(0) +{ + // mRenderer should remain unchanged during the lifetime of the Image11 object. + // This lets us safely use mRenderer (and its Feature Level) in Image11's methods. + mFeatureLevel = renderer->getFeatureLevel(); +} + +Image11::~Image11() +{ + disassociateStorage(); + releaseStagingTexture(); +} + +Image11 *Image11::makeImage11(ImageD3D *img) +{ + ASSERT(HAS_DYNAMIC_TYPE(Image11*, img)); + return static_cast(img); +} + +gl::Error 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()); + + const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(src->getDXGIFormat()); + ASSERT(dxgiFormatInfo.mipGenerationFunction != NULL); + + D3D11_MAPPED_SUBRESOURCE destMapped; + gl::Error error = dest->map(D3D11_MAP_WRITE, &destMapped); + if (error.isError()) + { + return error; + } + + D3D11_MAPPED_SUBRESOURCE srcMapped; + error = src->map(D3D11_MAP_READ, &srcMapped); + if (error.isError()) + { + dest->unmap(); + return error; + } + + const uint8_t *sourceData = reinterpret_cast(srcMapped.pData); + uint8_t *destData = reinterpret_cast(destMapped.pData); + + dxgiFormatInfo.mipGenerationFunction(src->getWidth(), src->getHeight(), src->getDepth(), + sourceData, srcMapped.RowPitch, srcMapped.DepthPitch, + destData, destMapped.RowPitch, destMapped.DepthPitch); + + dest->unmap(); + src->unmap(); + + dest->markDirty(); + + return gl::Error(GL_NO_ERROR); +} + +bool Image11::isDirty() const +{ + // If mDirty is true + // AND mStagingTexture doesn't exist AND mStagingTexture doesn't need to be recovered from TextureStorage + // AND the texture doesn't require init data (i.e. a blank new texture will suffice) + // then isDirty should still return false. + if (mDirty && !mStagingTexture && !mRecoverFromStorage && !(d3d11::GetTextureFormatInfo(mInternalFormat, mFeatureLevel).dataInitializerFunction != NULL)) + { + return false; + } + + return mDirty; +} + +gl::Error Image11::copyToStorage(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box ®ion) +{ + TextureStorage11 *storage11 = TextureStorage11::makeTextureStorage11(storage); + + // If an app's behavior results in an Image11 copying its data to/from to a TextureStorage multiple times, + // then we should just keep the staging texture around to prevent the copying from impacting perf. + // We allow the Image11 to copy its data to/from TextureStorage once. + // This accounts for an app making a late call to glGenerateMipmap. + bool attemptToReleaseStagingTexture = (mRecoveredFromStorageCount < 2); + + if (attemptToReleaseStagingTexture) + { + // If another image is relying on this Storage for its data, then we must let it recover its data before we overwrite it. + gl::Error error = storage11->releaseAssociatedImage(index, this); + if (error.isError()) + { + return error; + } + } + + ID3D11Resource *stagingTexture = NULL; + unsigned int stagingSubresourceIndex = 0; + gl::Error error = getStagingTexture(&stagingTexture, &stagingSubresourceIndex); + if (error.isError()) + { + return error; + } + + error = storage11->updateSubresourceLevel(stagingTexture, stagingSubresourceIndex, index, region); + if (error.isError()) + { + return error; + } + + // Once the image data has been copied into the Storage, we can release it locally. + if (attemptToReleaseStagingTexture) + { + storage11->associateImage(this, index); + releaseStagingTexture(); + mRecoverFromStorage = true; + mAssociatedStorage = storage11; + mAssociatedImageIndex = index; + } + + return gl::Error(GL_NO_ERROR); +} + +bool Image11::isAssociatedStorageValid(TextureStorage11* textureStorage) const +{ + return (mAssociatedStorage == textureStorage); +} + +gl::Error Image11::recoverFromAssociatedStorage() +{ + if (mRecoverFromStorage) + { + gl::Error error = createStagingTexture(); + if (error.isError()) + { + return error; + } + + bool textureStorageCorrect = mAssociatedStorage->isAssociatedImageValid(mAssociatedImageIndex, this); + + // This means that the cached TextureStorage has been modified after this Image11 released its copy of its data. + // This should not have happened. The TextureStorage should have told this Image11 to recover its data before it was overwritten. + ASSERT(textureStorageCorrect); + + if (textureStorageCorrect) + { + // CopySubResource from the Storage to the Staging texture + gl::Box region(0, 0, 0, mWidth, mHeight, mDepth); + error = mAssociatedStorage->copySubresourceLevel(mStagingTexture, mStagingSubresource, mAssociatedImageIndex, region); + if (error.isError()) + { + return error; + } + + mRecoveredFromStorageCount += 1; + } + + // Reset all the recovery parameters, even if the texture storage association is broken. + disassociateStorage(); + } + + return gl::Error(GL_NO_ERROR); +} + +void Image11::disassociateStorage() +{ + if (mRecoverFromStorage) + { + // Make the texturestorage release the Image11 too + mAssociatedStorage->disassociateImage(mAssociatedImageIndex, this); + + mRecoverFromStorage = false; + mAssociatedStorage = NULL; + mAssociatedImageIndex = gl::ImageIndex::MakeInvalid(); + } +} + +bool Image11::redefine(GLenum target, GLenum internalformat, const gl::Extents &size, bool forceRelease) +{ + if (mWidth != size.width || + mHeight != size.height || + mInternalFormat != internalformat || + forceRelease) + { + // End the association with the TextureStorage, since that data will be out of date. + // Also reset mRecoveredFromStorageCount since this Image is getting completely redefined. + disassociateStorage(); + mRecoveredFromStorageCount = 0; + + mWidth = size.width; + mHeight = size.height; + mDepth = size.depth; + mInternalFormat = internalformat; + mTarget = target; + + // compute the d3d format that will be used + const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat, mFeatureLevel); + mDXGIFormat = formatInfo.texFormat; + mRenderable = (formatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN); + + releaseStagingTexture(); + mDirty = (formatInfo.dataInitializerFunction != NULL); + + return true; + } + + return false; +} + +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. +gl::Error Image11::loadData(const gl::Box &area, const gl::PixelUnpackState &unpack, GLenum type, const void *input) +{ + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat); + GLsizei inputRowPitch = formatInfo.computeRowPitch(type, area.width, unpack.alignment, unpack.rowLength); + GLsizei inputDepthPitch = formatInfo.computeDepthPitch(type, area.width, area.height, unpack.alignment, unpack.rowLength); + + const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mDXGIFormat); + GLuint outputPixelSize = dxgiFormatInfo.pixelBytes; + + const d3d11::TextureFormat &d3dFormatInfo = d3d11::GetTextureFormatInfo(mInternalFormat, mFeatureLevel); + LoadImageFunction loadFunction = d3dFormatInfo.loadFunctions.at(type); + + D3D11_MAPPED_SUBRESOURCE mappedImage; + gl::Error error = map(D3D11_MAP_WRITE, &mappedImage); + if (error.isError()) + { + return error; + } + + uint8_t *offsetMappedData = (reinterpret_cast(mappedImage.pData) + (area.y * mappedImage.RowPitch + area.x * outputPixelSize + area.z * mappedImage.DepthPitch)); + loadFunction(area.width, area.height, area.depth, + reinterpret_cast(input), inputRowPitch, inputDepthPitch, + offsetMappedData, mappedImage.RowPitch, mappedImage.DepthPitch); + + unmap(); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Image11::loadCompressedData(const gl::Box &area, const void *input) +{ + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat); + GLsizei inputRowPitch = formatInfo.computeRowPitch(GL_UNSIGNED_BYTE, area.width, 1, 0); + GLsizei inputDepthPitch = formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, area.width, area.height, 1, 0); + + const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mDXGIFormat); + GLuint outputPixelSize = dxgiFormatInfo.pixelBytes; + GLuint outputBlockWidth = dxgiFormatInfo.blockWidth; + GLuint outputBlockHeight = dxgiFormatInfo.blockHeight; + + ASSERT(area.x % outputBlockWidth == 0); + ASSERT(area.y % outputBlockHeight == 0); + + const d3d11::TextureFormat &d3dFormatInfo = d3d11::GetTextureFormatInfo(mInternalFormat, mFeatureLevel); + LoadImageFunction loadFunction = d3dFormatInfo.loadFunctions.at(GL_UNSIGNED_BYTE); + + D3D11_MAPPED_SUBRESOURCE mappedImage; + gl::Error error = map(D3D11_MAP_WRITE, &mappedImage); + if (error.isError()) + { + return error; + } + + uint8_t* offsetMappedData = reinterpret_cast(mappedImage.pData) + ((area.y / outputBlockHeight) * mappedImage.RowPitch + + (area.x / outputBlockWidth) * outputPixelSize + + area.z * mappedImage.DepthPitch); + + loadFunction(area.width, area.height, area.depth, + reinterpret_cast(input), inputRowPitch, inputDepthPitch, + offsetMappedData, mappedImage.RowPitch, mappedImage.DepthPitch); + + unmap(); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Image11::copy(const gl::Offset &destOffset, const gl::Rectangle &sourceArea, RenderTargetD3D *source) +{ + RenderTarget11 *sourceRenderTarget = RenderTarget11::makeRenderTarget11(source); + ASSERT(sourceRenderTarget->getTexture()); + + ID3D11Resource *resource = sourceRenderTarget->getTexture(); + UINT subresourceIndex = sourceRenderTarget->getSubresourceIndex(); + + gl::Box sourceBox(sourceArea.x, sourceArea.y, 0, sourceArea.width, sourceArea.height, 1); + gl::Error error = copy(destOffset, sourceBox, resource, subresourceIndex); + + SafeRelease(resource); + + return error; +} + +gl::Error Image11::copy(const gl::Offset &destOffset, const gl::Box &sourceArea, const gl::ImageIndex &sourceIndex, TextureStorage *source) +{ + TextureStorage11 *sourceStorage11 = TextureStorage11::makeTextureStorage11(source); + + UINT subresourceIndex = sourceStorage11->getSubresourceIndex(sourceIndex); + ID3D11Resource *resource = NULL; + gl::Error error = sourceStorage11->getResource(&resource); + if (error.isError()) + { + return error; + } + + error = copy(destOffset, sourceArea, resource, subresourceIndex); + + SafeRelease(resource); + + return error; +} + +gl::Error Image11::copy(const gl::Offset &destOffset, const gl::Box &sourceArea, ID3D11Resource *source, UINT sourceSubResource) +{ + D3D11_RESOURCE_DIMENSION dim; + source->GetType(&dim); + + DXGI_FORMAT format = DXGI_FORMAT_UNKNOWN; + gl::Extents extents; + UINT sampleCount = 0; + + ID3D11Texture2D *source2D = NULL; + + if (dim == D3D11_RESOURCE_DIMENSION_TEXTURE2D) + { + D3D11_TEXTURE2D_DESC textureDesc2D; + source2D = d3d11::DynamicCastComObject(source); + ASSERT(source2D); + source2D->GetDesc(&textureDesc2D); + + format = textureDesc2D.Format; + extents = gl::Extents(textureDesc2D.Width, textureDesc2D.Height, 1); + sampleCount = textureDesc2D.SampleDesc.Count; + } + else if (dim == D3D11_RESOURCE_DIMENSION_TEXTURE3D) + { + D3D11_TEXTURE3D_DESC textureDesc3D; + ID3D11Texture3D *source3D = d3d11::DynamicCastComObject(source); + ASSERT(source3D); + source3D->GetDesc(&textureDesc3D); + + format = textureDesc3D.Format; + extents = gl::Extents(textureDesc3D.Width, textureDesc3D.Height, textureDesc3D.Depth); + sampleCount = 1; + } + else + { + UNREACHABLE(); + } + + if (format == mDXGIFormat) + { + // No conversion needed-- use copyback fastpath + ID3D11Resource *stagingTexture = NULL; + unsigned int stagingSubresourceIndex = 0; + gl::Error error = getStagingTexture(&stagingTexture, &stagingSubresourceIndex); + if (error.isError()) + { + return error; + } + + ID3D11Device *device = mRenderer->getDevice(); + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + + UINT subresourceAfterResolve = sourceSubResource; + + ID3D11Resource *srcTex = NULL; + + bool needResolve = (dim == D3D11_RESOURCE_DIMENSION_TEXTURE2D && sampleCount > 1); + + if (needResolve) + { + D3D11_TEXTURE2D_DESC resolveDesc; + resolveDesc.Width = extents.width; + resolveDesc.Height = extents.height; + resolveDesc.MipLevels = 1; + resolveDesc.ArraySize = 1; + resolveDesc.Format = format; + resolveDesc.SampleDesc.Count = 1; + resolveDesc.SampleDesc.Quality = 0; + resolveDesc.Usage = D3D11_USAGE_DEFAULT; + resolveDesc.BindFlags = 0; + resolveDesc.CPUAccessFlags = 0; + resolveDesc.MiscFlags = 0; + + ID3D11Texture2D *srcTex2D = NULL; + HRESULT result = device->CreateTexture2D(&resolveDesc, NULL, &srcTex2D); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create resolve texture for Image11::copy, HRESULT: 0x%X.", result); + } + srcTex = srcTex2D; + + deviceContext->ResolveSubresource(srcTex, 0, source, sourceSubResource, format); + subresourceAfterResolve = 0; + } + else + { + srcTex = source; + } + + D3D11_BOX srcBox; + srcBox.left = sourceArea.x; + srcBox.right = sourceArea.x + sourceArea.width; + srcBox.top = sourceArea.y; + srcBox.bottom = sourceArea.y + sourceArea.height; + srcBox.front = sourceArea.z; + srcBox.back = sourceArea.z + sourceArea.depth; + + deviceContext->CopySubresourceRegion(stagingTexture, stagingSubresourceIndex, destOffset.x, destOffset.y, + destOffset.z, srcTex, subresourceAfterResolve, &srcBox); + + if (needResolve) + { + SafeRelease(srcTex); + } + } + else + { + // This format requires conversion, so we must copy the texture to staging and manually convert via readPixels + D3D11_MAPPED_SUBRESOURCE mappedImage; + gl::Error error = map(D3D11_MAP_WRITE, &mappedImage); + if (error.isError()) + { + return error; + } + + // determine the offset coordinate into the destination buffer + const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mDXGIFormat); + GLsizei rowOffset = dxgiFormatInfo.pixelBytes * destOffset.x; + uint8_t *dataOffset = static_cast(mappedImage.pData) + mappedImage.RowPitch * destOffset.y + rowOffset + destOffset.z * mappedImage.DepthPitch; + + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat); + + // Currently in ANGLE, the source data may only need to be converted if the source is the current framebuffer + // and OpenGL ES framebuffers must be 2D textures therefore we should not need to convert 3D textures between different formats. + ASSERT(dim == D3D11_RESOURCE_DIMENSION_TEXTURE2D); + ASSERT(sourceArea.z == 0 && sourceArea.depth == 1); + gl::Rectangle sourceRect(sourceArea.x, sourceArea.y, sourceArea.width, sourceArea.height); + error = mRenderer->readTextureData(source2D, sourceSubResource, sourceRect, formatInfo.format, formatInfo.type, mappedImage.RowPitch, gl::PixelPackState(), dataOffset); + + unmap(); + + if (error.isError()) + { + return error; + } + } + + mDirty = true; + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Image11::getStagingTexture(ID3D11Resource **outStagingTexture, unsigned int *outSubresourceIndex) +{ + gl::Error error = createStagingTexture(); + if (error.isError()) + { + return error; + } + + *outStagingTexture = mStagingTexture; + *outSubresourceIndex = mStagingSubresource; + return gl::Error(GL_NO_ERROR); +} + +void Image11::releaseStagingTexture() +{ + SafeRelease(mStagingTexture); +} + +gl::Error Image11::createStagingTexture() +{ + if (mStagingTexture) + { + return gl::Error(GL_NO_ERROR); + } + + ASSERT(mWidth > 0 && mHeight > 0 && mDepth > 0); + + const DXGI_FORMAT dxgiFormat = getDXGIFormat(); + + ID3D11Device *device = mRenderer->getDevice(); + HRESULT result; + + int lodOffset = 1; + GLsizei width = mWidth; + GLsizei height = mHeight; + + // adjust size if needed for compressed textures + d3d11::MakeValidSize(false, dxgiFormat, &width, &height, &lodOffset); + + if (mTarget == GL_TEXTURE_3D) + { + ID3D11Texture3D *newTexture = NULL; + + D3D11_TEXTURE3D_DESC desc; + desc.Width = width; + desc.Height = height; + desc.Depth = mDepth; + desc.MipLevels = lodOffset + 1; + desc.Format = dxgiFormat; + desc.Usage = D3D11_USAGE_STAGING; + desc.BindFlags = 0; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + + if (d3d11::GetTextureFormatInfo(mInternalFormat, mFeatureLevel).dataInitializerFunction != NULL) + { + std::vector initialData; + std::vector< std::vector > textureData; + d3d11::GenerateInitialTextureData(mInternalFormat, mFeatureLevel, width, height, mDepth, + lodOffset + 1, &initialData, &textureData); + + result = device->CreateTexture3D(&desc, initialData.data(), &newTexture); + } + else + { + result = device->CreateTexture3D(&desc, NULL, &newTexture); + } + + if (FAILED(result)) + { + ASSERT(result == E_OUTOFMEMORY); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create staging texture, result: 0x%X.", result); + } + + mStagingTexture = newTexture; + mStagingSubresource = D3D11CalcSubresource(lodOffset, 0, lodOffset + 1); + } + else if (mTarget == GL_TEXTURE_2D || mTarget == GL_TEXTURE_2D_ARRAY || mTarget == GL_TEXTURE_CUBE_MAP) + { + ID3D11Texture2D *newTexture = NULL; + + D3D11_TEXTURE2D_DESC desc; + desc.Width = width; + desc.Height = height; + desc.MipLevels = lodOffset + 1; + desc.ArraySize = 1; + desc.Format = dxgiFormat; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Usage = D3D11_USAGE_STAGING; + desc.BindFlags = 0; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + + if (d3d11::GetTextureFormatInfo(mInternalFormat, mFeatureLevel).dataInitializerFunction != NULL) + { + std::vector initialData; + std::vector< std::vector > textureData; + d3d11::GenerateInitialTextureData(mInternalFormat, mFeatureLevel, width, height, 1, + lodOffset + 1, &initialData, &textureData); + + result = device->CreateTexture2D(&desc, initialData.data(), &newTexture); + } + else + { + result = device->CreateTexture2D(&desc, NULL, &newTexture); + } + + if (FAILED(result)) + { + ASSERT(result == E_OUTOFMEMORY); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create staging texture, result: 0x%X.", result); + } + + mStagingTexture = newTexture; + mStagingSubresource = D3D11CalcSubresource(lodOffset, 0, lodOffset + 1); + } + else + { + UNREACHABLE(); + } + + mDirty = false; + return gl::Error(GL_NO_ERROR); +} + +gl::Error Image11::map(D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map) +{ + // We must recover from the TextureStorage if necessary, even for D3D11_MAP_WRITE. + gl::Error error = recoverFromAssociatedStorage(); + if (error.isError()) + { + return error; + } + + ID3D11Resource *stagingTexture = NULL; + unsigned int subresourceIndex = 0; + error = getStagingTexture(&stagingTexture, &subresourceIndex); + if (error.isError()) + { + return error; + } + + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + + ASSERT(mStagingTexture); + HRESULT result = deviceContext->Map(stagingTexture, subresourceIndex, mapType, 0, map); + + // this can fail if the device is removed (from TDR) + if (d3d11::isDeviceLostError(result)) + { + mRenderer->notifyDeviceLost(); + } + else if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to map staging texture, result: 0x%X.", result); + } + + mDirty = true; + + return gl::Error(GL_NO_ERROR); +} + +void Image11::unmap() +{ + if (mStagingTexture) + { + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + deviceContext->Unmap(mStagingTexture, mStagingSubresource); + } +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Image11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Image11.h new file mode 100644 index 0000000000..5734f73b15 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Image11.h @@ -0,0 +1,84 @@ +// +// 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 LIBANGLE_RENDERER_D3D_D3D11_IMAGE11_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_IMAGE11_H_ + +#include "libANGLE/renderer/d3d/ImageD3D.h" +#include "libANGLE/ImageIndex.h" + +#include "common/debug.h" + +namespace gl +{ +class Framebuffer; +} + +namespace rx +{ +class Renderer11; +class TextureStorage11; + +class Image11 : public ImageD3D +{ + public: + Image11(Renderer11 *renderer); + virtual ~Image11(); + + static Image11 *makeImage11(ImageD3D *img); + + static gl::Error generateMipmap(Image11 *dest, Image11 *src); + + virtual bool isDirty() const; + + virtual gl::Error copyToStorage(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box ®ion); + + bool redefine(GLenum target, GLenum internalformat, const gl::Extents &size, bool forceRelease) override; + + DXGI_FORMAT getDXGIFormat() const; + + virtual gl::Error loadData(const gl::Box &area, const gl::PixelUnpackState &unpack, GLenum type, const void *input); + virtual gl::Error loadCompressedData(const gl::Box &area, const void *input); + + virtual gl::Error copy(const gl::Offset &destOffset, const gl::Rectangle &sourceArea, RenderTargetD3D *source); + virtual gl::Error copy(const gl::Offset &destOffset, const gl::Box &sourceArea, + const gl::ImageIndex &sourceIndex, TextureStorage *source); + + gl::Error recoverFromAssociatedStorage(); + bool isAssociatedStorageValid(TextureStorage11* textureStorage) const; + void disassociateStorage(); + + protected: + gl::Error map(D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map); + void unmap(); + + private: + gl::Error copyToStorageImpl(TextureStorage11 *storage11, const gl::ImageIndex &index, const gl::Box ®ion); + gl::Error copy(const gl::Offset &destOffset, const gl::Box &sourceArea, ID3D11Resource *source, UINT sourceSubResource); + + gl::Error getStagingTexture(ID3D11Resource **outStagingTexture, unsigned int *outSubresourceIndex); + gl::Error createStagingTexture(); + void releaseStagingTexture(); + + Renderer11 *mRenderer; + D3D_FEATURE_LEVEL mFeatureLevel; + + DXGI_FORMAT mDXGIFormat; + ID3D11Resource *mStagingTexture; + unsigned int mStagingSubresource; + + bool mRecoverFromStorage; + TextureStorage11 *mAssociatedStorage; + gl::ImageIndex mAssociatedImageIndex; + unsigned int mRecoveredFromStorageCount; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_D3D11_IMAGE11_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.cpp new file mode 100644 index 0000000000..99c199f2b9 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.cpp @@ -0,0 +1,162 @@ +// +// 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 "libANGLE/renderer/d3d/d3d11/IndexBuffer11.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" + +namespace rx +{ + +IndexBuffer11::IndexBuffer11(Renderer11 *const renderer) : mRenderer(renderer) +{ + mBuffer = NULL; + mBufferSize = 0; + mDynamicUsage = false; +} + +IndexBuffer11::~IndexBuffer11() +{ + SafeRelease(mBuffer); +} + +gl::Error IndexBuffer11::initialize(unsigned int bufferSize, GLenum indexType, bool dynamic) +{ + SafeRelease(mBuffer); + + 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 gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal index buffer of size, %lu.", bufferSize); + } + } + + mBufferSize = bufferSize; + mIndexType = indexType; + mDynamicUsage = dynamic; + + return gl::Error(GL_NO_ERROR); +} + +IndexBuffer11 *IndexBuffer11::makeIndexBuffer11(IndexBuffer *indexBuffer) +{ + ASSERT(HAS_DYNAMIC_TYPE(IndexBuffer11*, indexBuffer)); + return static_cast(indexBuffer); +} + +gl::Error IndexBuffer11::mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory) +{ + if (!mBuffer) + { + return gl::Error(GL_OUT_OF_MEMORY, "Internal index buffer is not initialized."); + } + + // Check for integer overflows and out-out-bounds map requests + if (offset + size < offset || offset + size > mBufferSize) + { + return gl::Error(GL_OUT_OF_MEMORY, "Index buffer map range is not inside the buffer."); + } + + ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); + + D3D11_MAPPED_SUBRESOURCE mappedResource; + HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mappedResource); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal index buffer, HRESULT: 0x%08x.", result); + } + + *outMappedMemory = reinterpret_cast(mappedResource.pData) + offset; + return gl::Error(GL_NO_ERROR); +} + +gl::Error IndexBuffer11::unmapBuffer() +{ + if (!mBuffer) + { + return gl::Error(GL_OUT_OF_MEMORY, "Internal index buffer is not initialized."); + } + + ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); + dxContext->Unmap(mBuffer, 0); + return gl::Error(GL_NO_ERROR); +} + +GLenum IndexBuffer11::getIndexType() const +{ + return mIndexType; +} + +unsigned int IndexBuffer11::getBufferSize() const +{ + return mBufferSize; +} + +gl::Error IndexBuffer11::setSize(unsigned int bufferSize, GLenum indexType) +{ + if (bufferSize > mBufferSize || indexType != mIndexType) + { + return initialize(bufferSize, indexType, mDynamicUsage); + } + else + { + return gl::Error(GL_NO_ERROR); + } +} + +gl::Error IndexBuffer11::discard() +{ + if (!mBuffer) + { + return gl::Error(GL_OUT_OF_MEMORY, "Internal index buffer is not initialized."); + } + + ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); + + D3D11_MAPPED_SUBRESOURCE mappedResource; + HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal index buffer, HRESULT: 0x%08x.", result); + } + + dxContext->Unmap(mBuffer, 0); + + return gl::Error(GL_NO_ERROR); +} + +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; +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.h new file mode 100644 index 0000000000..eadd03eb76 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.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. +// + +// IndexBuffer11.h: Defines the D3D11 IndexBuffer implementation. + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_INDEXBUFFER11_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_INDEXBUFFER11_H_ + +#include "libANGLE/renderer/d3d/IndexBuffer.h" + +namespace rx +{ +class Renderer11; + +class IndexBuffer11 : public IndexBuffer +{ + public: + explicit IndexBuffer11(Renderer11 *const renderer); + virtual ~IndexBuffer11(); + + virtual gl::Error initialize(unsigned int bufferSize, GLenum indexType, bool dynamic); + + static IndexBuffer11 *makeIndexBuffer11(IndexBuffer *indexBuffer); + + virtual gl::Error mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory); + virtual gl::Error unmapBuffer(); + + virtual GLenum getIndexType() const; + virtual unsigned int getBufferSize() const; + virtual gl::Error setSize(unsigned int bufferSize, GLenum indexType); + + virtual gl::Error discard(); + + DXGI_FORMAT getIndexFormat() const; + ID3D11Buffer *getBuffer() const; + + private: + Renderer11 *const mRenderer; + + ID3D11Buffer *mBuffer; + unsigned int mBufferSize; + GLenum mIndexType; + bool mDynamicUsage; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_D3D11_INDEXBUFFER11_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.cpp new file mode 100644 index 0000000000..242c09d6ce --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.cpp @@ -0,0 +1,430 @@ +// +// 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 "libANGLE/renderer/d3d/d3d11/InputLayoutCache.h" +#include "libANGLE/renderer/d3d/d3d11/VertexBuffer11.h" +#include "libANGLE/renderer/d3d/d3d11/Buffer11.h" +#include "libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h" +#include "libANGLE/renderer/d3d/d3d11/formatutils11.h" +#include "libANGLE/renderer/d3d/ProgramD3D.h" +#include "libANGLE/renderer/d3d/VertexDataManager.h" +#include "libANGLE/Program.h" +#include "libANGLE/VertexAttribute.h" + +#include "third_party/murmurhash/MurmurHash3.h" + +namespace rx +{ + +static void GetInputLayout(const TranslatedAttribute translatedAttributes[gl::MAX_VERTEX_ATTRIBS], + gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS]) +{ + for (unsigned int attributeIndex = 0; attributeIndex < gl::MAX_VERTEX_ATTRIBS; attributeIndex++) + { + const TranslatedAttribute &translatedAttribute = translatedAttributes[attributeIndex]; + + if (translatedAttributes[attributeIndex].active) + { + inputLayout[attributeIndex] = gl::VertexFormat(*translatedAttribute.attribute, + translatedAttribute.currentValueType); + } + } +} + +const unsigned int InputLayoutCache::kMaxInputLayouts = 1024; + +InputLayoutCache::InputLayoutCache() : mInputLayoutMap(kMaxInputLayouts, hashInputLayout, compareInputLayouts) +{ + mCounter = 0; + mDevice = NULL; + mDeviceContext = NULL; + mCurrentIL = NULL; + for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + mCurrentBuffers[i] = NULL; + mCurrentVertexStrides[i] = static_cast(-1); + mCurrentVertexOffsets[i] = static_cast(-1); + } + mPointSpriteVertexBuffer = NULL; + mPointSpriteIndexBuffer = NULL; +} + +InputLayoutCache::~InputLayoutCache() +{ + clear(); +} + +void InputLayoutCache::initialize(ID3D11Device *device, ID3D11DeviceContext *context) +{ + clear(); + mDevice = device; + mDeviceContext = context; + mFeatureLevel = device->GetFeatureLevel(); +} + +void InputLayoutCache::clear() +{ + for (InputLayoutMap::iterator i = mInputLayoutMap.begin(); i != mInputLayoutMap.end(); i++) + { + SafeRelease(i->second.inputLayout); + } + mInputLayoutMap.clear(); + SafeRelease(mPointSpriteVertexBuffer); + SafeRelease(mPointSpriteIndexBuffer); + markDirty(); +} + +void InputLayoutCache::markDirty() +{ + mCurrentIL = NULL; + for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + mCurrentBuffers[i] = NULL; + mCurrentVertexStrides[i] = static_cast(-1); + mCurrentVertexOffsets[i] = static_cast(-1); + } +} + +gl::Error InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS], + GLenum mode, gl::Program *program) +{ + ProgramD3D *programD3D = GetImplAs(program); + + int sortedSemanticIndices[gl::MAX_VERTEX_ATTRIBS]; + programD3D->sortAttributesByLayout(attributes, sortedSemanticIndices); + bool programUsesInstancedPointSprites = programD3D->usesPointSize() && programD3D->usesInstancedPointSpriteEmulation(); + bool instancedPointSpritesActive = programUsesInstancedPointSprites && (mode == GL_POINTS); + + if (!mDevice || !mDeviceContext) + { + return gl::Error(GL_OUT_OF_MEMORY, "Internal input layout cache is not initialized."); + } + + InputLayoutKey ilKey = { 0 }; + + static const char* semanticName = "TEXCOORD"; + + unsigned int firstIndexedElement = gl::MAX_VERTEX_ATTRIBS; + unsigned int firstInstancedElement = gl::MAX_VERTEX_ATTRIBS; + unsigned int nextAvailableInputSlot = 0; + + for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + if (attributes[i].active) + { + D3D11_INPUT_CLASSIFICATION inputClass = attributes[i].divisor > 0 ? D3D11_INPUT_PER_INSTANCE_DATA : D3D11_INPUT_PER_VERTEX_DATA; + // If rendering points and instanced pointsprite emulation is being used, the inputClass is required to be configured as per instance data + inputClass = instancedPointSpritesActive ? D3D11_INPUT_PER_INSTANCE_DATA : inputClass; + + gl::VertexFormat vertexFormat(*attributes[i].attribute, attributes[i].currentValueType); + const d3d11::VertexFormat &vertexFormatInfo = d3d11::GetVertexFormatInfo(vertexFormat, mFeatureLevel); + + // 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; + program->getActiveAttribute(ilKey.elementCount, 0, NULL, &attributeSize, &ilKey.elements[ilKey.elementCount].glslElementType, NULL); + + ilKey.elements[ilKey.elementCount].desc.SemanticName = semanticName; + ilKey.elements[ilKey.elementCount].desc.SemanticIndex = sortedSemanticIndices[i]; + ilKey.elements[ilKey.elementCount].desc.Format = vertexFormatInfo.nativeFormat; + ilKey.elements[ilKey.elementCount].desc.InputSlot = i; + ilKey.elements[ilKey.elementCount].desc.AlignedByteOffset = 0; + ilKey.elements[ilKey.elementCount].desc.InputSlotClass = inputClass; + ilKey.elements[ilKey.elementCount].desc.InstanceDataStepRate = instancedPointSpritesActive ? 1 : attributes[i].divisor; + + if (inputClass == D3D11_INPUT_PER_VERTEX_DATA && firstIndexedElement == gl::MAX_VERTEX_ATTRIBS) + { + firstIndexedElement = ilKey.elementCount; + } + else if (inputClass == D3D11_INPUT_PER_INSTANCE_DATA && firstInstancedElement == gl::MAX_VERTEX_ATTRIBS) + { + firstInstancedElement = ilKey.elementCount; + } + + ilKey.elementCount++; + nextAvailableInputSlot = i + 1; + } + } + + // Instanced PointSprite emulation requires additional entries in the + // inputlayout to support the vertices that make up the pointsprite quad. + // We do this even if mode != GL_POINTS, since the shader signature has these inputs, and the input layout must match the shader + if (programUsesInstancedPointSprites) + { + ilKey.elements[ilKey.elementCount].desc.SemanticName = "SPRITEPOSITION"; + ilKey.elements[ilKey.elementCount].desc.SemanticIndex = 0; + ilKey.elements[ilKey.elementCount].desc.Format = DXGI_FORMAT_R32G32B32_FLOAT; + ilKey.elements[ilKey.elementCount].desc.InputSlot = nextAvailableInputSlot; + ilKey.elements[ilKey.elementCount].desc.AlignedByteOffset = 0; + ilKey.elements[ilKey.elementCount].desc.InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; + ilKey.elements[ilKey.elementCount].desc.InstanceDataStepRate = 0; + + // The new elements are D3D11_INPUT_PER_VERTEX_DATA data so the indexed element + // tracking must be applied. This ensures that the instancing specific + // buffer swapping logic continues to work. + if (firstIndexedElement == gl::MAX_VERTEX_ATTRIBS) + { + firstIndexedElement = ilKey.elementCount; + } + + ilKey.elementCount++; + + ilKey.elements[ilKey.elementCount].desc.SemanticName = "SPRITETEXCOORD"; + ilKey.elements[ilKey.elementCount].desc.SemanticIndex = 0; + ilKey.elements[ilKey.elementCount].desc.Format = DXGI_FORMAT_R32G32_FLOAT; + ilKey.elements[ilKey.elementCount].desc.InputSlot = nextAvailableInputSlot; + ilKey.elements[ilKey.elementCount].desc.AlignedByteOffset = sizeof(float) * 3; + ilKey.elements[ilKey.elementCount].desc.InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; + ilKey.elements[ilKey.elementCount].desc.InstanceDataStepRate = 0; + + ilKey.elementCount++; + } + + // On 9_3, we must ensure that slot 0 contains non-instanced data. + // If slot 0 currently contains instanced data then we swap it with a non-instanced element. + // Note that instancing is only available on 9_3 via ANGLE_instanced_arrays, since 9_3 doesn't support OpenGL ES 3.0. + // As per the spec for ANGLE_instanced_arrays, not all attributes can be instanced simultaneously, so a non-instanced element must exist. + ASSERT(!(mFeatureLevel <= D3D_FEATURE_LEVEL_9_3 && firstIndexedElement == gl::MAX_VERTEX_ATTRIBS)); + bool moveFirstIndexedIntoSlotZero = mFeatureLevel <= D3D_FEATURE_LEVEL_9_3 && firstInstancedElement == 0 && firstIndexedElement != gl::MAX_VERTEX_ATTRIBS; + + if (moveFirstIndexedIntoSlotZero) + { + ilKey.elements[firstInstancedElement].desc.InputSlot = ilKey.elements[firstIndexedElement].desc.InputSlot; + ilKey.elements[firstIndexedElement].desc.InputSlot = 0; + + // Instanced PointSprite emulation uses multiple layout entries across a single vertex buffer. + // If an index swap is performed, we need to ensure that all elements get the proper InputSlot. + if (programUsesInstancedPointSprites) + { + ilKey.elements[firstIndexedElement + 1].desc.InputSlot = 0; + } + } + + ID3D11InputLayout *inputLayout = NULL; + + InputLayoutMap::iterator keyIter = mInputLayoutMap.find(ilKey); + if (keyIter != mInputLayoutMap.end()) + { + inputLayout = keyIter->second.inputLayout; + keyIter->second.lastUsedTime = mCounter++; + } + else + { + gl::VertexFormat shaderInputLayout[gl::MAX_VERTEX_ATTRIBS]; + GetInputLayout(attributes, shaderInputLayout); + + ShaderExecutableD3D *shader = NULL; + gl::Error error = programD3D->getVertexExecutableForInputLayout(shaderInputLayout, &shader, nullptr); + if (error.isError()) + { + return error; + } + + ShaderExecutableD3D *shader11 = ShaderExecutable11::makeShaderExecutable11(shader); + + D3D11_INPUT_ELEMENT_DESC descs[gl::MAX_VERTEX_ATTRIBS]; + for (unsigned int j = 0; j < ilKey.elementCount; ++j) + { + descs[j] = ilKey.elements[j].desc; + } + + HRESULT result = mDevice->CreateInputLayout(descs, ilKey.elementCount, shader11->getFunction(), shader11->getLength(), &inputLayout); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal input layout, HRESULT: 0x%08x", result); + } + + 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; + } + } + SafeRelease(leastRecentlyUsed->second.inputLayout); + mInputLayoutMap.erase(leastRecentlyUsed); + } + + InputLayoutCounterPair inputCounterPair; + inputCounterPair.inputLayout = inputLayout; + inputCounterPair.lastUsedTime = mCounter++; + + mInputLayoutMap.insert(std::make_pair(ilKey, inputCounterPair)); + } + + if (inputLayout != mCurrentIL) + { + mDeviceContext->IASetInputLayout(inputLayout); + mCurrentIL = inputLayout; + } + + bool dirtyBuffers = false; + size_t minDiff = gl::MAX_VERTEX_ATTRIBS; + size_t maxDiff = 0; + unsigned int nextAvailableIndex = 0; + + for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + ID3D11Buffer *buffer = NULL; + + if (attributes[i].active) + { + VertexBuffer11 *vertexBuffer = VertexBuffer11::makeVertexBuffer11(attributes[i].vertexBuffer); + Buffer11 *bufferStorage = attributes[i].storage ? Buffer11::makeBuffer11(attributes[i].storage) : NULL; + + buffer = bufferStorage ? bufferStorage->getBuffer(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK) + : vertexBuffer->getBuffer(); + } + + UINT vertexStride = attributes[i].stride; + UINT vertexOffset = attributes[i].offset; + + if (buffer != mCurrentBuffers[i] || vertexStride != mCurrentVertexStrides[i] || + vertexOffset != mCurrentVertexOffsets[i]) + { + dirtyBuffers = true; + minDiff = std::min(minDiff, static_cast(i)); + maxDiff = std::max(maxDiff, static_cast(i)); + + mCurrentBuffers[i] = buffer; + mCurrentVertexStrides[i] = vertexStride; + mCurrentVertexOffsets[i] = vertexOffset; + + // If a non null ID3D11Buffer is being assigned to mCurrentBuffers, + // then the next available index needs to be tracked to ensure + // that any instanced pointsprite emulation buffers will be properly packed. + if (buffer) + { + nextAvailableIndex = i + 1; + } + } + } + + // Instanced PointSprite emulation requires two additional ID3D11Buffers. + // A vertex buffer needs to be created and added to the list of current buffers, + // strides and offsets collections. This buffer contains the vertices for a single + // PointSprite quad. + // An index buffer also needs to be created and applied because rendering instanced + // data on D3D11 FL9_3 requires DrawIndexedInstanced() to be used. + if (instancedPointSpritesActive) + { + HRESULT result = S_OK; + const UINT pointSpriteVertexStride = sizeof(float) * 5; + + if (!mPointSpriteVertexBuffer) + { + static const float pointSpriteVertices[] = + { + // Position // TexCoord + -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, + -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, + 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, + 1.0f, -1.0f, 0.0f, 1.0f, 1.0f, + -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, + 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, + }; + + D3D11_SUBRESOURCE_DATA vertexBufferData = { pointSpriteVertices, 0, 0 }; + D3D11_BUFFER_DESC vertexBufferDesc; + vertexBufferDesc.ByteWidth = sizeof(pointSpriteVertices); + vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + vertexBufferDesc.Usage = D3D11_USAGE_IMMUTABLE; + vertexBufferDesc.CPUAccessFlags = 0; + vertexBufferDesc.MiscFlags = 0; + vertexBufferDesc.StructureByteStride = 0; + + result = mDevice->CreateBuffer(&vertexBufferDesc, &vertexBufferData, &mPointSpriteVertexBuffer); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create instanced pointsprite emulation vertex buffer, HRESULT: 0x%08x", result); + } + } + + mCurrentBuffers[nextAvailableIndex] = mPointSpriteVertexBuffer; + mCurrentVertexStrides[nextAvailableIndex] = pointSpriteVertexStride; + mCurrentVertexOffsets[nextAvailableIndex] = 0; + + if (!mPointSpriteIndexBuffer) + { + // Create an index buffer and set it for pointsprite rendering + static const unsigned short pointSpriteIndices[] = + { + 0, 1, 2, 3, 4, 5, + }; + + D3D11_SUBRESOURCE_DATA indexBufferData = { pointSpriteIndices, 0, 0 }; + D3D11_BUFFER_DESC indexBufferDesc; + indexBufferDesc.ByteWidth = sizeof(pointSpriteIndices); + indexBufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; + indexBufferDesc.Usage = D3D11_USAGE_IMMUTABLE; + indexBufferDesc.CPUAccessFlags = 0; + indexBufferDesc.MiscFlags = 0; + indexBufferDesc.StructureByteStride = 0; + + result = mDevice->CreateBuffer(&indexBufferDesc, &indexBufferData, &mPointSpriteIndexBuffer); + if (FAILED(result)) + { + SafeRelease(mPointSpriteVertexBuffer); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create instanced pointsprite emulation index buffer, HRESULT: 0x%08x", result); + } + } + + // The index buffer is applied here because Instanced PointSprite emulation uses + // the a non-indexed rendering path in ANGLE (DrawArrays). This means that applyIndexBuffer() + // on the renderer will not be called and setting this buffer here ensures that the rendering + // path will contain the correct index buffers. + mDeviceContext->IASetIndexBuffer(mPointSpriteIndexBuffer, DXGI_FORMAT_R16_UINT, 0); + } + + if (moveFirstIndexedIntoSlotZero) + { + // In this case, we swapped the slots of the first instanced element and the first indexed element, to ensure + // that the first slot contains non-instanced data (required by Feature Level 9_3). + // We must also swap the corresponding buffers sent to IASetVertexBuffers so that the correct data is sent to each slot. + std::swap(mCurrentBuffers[firstIndexedElement], mCurrentBuffers[firstInstancedElement]); + std::swap(mCurrentVertexStrides[firstIndexedElement], mCurrentVertexStrides[firstInstancedElement]); + std::swap(mCurrentVertexOffsets[firstIndexedElement], mCurrentVertexOffsets[firstInstancedElement]); + } + + if (dirtyBuffers) + { + ASSERT(minDiff <= maxDiff && maxDiff < gl::MAX_VERTEX_ATTRIBS); + mDeviceContext->IASetVertexBuffers(minDiff, maxDiff - minDiff + 1, mCurrentBuffers + minDiff, + mCurrentVertexStrides + minDiff, mCurrentVertexOffsets + minDiff); + } + + return gl::Error(GL_NO_ERROR); +} + +std::size_t InputLayoutCache::hashInputLayout(const InputLayoutKey &inputLayout) +{ + static const unsigned int seed = 0xDEADBEEF; + + std::size_t hash = 0; + MurmurHash3_x86_32(inputLayout.begin(), inputLayout.end() - inputLayout.begin(), seed, &hash); + return hash; +} + +bool InputLayoutCache::compareInputLayouts(const InputLayoutKey &a, const InputLayoutKey &b) +{ + if (a.elementCount != b.elementCount) + { + return false; + } + + return std::equal(a.begin(), a.end(), b.begin()); +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.h new file mode 100644 index 0000000000..2c94c57595 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.h @@ -0,0 +1,103 @@ +// +// 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 LIBANGLE_RENDERER_D3D_D3D11_INPUTLAYOUTCACHE_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_INPUTLAYOUTCACHE_H_ + +#include "libANGLE/Constants.h" +#include "libANGLE/Error.h" +#include "common/angleutils.h" + +#include + +#include +#include + +namespace gl +{ +class Program; +} + +namespace rx +{ +struct TranslatedAttribute; + +class InputLayoutCache : angle::NonCopyable +{ + public: + InputLayoutCache(); + virtual ~InputLayoutCache(); + + void initialize(ID3D11Device *device, ID3D11DeviceContext *context); + void clear(); + void markDirty(); + + gl::Error applyVertexBuffers(TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS], + GLenum mode, gl::Program *program); + + private: + struct InputLayoutElement + { + D3D11_INPUT_ELEMENT_DESC desc; + GLenum glslElementType; + }; + + struct InputLayoutKey + { + unsigned int elementCount; + InputLayoutElement elements[gl::MAX_VERTEX_ATTRIBS]; + + const char *begin() const + { + return reinterpret_cast(&elementCount); + } + + const char *end() const + { + return reinterpret_cast(&elements[elementCount]); + } + }; + + struct InputLayoutCounterPair + { + ID3D11InputLayout *inputLayout; + unsigned long long lastUsedTime; + }; + + ID3D11InputLayout *mCurrentIL; + ID3D11Buffer *mCurrentBuffers[gl::MAX_VERTEX_ATTRIBS]; + UINT mCurrentVertexStrides[gl::MAX_VERTEX_ATTRIBS]; + UINT mCurrentVertexOffsets[gl::MAX_VERTEX_ATTRIBS]; + + ID3D11Buffer *mPointSpriteVertexBuffer; + ID3D11Buffer *mPointSpriteIndexBuffer; + + 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; + D3D_FEATURE_LEVEL mFeatureLevel; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_D3D11_INPUTLAYOUTCACHE_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow.h new file mode 100644 index 0000000000..81b9ea748d --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow.h @@ -0,0 +1,80 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// NativeWindow.h: Defines NativeWindow, a class for managing and +// performing operations on an EGLNativeWindowType. +// It is used for HWND (Desktop Windows) and IInspectable objects +//(Windows Store Applications). + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_NATIVEWINDOW_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_NATIVEWINDOW_H_ + +#include "common/debug.h" +#include "common/platform.h" + +#include + +// DXGISwapChain and DXGIFactory are typedef'd to specific required +// types. The HWND NativeWindow implementation requires IDXGISwapChain +// and IDXGIFactory and the Windows Store NativeWindow +// implementation requires IDXGISwapChain1 and IDXGIFactory2. +#if defined(ANGLE_ENABLE_WINDOWS_STORE) +typedef IDXGISwapChain1 DXGISwapChain; +typedef IDXGIFactory2 DXGIFactory; + +#include +#include +#include +#include + +namespace rx +{ +class InspectableNativeWindow; +} + +using namespace Microsoft::WRL; +using namespace Microsoft::WRL::Wrappers; + +#else +typedef IDXGISwapChain DXGISwapChain; +typedef IDXGIFactory DXGIFactory; +#endif + +namespace rx +{ + +class NativeWindow +{ + public: + enum RotationFlags { RotateNone = 0, RotateLeft = 1, RotateRight = 2 }; + explicit NativeWindow(EGLNativeWindowType window); + + bool initialize(); + bool getClientRect(LPRECT rect); + bool isIconic(); +#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) + RotationFlags rotationFlags() const; +#endif + static bool isValidNativeWindow(EGLNativeWindowType window); + + HRESULT createSwapChain(ID3D11Device* device, DXGIFactory* factory, + DXGI_FORMAT format, UINT width, UINT height, + DXGISwapChain** swapChain); + + inline EGLNativeWindowType getNativeWindow() const { return mWindow; } + + private: + EGLNativeWindowType mWindow; + +#if defined(ANGLE_ENABLE_WINDOWS_STORE) + std::shared_ptr mImpl; +#endif + +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_D3D11_NATIVEWINDOW_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.cpp new file mode 100644 index 0000000000..5fd5237d90 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.cpp @@ -0,0 +1,302 @@ +// +// 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. +// + +// PixelTransfer11.cpp: +// Implementation for buffer-to-texture and texture-to-buffer copies. +// Used to implement pixel transfers from unpack and to pack buffers. +// + +#include "libANGLE/renderer/d3d/d3d11/PixelTransfer11.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" +#include "libANGLE/renderer/d3d/d3d11/formatutils11.h" +#include "libANGLE/renderer/d3d/d3d11/Buffer11.h" +#include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h" +#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/Texture.h" +#include "libANGLE/Buffer.h" +#include "libANGLE/Context.h" + +// Precompiled shaders +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_vs.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_gs.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4f.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4i.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4ui.h" + +namespace rx +{ + +PixelTransfer11::PixelTransfer11(Renderer11 *renderer) + : mRenderer(renderer), + mResourcesLoaded(false), + mBufferToTextureVS(NULL), + mBufferToTextureGS(NULL), + mParamsConstantBuffer(NULL), + mCopyRasterizerState(NULL), + mCopyDepthStencilState(NULL) +{ +} + +PixelTransfer11::~PixelTransfer11() +{ + for (auto shaderMapIt = mBufferToTexturePSMap.begin(); shaderMapIt != mBufferToTexturePSMap.end(); shaderMapIt++) + { + SafeRelease(shaderMapIt->second); + } + + mBufferToTexturePSMap.clear(); + + SafeRelease(mBufferToTextureVS); + SafeRelease(mBufferToTextureGS); + SafeRelease(mParamsConstantBuffer); + SafeRelease(mCopyRasterizerState); + SafeRelease(mCopyDepthStencilState); +} + +gl::Error PixelTransfer11::loadResources() +{ + if (mResourcesLoaded) + { + return gl::Error(GL_NO_ERROR); + } + + HRESULT result = S_OK; + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_RASTERIZER_DESC rasterDesc; + rasterDesc.FillMode = D3D11_FILL_SOLID; + rasterDesc.CullMode = D3D11_CULL_NONE; + rasterDesc.FrontCounterClockwise = FALSE; + rasterDesc.DepthBias = 0; + rasterDesc.SlopeScaledDepthBias = 0.0f; + rasterDesc.DepthBiasClamp = 0.0f; + rasterDesc.DepthClipEnable = TRUE; + rasterDesc.ScissorEnable = FALSE; + rasterDesc.MultisampleEnable = FALSE; + rasterDesc.AntialiasedLineEnable = FALSE; + + result = device->CreateRasterizerState(&rasterDesc, &mCopyRasterizerState); + ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal pixel transfer rasterizer state, result: 0x%X.", result); + } + + D3D11_DEPTH_STENCIL_DESC depthStencilDesc; + depthStencilDesc.DepthEnable = true; + depthStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; + depthStencilDesc.DepthFunc = D3D11_COMPARISON_ALWAYS; + depthStencilDesc.StencilEnable = FALSE; + depthStencilDesc.StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK; + depthStencilDesc.StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK; + depthStencilDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; + depthStencilDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP; + depthStencilDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; + depthStencilDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS; + depthStencilDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; + depthStencilDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP; + depthStencilDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; + depthStencilDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS; + + result = device->CreateDepthStencilState(&depthStencilDesc, &mCopyDepthStencilState); + ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal pixel transfer depth stencil state, result: 0x%X.", result); + } + + D3D11_BUFFER_DESC constantBufferDesc = { 0 }; + constantBufferDesc.ByteWidth = roundUp(sizeof(CopyShaderParams), 32u); + constantBufferDesc.Usage = D3D11_USAGE_DYNAMIC; + constantBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + constantBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + constantBufferDesc.MiscFlags = 0; + constantBufferDesc.StructureByteStride = 0; + + result = device->CreateBuffer(&constantBufferDesc, NULL, &mParamsConstantBuffer); + ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal pixel transfer constant buffer, result: 0x%X.", result); + } + d3d11::SetDebugName(mParamsConstantBuffer, "PixelTransfer11 constant buffer"); + + // init shaders + mBufferToTextureVS = d3d11::CompileVS(device, g_VS_BufferToTexture, "BufferToTexture VS"); + if (!mBufferToTextureVS) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal buffer to texture vertex shader."); + } + + mBufferToTextureGS = d3d11::CompileGS(device, g_GS_BufferToTexture, "BufferToTexture GS"); + if (!mBufferToTextureGS) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal buffer to texture geometry shader."); + } + + gl::Error error = buildShaderMap(); + if (error.isError()) + { + return error; + } + + StructZero(&mParamsData); + + mResourcesLoaded = true; + + return gl::Error(GL_NO_ERROR); +} + +void PixelTransfer11::setBufferToTextureCopyParams(const gl::Box &destArea, const gl::Extents &destSize, GLenum internalFormat, + const gl::PixelUnpackState &unpack, unsigned int offset, CopyShaderParams *parametersOut) +{ + StructZero(parametersOut); + + float texelCenterX = 0.5f / static_cast(destSize.width - 1); + float texelCenterY = 0.5f / static_cast(destSize.height - 1); + + unsigned int bytesPerPixel = gl::GetInternalFormatInfo(internalFormat).pixelBytes; + unsigned int alignmentBytes = static_cast(unpack.alignment); + unsigned int alignmentPixels = (alignmentBytes <= bytesPerPixel ? 1 : alignmentBytes / bytesPerPixel); + + parametersOut->FirstPixelOffset = offset / bytesPerPixel; + parametersOut->PixelsPerRow = static_cast((unpack.rowLength > 0) ? unpack.rowLength : destArea.width); + parametersOut->RowStride = roundUp(parametersOut->PixelsPerRow, alignmentPixels); + parametersOut->RowsPerSlice = static_cast(destArea.height); + parametersOut->PositionOffset[0] = texelCenterX + (destArea.x / float(destSize.width)) * 2.0f - 1.0f; + parametersOut->PositionOffset[1] = texelCenterY + ((destSize.height - destArea.y - 1) / float(destSize.height)) * 2.0f - 1.0f; + parametersOut->PositionScale[0] = 2.0f / static_cast(destSize.width); + parametersOut->PositionScale[1] = -2.0f / static_cast(destSize.height); + parametersOut->FirstSlice = destArea.z; +} + +gl::Error PixelTransfer11::copyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTargetD3D *destRenderTarget, + GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea) +{ + gl::Error error = loadResources(); + if (error.isError()) + { + return error; + } + + gl::Extents destSize = destRenderTarget->getExtents(); + + ASSERT(destArea.x >= 0 && destArea.x + destArea.width <= destSize.width && + destArea.y >= 0 && destArea.y + destArea.height <= destSize.height && + destArea.z >= 0 && destArea.z + destArea.depth <= destSize.depth ); + + const gl::Buffer &sourceBuffer = *unpack.pixelBuffer.get(); + + ASSERT(mRenderer->supportsFastCopyBufferToTexture(destinationFormat)); + + ID3D11PixelShader *pixelShader = findBufferToTexturePS(destinationFormat); + ASSERT(pixelShader); + + // The SRV must be in the proper read format, which may be different from the destination format + // EG: for half float data, we can load full precision floats with implicit conversion + GLenum unsizedFormat = gl::GetInternalFormatInfo(destinationFormat).format; + GLenum sourceFormat = gl::GetSizedInternalFormat(unsizedFormat, sourcePixelsType); + + const d3d11::TextureFormat &sourceFormatInfo = d3d11::GetTextureFormatInfo(sourceFormat, mRenderer->getFeatureLevel()); + DXGI_FORMAT srvFormat = sourceFormatInfo.srvFormat; + ASSERT(srvFormat != DXGI_FORMAT_UNKNOWN); + Buffer11 *bufferStorage11 = Buffer11::makeBuffer11(sourceBuffer.getImplementation()); + ID3D11ShaderResourceView *bufferSRV = bufferStorage11->getSRV(srvFormat); + ASSERT(bufferSRV != NULL); + + ID3D11RenderTargetView *textureRTV = RenderTarget11::makeRenderTarget11(destRenderTarget)->getRenderTargetView(); + ASSERT(textureRTV != NULL); + + CopyShaderParams shaderParams; + setBufferToTextureCopyParams(destArea, destSize, sourceFormat, unpack, offset, &shaderParams); + + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + + ID3D11Buffer *nullBuffer = NULL; + UINT zero = 0; + + // Are we doing a 2D or 3D copy? + ID3D11GeometryShader *geometryShader = ((destSize.depth > 1) ? mBufferToTextureGS : NULL); + + deviceContext->VSSetShader(mBufferToTextureVS, NULL, 0); + deviceContext->GSSetShader(geometryShader, NULL, 0); + deviceContext->PSSetShader(pixelShader, NULL, 0); + mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, bufferSRV); + deviceContext->IASetInputLayout(NULL); + deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST); + + deviceContext->IASetVertexBuffers(0, 1, &nullBuffer, &zero, &zero); + deviceContext->OMSetBlendState(NULL, NULL, 0xFFFFFFF); + deviceContext->OMSetDepthStencilState(mCopyDepthStencilState, 0xFFFFFFFF); + deviceContext->RSSetState(mCopyRasterizerState); + + mRenderer->setOneTimeRenderTarget(textureRTV); + + if (!StructEquals(mParamsData, shaderParams)) + { + d3d11::SetBufferData(deviceContext, mParamsConstantBuffer, shaderParams); + mParamsData = shaderParams; + } + + deviceContext->VSSetConstantBuffers(0, 1, &mParamsConstantBuffer); + + // Set the viewport + D3D11_VIEWPORT viewport; + viewport.TopLeftX = 0; + viewport.TopLeftY = 0; + viewport.Width = destSize.width; + viewport.Height = destSize.height; + viewport.MinDepth = 0.0f; + viewport.MaxDepth = 1.0f; + deviceContext->RSSetViewports(1, &viewport); + + UINT numPixels = (destArea.width * destArea.height * destArea.depth); + deviceContext->Draw(numPixels, 0); + + // Unbind textures and render targets and vertex buffer + mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, NULL); + deviceContext->VSSetConstantBuffers(0, 1, &nullBuffer); + + mRenderer->markAllStateDirty(); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error PixelTransfer11::buildShaderMap() +{ + ID3D11Device *device = mRenderer->getDevice(); + + mBufferToTexturePSMap[GL_FLOAT] = d3d11::CompilePS(device, g_PS_BufferToTexture_4F, "BufferToTexture RGBA ps"); + mBufferToTexturePSMap[GL_INT] = d3d11::CompilePS(device, g_PS_BufferToTexture_4I, "BufferToTexture RGBA-I ps"); + mBufferToTexturePSMap[GL_UNSIGNED_INT] = d3d11::CompilePS(device, g_PS_BufferToTexture_4UI, "BufferToTexture RGBA-UI ps"); + + // Check that all the shaders were created successfully + for (auto shaderMapIt = mBufferToTexturePSMap.begin(); shaderMapIt != mBufferToTexturePSMap.end(); shaderMapIt++) + { + if (shaderMapIt->second == NULL) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal buffer to texture pixel shader."); + } + } + + return gl::Error(GL_NO_ERROR); +} + +ID3D11PixelShader *PixelTransfer11::findBufferToTexturePS(GLenum internalFormat) const +{ + GLenum componentType = gl::GetInternalFormatInfo(internalFormat).componentType; + if (componentType == GL_SIGNED_NORMALIZED || componentType == GL_UNSIGNED_NORMALIZED) + { + componentType = GL_FLOAT; + } + + auto shaderMapIt = mBufferToTexturePSMap.find(componentType); + return (shaderMapIt == mBufferToTexturePSMap.end() ? NULL : shaderMapIt->second); +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.h new file mode 100644 index 0000000000..1672121ec7 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.h @@ -0,0 +1,89 @@ +// +// 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. +// + +// PixelTransfer11.h: +// Buffer-to-Texture and Texture-to-Buffer data transfers. +// Used to implement pixel unpack and pixel pack buffers in ES3. + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_PIXELTRANSFER11_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_PIXELTRANSFER11_H_ + +#include "libANGLE/Error.h" + +#include "common/platform.h" + +#include + +#include + +namespace gl +{ + +class Buffer; +struct Box; +struct Extents; +struct PixelUnpackState; + +} + +namespace rx +{ +class Renderer11; +class RenderTargetD3D; + +class PixelTransfer11 +{ + public: + explicit PixelTransfer11(Renderer11 *renderer); + ~PixelTransfer11(); + + // unpack: the source buffer is stored in the unpack state, and buffer strides + // offset: the start of the data within the unpack buffer + // destRenderTarget: individual slice/layer of a target texture + // destinationFormat/sourcePixelsType: determines shaders + shader parameters + // destArea: the sub-section of destRenderTarget to copy to + gl::Error copyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTargetD3D *destRenderTarget, + GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea); + + private: + + struct CopyShaderParams + { + unsigned int FirstPixelOffset; + unsigned int PixelsPerRow; + unsigned int RowStride; + unsigned int RowsPerSlice; + float PositionOffset[2]; + float PositionScale[2]; + int TexLocationOffset[2]; + int TexLocationScale[2]; + unsigned int FirstSlice; + }; + + static void setBufferToTextureCopyParams(const gl::Box &destArea, const gl::Extents &destSize, GLenum internalFormat, + const gl::PixelUnpackState &unpack, unsigned int offset, CopyShaderParams *parametersOut); + + gl::Error loadResources(); + gl::Error buildShaderMap(); + ID3D11PixelShader *findBufferToTexturePS(GLenum internalFormat) const; + + Renderer11 *mRenderer; + + bool mResourcesLoaded; + std::map mBufferToTexturePSMap; + ID3D11VertexShader *mBufferToTextureVS; + ID3D11GeometryShader *mBufferToTextureGS; + ID3D11Buffer *mParamsConstantBuffer; + CopyShaderParams mParamsData; + + ID3D11RasterizerState *mCopyRasterizerState; + ID3D11DepthStencilState *mCopyDepthStencilState; + +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_D3D11_PIXELTRANSFER11_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Query11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Query11.cpp new file mode 100644 index 0000000000..4979ff51a9 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Query11.cpp @@ -0,0 +1,164 @@ +// +// 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 "libANGLE/renderer/d3d/d3d11/Query11.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" +#include "common/utilities.h" + +#include + +#if defined(ANGLE_MINGW32_COMPAT) +typedef struct D3D11_QUERY_DATA_SO_STATISTICS { + UINT64 NumPrimitivesWritten; + UINT64 PrimitivesStorageNeeded; +} D3D11_QUERY_DATA_SO_STATISTICS; +#endif + +namespace rx +{ + +Query11::Query11(Renderer11 *renderer, GLenum type) + : QueryImpl(type), + mResult(0), + mQueryFinished(false), + mRenderer(renderer), + mQuery(NULL) +{ +} + +Query11::~Query11() +{ + SafeRelease(mQuery); +} + +gl::Error Query11::begin() +{ + if (mQuery == NULL) + { + D3D11_QUERY_DESC queryDesc; + queryDesc.Query = gl_d3d11::ConvertQueryType(getType()); + queryDesc.MiscFlags = 0; + + HRESULT result = mRenderer->getDevice()->CreateQuery(&queryDesc, &mQuery); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Internal query creation failed, result: 0x%X.", result); + } + } + + mRenderer->getDeviceContext()->Begin(mQuery); + return gl::Error(GL_NO_ERROR); +} + +gl::Error Query11::end() +{ + ASSERT(mQuery); + mRenderer->getDeviceContext()->End(mQuery); + + mQueryFinished = false; + mResult = GL_FALSE; + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Query11::getResult(GLuint *params) +{ + while (!mQueryFinished) + { + gl::Error error = testQuery(); + if (error.isError()) + { + return error; + } + + if (!mQueryFinished) + { + ScheduleYield(); + } + } + + ASSERT(mQueryFinished); + *params = mResult; + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Query11::isResultAvailable(GLuint *available) +{ + gl::Error error = testQuery(); + if (error.isError()) + { + return error; + } + + *available = (mQueryFinished ? GL_TRUE : GL_FALSE); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Query11::testQuery() +{ + if (!mQueryFinished) + { + ASSERT(mQuery); + + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + switch (getType()) + { + case GL_ANY_SAMPLES_PASSED_EXT: + case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT: + { + UINT64 numPixels = 0; + HRESULT result = context->GetData(mQuery, &numPixels, sizeof(numPixels), 0); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to get the data of an internal query, result: 0x%X.", result); + } + + if (result == S_OK) + { + mQueryFinished = true; + mResult = (numPixels > 0) ? GL_TRUE : GL_FALSE; + } + } + break; + + case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: + { + D3D11_QUERY_DATA_SO_STATISTICS soStats = { 0 }; + HRESULT result = context->GetData(mQuery, &soStats, sizeof(soStats), 0); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to get the data of an internal query, result: 0x%X.", result); + } + + if (result == S_OK) + { + mQueryFinished = true; + mResult = static_cast(soStats.NumPrimitivesWritten); + } + } + break; + + default: + UNREACHABLE(); + break; + } + + if (!mQueryFinished && mRenderer->testDeviceLost()) + { + mRenderer->notifyDeviceLost(); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to test get query result, device is lost."); + } + } + + return gl::Error(GL_NO_ERROR); +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Query11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Query11.h new file mode 100644 index 0000000000..bd53fed250 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Query11.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. +// + +// Query11.h: Defines the rx::Query11 class which implements rx::QueryImpl. + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_QUERY11_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_QUERY11_H_ + +#include "libANGLE/renderer/QueryImpl.h" + +namespace rx +{ +class Renderer11; + +class Query11 : public QueryImpl +{ + public: + Query11(Renderer11 *renderer, GLenum type); + virtual ~Query11(); + + virtual gl::Error begin(); + virtual gl::Error end(); + virtual gl::Error getResult(GLuint *params); + virtual gl::Error isResultAvailable(GLuint *available); + + private: + gl::Error testQuery(); + + GLuint mResult; + + bool mQueryFinished; + + Renderer11 *mRenderer; + ID3D11Query *mQuery; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_D3D11_QUERY11_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.cpp new file mode 100644 index 0000000000..4990e6bc6e --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.cpp @@ -0,0 +1,452 @@ +// +// Copyright (c) 2012-2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// RenderStateCache.cpp: Defines rx::RenderStateCache, a cache of Direct3D render +// state objects. + +#include "libANGLE/renderer/d3d/d3d11/RenderStateCache.h" + +#include + +#include "common/debug.h" +#include "libANGLE/Framebuffer.h" +#include "libANGLE/FramebufferAttachment.h" +#include "libANGLE/renderer/d3d/FramebufferD3D.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" +#include "third_party/murmurhash/MurmurHash3.h" + +namespace rx +{ + +template +static void ClearStateMap(mapType &map) +{ + for (typename mapType::iterator i = map.begin(); i != map.end(); i++) + { + SafeRelease(i->second.first); + } + map.clear(); +} + +// 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(Renderer11 *renderer) + : mRenderer(renderer), + 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() +{ + ClearStateMap(mBlendStateCache); + ClearStateMap(mRasterizerStateCache); + ClearStateMap(mDepthStencilStateCache); + ClearStateMap(mSamplerStateCache); +} + +std::size_t RenderStateCache::hashBlendState(const BlendStateKey &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 BlendStateKey &a, const BlendStateKey &b) +{ + return memcmp(&a, &b, sizeof(BlendStateKey)) == 0; +} + +gl::Error RenderStateCache::getBlendState(const gl::Framebuffer *framebuffer, const gl::BlendState &blendState, + ID3D11BlendState **outBlendState) +{ + if (!mDevice) + { + return gl::Error(GL_OUT_OF_MEMORY, "Internal error, RenderStateCache is not initialized."); + } + + bool mrt = false; + + const FramebufferD3D *framebufferD3D = GetImplAs(framebuffer); + const gl::AttachmentList &colorbuffers = framebufferD3D->getColorAttachmentsForRender(mRenderer->getWorkarounds()); + + BlendStateKey key = { 0 }; + key.blendState = blendState; + for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment) + { + const gl::FramebufferAttachment *attachment = colorbuffers[colorAttachment]; + + auto rtChannels = key.rtChannels[colorAttachment]; + + if (attachment) + { + if (colorAttachment > 0) + { + mrt = true; + } + + rtChannels[0] = attachment->getRedSize() > 0; + rtChannels[1] = attachment->getGreenSize() > 0; + rtChannels[2] = attachment->getBlueSize() > 0; + rtChannels[3] = attachment->getAlphaSize() > 0; + } + } + + BlendStateMap::iterator keyIter = mBlendStateCache.find(key); + if (keyIter != mBlendStateCache.end()) + { + BlendStateCounterPair &state = keyIter->second; + state.second = mCounter++; + *outBlendState = state.first; + return gl::Error(GL_NO_ERROR); + } + 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; + } + } + SafeRelease(leastRecentlyUsed->second.first); + mBlendStateCache.erase(leastRecentlyUsed); + } + + // Create a new blend state and insert it into the cache + D3D11_BLEND_DESC blendDesc = { 0 }; + blendDesc.AlphaToCoverageEnable = blendState.sampleAlphaToCoverage; + blendDesc.IndependentBlendEnable = mrt ? TRUE : FALSE; + + for (unsigned int i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++) + { + D3D11_RENDER_TARGET_BLEND_DESC &rtBlend = blendDesc.RenderTarget[i]; + + rtBlend.BlendEnable = blendState.blend; + if (blendState.blend) + { + rtBlend.SrcBlend = gl_d3d11::ConvertBlendFunc(blendState.sourceBlendRGB, false); + rtBlend.DestBlend = gl_d3d11::ConvertBlendFunc(blendState.destBlendRGB, false); + rtBlend.BlendOp = gl_d3d11::ConvertBlendOp(blendState.blendEquationRGB); + + rtBlend.SrcBlendAlpha = gl_d3d11::ConvertBlendFunc(blendState.sourceBlendAlpha, true); + rtBlend.DestBlendAlpha = gl_d3d11::ConvertBlendFunc(blendState.destBlendAlpha, true); + rtBlend.BlendOpAlpha = gl_d3d11::ConvertBlendOp(blendState.blendEquationAlpha); + } + + rtBlend.RenderTargetWriteMask = gl_d3d11::ConvertColorMask(key.rtChannels[i][0] && blendState.colorMaskRed, + key.rtChannels[i][1] && blendState.colorMaskGreen, + key.rtChannels[i][2] && blendState.colorMaskBlue, + key.rtChannels[i][3] && blendState.colorMaskAlpha); + } + + ID3D11BlendState *dx11BlendState = NULL; + HRESULT result = mDevice->CreateBlendState(&blendDesc, &dx11BlendState); + if (FAILED(result) || !dx11BlendState) + { + return gl::Error(GL_OUT_OF_MEMORY, "Unable to create a ID3D11BlendState, HRESULT: 0x%X.", result); + } + + mBlendStateCache.insert(std::make_pair(key, std::make_pair(dx11BlendState, mCounter++))); + + *outBlendState = dx11BlendState; + return gl::Error(GL_NO_ERROR); + } +} + +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; +} + +gl::Error RenderStateCache::getRasterizerState(const gl::RasterizerState &rasterState, bool scissorEnabled, + ID3D11RasterizerState **outRasterizerState) +{ + if (!mDevice) + { + return gl::Error(GL_OUT_OF_MEMORY, "Internal error, RenderStateCache is not initialized."); + } + + RasterizerStateKey key = { 0 }; + key.rasterizerState = rasterState; + key.scissorEnabled = scissorEnabled; + + RasterizerStateMap::iterator keyIter = mRasterizerStateCache.find(key); + if (keyIter != mRasterizerStateCache.end()) + { + RasterizerStateCounterPair &state = keyIter->second; + state.second = mCounter++; + *outRasterizerState = state.first; + return gl::Error(GL_NO_ERROR); + } + 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; + } + } + SafeRelease(leastRecentlyUsed->second.first); + 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.DepthBiasClamp = 0.0f; // MSDN documentation of DepthBiasClamp implies a value of zero will preform no clamping, must be tested though. + rasterDesc.DepthClipEnable = TRUE; + rasterDesc.ScissorEnable = scissorEnabled ? TRUE : FALSE; + rasterDesc.MultisampleEnable = rasterState.multiSample; + rasterDesc.AntialiasedLineEnable = FALSE; + + if (rasterState.polygonOffsetFill) + { + rasterDesc.SlopeScaledDepthBias = rasterState.polygonOffsetFactor; + rasterDesc.DepthBias = (INT)rasterState.polygonOffsetUnits; + } + else + { + rasterDesc.SlopeScaledDepthBias = 0.0f; + rasterDesc.DepthBias = 0; + } + + ID3D11RasterizerState *dx11RasterizerState = NULL; + HRESULT result = mDevice->CreateRasterizerState(&rasterDesc, &dx11RasterizerState); + if (FAILED(result) || !dx11RasterizerState) + { + return gl::Error(GL_OUT_OF_MEMORY, "Unable to create a ID3D11RasterizerState, HRESULT: 0x%X.", result); + } + + mRasterizerStateCache.insert(std::make_pair(key, std::make_pair(dx11RasterizerState, mCounter++))); + + *outRasterizerState = dx11RasterizerState; + return gl::Error(GL_NO_ERROR); + } +} + +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; +} + +gl::Error RenderStateCache::getDepthStencilState(const gl::DepthStencilState &dsState, ID3D11DepthStencilState **outDSState) +{ + if (!mDevice) + { + return gl::Error(GL_OUT_OF_MEMORY, "Internal error, RenderStateCache is not initialized."); + } + + DepthStencilStateMap::iterator keyIter = mDepthStencilStateCache.find(dsState); + if (keyIter != mDepthStencilStateCache.end()) + { + DepthStencilStateCounterPair &state = keyIter->second; + state.second = mCounter++; + *outDSState = state.first; + return gl::Error(GL_NO_ERROR); + } + 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; + } + } + SafeRelease(leastRecentlyUsed->second.first); + 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) + { + return gl::Error(GL_OUT_OF_MEMORY, "Unable to create a ID3D11DepthStencilState, HRESULT: 0x%X.", result); + } + + mDepthStencilStateCache.insert(std::make_pair(dsState, std::make_pair(dx11DepthStencilState, mCounter++))); + + *outDSState = dx11DepthStencilState; + return gl::Error(GL_NO_ERROR); + } +} + +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; +} + +gl::Error RenderStateCache::getSamplerState(const gl::SamplerState &samplerState, ID3D11SamplerState **outSamplerState) +{ + if (!mDevice) + { + return gl::Error(GL_OUT_OF_MEMORY, "Internal error, RenderStateCache is not initialized."); + } + + SamplerStateMap::iterator keyIter = mSamplerStateCache.find(samplerState); + if (keyIter != mSamplerStateCache.end()) + { + SamplerStateCounterPair &state = keyIter->second; + state.second = mCounter++; + *outSamplerState = state.first; + return gl::Error(GL_NO_ERROR); + } + 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; + } + } + SafeRelease(leastRecentlyUsed->second.first); + mSamplerStateCache.erase(leastRecentlyUsed); + } + + D3D11_SAMPLER_DESC samplerDesc; + samplerDesc.Filter = gl_d3d11::ConvertFilter(samplerState.minFilter, samplerState.magFilter, + samplerState.maxAnisotropy, samplerState.compareMode); + samplerDesc.AddressU = gl_d3d11::ConvertTextureWrap(samplerState.wrapS); + samplerDesc.AddressV = gl_d3d11::ConvertTextureWrap(samplerState.wrapT); + samplerDesc.AddressW = gl_d3d11::ConvertTextureWrap(samplerState.wrapR); + samplerDesc.MipLODBias = 0; + samplerDesc.MaxAnisotropy = samplerState.maxAnisotropy; + samplerDesc.ComparisonFunc = gl_d3d11::ConvertComparison(samplerState.compareFunc); + samplerDesc.BorderColor[0] = 0.0f; + samplerDesc.BorderColor[1] = 0.0f; + samplerDesc.BorderColor[2] = 0.0f; + samplerDesc.BorderColor[3] = 0.0f; + samplerDesc.MinLOD = samplerState.minLod; + samplerDesc.MaxLOD = samplerState.maxLod; + + if (mRenderer->getFeatureLevel() <= D3D_FEATURE_LEVEL_9_3) + { + // Check that maxLOD is nearly FLT_MAX (1000.0f is the default), since 9_3 doesn't support anything other than FLT_MAX. + // Note that Feature Level 9_* only supports GL ES 2.0, so the consumer of ANGLE can't modify the Max LOD themselves. + ASSERT(samplerState.maxLod >= 999.9f); + + // Now just set MaxLOD to FLT_MAX. Other parts of the renderer (e.g. the non-zero max LOD workaround) should take account of this. + samplerDesc.MaxLOD = FLT_MAX; + } + + ID3D11SamplerState *dx11SamplerState = NULL; + HRESULT result = mDevice->CreateSamplerState(&samplerDesc, &dx11SamplerState); + if (FAILED(result) || !dx11SamplerState) + { + return gl::Error(GL_OUT_OF_MEMORY, "Unable to create a ID3D11SamplerState, HRESULT: 0x%X.", result); + } + + mSamplerStateCache.insert(std::make_pair(samplerState, std::make_pair(dx11SamplerState, mCounter++))); + + *outSamplerState = dx11SamplerState; + return gl::Error(GL_NO_ERROR); + } +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.h new file mode 100644 index 0000000000..0099b94a04 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.h @@ -0,0 +1,111 @@ +// +// Copyright (c) 2012-2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// RenderStateCache.h: Defines rx::RenderStateCache, a cache of Direct3D render +// state objects. + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_RENDERSTATECACHE_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_RENDERSTATECACHE_H_ + +#include "libANGLE/angletypes.h" +#include "libANGLE/Error.h" +#include "common/angleutils.h" + +#include + +namespace gl +{ +class Framebuffer; +} + +namespace rx +{ +class Renderer11; + +class RenderStateCache : angle::NonCopyable +{ + public: + RenderStateCache(Renderer11 *renderer); + virtual ~RenderStateCache(); + + void initialize(ID3D11Device *device); + void clear(); + + gl::Error getBlendState(const gl::Framebuffer *framebuffer, const gl::BlendState &blendState, ID3D11BlendState **outBlendState); + gl::Error getRasterizerState(const gl::RasterizerState &rasterState, bool scissorEnabled, ID3D11RasterizerState **outRasterizerState); + gl::Error getDepthStencilState(const gl::DepthStencilState &dsState, ID3D11DepthStencilState **outDSState); + gl::Error getSamplerState(const gl::SamplerState &samplerState, ID3D11SamplerState **outSamplerState); + + private: + Renderer11 *mRenderer; + unsigned long long mCounter; + + // Blend state cache + struct BlendStateKey + { + gl::BlendState blendState; + bool rtChannels[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT][4]; + }; + static std::size_t hashBlendState(const BlendStateKey &blendState); + static bool compareBlendStates(const BlendStateKey &a, const BlendStateKey &b); + static const unsigned int kMaxBlendStates; + + typedef std::size_t (*BlendStateHashFunction)(const BlendStateKey &); + typedef bool (*BlendStateEqualityFunction)(const BlendStateKey &, const BlendStateKey &); + typedef std::pair BlendStateCounterPair; + typedef std::unordered_map BlendStateMap; + BlendStateMap mBlendStateCache; + + // Rasterizer state cache + struct RasterizerStateKey + { + gl::RasterizerState rasterizerState; + bool scissorEnabled; + }; + 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 // LIBANGLE_RENDERER_D3D_D3D11_RENDERSTATECACHE_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.cpp new file mode 100644 index 0000000000..ecd9e13c90 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.cpp @@ -0,0 +1,394 @@ +// +// 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 "libANGLE/renderer/d3d/d3d11/RenderTarget11.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" +#include "libANGLE/renderer/d3d/d3d11/SwapChain11.h" +#include "libANGLE/renderer/d3d/d3d11/formatutils11.h" + +namespace rx +{ + +static bool getTextureProperties(ID3D11Resource *resource, unsigned int *mipLevels, unsigned int *samples) +{ + ID3D11Texture1D *texture1D = d3d11::DynamicCastComObject(resource); + if (texture1D) + { + D3D11_TEXTURE1D_DESC texDesc; + texture1D->GetDesc(&texDesc); + SafeRelease(texture1D); + + *mipLevels = texDesc.MipLevels; + *samples = 0; + + return true; + } + + ID3D11Texture2D *texture2D = d3d11::DynamicCastComObject(resource); + if (texture2D) + { + D3D11_TEXTURE2D_DESC texDesc; + texture2D->GetDesc(&texDesc); + SafeRelease(texture2D); + + *mipLevels = texDesc.MipLevels; + *samples = texDesc.SampleDesc.Count > 1 ? texDesc.SampleDesc.Count : 0; + + return true; + } + + ID3D11Texture3D *texture3D = d3d11::DynamicCastComObject(resource); + if (texture3D) + { + D3D11_TEXTURE3D_DESC texDesc; + texture3D->GetDesc(&texDesc); + SafeRelease(texture3D); + + *mipLevels = texDesc.MipLevels; + *samples = 0; + + return true; + } + + return false; +} + +static unsigned int getRTVSubresourceIndex(ID3D11Resource *resource, ID3D11RenderTargetView *view) +{ + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + view->GetDesc(&rtvDesc); + + unsigned int mipSlice = 0; + unsigned int arraySlice = 0; + + 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; + } + + unsigned int mipLevels, samples; + getTextureProperties(resource, &mipLevels, &samples); + + return D3D11CalcSubresource(mipSlice, arraySlice, mipLevels); +} + +static unsigned int getDSVSubresourceIndex(ID3D11Resource *resource, ID3D11DepthStencilView *view) +{ + D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; + view->GetDesc(&dsvDesc); + + unsigned int mipSlice = 0; + unsigned int arraySlice = 0; + + 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_DSV_DIMENSION_UNKNOWN: + UNIMPLEMENTED(); + break; + + default: + UNREACHABLE(); + break; + } + + unsigned int mipLevels, samples; + getTextureProperties(resource, &mipLevels, &samples); + + return D3D11CalcSubresource(mipSlice, arraySlice, mipLevels); +} + +RenderTarget11 *RenderTarget11::makeRenderTarget11(RenderTargetD3D *target) +{ + ASSERT(HAS_DYNAMIC_TYPE(RenderTarget11*, target)); + return static_cast(target); +} + +TextureRenderTarget11::TextureRenderTarget11(ID3D11RenderTargetView *rtv, ID3D11Resource *resource, ID3D11ShaderResourceView *srv, + GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLsizei samples) + : mWidth(width), + mHeight(height), + mDepth(depth), + mInternalFormat(internalFormat), + mDXGIFormat(DXGI_FORMAT_UNKNOWN), + mSamples(samples), + mSubresourceIndex(0), + mTexture(resource), + mRenderTarget(rtv), + mDepthStencil(NULL), + mShaderResource(srv) +{ + if (mTexture) + { + mTexture->AddRef(); + } + + if (mRenderTarget) + { + mRenderTarget->AddRef(); + } + + if (mShaderResource) + { + mShaderResource->AddRef(); + } + + if (mRenderTarget && mTexture) + { + mSubresourceIndex = getRTVSubresourceIndex(mTexture, mRenderTarget); + + D3D11_RENDER_TARGET_VIEW_DESC desc; + mRenderTarget->GetDesc(&desc); + mDXGIFormat = desc.Format; + } +} + +TextureRenderTarget11::TextureRenderTarget11(ID3D11DepthStencilView *dsv, ID3D11Resource *resource, ID3D11ShaderResourceView *srv, + GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLsizei samples) + : mWidth(width), + mHeight(height), + mDepth(depth), + mInternalFormat(internalFormat), + mDXGIFormat(DXGI_FORMAT_UNKNOWN), + mSamples(samples), + mSubresourceIndex(0), + mTexture(resource), + mRenderTarget(NULL), + mDepthStencil(dsv), + mShaderResource(srv) +{ + if (mTexture) + { + mTexture->AddRef(); + } + + if (mDepthStencil) + { + mDepthStencil->AddRef(); + } + + if (mShaderResource) + { + mShaderResource->AddRef(); + } + + if (mDepthStencil && mTexture) + { + mSubresourceIndex = getDSVSubresourceIndex(mTexture, mDepthStencil); + + D3D11_DEPTH_STENCIL_VIEW_DESC desc; + mDepthStencil->GetDesc(&desc); + mDXGIFormat = desc.Format; + } +} + +TextureRenderTarget11::~TextureRenderTarget11() +{ + SafeRelease(mTexture); + SafeRelease(mRenderTarget); + SafeRelease(mDepthStencil); + SafeRelease(mShaderResource); +} + +ID3D11Resource *TextureRenderTarget11::getTexture() const +{ + return mTexture; +} + +ID3D11RenderTargetView *TextureRenderTarget11::getRenderTargetView() const +{ + return mRenderTarget; +} + +ID3D11DepthStencilView *TextureRenderTarget11::getDepthStencilView() const +{ + return mDepthStencil; +} + +ID3D11ShaderResourceView *TextureRenderTarget11::getShaderResourceView() const +{ + return mShaderResource; +} + +GLsizei TextureRenderTarget11::getWidth() const +{ + return mWidth; +} + +GLsizei TextureRenderTarget11::getHeight() const +{ + return mHeight; +} + +GLsizei TextureRenderTarget11::getDepth() const +{ + return mDepth; +} + +GLenum TextureRenderTarget11::getInternalFormat() const +{ + return mInternalFormat; +} + +GLsizei TextureRenderTarget11::getSamples() const +{ + return mSamples; +} + +unsigned int TextureRenderTarget11::getSubresourceIndex() const +{ + return mSubresourceIndex; +} + +DXGI_FORMAT TextureRenderTarget11::getDXGIFormat() const +{ + return mDXGIFormat; +} + +SurfaceRenderTarget11::SurfaceRenderTarget11(SwapChain11 *swapChain, Renderer11 *renderer, bool depth) + : mSwapChain(swapChain), + mRenderer(renderer), + mDepth(depth) +{ + ASSERT(mSwapChain); +} + +SurfaceRenderTarget11::~SurfaceRenderTarget11() +{ +} + +GLsizei SurfaceRenderTarget11::getWidth() const +{ + return mSwapChain->getWidth(); +} + +GLsizei SurfaceRenderTarget11::getHeight() const +{ + return mSwapChain->getHeight(); +} + +GLsizei SurfaceRenderTarget11::getDepth() const +{ + return 1; +} + +GLenum SurfaceRenderTarget11::getInternalFormat() const +{ + return (mDepth ? mSwapChain->GetDepthBufferInternalFormat() : mSwapChain->GetBackBufferInternalFormat()); +} + +GLsizei SurfaceRenderTarget11::getSamples() const +{ + // Our EGL surfaces do not support multisampling. + return 0; +} + +ID3D11Resource *SurfaceRenderTarget11::getTexture() const +{ + return (mDepth ? mSwapChain->getDepthStencilTexture() : mSwapChain->getOffscreenTexture()); +} + +ID3D11RenderTargetView *SurfaceRenderTarget11::getRenderTargetView() const +{ + return (mDepth ? NULL : mSwapChain->getRenderTarget()); +} + +ID3D11DepthStencilView *SurfaceRenderTarget11::getDepthStencilView() const +{ + return (mDepth ? mSwapChain->getDepthStencil() : NULL); +} + +ID3D11ShaderResourceView *SurfaceRenderTarget11::getShaderResourceView() const +{ + return (mDepth ? mSwapChain->getDepthStencilShaderResource() : mSwapChain->getRenderTargetShaderResource()); +} + +unsigned int SurfaceRenderTarget11::getSubresourceIndex() const +{ + return 0; +} + +DXGI_FORMAT SurfaceRenderTarget11::getDXGIFormat() const +{ + return d3d11::GetTextureFormatInfo(getInternalFormat(), mRenderer->getFeatureLevel()).texFormat; +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.h new file mode 100644 index 0000000000..4472a56175 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.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. +// + +// RenderTarget11.h: Defines a DX11-specific wrapper for ID3D11View pointers +// retained by Renderbuffers. + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_RENDERTARGET11_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_RENDERTARGET11_H_ + +#include "libANGLE/renderer/d3d/RenderTargetD3D.h" + +namespace rx +{ +class SwapChain11; +class Renderer11; + +class RenderTarget11 : public RenderTargetD3D +{ + public: + RenderTarget11() { } + virtual ~RenderTarget11() { } + + static RenderTarget11 *makeRenderTarget11(RenderTargetD3D *renderTarget); + + virtual ID3D11Resource *getTexture() const = 0; + virtual ID3D11RenderTargetView *getRenderTargetView() const = 0; + virtual ID3D11DepthStencilView *getDepthStencilView() const = 0; + virtual ID3D11ShaderResourceView *getShaderResourceView() const = 0; + + virtual unsigned int getSubresourceIndex() const = 0; + + virtual DXGI_FORMAT getDXGIFormat() const = 0; + + private: + D3D_FEATURE_LEVEL mFeatureLevel; +}; + +class TextureRenderTarget11 : public RenderTarget11 +{ + public: + // TextureRenderTarget11 takes ownership of any D3D11 resources it is given and will AddRef them + TextureRenderTarget11(ID3D11RenderTargetView *rtv, ID3D11Resource *resource, ID3D11ShaderResourceView *srv, + GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLsizei samples); + TextureRenderTarget11(ID3D11DepthStencilView *dsv, ID3D11Resource *resource, ID3D11ShaderResourceView *srv, + GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLsizei samples); + virtual ~TextureRenderTarget11(); + + GLsizei getWidth() const override; + GLsizei getHeight() const override; + GLsizei getDepth() const override; + GLenum getInternalFormat() const override; + GLsizei getSamples() const override; + + ID3D11Resource *getTexture() const override; + ID3D11RenderTargetView *getRenderTargetView() const override; + ID3D11DepthStencilView *getDepthStencilView() const override; + ID3D11ShaderResourceView *getShaderResourceView() const override; + + unsigned int getSubresourceIndex() const override; + + DXGI_FORMAT getDXGIFormat() const override; + + private: + GLsizei mWidth; + GLsizei mHeight; + GLsizei mDepth; + GLenum mInternalFormat; + DXGI_FORMAT mDXGIFormat; + GLsizei mSamples; + + unsigned int mSubresourceIndex; + ID3D11Resource *mTexture; + ID3D11RenderTargetView *mRenderTarget; + ID3D11DepthStencilView *mDepthStencil; + ID3D11ShaderResourceView *mShaderResource; +}; + +class SurfaceRenderTarget11 : public RenderTarget11 +{ + public: + SurfaceRenderTarget11(SwapChain11 *swapChain, Renderer11 *renderer, bool depth); + virtual ~SurfaceRenderTarget11(); + + GLsizei getWidth() const override; + GLsizei getHeight() const override; + GLsizei getDepth() const override; + GLenum getInternalFormat() const override; + GLsizei getSamples() const override; + + ID3D11Resource *getTexture() const override; + ID3D11RenderTargetView *getRenderTargetView() const override; + ID3D11DepthStencilView *getDepthStencilView() const override; + ID3D11ShaderResourceView *getShaderResourceView() const override; + + unsigned int getSubresourceIndex() const override; + + DXGI_FORMAT getDXGIFormat() const override; + + private: + SwapChain11 *mSwapChain; + Renderer11 *mRenderer; + bool mDepth; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_D3D11_RENDERTARGET11_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp new file mode 100644 index 0000000000..5291a3a086 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp @@ -0,0 +1,3585 @@ +// +// Copyright (c) 2012-2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Renderer11.cpp: Implements a back-end specific class for the D3D11 renderer. + +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" + +#include "common/utilities.h" +#include "common/tls.h" +#include "libANGLE/Buffer.h" +#include "libANGLE/Display.h" +#include "libANGLE/Framebuffer.h" +#include "libANGLE/FramebufferAttachment.h" +#include "libANGLE/Program.h" +#include "libANGLE/State.h" +#include "libANGLE/Surface.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/renderer/d3d/CompilerD3D.h" +#include "libANGLE/renderer/d3d/FramebufferD3D.h" +#include "libANGLE/renderer/d3d/IndexDataManager.h" +#include "libANGLE/renderer/d3d/ProgramD3D.h" +#include "libANGLE/renderer/d3d/RenderbufferD3D.h" +#include "libANGLE/renderer/d3d/ShaderD3D.h" +#include "libANGLE/renderer/d3d/SurfaceD3D.h" +#include "libANGLE/renderer/d3d/TextureD3D.h" +#include "libANGLE/renderer/d3d/TransformFeedbackD3D.h" +#include "libANGLE/renderer/d3d/VertexDataManager.h" +#include "libANGLE/renderer/d3d/d3d11/Blit11.h" +#include "libANGLE/renderer/d3d/d3d11/Buffer11.h" +#include "libANGLE/renderer/d3d/d3d11/Clear11.h" +#include "libANGLE/renderer/d3d/d3d11/Fence11.h" +#include "libANGLE/renderer/d3d/d3d11/Framebuffer11.h" +#include "libANGLE/renderer/d3d/d3d11/Image11.h" +#include "libANGLE/renderer/d3d/d3d11/IndexBuffer11.h" +#include "libANGLE/renderer/d3d/d3d11/PixelTransfer11.h" +#include "libANGLE/renderer/d3d/d3d11/Query11.h" +#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h" +#include "libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h" +#include "libANGLE/renderer/d3d/d3d11/SwapChain11.h" +#include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h" +#include "libANGLE/renderer/d3d/d3d11/Trim11.h" +#include "libANGLE/renderer/d3d/d3d11/VertexArray11.h" +#include "libANGLE/renderer/d3d/d3d11/VertexBuffer11.h" +#include "libANGLE/renderer/d3d/d3d11/formatutils11.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" + +#include +#include + +// Enable ANGLE_SKIP_DXGI_1_2_CHECK if there is not a possibility of using cross-process +// HWNDs or the Windows 7 Platform Update (KB2670838) is expected to be installed. +#ifndef ANGLE_SKIP_DXGI_1_2_CHECK +#define ANGLE_SKIP_DXGI_1_2_CHECK 0 +#endif + +#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 + +#ifndef __d3d11sdklayers_h__ +#define D3D11_MESSAGE_CATEGORY UINT +#define D3D11_MESSAGE_SEVERITY UINT +#define D3D11_MESSAGE_ID UINT +struct D3D11_MESSAGE; +typedef struct D3D11_INFO_QUEUE_FILTER_DESC +{ + UINT NumCategories; + D3D11_MESSAGE_CATEGORY *pCategoryList; + UINT NumSeverities; + D3D11_MESSAGE_SEVERITY *pSeverityList; + UINT NumIDs; + D3D11_MESSAGE_ID *pIDList; +} D3D11_INFO_QUEUE_FILTER_DESC; +typedef struct D3D11_INFO_QUEUE_FILTER +{ + D3D11_INFO_QUEUE_FILTER_DESC AllowList; + D3D11_INFO_QUEUE_FILTER_DESC DenyList; +} D3D11_INFO_QUEUE_FILTER; +static const IID IID_ID3D11InfoQueue = { 0x6543dbb6, 0x1b48, 0x42f5, 0xab, 0x82, 0xe9, 0x7e, 0xc7, 0x43, 0x26, 0xf6 }; +MIDL_INTERFACE("6543dbb6-1b48-42f5-ab82-e97ec74326f6") ID3D11InfoQueue : public IUnknown +{ +public: + virtual HRESULT __stdcall SetMessageCountLimit(UINT64) = 0; + virtual void __stdcall ClearStoredMessages() = 0; + virtual HRESULT __stdcall GetMessage(UINT64, D3D11_MESSAGE *, SIZE_T *) = 0; + virtual UINT64 __stdcall GetNumMessagesAllowedByStorageFilter() = 0; + virtual UINT64 __stdcall GetNumMessagesDeniedByStorageFilter() = 0; + virtual UINT64 __stdcall GetNumStoredMessages() = 0; + virtual UINT64 __stdcall GetNumStoredMessagesAllowedByRetrievalFilter() = 0; + virtual UINT64 __stdcall GetNumMessagesDiscardedByMessageCountLimit() = 0; + virtual UINT64 __stdcall GetMessageCountLimit() = 0; + virtual HRESULT __stdcall AddStorageFilterEntries(D3D11_INFO_QUEUE_FILTER *) = 0; + virtual HRESULT __stdcall GetStorageFilter(D3D11_INFO_QUEUE_FILTER *, SIZE_T *) = 0; + virtual void __stdcall ClearStorageFilter() = 0; + virtual HRESULT __stdcall PushEmptyStorageFilter() = 0; + virtual HRESULT __stdcall PushCopyOfStorageFilter() = 0; + virtual HRESULT __stdcall PushStorageFilter(D3D11_INFO_QUEUE_FILTER *) = 0; + virtual void __stdcall PopStorageFilter() = 0; + virtual UINT __stdcall GetStorageFilterStackSize() = 0; + virtual HRESULT __stdcall AddRetrievalFilterEntries(D3D11_INFO_QUEUE_FILTER *) = 0; + virtual HRESULT __stdcall GetRetrievalFilter(D3D11_INFO_QUEUE_FILTER *, SIZE_T *) = 0; + virtual void __stdcall ClearRetrievalFilter() = 0; + virtual HRESULT __stdcall PushEmptyRetrievalFilter() = 0; + virtual HRESULT __stdcall PushCopyOfRetrievalFilter() = 0; + virtual HRESULT __stdcall PushRetrievalFilter(D3D11_INFO_QUEUE_FILTER *) = 0; + virtual void __stdcall PopRetrievalFilter() = 0; + virtual UINT __stdcall GetRetrievalFilterStackSize() = 0; + virtual HRESULT __stdcall AddMessage(D3D11_MESSAGE_CATEGORY, D3D11_MESSAGE_SEVERITY, D3D11_MESSAGE_ID, LPCSTR) = 0; + virtual HRESULT __stdcall AddApplicationMessage(D3D11_MESSAGE_SEVERITY, LPCSTR) = 0; + virtual HRESULT __stdcall SetBreakOnCategory(D3D11_MESSAGE_CATEGORY, BOOL) = 0; + virtual HRESULT __stdcall SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY, BOOL) = 0; + virtual HRESULT __stdcall SetBreakOnID(D3D11_MESSAGE_ID, BOOL) = 0; + virtual BOOL __stdcall GetBreakOnCategory(D3D11_MESSAGE_CATEGORY) = 0; + virtual BOOL __stdcall GetBreakOnSeverity(D3D11_MESSAGE_SEVERITY) = 0; + virtual BOOL __stdcall GetBreakOnID(D3D11_MESSAGE_ID) = 0; + virtual void __stdcall SetMuteDebugOutput(BOOL) = 0; + virtual BOOL __stdcall GetMuteDebugOutput() = 0; +}; +#endif + +namespace rx +{ + +namespace +{ + +enum +{ + MAX_TEXTURE_IMAGE_UNITS_VTF_SM4 = 16 +}; + +// dirtyPointer is a special value that will make the comparison with any valid pointer fail and force the renderer to re-apply the state. +static const uintptr_t DirtyPointer = static_cast(-1); + +static bool ImageIndexConflictsWithSRV(const gl::ImageIndex *index, D3D11_SHADER_RESOURCE_VIEW_DESC desc) +{ + unsigned mipLevel = index->mipIndex; + unsigned layerIndex = index->layerIndex; + GLenum type = index->type; + + switch (desc.ViewDimension) + { + case D3D11_SRV_DIMENSION_TEXTURE2D: + { + unsigned maxSrvMip = desc.Texture2D.MipLevels + desc.Texture2D.MostDetailedMip; + maxSrvMip = (desc.Texture2D.MipLevels == -1) ? INT_MAX : maxSrvMip; + + unsigned mipMin = index->mipIndex; + unsigned mipMax = (layerIndex == -1) ? INT_MAX : layerIndex; + + return type == GL_TEXTURE_2D && RangeUI(mipMin, mipMax).intersects(RangeUI(desc.Texture2D.MostDetailedMip, maxSrvMip)); + } + + case D3D11_SRV_DIMENSION_TEXTURE2DARRAY: + { + unsigned maxSrvMip = desc.Texture2DArray.MipLevels + desc.Texture2DArray.MostDetailedMip; + maxSrvMip = (desc.Texture2DArray.MipLevels == -1) ? INT_MAX : maxSrvMip; + + unsigned maxSlice = desc.Texture2DArray.FirstArraySlice + desc.Texture2DArray.ArraySize; + + // Cube maps can be mapped to Texture2DArray SRVs + return (type == GL_TEXTURE_2D_ARRAY || gl::IsCubeMapTextureTarget(type)) && + desc.Texture2DArray.MostDetailedMip <= mipLevel && mipLevel < maxSrvMip && + desc.Texture2DArray.FirstArraySlice <= layerIndex && layerIndex < maxSlice; + } + + case D3D11_SRV_DIMENSION_TEXTURECUBE: + { + unsigned maxSrvMip = desc.TextureCube.MipLevels + desc.TextureCube.MostDetailedMip; + maxSrvMip = (desc.TextureCube.MipLevels == -1) ? INT_MAX : maxSrvMip; + + return gl::IsCubeMapTextureTarget(type) && + desc.TextureCube.MostDetailedMip <= mipLevel && mipLevel < maxSrvMip; + } + + case D3D11_SRV_DIMENSION_TEXTURE3D: + { + unsigned maxSrvMip = desc.Texture3D.MipLevels + desc.Texture3D.MostDetailedMip; + maxSrvMip = (desc.Texture3D.MipLevels == -1) ? INT_MAX : maxSrvMip; + + return type == GL_TEXTURE_3D && + desc.Texture3D.MostDetailedMip <= mipLevel && mipLevel < maxSrvMip; + } + default: + // We only handle the cases corresponding to valid image indexes + UNIMPLEMENTED(); + } + + return false; +} + +// Does *not* increment the resource ref count!! +ID3D11Resource *GetViewResource(ID3D11View *view) +{ + ID3D11Resource *resource = NULL; + ASSERT(view); + view->GetResource(&resource); + resource->Release(); + return resource; +} + +void CalculateConstantBufferParams(GLintptr offset, GLsizeiptr size, UINT *outFirstConstant, UINT *outNumConstants) +{ + // The offset must be aligned to 256 bytes (should have been enforced by glBindBufferRange). + ASSERT(offset % 256 == 0); + + // firstConstant and numConstants are expressed in constants of 16-bytes. Furthermore they must be a multiple of 16 constants. + *outFirstConstant = offset / 16; + + // The GL size is not required to be aligned to a 256 bytes boundary. + // Round the size up to a 256 bytes boundary then express the results in constants of 16-bytes. + *outNumConstants = rx::roundUp(size, static_cast(256)) / 16; + + // Since the size is rounded up, firstConstant + numConstants may be bigger than the actual size of the buffer. + // This behaviour is explictly allowed according to the documentation on ID3D11DeviceContext1::PSSetConstantBuffers1 + // https://msdn.microsoft.com/en-us/library/windows/desktop/hh404649%28v=vs.85%29.aspx +} + +} + +Renderer11::Renderer11(egl::Display *display) + : RendererD3D(display), + mStateCache(this) +{ + // Initialize global annotator + gl::InitializeDebugAnnotations(&mAnnotator); + + mVertexDataManager = NULL; + mIndexDataManager = NULL; + + mLineLoopIB = NULL; + mTriangleFanIB = NULL; + + mBlit = NULL; + mPixelTransfer = NULL; + + mClear = NULL; + + mTrim = NULL; + + mSyncQuery = NULL; + + mSupportsConstantBufferOffsets = false; + + mD3d11Module = NULL; + mDxgiModule = NULL; + + mDevice = NULL; + mDeviceContext = NULL; + mDeviceContext1 = NULL; + mDxgiAdapter = NULL; + mDxgiFactory = NULL; + + mDriverConstantBufferVS = NULL; + mDriverConstantBufferPS = NULL; + + mAppliedVertexShader = NULL; + mAppliedGeometryShader = NULL; + mAppliedPixelShader = NULL; + + mAppliedNumXFBBindings = static_cast(-1); + + const auto &attributes = mDisplay->getAttributeMap(); + + EGLint requestedMajorVersion = attributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, EGL_DONT_CARE); + EGLint requestedMinorVersion = attributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, EGL_DONT_CARE); + + if (requestedMajorVersion == EGL_DONT_CARE || requestedMajorVersion >= 11) + { + if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 0) + { + mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_11_0); + } + } + + if (requestedMajorVersion == EGL_DONT_CARE || requestedMajorVersion >= 10) + { + if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 1) + { + mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_10_1); + } + if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 0) + { + mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_10_0); + } + } + +#if defined(ANGLE_ENABLE_WINDOWS_STORE) + if (requestedMajorVersion == EGL_DONT_CARE || requestedMajorVersion >= 9) +#else + if (requestedMajorVersion == 9 && requestedMinorVersion == 3) +#endif + { + mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_3); + } + + EGLint requestedDeviceType = attributes.get(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, + EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE); + switch (requestedDeviceType) + { + case EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE: + mDriverType = D3D_DRIVER_TYPE_HARDWARE; + break; + + case EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE: + mDriverType = D3D_DRIVER_TYPE_WARP; + break; + + case EGL_PLATFORM_ANGLE_DEVICE_TYPE_REFERENCE_ANGLE: + mDriverType = D3D_DRIVER_TYPE_REFERENCE; + break; + + case EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE: + mDriverType = D3D_DRIVER_TYPE_NULL; + break; + + default: + UNREACHABLE(); + } +} + +Renderer11::~Renderer11() +{ + release(); + + gl::UninitializeDebugAnnotations(); +} + +Renderer11 *Renderer11::makeRenderer11(Renderer *renderer) +{ + ASSERT(HAS_DYNAMIC_TYPE(Renderer11*, renderer)); + return static_cast(renderer); +} + +#ifndef __d3d11_1_h__ +#define D3D11_MESSAGE_ID_DEVICE_DRAW_RENDERTARGETVIEW_NOT_SET ((D3D11_MESSAGE_ID)3146081) +#endif + +egl::Error Renderer11::initialize() +{ + if (!mCompiler.initialize()) + { + return egl::Error(EGL_NOT_INITIALIZED, + D3D11_INIT_COMPILER_ERROR, + "Failed to initialize compiler."); + } + +#if !defined(ANGLE_ENABLE_WINDOWS_STORE) + mDxgiModule = LoadLibrary(TEXT("dxgi.dll")); + mD3d11Module = LoadLibrary(TEXT("d3d11.dll")); + + if (mD3d11Module == NULL || mDxgiModule == NULL) + { + return egl::Error(EGL_NOT_INITIALIZED, + D3D11_INIT_MISSING_DEP, + "Could not load D3D11 or DXGI library."); + } + + // create the D3D11 device + ASSERT(mDevice == NULL); + PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE)GetProcAddress(mD3d11Module, "D3D11CreateDevice"); + + if (D3D11CreateDevice == NULL) + { + return egl::Error(EGL_NOT_INITIALIZED, + D3D11_INIT_MISSING_DEP, + "Could not retrieve D3D11CreateDevice address."); + } +#endif + + HRESULT result = S_OK; +#ifdef _DEBUG + result = D3D11CreateDevice(NULL, + mDriverType, + NULL, + D3D11_CREATE_DEVICE_DEBUG, + mAvailableFeatureLevels.data(), + mAvailableFeatureLevels.size(), + D3D11_SDK_VERSION, + &mDevice, + &mFeatureLevel, + &mDeviceContext); + + if (!mDevice || FAILED(result)) + { + ERR("Failed creating Debug D3D11 device - falling back to release runtime.\n"); + } + + if (!mDevice || FAILED(result)) +#endif + { + result = D3D11CreateDevice(NULL, + mDriverType, + NULL, + 0, + mAvailableFeatureLevels.data(), + mAvailableFeatureLevels.size(), + D3D11_SDK_VERSION, + &mDevice, + &mFeatureLevel, + &mDeviceContext); + + if (result == E_INVALIDARG) + { + // Cleanup done by destructor through glDestroyRenderer + return egl::Error(EGL_NOT_INITIALIZED, + D3D11_INIT_CREATEDEVICE_INVALIDARG, + "Could not create D3D11 device."); + } + + if (!mDevice || FAILED(result)) + { + // Cleanup done by destructor through glDestroyRenderer + return egl::Error(EGL_NOT_INITIALIZED, + D3D11_INIT_CREATEDEVICE_ERROR, + "Could not create D3D11 device."); + } + } + +#if !defined(ANGLE_ENABLE_WINDOWS_STORE) +#if !ANGLE_SKIP_DXGI_1_2_CHECK + // In order to create a swap chain for an HWND owned by another process, DXGI 1.2 is required. + // The easiest way to check is to query for a IDXGIDevice2. + bool requireDXGI1_2 = false; + HWND hwnd = WindowFromDC(mDisplay->getNativeDisplayId()); + if (hwnd) + { + DWORD currentProcessId = GetCurrentProcessId(); + DWORD wndProcessId; + GetWindowThreadProcessId(hwnd, &wndProcessId); + requireDXGI1_2 = (currentProcessId != wndProcessId); + } + else + { + requireDXGI1_2 = true; + } + + if (requireDXGI1_2) + { + IDXGIDevice2 *dxgiDevice2 = NULL; + result = mDevice->QueryInterface(__uuidof(IDXGIDevice2), (void**)&dxgiDevice2); + if (FAILED(result)) + { + return egl::Error(EGL_NOT_INITIALIZED, + D3D11_INIT_INCOMPATIBLE_DXGI, + "DXGI 1.2 required to present to HWNDs owned by another process."); + } + SafeRelease(dxgiDevice2); + } +#endif +#endif + + // Cast the DeviceContext to a DeviceContext1. + // This could fail on Windows 7 without the Platform Update. + // Don't error in this case- just don't use mDeviceContext1. +#if defined(ANGLE_ENABLE_D3D11_1) + mDeviceContext1 = d3d11::DynamicCastComObject(mDeviceContext); +#endif + + IDXGIDevice *dxgiDevice = NULL; + result = mDevice->QueryInterface(__uuidof(IDXGIDevice), (void**)&dxgiDevice); + + if (FAILED(result)) + { + return egl::Error(EGL_NOT_INITIALIZED, + D3D11_INIT_OTHER_ERROR, + "Could not query DXGI device."); + } + + result = dxgiDevice->GetParent(__uuidof(IDXGIAdapter), (void**)&mDxgiAdapter); + + if (FAILED(result)) + { + return egl::Error(EGL_NOT_INITIALIZED, + D3D11_INIT_OTHER_ERROR, + "Could not retrieve DXGI adapter"); + } + + SafeRelease(dxgiDevice); + +#if defined(ANGLE_ENABLE_D3D11_1) + IDXGIAdapter2 *dxgiAdapter2 = d3d11::DynamicCastComObject(mDxgiAdapter); + + // On D3D_FEATURE_LEVEL_9_*, IDXGIAdapter::GetDesc returns "Software Adapter" for the description string. + // If DXGI1.2 is available then IDXGIAdapter2::GetDesc2 can be used to get the actual hardware values. + if (mFeatureLevel <= D3D_FEATURE_LEVEL_9_3 && dxgiAdapter2 != NULL) + { + DXGI_ADAPTER_DESC2 adapterDesc2 = {0}; + dxgiAdapter2->GetDesc2(&adapterDesc2); + + // Copy the contents of the DXGI_ADAPTER_DESC2 into mAdapterDescription (a DXGI_ADAPTER_DESC). + memcpy(mAdapterDescription.Description, adapterDesc2.Description, sizeof(mAdapterDescription.Description)); + mAdapterDescription.VendorId = adapterDesc2.VendorId; + mAdapterDescription.DeviceId = adapterDesc2.DeviceId; + mAdapterDescription.SubSysId = adapterDesc2.SubSysId; + mAdapterDescription.Revision = adapterDesc2.Revision; + mAdapterDescription.DedicatedVideoMemory = adapterDesc2.DedicatedVideoMemory; + mAdapterDescription.DedicatedSystemMemory = adapterDesc2.DedicatedSystemMemory; + mAdapterDescription.SharedSystemMemory = adapterDesc2.SharedSystemMemory; + mAdapterDescription.AdapterLuid = adapterDesc2.AdapterLuid; + } + else + { + mDxgiAdapter->GetDesc(&mAdapterDescription); + } + + SafeRelease(dxgiAdapter2); +#endif + + memset(mDescription, 0, sizeof(mDescription)); + wcstombs(mDescription, mAdapterDescription.Description, sizeof(mDescription) - 1); + + result = mDxgiAdapter->GetParent(__uuidof(IDXGIFactory), (void**)&mDxgiFactory); + + if (!mDxgiFactory || FAILED(result)) + { + return egl::Error(EGL_NOT_INITIALIZED, + D3D11_INIT_OTHER_ERROR, + "Could not create DXGI factory."); + } + + // 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(IID_ID3D11InfoQueue, (void **)&infoQueue); + + if (SUCCEEDED(result)) + { + D3D11_MESSAGE_ID hideMessages[] = + { + D3D11_MESSAGE_ID_DEVICE_DRAW_RENDERTARGETVIEW_NOT_SET + }; + + D3D11_INFO_QUEUE_FILTER filter = {0}; + filter.DenyList.NumIDs = ArraySize(hideMessages); + filter.DenyList.pIDList = hideMessages; + + infoQueue->AddStorageFilterEntries(&filter); + SafeRelease(infoQueue); + } +#endif + + initializeDevice(); + + return egl::Error(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, getRendererClass()); + + ASSERT(!mBlit); + mBlit = new Blit11(this); + + ASSERT(!mClear); + mClear = new Clear11(this); + + const auto &attributes = mDisplay->getAttributeMap(); + // If automatic trim is enabled, DXGIDevice3::Trim( ) is called for the application + // automatically when an application is suspended by the OS. This feature is currently + // only supported for Windows Store applications. + EGLint enableAutoTrim = attributes.get(EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, EGL_FALSE); + + if (enableAutoTrim == EGL_TRUE) + { + ASSERT(!mTrim); + mTrim = new Trim11(this); + } + + ASSERT(!mPixelTransfer); + mPixelTransfer = new PixelTransfer11(this); + + const gl::Caps &rendererCaps = getRendererCaps(); + +#if defined(ANGLE_ENABLE_D3D11_1) + if (getDeviceContext1IfSupported()) + { + D3D11_FEATURE_DATA_D3D11_OPTIONS d3d11Options; + mDevice->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS, &d3d11Options, sizeof(D3D11_FEATURE_DATA_D3D11_OPTIONS)); + mSupportsConstantBufferOffsets = (d3d11Options.ConstantBufferOffsetting != FALSE); + } +#endif + + mForceSetVertexSamplerStates.resize(rendererCaps.maxVertexTextureImageUnits); + mCurVertexSamplerStates.resize(rendererCaps.maxVertexTextureImageUnits); + + mForceSetPixelSamplerStates.resize(rendererCaps.maxTextureImageUnits); + mCurPixelSamplerStates.resize(rendererCaps.maxTextureImageUnits); + + mCurVertexSRVs.resize(rendererCaps.maxVertexTextureImageUnits); + mCurPixelSRVs.resize(rendererCaps.maxTextureImageUnits); + + markAllStateDirty(); +} + +egl::ConfigSet Renderer11::generateConfigs() const +{ + static const GLenum colorBufferFormats[] = + { + GL_BGRA8_EXT, + GL_RGBA8_OES, + }; + + static const GLenum depthStencilBufferFormats[] = + { + GL_NONE, + GL_DEPTH24_STENCIL8_OES, + GL_DEPTH_COMPONENT16, + }; + + const gl::Caps &rendererCaps = getRendererCaps(); + const gl::TextureCapsMap &rendererTextureCaps = getRendererTextureCaps(); + + egl::ConfigSet configs; + for (size_t formatIndex = 0; formatIndex < ArraySize(colorBufferFormats); formatIndex++) + { + GLenum colorBufferInternalFormat = colorBufferFormats[formatIndex]; + const gl::TextureCaps &colorBufferFormatCaps = rendererTextureCaps.get(colorBufferInternalFormat); + if (colorBufferFormatCaps.renderable) + { + for (size_t depthStencilIndex = 0; depthStencilIndex < ArraySize(depthStencilBufferFormats); depthStencilIndex++) + { + GLenum depthStencilBufferInternalFormat = depthStencilBufferFormats[depthStencilIndex]; + const gl::TextureCaps &depthStencilBufferFormatCaps = rendererTextureCaps.get(depthStencilBufferInternalFormat); + if (depthStencilBufferFormatCaps.renderable || depthStencilBufferInternalFormat == GL_NONE) + { + const gl::InternalFormat &colorBufferFormatInfo = gl::GetInternalFormatInfo(colorBufferInternalFormat); + const gl::InternalFormat &depthStencilBufferFormatInfo = gl::GetInternalFormatInfo(depthStencilBufferInternalFormat); + + egl::Config config; + config.renderTargetFormat = colorBufferInternalFormat; + config.depthStencilFormat = depthStencilBufferInternalFormat; + config.bufferSize = colorBufferFormatInfo.pixelBytes * 8; + config.redSize = colorBufferFormatInfo.redBits; + config.greenSize = colorBufferFormatInfo.greenBits; + config.blueSize = colorBufferFormatInfo.blueBits; + config.luminanceSize = colorBufferFormatInfo.luminanceBits; + config.alphaSize = colorBufferFormatInfo.alphaBits; + config.alphaMaskSize = 0; + config.bindToTextureRGB = (colorBufferFormatInfo.format == GL_RGB); + config.bindToTextureRGBA = (colorBufferFormatInfo.format == GL_RGBA || colorBufferFormatInfo.format == GL_BGRA_EXT); + config.colorBufferType = EGL_RGB_BUFFER; + config.configID = static_cast(configs.size() + 1); + // Can only support a conformant ES2 with feature level greater than 10.0. + config.conformant = (mFeatureLevel >= D3D_FEATURE_LEVEL_10_0) ? (EGL_OPENGL_ES2_BIT | EGL_OPENGL_ES3_BIT_KHR) : EGL_NONE; + config.configCaveat = config.conformant == EGL_NONE ? EGL_NON_CONFORMANT_CONFIG : EGL_NONE; + config.depthSize = depthStencilBufferFormatInfo.depthBits; + config.level = 0; + config.matchNativePixmap = EGL_NONE; + config.maxPBufferWidth = rendererCaps.max2DTextureSize; + config.maxPBufferHeight = rendererCaps.max2DTextureSize; + config.maxPBufferPixels = rendererCaps.max2DTextureSize * rendererCaps.max2DTextureSize; + config.maxSwapInterval = 4; + config.minSwapInterval = 0; + config.nativeRenderable = EGL_FALSE; + config.nativeVisualID = 0; + config.nativeVisualType = EGL_NONE; + // Can't support ES3 at all without feature level 10.0 + config.renderableType = EGL_OPENGL_ES2_BIT | ((mFeatureLevel >= D3D_FEATURE_LEVEL_10_0) ? EGL_OPENGL_ES3_BIT_KHR : 0); + config.sampleBuffers = 0; // FIXME: enumerate multi-sampling + config.samples = 0; + config.stencilSize = depthStencilBufferFormatInfo.stencilBits; + config.surfaceType = EGL_PBUFFER_BIT | EGL_WINDOW_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT; + config.transparentType = EGL_NONE; + config.transparentRedValue = 0; + config.transparentGreenValue = 0; + config.transparentBlueValue = 0; + + configs.add(config); + } + } + } + } + + ASSERT(configs.size() > 0); + return configs; +} + +gl::Error Renderer11::flush() +{ + mDeviceContext->Flush(); + return gl::Error(GL_NO_ERROR); +} + +gl::Error Renderer11::finish() +{ + HRESULT result; + + if (!mSyncQuery) + { + D3D11_QUERY_DESC queryDesc; + queryDesc.Query = D3D11_QUERY_EVENT; + queryDesc.MiscFlags = 0; + + result = mDevice->CreateQuery(&queryDesc, &mSyncQuery); + ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create event query, result: 0x%X.", result); + } + } + + mDeviceContext->End(mSyncQuery); + mDeviceContext->Flush(); + + do + { + result = mDeviceContext->GetData(mSyncQuery, NULL, 0, D3D11_ASYNC_GETDATA_DONOTFLUSH); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to get event query data, result: 0x%X.", result); + } + + // Keep polling, but allow other threads to do something useful first + ScheduleYield(); + + if (testDeviceLost()) + { + mDisplay->notifyDeviceLost(); + return gl::Error(GL_OUT_OF_MEMORY, "Device was lost while waiting for sync."); + } + } + while (result == S_FALSE); + + return gl::Error(GL_NO_ERROR); +} + +SwapChainD3D *Renderer11::createSwapChain(NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) +{ + return new SwapChain11(this, nativeWindow, shareHandle, backBufferFormat, depthBufferFormat); +} + +gl::Error Renderer11::generateSwizzle(gl::Texture *texture) +{ + if (texture) + { + TextureD3D *textureD3D = GetImplAs(texture); + ASSERT(textureD3D); + + TextureStorage *texStorage = nullptr; + gl::Error error = textureD3D->getNativeTexture(&texStorage); + if (error.isError()) + { + return error; + } + + if (texStorage) + { + TextureStorage11 *storage11 = TextureStorage11::makeTextureStorage11(texStorage); + error = storage11->generateSwizzles(texture->getSamplerState().swizzleRed, + texture->getSamplerState().swizzleGreen, + texture->getSamplerState().swizzleBlue, + texture->getSamplerState().swizzleAlpha); + if (error.isError()) + { + return error; + } + } + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Renderer11::setSamplerState(gl::SamplerType type, int index, gl::Texture *texture, const gl::SamplerState &samplerStateParam) +{ + // Make sure to add the level offset for our tiny compressed texture workaround + TextureD3D *textureD3D = GetImplAs(texture); + gl::SamplerState samplerStateInternal = samplerStateParam; + + TextureStorage *storage = nullptr; + gl::Error error = textureD3D->getNativeTexture(&storage); + if (error.isError()) + { + return error; + } + + // Storage should exist, texture should be complete + ASSERT(storage); + + samplerStateInternal.baseLevel += storage->getTopLevel(); + + if (type == gl::SAMPLER_PIXEL) + { + ASSERT(static_cast(index) < getRendererCaps().maxTextureImageUnits); + + if (mForceSetPixelSamplerStates[index] || memcmp(&samplerStateInternal, &mCurPixelSamplerStates[index], sizeof(gl::SamplerState)) != 0) + { + ID3D11SamplerState *dxSamplerState = NULL; + error = mStateCache.getSamplerState(samplerStateInternal, &dxSamplerState); + if (error.isError()) + { + return error; + } + + ASSERT(dxSamplerState != NULL); + mDeviceContext->PSSetSamplers(index, 1, &dxSamplerState); + + mCurPixelSamplerStates[index] = samplerStateInternal; + } + + mForceSetPixelSamplerStates[index] = false; + } + else if (type == gl::SAMPLER_VERTEX) + { + ASSERT(static_cast(index) < getRendererCaps().maxVertexTextureImageUnits); + + if (mForceSetVertexSamplerStates[index] || memcmp(&samplerStateInternal, &mCurVertexSamplerStates[index], sizeof(gl::SamplerState)) != 0) + { + ID3D11SamplerState *dxSamplerState = NULL; + error = mStateCache.getSamplerState(samplerStateInternal, &dxSamplerState); + if (error.isError()) + { + return error; + } + + ASSERT(dxSamplerState != NULL); + mDeviceContext->VSSetSamplers(index, 1, &dxSamplerState); + + mCurVertexSamplerStates[index] = samplerStateInternal; + } + + mForceSetVertexSamplerStates[index] = false; + } + else UNREACHABLE(); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Renderer11::setTexture(gl::SamplerType type, int index, gl::Texture *texture) +{ + ID3D11ShaderResourceView *textureSRV = NULL; + + if (texture) + { + TextureD3D *textureImpl = GetImplAs(texture); + + TextureStorage *texStorage = nullptr; + gl::Error error = textureImpl->getNativeTexture(&texStorage); + if (error.isError()) + { + return error; + } + + // Texture should be complete and have a storage + ASSERT(texStorage); + + TextureStorage11 *storage11 = TextureStorage11::makeTextureStorage11(texStorage); + + // Make sure to add the level offset for our tiny compressed texture workaround + gl::SamplerState samplerState = texture->getSamplerState(); + samplerState.baseLevel += storage11->getTopLevel(); + + error = storage11->getSRV(samplerState, &textureSRV); + if (error.isError()) + { + return error; + } + + // 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); + + textureImpl->resetDirty(); + } + + ASSERT((type == gl::SAMPLER_PIXEL && static_cast(index) < getRendererCaps().maxTextureImageUnits) || + (type == gl::SAMPLER_VERTEX && static_cast(index) < getRendererCaps().maxVertexTextureImageUnits)); + + setShaderResource(type, index, textureSRV); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Renderer11::setUniformBuffers(const gl::Data &data, + const GLint vertexUniformBuffers[], + const GLint fragmentUniformBuffers[]) +{ + for (unsigned int uniformBufferIndex = 0; uniformBufferIndex < data.caps->maxVertexUniformBlocks; uniformBufferIndex++) + { + GLint binding = vertexUniformBuffers[uniformBufferIndex]; + + if (binding == -1) + { + continue; + } + + gl::Buffer *uniformBuffer = data.state->getIndexedUniformBuffer(binding); + GLintptr uniformBufferOffset = data.state->getIndexedUniformBufferOffset(binding); + GLsizeiptr uniformBufferSize = data.state->getIndexedUniformBufferSize(binding); + + if (uniformBuffer) + { + Buffer11 *bufferStorage = Buffer11::makeBuffer11(uniformBuffer->getImplementation()); + ID3D11Buffer *constantBuffer = bufferStorage->getBuffer(BUFFER_USAGE_UNIFORM); + + if (!constantBuffer) + { + return gl::Error(GL_OUT_OF_MEMORY); + } + + if (mCurrentConstantBufferVS[uniformBufferIndex] != bufferStorage->getSerial() || + mCurrentConstantBufferVSOffset[uniformBufferIndex] != uniformBufferOffset || + mCurrentConstantBufferVSSize[uniformBufferIndex] != uniformBufferSize) + { +#if defined(ANGLE_ENABLE_D3D11_1) + if (mSupportsConstantBufferOffsets && uniformBufferSize != 0) + { + UINT firstConstant = 0, numConstants = 0; + CalculateConstantBufferParams(uniformBufferOffset, uniformBufferSize, &firstConstant, &numConstants); + mDeviceContext1->VSSetConstantBuffers1(getReservedVertexUniformBuffers() + uniformBufferIndex, + 1, &constantBuffer, &firstConstant, &numConstants); + } + else +#endif + { + ASSERT(uniformBufferOffset == 0); + mDeviceContext->VSSetConstantBuffers(getReservedVertexUniformBuffers() + uniformBufferIndex, + 1, &constantBuffer); + } + + mCurrentConstantBufferVS[uniformBufferIndex] = bufferStorage->getSerial(); + mCurrentConstantBufferVSOffset[uniformBufferIndex] = uniformBufferOffset; + mCurrentConstantBufferVSSize[uniformBufferIndex] = uniformBufferSize; + } + } + } + + for (unsigned int uniformBufferIndex = 0; uniformBufferIndex < data.caps->maxFragmentUniformBlocks; uniformBufferIndex++) + { + GLint binding = fragmentUniformBuffers[uniformBufferIndex]; + + if (binding == -1) + { + continue; + } + + gl::Buffer *uniformBuffer = data.state->getIndexedUniformBuffer(binding); + GLintptr uniformBufferOffset = data.state->getIndexedUniformBufferOffset(binding); + GLsizeiptr uniformBufferSize = data.state->getIndexedUniformBufferSize(binding); + + if (uniformBuffer) + { + Buffer11 *bufferStorage = Buffer11::makeBuffer11(uniformBuffer->getImplementation()); + ID3D11Buffer *constantBuffer = bufferStorage->getBuffer(BUFFER_USAGE_UNIFORM); + + if (!constantBuffer) + { + return gl::Error(GL_OUT_OF_MEMORY); + } + + if (mCurrentConstantBufferPS[uniformBufferIndex] != bufferStorage->getSerial() || + mCurrentConstantBufferPSOffset[uniformBufferIndex] != uniformBufferOffset || + mCurrentConstantBufferPSSize[uniformBufferIndex] != uniformBufferSize) + { +#if defined(ANGLE_ENABLE_D3D11_1) + if (mSupportsConstantBufferOffsets && uniformBufferSize != 0) + { + UINT firstConstant = 0, numConstants = 0; + CalculateConstantBufferParams(uniformBufferOffset, uniformBufferSize, &firstConstant, &numConstants); + mDeviceContext1->PSSetConstantBuffers1(getReservedFragmentUniformBuffers() + uniformBufferIndex, + 1, &constantBuffer, &firstConstant, &numConstants); + } + else +#endif + { + ASSERT(uniformBufferOffset == 0); + mDeviceContext->PSSetConstantBuffers(getReservedFragmentUniformBuffers() + uniformBufferIndex, + 1, &constantBuffer); + } + + mCurrentConstantBufferPS[uniformBufferIndex] = bufferStorage->getSerial(); + mCurrentConstantBufferPSOffset[uniformBufferIndex] = uniformBufferOffset; + mCurrentConstantBufferPSSize[uniformBufferIndex] = uniformBufferSize; + } + } + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Renderer11::setRasterizerState(const gl::RasterizerState &rasterState) +{ + if (mForceSetRasterState || memcmp(&rasterState, &mCurRasterState, sizeof(gl::RasterizerState)) != 0) + { + ID3D11RasterizerState *dxRasterState = NULL; + gl::Error error = mStateCache.getRasterizerState(rasterState, mScissorEnabled, &dxRasterState); + if (error.isError()) + { + return error; + } + + mDeviceContext->RSSetState(dxRasterState); + + mCurRasterState = rasterState; + } + + mForceSetRasterState = false; + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Renderer11::setBlendState(const gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::ColorF &blendColor, + unsigned int sampleMask) +{ + if (mForceSetBlendState || + memcmp(&blendState, &mCurBlendState, sizeof(gl::BlendState)) != 0 || + memcmp(&blendColor, &mCurBlendColor, sizeof(gl::ColorF)) != 0 || + sampleMask != mCurSampleMask) + { + ID3D11BlendState *dxBlendState = NULL; + gl::Error error = mStateCache.getBlendState(framebuffer, blendState, &dxBlendState); + if (error.isError()) + { + return error; + } + + ASSERT(dxBlendState != NULL); + + float blendColors[4] = {0.0f}; + if (blendState.sourceBlendRGB != GL_CONSTANT_ALPHA && blendState.sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA && + blendState.destBlendRGB != GL_CONSTANT_ALPHA && blendState.destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA) + { + blendColors[0] = blendColor.red; + blendColors[1] = blendColor.green; + blendColors[2] = blendColor.blue; + blendColors[3] = blendColor.alpha; + } + else + { + blendColors[0] = blendColor.alpha; + blendColors[1] = blendColor.alpha; + blendColors[2] = blendColor.alpha; + blendColors[3] = blendColor.alpha; + } + + mDeviceContext->OMSetBlendState(dxBlendState, blendColors, sampleMask); + + mCurBlendState = blendState; + mCurBlendColor = blendColor; + mCurSampleMask = sampleMask; + } + + mForceSetBlendState = false; + + return gl::Error(GL_NO_ERROR); +} + +gl::Error 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) + { + ASSERT(depthStencilState.stencilWritemask == depthStencilState.stencilBackWritemask); + ASSERT(stencilRef == stencilBackRef); + ASSERT(depthStencilState.stencilMask == depthStencilState.stencilBackMask); + + ID3D11DepthStencilState *dxDepthStencilState = NULL; + gl::Error error = mStateCache.getDepthStencilState(depthStencilState, &dxDepthStencilState); + if (error.isError()) + { + return error; + } + + ASSERT(dxDepthStencilState); + + // Max D3D11 stencil reference value is 0xFF, corresponding to the max 8 bits in a stencil buffer + // GL specifies we should clamp the ref value to the nearest bit depth when doing stencil ops + static_assert(D3D11_DEFAULT_STENCIL_READ_MASK == 0xFF, "Unexpected value of D3D11_DEFAULT_STENCIL_READ_MASK"); + static_assert(D3D11_DEFAULT_STENCIL_WRITE_MASK == 0xFF, "Unexpected value of D3D11_DEFAULT_STENCIL_WRITE_MASK"); + UINT dxStencilRef = std::min(stencilRef, 0xFFu); + + mDeviceContext->OMSetDepthStencilState(dxDepthStencilState, dxStencilRef); + + mCurDepthStencilState = depthStencilState; + mCurStencilRef = stencilRef; + mCurStencilBackRef = stencilBackRef; + } + + mForceSetDepthStencilState = false; + + return gl::Error(GL_NO_ERROR); +} + +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; +} + +void 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; + } + + bool viewportChanged = mForceSetViewport || memcmp(&actualViewport, &mCurViewport, sizeof(gl::Rectangle)) != 0 || + actualZNear != mCurNear || actualZFar != mCurFar; + + if (viewportChanged) + { + const gl::Caps& caps = getRendererCaps(); + + int dxMaxViewportBoundsX = static_cast(caps.maxViewportWidth); + int dxMaxViewportBoundsY = static_cast(caps.maxViewportHeight); + int dxMinViewportBoundsX = -dxMaxViewportBoundsX; + int dxMinViewportBoundsY = -dxMaxViewportBoundsY; + + if (mFeatureLevel <= D3D_FEATURE_LEVEL_9_3) + { + // Feature Level 9 viewports shouldn't exceed the dimensions of the rendertarget. + dxMaxViewportBoundsX = mRenderTargetDesc.width; + dxMaxViewportBoundsY = mRenderTargetDesc.height; + dxMinViewportBoundsX = 0; + dxMinViewportBoundsY = 0; + } + + int dxViewportTopLeftX = gl::clamp(actualViewport.x, dxMinViewportBoundsX, dxMaxViewportBoundsX); + int dxViewportTopLeftY = gl::clamp(actualViewport.y, dxMinViewportBoundsY, dxMaxViewportBoundsY); + int dxViewportWidth = gl::clamp(actualViewport.width, 0, dxMaxViewportBoundsX - dxViewportTopLeftX); + int dxViewportHeight = gl::clamp(actualViewport.height, 0, dxMaxViewportBoundsY - dxViewportTopLeftY); + + D3D11_VIEWPORT dxViewport; + dxViewport.TopLeftX = static_cast(dxViewportTopLeftX); + dxViewport.TopLeftY = static_cast(dxViewportTopLeftY); + dxViewport.Width = static_cast(dxViewportWidth); + dxViewport.Height = static_cast(dxViewportHeight); + dxViewport.MinDepth = actualZNear; + dxViewport.MaxDepth = actualZFar; + + mDeviceContext->RSSetViewports(1, &dxViewport); + + mCurViewport = actualViewport; + mCurNear = actualZNear; + mCurFar = actualZFar; + + // On Feature Level 9_*, we must emulate large and/or negative viewports in the shaders using viewAdjust (like the D3D9 renderer). + if (mFeatureLevel <= D3D_FEATURE_LEVEL_9_3) + { + mVertexConstants.viewAdjust[0] = static_cast((actualViewport.width - dxViewportWidth) + 2 * (actualViewport.x - dxViewportTopLeftX)) / dxViewport.Width; + mVertexConstants.viewAdjust[1] = static_cast((actualViewport.height - dxViewportHeight) + 2 * (actualViewport.y - dxViewportTopLeftY)) / dxViewport.Height; + mVertexConstants.viewAdjust[2] = static_cast(actualViewport.width) / dxViewport.Width; + mVertexConstants.viewAdjust[3] = static_cast(actualViewport.height) / dxViewport.Height; + } + + 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); + + // Instanced pointsprite emulation requires ViewCoords to be defined in the + // the vertex shader. + mVertexConstants.viewCoords[0] = mPixelConstants.viewCoords[0]; + mVertexConstants.viewCoords[1] = mPixelConstants.viewCoords[1]; + mVertexConstants.viewCoords[2] = mPixelConstants.viewCoords[2]; + mVertexConstants.viewCoords[3] = mPixelConstants.viewCoords[3]; + + 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; +} + +bool Renderer11::applyPrimitiveType(GLenum mode, GLsizei count, bool usesPointSize) +{ + D3D11_PRIMITIVE_TOPOLOGY primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED; + + GLsizei minCount = 0; + + switch (mode) + { + case GL_POINTS: primitiveTopology = D3D11_PRIMITIVE_TOPOLOGY_POINTLIST; minCount = 1; break; + case GL_LINES: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINELIST; minCount = 2; break; + case GL_LINE_LOOP: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP; minCount = 2; break; + case GL_LINE_STRIP: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP; minCount = 2; break; + case GL_TRIANGLES: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; minCount = 3; break; + case GL_TRIANGLE_STRIP: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP; minCount = 3; break; + // emulate fans via rewriting index buffer + case GL_TRIANGLE_FAN: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; minCount = 3; break; + default: + UNREACHABLE(); + return false; + } + + // If instanced pointsprite emulation is being used and If gl_PointSize is used in the shader, + // GL_POINTS mode is expected to render pointsprites. + // Instanced PointSprite emulation requires that the topology to be D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST. + if (mode == GL_POINTS && usesPointSize && getWorkarounds().useInstancedPointSpriteEmulation) + { + primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; + } + + if (primitiveTopology != mCurrentPrimitiveTopology) + { + mDeviceContext->IASetPrimitiveTopology(primitiveTopology); + mCurrentPrimitiveTopology = primitiveTopology; + } + + return count >= minCount; +} + +void Renderer11::unsetConflictingSRVs(gl::SamplerType samplerType, uintptr_t resource, const gl::ImageIndex *index) +{ + auto ¤tSRVs = (samplerType == gl::SAMPLER_VERTEX ? mCurVertexSRVs : mCurPixelSRVs); + + for (size_t resourceIndex = 0; resourceIndex < currentSRVs.size(); ++resourceIndex) + { + auto &record = currentSRVs[resourceIndex]; + + if (record.srv && record.resource == resource && ImageIndexConflictsWithSRV(index, record.desc)) + { + setShaderResource(samplerType, static_cast(resourceIndex), NULL); + } + } +} + +gl::Error Renderer11::applyRenderTarget(const 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; + DXGI_FORMAT renderTargetFormat = DXGI_FORMAT_UNKNOWN; + ID3D11RenderTargetView* framebufferRTVs[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS] = {NULL}; + bool missingColorRenderTarget = true; + + const FramebufferD3D *framebufferD3D = GetImplAs(framebuffer); + const gl::AttachmentList &colorbuffers = framebufferD3D->getColorAttachmentsForRender(getWorkarounds()); + + for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment) + { + gl::FramebufferAttachment *colorbuffer = colorbuffers[colorAttachment]; + + if (colorbuffer) + { + // the draw buffer must be either "none", "back" for the default buffer or the same index as this color (in order) + + // 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 gl::Error(GL_NO_ERROR); + } + + // Extract the render target dimensions and view + RenderTarget11 *renderTarget = NULL; + gl::Error error = d3d11::GetAttachmentRenderTarget(colorbuffer, &renderTarget); + if (error.isError()) + { + return error; + } + ASSERT(renderTarget); + + framebufferRTVs[colorAttachment] = renderTarget->getRenderTargetView(); + ASSERT(framebufferRTVs[colorAttachment]); + + if (missingColorRenderTarget) + { + renderTargetWidth = renderTarget->getWidth(); + renderTargetHeight = renderTarget->getHeight(); + renderTargetFormat = renderTarget->getDXGIFormat(); + missingColorRenderTarget = false; + } + + // Unbind render target SRVs from the shader here to prevent D3D11 warnings. + if (colorbuffer->type() == GL_TEXTURE) + { + uintptr_t rtResource = reinterpret_cast(GetViewResource(framebufferRTVs[colorAttachment])); + const gl::ImageIndex *index = colorbuffer->getTextureImageIndex(); + ASSERT(index); + // The index doesn't need to be corrected for the small compressed texture workaround + // because a rendertarget is never compressed. + unsetConflictingSRVs(gl::SAMPLER_VERTEX, rtResource, index); + unsetConflictingSRVs(gl::SAMPLER_PIXEL, rtResource, index); + } + } + } + + // Get the depth stencil buffers + ID3D11DepthStencilView* framebufferDSV = NULL; + gl::FramebufferAttachment *depthStencil = framebuffer->getDepthOrStencilbuffer(); + if (depthStencil) + { + RenderTarget11 *depthStencilRenderTarget = NULL; + gl::Error error = d3d11::GetAttachmentRenderTarget(depthStencil, &depthStencilRenderTarget); + if (error.isError()) + { + SafeRelease(framebufferRTVs); + return error; + } + ASSERT(depthStencilRenderTarget); + + framebufferDSV = depthStencilRenderTarget->getDepthStencilView(); + ASSERT(framebufferDSV); + + // If there is no render buffer, the width, height and format values come from + // the depth stencil + if (missingColorRenderTarget) + { + renderTargetWidth = depthStencilRenderTarget->getWidth(); + renderTargetHeight = depthStencilRenderTarget->getHeight(); + renderTargetFormat = depthStencilRenderTarget->getDXGIFormat(); + } + + // Unbind render target SRVs from the shader here to prevent D3D11 warnings. + if (depthStencil->type() == GL_TEXTURE) + { + uintptr_t depthStencilResource = reinterpret_cast(GetViewResource(framebufferDSV)); + const gl::ImageIndex *index = depthStencil->getTextureImageIndex(); + ASSERT(index); + // The index doesn't need to be corrected for the small compressed texture workaround + // because a rendertarget is never compressed. + unsetConflictingSRVs(gl::SAMPLER_VERTEX, depthStencilResource, index); + unsetConflictingSRVs(gl::SAMPLER_PIXEL, depthStencilResource, index); + } + } + + // Apply the render target and depth stencil + if (!mRenderTargetDescInitialized || !mDepthStencilInitialized || + memcmp(framebufferRTVs, mAppliedRTVs, sizeof(framebufferRTVs)) != 0 || + reinterpret_cast(framebufferDSV) != mAppliedDSV) + { + mDeviceContext->OMSetRenderTargets(getRendererCaps().maxDrawBuffers, framebufferRTVs, framebufferDSV); + + mRenderTargetDesc.width = renderTargetWidth; + mRenderTargetDesc.height = renderTargetHeight; + mRenderTargetDesc.format = renderTargetFormat; + mForceSetViewport = true; + mForceSetScissor = true; + mForceSetBlendState = true; + + if (!mDepthStencilInitialized) + { + mForceSetRasterState = true; + } + + for (size_t rtIndex = 0; rtIndex < ArraySize(framebufferRTVs); rtIndex++) + { + mAppliedRTVs[rtIndex] = reinterpret_cast(framebufferRTVs[rtIndex]); + } + mAppliedDSV = reinterpret_cast(framebufferDSV); + mRenderTargetDescInitialized = true; + mDepthStencilInitialized = true; + } + + const Framebuffer11 *framebuffer11 = GetImplAs(framebuffer); + gl::Error error = framebuffer11->invalidateSwizzles(); + if (error.isError()) + { + return error; + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Renderer11::applyVertexBuffer(const gl::State &state, GLenum mode, GLint first, GLsizei count, GLsizei instances) +{ + TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS]; + gl::Error error = mVertexDataManager->prepareVertexData(state, first, count, attributes, instances); + if (error.isError()) + { + return error; + } + + return mInputLayoutCache.applyVertexBuffers(attributes, mode, state.getProgram()); +} + +gl::Error Renderer11::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo) +{ + gl::Error error = mIndexDataManager->prepareIndexData(type, count, elementArrayBuffer, indices, indexInfo); + if (error.isError()) + { + return error; + } + + ID3D11Buffer *buffer = NULL; + DXGI_FORMAT bufferFormat = (indexInfo->indexType == GL_UNSIGNED_INT) ? DXGI_FORMAT_R32_UINT : DXGI_FORMAT_R16_UINT; + + if (indexInfo->storage) + { + Buffer11 *storage = Buffer11::makeBuffer11(indexInfo->storage); + buffer = storage->getBuffer(BUFFER_USAGE_INDEX); + } + else + { + IndexBuffer11* indexBuffer = IndexBuffer11::makeIndexBuffer11(indexInfo->indexBuffer); + buffer = indexBuffer->getBuffer(); + } + + if (buffer != mAppliedIB || bufferFormat != mAppliedIBFormat || indexInfo->startOffset != mAppliedIBOffset) + { + mDeviceContext->IASetIndexBuffer(buffer, bufferFormat, indexInfo->startOffset); + + mAppliedIB = buffer; + mAppliedIBFormat = bufferFormat; + mAppliedIBOffset = indexInfo->startOffset; + } + + return gl::Error(GL_NO_ERROR); +} + +void Renderer11::applyTransformFeedbackBuffers(const gl::State &state) +{ + size_t numXFBBindings = 0; + bool requiresUpdate = false; + + if (state.isTransformFeedbackActiveUnpaused()) + { + numXFBBindings = state.getTransformFeedbackBufferIndexRange(); + ASSERT(numXFBBindings <= gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS); + + for (size_t i = 0; i < numXFBBindings; i++) + { + gl::Buffer *curXFBBuffer = state.getIndexedTransformFeedbackBuffer(i); + GLintptr curXFBOffset = state.getIndexedTransformFeedbackBufferOffset(i); + ID3D11Buffer *d3dBuffer = NULL; + if (curXFBBuffer) + { + Buffer11 *storage = Buffer11::makeBuffer11(curXFBBuffer->getImplementation()); + d3dBuffer = storage->getBuffer(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK); + } + + // TODO: mAppliedTFBuffers and friends should also be kept in a vector. + if (d3dBuffer != mAppliedTFBuffers[i] || curXFBOffset != mAppliedTFOffsets[i]) + { + requiresUpdate = true; + } + } + } + + if (requiresUpdate || numXFBBindings != mAppliedNumXFBBindings) + { + for (size_t i = 0; i < numXFBBindings; ++i) + { + gl::Buffer *curXFBBuffer = state.getIndexedTransformFeedbackBuffer(i); + GLintptr curXFBOffset = state.getIndexedTransformFeedbackBufferOffset(i); + + if (curXFBBuffer) + { + Buffer11 *storage = Buffer11::makeBuffer11(curXFBBuffer->getImplementation()); + ID3D11Buffer *d3dBuffer = storage->getBuffer(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK); + + mCurrentD3DOffsets[i] = (mAppliedTFBuffers[i] != d3dBuffer || mAppliedTFOffsets[i] != curXFBOffset) ? + static_cast(curXFBOffset) : -1; + mAppliedTFBuffers[i] = d3dBuffer; + } + else + { + mAppliedTFBuffers[i] = NULL; + mCurrentD3DOffsets[i] = 0; + } + mAppliedTFOffsets[i] = curXFBOffset; + } + + mAppliedNumXFBBindings = numXFBBindings; + + mDeviceContext->SOSetTargets(numXFBBindings, mAppliedTFBuffers, mCurrentD3DOffsets); + } +} + +gl::Error Renderer11::drawArrays(const gl::Data &data, GLenum mode, GLsizei count, GLsizei instances, bool usesPointSize) +{ + bool useInstancedPointSpriteEmulation = usesPointSize && getWorkarounds().useInstancedPointSpriteEmulation; + if (mode == GL_POINTS && data.state->isTransformFeedbackActiveUnpaused()) + { + // Since point sprites are generated with a geometry shader, too many vertices will + // be written if transform feedback is active. To work around this, draw only the points + // with the stream out shader and no pixel shader to feed the stream out buffers and then + // draw again with the point sprite geometry shader to rasterize the point sprites. + + mDeviceContext->PSSetShader(NULL, NULL, 0); + + if (instances > 0) + { + mDeviceContext->DrawInstanced(count, instances, 0, 0); + } + else + { + mDeviceContext->Draw(count, 0); + } + + ProgramD3D *programD3D = GetImplAs(data.state->getProgram()); + + rx::ShaderExecutableD3D *pixelExe = NULL; + gl::Error error = programD3D->getPixelExecutableForFramebuffer(data.state->getDrawFramebuffer(), &pixelExe); + if (error.isError()) + { + return error; + } + + // Skip this step if we're doing rasterizer discard. + if (pixelExe && !data.state->getRasterizerState().rasterizerDiscard && usesPointSize) + { + ID3D11PixelShader *pixelShader = ShaderExecutable11::makeShaderExecutable11(pixelExe)->getPixelShader(); + ASSERT(reinterpret_cast(pixelShader) == mAppliedPixelShader); + mDeviceContext->PSSetShader(pixelShader, NULL, 0); + + // Retrieve the point sprite geometry shader + rx::ShaderExecutableD3D *geometryExe = programD3D->getGeometryExecutable(); + ID3D11GeometryShader *geometryShader = (geometryExe ? ShaderExecutable11::makeShaderExecutable11(geometryExe)->getGeometryShader() : NULL); + mAppliedGeometryShader = reinterpret_cast(geometryShader); + ASSERT(geometryShader); + mDeviceContext->GSSetShader(geometryShader, NULL, 0); + + if (instances > 0) + { + mDeviceContext->DrawInstanced(count, instances, 0, 0); + } + else + { + mDeviceContext->Draw(count, 0); + } + } + + return gl::Error(GL_NO_ERROR); + } + else if (mode == GL_LINE_LOOP) + { + return drawLineLoop(count, GL_NONE, NULL, 0, NULL); + } + else if (mode == GL_TRIANGLE_FAN) + { + return drawTriangleFan(count, GL_NONE, NULL, 0, NULL, instances); + } + else if (instances > 0) + { + mDeviceContext->DrawInstanced(count, instances, 0, 0); + return gl::Error(GL_NO_ERROR); + } + else + { + // If gl_PointSize is used and GL_POINTS is specified, then it is expected to render pointsprites. + // If instanced pointsprite emulation is being used the topology is expexted to be + // D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST and DrawIndexedInstanced must be used. + if (mode == GL_POINTS && useInstancedPointSpriteEmulation) + { + mDeviceContext->DrawIndexedInstanced(6, count, 0, 0, 0); + } + else + { + mDeviceContext->Draw(count, 0); + } + return gl::Error(GL_NO_ERROR); + } +} + +gl::Error Renderer11::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, + gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances) +{ + int minIndex = static_cast(indexInfo.indexRange.start); + + if (mode == GL_LINE_LOOP) + { + return drawLineLoop(count, type, indices, minIndex, elementArrayBuffer); + } + else if (mode == GL_TRIANGLE_FAN) + { + return drawTriangleFan(count, type, indices, minIndex, elementArrayBuffer, instances); + } + else if (instances > 0) + { + mDeviceContext->DrawIndexedInstanced(count, instances, 0, -minIndex, 0); + return gl::Error(GL_NO_ERROR); + } + else + { + mDeviceContext->DrawIndexed(count, 0, -minIndex); + return gl::Error(GL_NO_ERROR); + } +} + +gl::Error 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) + { + BufferD3D *storage = GetImplAs(elementArrayBuffer); + intptr_t offset = reinterpret_cast(indices); + + const uint8_t *bufferData = NULL; + gl::Error error = storage->getData(&bufferData); + if (error.isError()) + { + return error; + } + + indices = bufferData + offset; + } + + if (!mLineLoopIB) + { + mLineLoopIB = new StreamingIndexBufferInterface(this); + gl::Error error = mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT); + if (error.isError()) + { + SafeDelete(mLineLoopIB); + return error; + } + } + + // Checked by Renderer11::applyPrimitiveType + ASSERT(count >= 0); + + if (static_cast(count) + 1 > (std::numeric_limits::max() / sizeof(unsigned int))) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create a 32-bit looping index buffer for GL_LINE_LOOP, too many indices required."); + } + + const unsigned int spaceNeeded = (static_cast(count) + 1) * sizeof(unsigned int); + gl::Error error = mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT); + if (error.isError()) + { + return error; + } + + void* mappedMemory = NULL; + unsigned int offset; + error = mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset); + if (error.isError()) + { + return error; + } + + unsigned int *data = reinterpret_cast(mappedMemory); + unsigned int indexBufferOffset = offset; + + switch (type) + { + case GL_NONE: // Non-indexed draw + for (int i = 0; i < count; i++) + { + data[i] = i; + } + data[count] = 0; + break; + case GL_UNSIGNED_BYTE: + for (int i = 0; i < count; i++) + { + data[i] = static_cast(indices)[i]; + } + data[count] = static_cast(indices)[0]; + break; + case GL_UNSIGNED_SHORT: + for (int i = 0; i < count; i++) + { + data[i] = static_cast(indices)[i]; + } + data[count] = static_cast(indices)[0]; + break; + case GL_UNSIGNED_INT: + for (int i = 0; i < count; i++) + { + data[i] = static_cast(indices)[i]; + } + data[count] = static_cast(indices)[0]; + break; + default: UNREACHABLE(); + } + + error = mLineLoopIB->unmapBuffer(); + if (error.isError()) + { + return error; + } + + IndexBuffer11 *indexBuffer = IndexBuffer11::makeIndexBuffer11(mLineLoopIB->getIndexBuffer()); + ID3D11Buffer *d3dIndexBuffer = indexBuffer->getBuffer(); + DXGI_FORMAT indexFormat = indexBuffer->getIndexFormat(); + + if (mAppliedIB != d3dIndexBuffer || mAppliedIBFormat != indexFormat || mAppliedIBOffset != indexBufferOffset) + { + mDeviceContext->IASetIndexBuffer(d3dIndexBuffer, indexFormat, indexBufferOffset); + mAppliedIB = d3dIndexBuffer; + mAppliedIBFormat = indexFormat; + mAppliedIBOffset = indexBufferOffset; + } + + mDeviceContext->DrawIndexed(count + 1, 0, -minIndex); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error 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) + { + BufferD3D *storage = GetImplAs(elementArrayBuffer); + intptr_t offset = reinterpret_cast(indices); + + const uint8_t *bufferData = NULL; + gl::Error error = storage->getData(&bufferData); + if (error.isError()) + { + return error; + } + + indices = bufferData + offset; + } + + if (!mTriangleFanIB) + { + mTriangleFanIB = new StreamingIndexBufferInterface(this); + gl::Error error = mTriangleFanIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT); + if (error.isError()) + { + SafeDelete(mTriangleFanIB); + return error; + } + } + + // Checked by Renderer11::applyPrimitiveType + ASSERT(count >= 3); + + const unsigned int numTris = count - 2; + + if (numTris > (std::numeric_limits::max() / (sizeof(unsigned int) * 3))) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create a scratch index buffer for GL_TRIANGLE_FAN, too many indices required."); + } + + const unsigned int spaceNeeded = (numTris * 3) * sizeof(unsigned int); + gl::Error error = mTriangleFanIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT); + if (error.isError()) + { + return error; + } + + void* mappedMemory = NULL; + unsigned int offset; + error = mTriangleFanIB->mapBuffer(spaceNeeded, &mappedMemory, &offset); + if (error.isError()) + { + return error; + } + + unsigned int *data = reinterpret_cast(mappedMemory); + unsigned int indexBufferOffset = offset; + + switch (type) + { + case GL_NONE: // Non-indexed draw + for (unsigned int i = 0; i < numTris; i++) + { + data[i*3 + 0] = 0; + data[i*3 + 1] = i + 1; + data[i*3 + 2] = i + 2; + } + break; + case GL_UNSIGNED_BYTE: + for (unsigned int i = 0; i < numTris; i++) + { + data[i*3 + 0] = static_cast(indices)[0]; + data[i*3 + 1] = static_cast(indices)[i + 1]; + data[i*3 + 2] = static_cast(indices)[i + 2]; + } + break; + case GL_UNSIGNED_SHORT: + for (unsigned int i = 0; i < numTris; i++) + { + data[i*3 + 0] = static_cast(indices)[0]; + data[i*3 + 1] = static_cast(indices)[i + 1]; + data[i*3 + 2] = static_cast(indices)[i + 2]; + } + break; + case GL_UNSIGNED_INT: + for (unsigned int i = 0; i < numTris; i++) + { + data[i*3 + 0] = static_cast(indices)[0]; + data[i*3 + 1] = static_cast(indices)[i + 1]; + data[i*3 + 2] = static_cast(indices)[i + 2]; + } + break; + default: UNREACHABLE(); + } + + error = mTriangleFanIB->unmapBuffer(); + if (error.isError()) + { + return error; + } + + IndexBuffer11 *indexBuffer = IndexBuffer11::makeIndexBuffer11(mTriangleFanIB->getIndexBuffer()); + ID3D11Buffer *d3dIndexBuffer = indexBuffer->getBuffer(); + DXGI_FORMAT indexFormat = indexBuffer->getIndexFormat(); + + if (mAppliedIB != d3dIndexBuffer || mAppliedIBFormat != indexFormat || mAppliedIBOffset != indexBufferOffset) + { + mDeviceContext->IASetIndexBuffer(d3dIndexBuffer, indexFormat, indexBufferOffset); + mAppliedIB = d3dIndexBuffer; + mAppliedIBFormat = indexFormat; + mAppliedIBOffset = indexBufferOffset; + } + + if (instances > 0) + { + mDeviceContext->DrawIndexedInstanced(numTris * 3, instances, 0, -minIndex, 0); + } + else + { + mDeviceContext->DrawIndexed(numTris * 3, 0, -minIndex); + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Renderer11::applyShaders(gl::Program *program, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer, + bool rasterizerDiscard, bool transformFeedbackActive) +{ + ProgramD3D *programD3D = GetImplAs(program); + + ShaderExecutableD3D *vertexExe = NULL; + gl::Error error = programD3D->getVertexExecutableForInputLayout(inputLayout, &vertexExe, nullptr); + if (error.isError()) + { + return error; + } + + ShaderExecutableD3D *pixelExe = NULL; + error = programD3D->getPixelExecutableForFramebuffer(framebuffer, &pixelExe); + if (error.isError()) + { + return error; + } + + ShaderExecutableD3D *geometryExe = programD3D->getGeometryExecutable(); + + ID3D11VertexShader *vertexShader = (vertexExe ? ShaderExecutable11::makeShaderExecutable11(vertexExe)->getVertexShader() : NULL); + + ID3D11PixelShader *pixelShader = NULL; + // Skip pixel shader if we're doing rasterizer discard. + if (!rasterizerDiscard) + { + pixelShader = (pixelExe ? ShaderExecutable11::makeShaderExecutable11(pixelExe)->getPixelShader() : NULL); + } + + ID3D11GeometryShader *geometryShader = NULL; + if (transformFeedbackActive) + { + geometryShader = (vertexExe ? ShaderExecutable11::makeShaderExecutable11(vertexExe)->getStreamOutShader() : NULL); + } + else if (mCurRasterState.pointDrawMode) + { + geometryShader = (geometryExe ? ShaderExecutable11::makeShaderExecutable11(geometryExe)->getGeometryShader() : NULL); + } + + bool dirtyUniforms = false; + + if (reinterpret_cast(vertexShader) != mAppliedVertexShader) + { + mDeviceContext->VSSetShader(vertexShader, NULL, 0); + mAppliedVertexShader = reinterpret_cast(vertexShader); + dirtyUniforms = true; + } + + if (reinterpret_cast(geometryShader) != mAppliedGeometryShader) + { + mDeviceContext->GSSetShader(geometryShader, NULL, 0); + mAppliedGeometryShader = reinterpret_cast(geometryShader); + dirtyUniforms = true; + } + + if (reinterpret_cast(pixelShader) != mAppliedPixelShader) + { + mDeviceContext->PSSetShader(pixelShader, NULL, 0); + mAppliedPixelShader = reinterpret_cast(pixelShader); + dirtyUniforms = true; + } + + if (dirtyUniforms) + { + programD3D->dirtyAllUniforms(); + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Renderer11::applyUniforms(const ProgramImpl &program, const std::vector &uniformArray) +{ + unsigned int totalRegisterCountVS = 0; + unsigned int totalRegisterCountPS = 0; + + bool vertexUniformsDirty = false; + bool pixelUniformsDirty = false; + + for (size_t uniformIndex = 0; uniformIndex < uniformArray.size(); uniformIndex++) + { + const gl::LinkedUniform &uniform = *uniformArray[uniformIndex]; + + if (uniform.isReferencedByVertexShader() && !uniform.isSampler()) + { + totalRegisterCountVS += uniform.registerCount; + vertexUniformsDirty = (vertexUniformsDirty || uniform.dirty); + } + + if (uniform.isReferencedByFragmentShader() && !uniform.isSampler()) + { + totalRegisterCountPS += uniform.registerCount; + pixelUniformsDirty = (pixelUniformsDirty || uniform.dirty); + } + } + + const ProgramD3D *programD3D = GetAs(&program); + const UniformStorage11 *vertexUniformStorage = UniformStorage11::makeUniformStorage11(&programD3D->getVertexUniformStorage()); + const UniformStorage11 *fragmentUniformStorage = UniformStorage11::makeUniformStorage11(&programD3D->getFragmentUniformStorage()); + ASSERT(vertexUniformStorage); + ASSERT(fragmentUniformStorage); + + ID3D11Buffer *vertexConstantBuffer = vertexUniformStorage->getConstantBuffer(); + ID3D11Buffer *pixelConstantBuffer = fragmentUniformStorage->getConstantBuffer(); + + 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); + UNUSED_ASSERTION_VARIABLE(result); + 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); + UNUSED_ASSERTION_VARIABLE(result); + ASSERT(SUCCEEDED(result)); + mapPS = (float(*)[4])map.pData; + } + + for (size_t uniformIndex = 0; uniformIndex < uniformArray.size(); uniformIndex++) + { + gl::LinkedUniform *uniform = uniformArray[uniformIndex]; + + if (!uniform->isSampler()) + { + unsigned int componentCount = (4 - uniform->registerElement); + + // we assume that uniforms from structs are arranged in struct order in our uniforms list. otherwise we would + // overwrite previously written regions of memory. + + if (uniform->isReferencedByVertexShader() && mapVS) + { + memcpy(&mapVS[uniform->vsRegisterIndex][uniform->registerElement], uniform->data, uniform->registerCount * sizeof(float) * componentCount); + } + + if (uniform->isReferencedByFragmentShader() && mapPS) + { + memcpy(&mapPS[uniform->psRegisterIndex][uniform->registerElement], uniform->data, uniform->registerCount * sizeof(float) * componentCount); + } + } + } + + if (mapVS) + { + mDeviceContext->Unmap(vertexConstantBuffer, 0); + } + + if (mapPS) + { + mDeviceContext->Unmap(pixelConstantBuffer, 0); + } + + if (mCurrentVertexConstantBuffer != vertexConstantBuffer) + { + mDeviceContext->VSSetConstantBuffers(0, 1, &vertexConstantBuffer); + mCurrentVertexConstantBuffer = vertexConstantBuffer; + } + + if (mCurrentPixelConstantBuffer != pixelConstantBuffer) + { + mDeviceContext->PSSetConstantBuffers(0, 1, &pixelConstantBuffer); + mCurrentPixelConstantBuffer = pixelConstantBuffer; + } + + // Driver uniforms + if (!mDriverConstantBufferVS) + { + D3D11_BUFFER_DESC constantBufferDescription = {0}; + constantBufferDescription.ByteWidth = sizeof(dx_VertexConstants); + constantBufferDescription.Usage = D3D11_USAGE_DEFAULT; + constantBufferDescription.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + constantBufferDescription.CPUAccessFlags = 0; + constantBufferDescription.MiscFlags = 0; + constantBufferDescription.StructureByteStride = 0; + + HRESULT result = mDevice->CreateBuffer(&constantBufferDescription, NULL, &mDriverConstantBufferVS); + UNUSED_ASSERTION_VARIABLE(result); + 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); + UNUSED_ASSERTION_VARIABLE(result); + 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)); + } + + // GSSetConstantBuffers triggers device removal on 9_3, so we should only call it if necessary + if (programD3D->usesGeometryShader()) + { + // needed for the point sprite geometry shader + if (mCurrentGeometryConstantBuffer != mDriverConstantBufferPS) + { + mDeviceContext->GSSetConstantBuffers(0, 1, &mDriverConstantBufferPS); + mCurrentGeometryConstantBuffer = mDriverConstantBufferPS; + } + } + + return gl::Error(GL_NO_ERROR); +} + +void Renderer11::markAllStateDirty() +{ + for (size_t rtIndex = 0; rtIndex < ArraySize(mAppliedRTVs); rtIndex++) + { + mAppliedRTVs[rtIndex] = DirtyPointer; + } + mAppliedDSV = DirtyPointer; + mDepthStencilInitialized = false; + mRenderTargetDescInitialized = false; + + // We reset the current SRV data because it might not be in sync with D3D's state + // anymore. For example when a currently used SRV is used as an RTV, D3D silently + // remove it from its state. + memset(mCurVertexSRVs.data(), 0, sizeof(SRVRecord) * mCurVertexSRVs.size()); + memset(mCurPixelSRVs.data(), 0, sizeof(SRVRecord) * mCurPixelSRVs.size()); + + ASSERT(mForceSetVertexSamplerStates.size() == mCurVertexSRVs.size()); + for (size_t vsamplerId = 0; vsamplerId < mForceSetVertexSamplerStates.size(); ++vsamplerId) + { + mForceSetVertexSamplerStates[vsamplerId] = true; + } + + ASSERT(mForceSetPixelSamplerStates.size() == mCurPixelSRVs.size()); + for (size_t fsamplerId = 0; fsamplerId < mForceSetPixelSamplerStates.size(); ++fsamplerId) + { + mForceSetPixelSamplerStates[fsamplerId] = true; + } + + mForceSetBlendState = true; + mForceSetRasterState = true; + mForceSetDepthStencilState = true; + mForceSetScissor = true; + mForceSetViewport = true; + + mAppliedIB = NULL; + mAppliedIBFormat = DXGI_FORMAT_UNKNOWN; + mAppliedIBOffset = 0; + + mAppliedVertexShader = DirtyPointer; + mAppliedGeometryShader = DirtyPointer; + mAppliedPixelShader = DirtyPointer; + + mAppliedNumXFBBindings = static_cast(-1); + + for (size_t i = 0; i < gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS; i++) + { + mAppliedTFBuffers[i] = NULL; + mAppliedTFOffsets[i] = 0; + } + + memset(&mAppliedVertexConstants, 0, sizeof(dx_VertexConstants)); + memset(&mAppliedPixelConstants, 0, sizeof(dx_PixelConstants)); + + mInputLayoutCache.markDirty(); + + for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS; i++) + { + mCurrentConstantBufferVS[i] = static_cast(-1); + mCurrentConstantBufferVSOffset[i] = 0; + mCurrentConstantBufferVSSize[i] = 0; + mCurrentConstantBufferPS[i] = static_cast(-1); + mCurrentConstantBufferPSOffset[i] = 0; + mCurrentConstantBufferPSSize[i] = 0; + } + + mCurrentVertexConstantBuffer = NULL; + mCurrentPixelConstantBuffer = NULL; + mCurrentGeometryConstantBuffer = NULL; + + mCurrentPrimitiveTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED; +} + +void Renderer11::releaseDeviceResources() +{ + mStateCache.clear(); + mInputLayoutCache.clear(); + + SafeDelete(mVertexDataManager); + SafeDelete(mIndexDataManager); + SafeDelete(mLineLoopIB); + SafeDelete(mTriangleFanIB); + SafeDelete(mBlit); + SafeDelete(mClear); + SafeDelete(mTrim); + SafeDelete(mPixelTransfer); + + SafeRelease(mDriverConstantBufferVS); + SafeRelease(mDriverConstantBufferPS); + SafeRelease(mSyncQuery); +} + +// set notify to true to broadcast a message to all contexts of the device loss +bool Renderer11::testDeviceLost() +{ + 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; + } + + 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; + } + + ID3D11Device* dummyDevice; + D3D_FEATURE_LEVEL dummyFeatureLevel; + ID3D11DeviceContext* dummyContext; + + HRESULT result = D3D11CreateDevice(NULL, + mDriverType, + NULL, + #if defined(_DEBUG) + D3D11_CREATE_DEVICE_DEBUG, + #else + 0, + #endif + mAvailableFeatureLevels.data(), + mAvailableFeatureLevels.size(), + D3D11_SDK_VERSION, + &dummyDevice, + &dummyFeatureLevel, + &dummyContext); + + if (!mDevice || FAILED(result)) + { + return false; + } + + SafeRelease(dummyContext); + SafeRelease(dummyDevice); + + return true; +} + +void Renderer11::release() +{ + RendererD3D::cleanup(); + + releaseDeviceResources(); + + SafeRelease(mDxgiFactory); + SafeRelease(mDxgiAdapter); + +#if defined(ANGLE_ENABLE_D3D11_1) + SafeRelease(mDeviceContext1); +#endif + + if (mDeviceContext) + { + mDeviceContext->ClearState(); + mDeviceContext->Flush(); + SafeRelease(mDeviceContext); + } + + SafeRelease(mDevice); + + if (mD3d11Module) + { + FreeLibrary(mD3d11Module); + mD3d11Module = NULL; + } + + if (mDxgiModule) + { + FreeLibrary(mDxgiModule); + mDxgiModule = NULL; + } + + mCompiler.release(); +} + +bool Renderer11::resetDevice() +{ + // recreate everything + release(); + egl::Error result = initialize(); + + if (result.isError()) + { + ERR("Could not reinitialize D3D11 device: %08X", result.getCode()); + return false; + } + + mDeviceLost = false; + + return true; +} + +VendorID Renderer11::getVendorId() const +{ + return static_cast(mAdapterDescription.VendorId); +} + +std::string Renderer11::getRendererDescription() const +{ + std::ostringstream rendererString; + + rendererString << mDescription; + rendererString << " Direct3D11"; + + rendererString << " vs_" << getMajorShaderModel() << "_" << getMinorShaderModel() << getShaderModelSuffix(); + rendererString << " ps_" << getMajorShaderModel() << "_" << getMinorShaderModel() << getShaderModelSuffix(); + + 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 + static_assert(sizeof(LUID) <= sizeof(GUID), "Size of GUID must be at least as large as LUID."); + GUID adapterId = {0}; + memcpy(&adapterId, &mAdapterDescription.AdapterLuid, sizeof(LUID)); + return adapterId; +} + +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::getReservedVertexUniformBuffers() const +{ + // we reserve one buffer for the application uniforms, and one for driver uniforms + return 2; +} + +unsigned int Renderer11::getReservedFragmentUniformBuffers() const +{ + // we reserve one buffer for the application uniforms, and one for driver uniforms + return 2; +} + +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. + // Also disable share handles on Feature Level 9_3, since it doesn't support share handles on RGBA8 textures/swapchains. + return getRendererExtensions().textureFormatBGRA8888 && !gl::DebugAnnotationsActive();// && !(mFeatureLevel <= D3D_FEATURE_LEVEL_9_3); Qt: we don't care about the 9_3 limitation +} + +bool Renderer11::getPostSubBufferSupport() const +{ + // D3D11 does not support present with dirty rectangles until D3D11.1 and DXGI 1.2. + return false; +} + +int Renderer11::getMajorShaderModel() const +{ + switch (mFeatureLevel) + { + case D3D_FEATURE_LEVEL_11_0: return D3D11_SHADER_MAJOR_VERSION; // 5 + case D3D_FEATURE_LEVEL_10_1: return D3D10_1_SHADER_MAJOR_VERSION; // 4 + case D3D_FEATURE_LEVEL_10_0: return D3D10_SHADER_MAJOR_VERSION; // 4 + case D3D_FEATURE_LEVEL_9_3: 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 + case D3D_FEATURE_LEVEL_9_3: return D3D10_SHADER_MINOR_VERSION; // 0 + default: UNREACHABLE(); return 0; + } +} + +std::string Renderer11::getShaderModelSuffix() const +{ + switch (mFeatureLevel) + { + case D3D_FEATURE_LEVEL_11_0: return ""; + case D3D_FEATURE_LEVEL_10_1: return ""; + case D3D_FEATURE_LEVEL_10_0: return ""; + case D3D_FEATURE_LEVEL_9_3: return "_level_9_3"; + default: UNREACHABLE(); return ""; + } +} + +gl::Error Renderer11::copyImage2D(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + const gl::Offset &destOffset, TextureStorage *storage, GLint level) +{ + gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer(); + ASSERT(colorbuffer); + + RenderTarget11 *sourceRenderTarget = NULL; + gl::Error error = d3d11::GetAttachmentRenderTarget(colorbuffer, &sourceRenderTarget); + if (error.isError()) + { + return error; + } + ASSERT(sourceRenderTarget); + + ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView(); + ASSERT(source); + + TextureStorage11_2D *storage11 = TextureStorage11_2D::makeTextureStorage11_2D(storage); + ASSERT(storage11); + + gl::ImageIndex index = gl::ImageIndex::Make2D(level); + RenderTargetD3D *destRenderTarget = NULL; + error = storage11->getRenderTarget(index, &destRenderTarget); + if (error.isError()) + { + return error; + } + ASSERT(destRenderTarget); + + ID3D11RenderTargetView *dest = RenderTarget11::makeRenderTarget11(destRenderTarget)->getRenderTargetView(); + ASSERT(dest); + + gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1); + gl::Extents sourceSize(sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), 1); + + gl::Box destArea(destOffset.x, destOffset.y, 0, sourceRect.width, sourceRect.height, 1); + gl::Extents destSize(destRenderTarget->getWidth(), destRenderTarget->getHeight(), 1); + + // Use nearest filtering because source and destination are the same size for the direct + // copy + mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL, destFormat, GL_NEAREST); + if (error.isError()) + { + return error; + } + + storage11->invalidateSwizzleCacheLevel(level); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Renderer11::copyImageCube(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + const gl::Offset &destOffset, TextureStorage *storage, GLenum target, GLint level) +{ + gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer(); + ASSERT(colorbuffer); + + RenderTarget11 *sourceRenderTarget = NULL; + gl::Error error = d3d11::GetAttachmentRenderTarget(colorbuffer, &sourceRenderTarget); + if (error.isError()) + { + return error; + } + ASSERT(sourceRenderTarget); + + ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView(); + ASSERT(source); + + TextureStorage11_Cube *storage11 = TextureStorage11_Cube::makeTextureStorage11_Cube(storage); + ASSERT(storage11); + + gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level); + RenderTargetD3D *destRenderTarget = NULL; + error = storage11->getRenderTarget(index, &destRenderTarget); + if (error.isError()) + { + return error; + } + ASSERT(destRenderTarget); + + ID3D11RenderTargetView *dest = RenderTarget11::makeRenderTarget11(destRenderTarget)->getRenderTargetView(); + ASSERT(dest); + + gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1); + gl::Extents sourceSize(sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), 1); + + gl::Box destArea(destOffset.x, destOffset.y, 0, sourceRect.width, sourceRect.height, 1); + gl::Extents destSize(destRenderTarget->getWidth(), destRenderTarget->getHeight(), 1); + + // Use nearest filtering because source and destination are the same size for the direct + // copy + error = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL, destFormat, GL_NEAREST); + if (error.isError()) + { + return error; + } + + storage11->invalidateSwizzleCacheLevel(level); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Renderer11::copyImage3D(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + const gl::Offset &destOffset, TextureStorage *storage, GLint level) +{ + gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer(); + ASSERT(colorbuffer); + + RenderTarget11 *sourceRenderTarget = NULL; + gl::Error error = d3d11::GetAttachmentRenderTarget(colorbuffer, &sourceRenderTarget); + if (error.isError()) + { + return error; + } + ASSERT(sourceRenderTarget); + + ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView(); + ASSERT(source); + + TextureStorage11_3D *storage11 = TextureStorage11_3D::makeTextureStorage11_3D(storage); + ASSERT(storage11); + + gl::ImageIndex index = gl::ImageIndex::Make3D(level, destOffset.z); + RenderTargetD3D *destRenderTarget = NULL; + error = storage11->getRenderTarget(index, &destRenderTarget); + if (error.isError()) + { + return error; + } + ASSERT(destRenderTarget); + + ID3D11RenderTargetView *dest = RenderTarget11::makeRenderTarget11(destRenderTarget)->getRenderTargetView(); + ASSERT(dest); + + gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1); + gl::Extents sourceSize(sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), 1); + + gl::Box destArea(destOffset.x, destOffset.y, 0, sourceRect.width, sourceRect.height, 1); + gl::Extents destSize(destRenderTarget->getWidth(), destRenderTarget->getHeight(), 1); + + // Use nearest filtering because source and destination are the same size for the direct + // copy + error = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL, destFormat, GL_NEAREST); + if (error.isError()) + { + return error; + } + + storage11->invalidateSwizzleCacheLevel(level); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Renderer11::copyImage2DArray(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + const gl::Offset &destOffset, TextureStorage *storage, GLint level) +{ + gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer(); + ASSERT(colorbuffer); + + RenderTarget11 *sourceRenderTarget = NULL; + gl::Error error = d3d11::GetAttachmentRenderTarget(colorbuffer, &sourceRenderTarget); + if (error.isError()) + { + return error; + } + ASSERT(sourceRenderTarget); + + ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView(); + ASSERT(source); + + TextureStorage11_2DArray *storage11 = TextureStorage11_2DArray::makeTextureStorage11_2DArray(storage); + ASSERT(storage11); + + gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, destOffset.z); + RenderTargetD3D *destRenderTarget = NULL; + error = storage11->getRenderTarget(index, &destRenderTarget); + if (error.isError()) + { + return error; + } + ASSERT(destRenderTarget); + + ID3D11RenderTargetView *dest = RenderTarget11::makeRenderTarget11(destRenderTarget)->getRenderTargetView(); + ASSERT(dest); + + gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1); + gl::Extents sourceSize(sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), 1); + + gl::Box destArea(destOffset.x, destOffset.y, 0, sourceRect.width, sourceRect.height, 1); + gl::Extents destSize(destRenderTarget->getWidth(), destRenderTarget->getHeight(), 1); + + // Use nearest filtering because source and destination are the same size for the direct + // copy + error = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL, destFormat, GL_NEAREST); + if (error.isError()) + { + return error; + } + + storage11->invalidateSwizzleCacheLevel(level); + + return gl::Error(GL_NO_ERROR); +} + +void Renderer11::unapplyRenderTargets() +{ + setOneTimeRenderTarget(NULL); +} + +// When finished with this rendertarget, markAllStateDirty must be called. +void Renderer11::setOneTimeRenderTarget(ID3D11RenderTargetView *renderTargetView) +{ + ID3D11RenderTargetView *rtvArray[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS] = {NULL}; + + rtvArray[0] = renderTargetView; + + mDeviceContext->OMSetRenderTargets(getRendererCaps().maxDrawBuffers, rtvArray, NULL); + + // Do not preserve the serial for this one-time-use render target + for (size_t rtIndex = 0; rtIndex < ArraySize(mAppliedRTVs); rtIndex++) + { + mAppliedRTVs[rtIndex] = DirtyPointer; + } + mAppliedDSV = DirtyPointer; +} + +gl::Error Renderer11::createRenderTarget(int width, int height, GLenum format, GLsizei samples, RenderTargetD3D **outRT) +{ + const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(format, mFeatureLevel); + + const gl::TextureCaps &textureCaps = getRendererTextureCaps().get(format); + GLuint supportedSamples = textureCaps.getNearestSamples(samples); + + 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 = formatInfo.texFormat; + desc.SampleDesc.Count = (supportedSamples == 0) ? 1 : supportedSamples; + desc.SampleDesc.Quality = 0; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.CPUAccessFlags = 0; + desc.MiscFlags = 0; + + // If a rendertarget or depthstencil format exists for this texture format, + // we'll flag it to allow binding that way. Shader resource views are a little + // more complicated. + bool bindRTV = false, bindDSV = false, bindSRV = false; + bindRTV = (formatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN); + bindDSV = (formatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN); + if (formatInfo.srvFormat != DXGI_FORMAT_UNKNOWN) + { + // Multisample targets flagged for binding as depth stencil cannot also be + // flagged for binding as SRV, so make certain not to add the SRV flag for + // these targets. + bindSRV = !(formatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN && desc.SampleDesc.Count > 1); + } + + desc.BindFlags = (bindRTV ? D3D11_BIND_RENDER_TARGET : 0) | + (bindDSV ? D3D11_BIND_DEPTH_STENCIL : 0) | + (bindSRV ? D3D11_BIND_SHADER_RESOURCE : 0); + + // The format must be either an RTV or a DSV + ASSERT(bindRTV != bindDSV); + + ID3D11Texture2D *texture = NULL; + HRESULT result = mDevice->CreateTexture2D(&desc, NULL, &texture); + if (FAILED(result)) + { + ASSERT(result == E_OUTOFMEMORY); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create render target texture, result: 0x%X.", result); + } + + ID3D11ShaderResourceView *srv = NULL; + if (bindSRV) + { + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; + srvDesc.Format = formatInfo.srvFormat; + srvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_SRV_DIMENSION_TEXTURE2D : D3D11_SRV_DIMENSION_TEXTURE2DMS; + srvDesc.Texture2D.MostDetailedMip = 0; + srvDesc.Texture2D.MipLevels = 1; + + result = mDevice->CreateShaderResourceView(texture, &srvDesc, &srv); + if (FAILED(result)) + { + ASSERT(result == E_OUTOFMEMORY); + SafeRelease(texture); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create render target shader resource view, result: 0x%X.", result); + } + } + + if (bindDSV) + { + D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; + dsvDesc.Format = formatInfo.dsvFormat; + dsvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_DSV_DIMENSION_TEXTURE2D : D3D11_DSV_DIMENSION_TEXTURE2DMS; + dsvDesc.Texture2D.MipSlice = 0; + dsvDesc.Flags = 0; + + ID3D11DepthStencilView *dsv = NULL; + result = mDevice->CreateDepthStencilView(texture, &dsvDesc, &dsv); + if (FAILED(result)) + { + ASSERT(result == E_OUTOFMEMORY); + SafeRelease(texture); + SafeRelease(srv); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create render target depth stencil view, result: 0x%X.", result); + } + + *outRT = new TextureRenderTarget11(dsv, texture, srv, format, width, height, 1, supportedSamples); + + SafeRelease(dsv); + } + else if (bindRTV) + { + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = formatInfo.rtvFormat; + rtvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_RTV_DIMENSION_TEXTURE2D : D3D11_RTV_DIMENSION_TEXTURE2DMS; + rtvDesc.Texture2D.MipSlice = 0; + + ID3D11RenderTargetView *rtv = NULL; + result = mDevice->CreateRenderTargetView(texture, &rtvDesc, &rtv); + if (FAILED(result)) + { + ASSERT(result == E_OUTOFMEMORY); + SafeRelease(texture); + SafeRelease(srv); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create render target render target view, result: 0x%X.", result); + } + + if (formatInfo.dataInitializerFunction != NULL) + { + const float clearValues[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; + mDeviceContext->ClearRenderTargetView(rtv, clearValues); + } + + *outRT = new TextureRenderTarget11(rtv, texture, srv, format, width, height, 1, supportedSamples); + + SafeRelease(rtv); + } + else + { + UNREACHABLE(); + } + + SafeRelease(texture); + SafeRelease(srv); + } + else + { + *outRT = new TextureRenderTarget11(reinterpret_cast(NULL), NULL, NULL, format, width, height, 1, supportedSamples); + } + + return gl::Error(GL_NO_ERROR); +} + +FramebufferImpl *Renderer11::createDefaultFramebuffer(const gl::Framebuffer::Data &data) +{ + return createFramebuffer(data); +} + +FramebufferImpl *Renderer11::createFramebuffer(const gl::Framebuffer::Data &data) +{ + return new Framebuffer11(data, this); +} + +CompilerImpl *Renderer11::createCompiler(const gl::Data &data) +{ + return new CompilerD3D(data, SH_HLSL11_OUTPUT); +} + +ShaderImpl *Renderer11::createShader(GLenum type) +{ + return new ShaderD3D(type); +} + +ProgramImpl *Renderer11::createProgram() +{ + return new ProgramD3D(this); +} + +gl::Error Renderer11::loadExecutable(const void *function, size_t length, ShaderType type, + const std::vector &transformFeedbackVaryings, + bool separatedOutputBuffers, ShaderExecutableD3D **outExecutable) +{ + switch (type) + { + case SHADER_VERTEX: + { + ID3D11VertexShader *vertexShader = NULL; + ID3D11GeometryShader *streamOutShader = NULL; + + HRESULT result = mDevice->CreateVertexShader(function, length, NULL, &vertexShader); + ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create vertex shader, result: 0x%X.", result); + } + + if (transformFeedbackVaryings.size() > 0) + { + std::vector soDeclaration; + for (size_t i = 0; i < transformFeedbackVaryings.size(); i++) + { + const gl::LinkedVarying &varying = transformFeedbackVaryings[i]; + GLenum transposedType = gl::TransposeMatrixType(varying.type); + + for (size_t j = 0; j < varying.semanticIndexCount; j++) + { + D3D11_SO_DECLARATION_ENTRY entry = { 0 }; + entry.Stream = 0; + entry.SemanticName = varying.semanticName.c_str(); + entry.SemanticIndex = varying.semanticIndex + j; + entry.StartComponent = 0; + entry.ComponentCount = gl::VariableColumnCount(transposedType); + entry.OutputSlot = (separatedOutputBuffers ? i : 0); + soDeclaration.push_back(entry); + } + } + + result = mDevice->CreateGeometryShaderWithStreamOutput(function, length, soDeclaration.data(), soDeclaration.size(), + NULL, 0, 0, NULL, &streamOutShader); + ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create steam output shader, result: 0x%X.", result); + } + } + + *outExecutable = new ShaderExecutable11(function, length, vertexShader, streamOutShader); + } + break; + case SHADER_PIXEL: + { + ID3D11PixelShader *pixelShader = NULL; + + HRESULT result = mDevice->CreatePixelShader(function, length, NULL, &pixelShader); + ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create pixel shader, result: 0x%X.", result); + } + + *outExecutable = new ShaderExecutable11(function, length, pixelShader); + } + break; + case SHADER_GEOMETRY: + { + ID3D11GeometryShader *geometryShader = NULL; + + HRESULT result = mDevice->CreateGeometryShader(function, length, NULL, &geometryShader); + ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create geometry shader, result: 0x%X.", result); + } + + *outExecutable = new ShaderExecutable11(function, length, geometryShader); + } + break; + default: + UNREACHABLE(); + return gl::Error(GL_INVALID_OPERATION); + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Renderer11::compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, ShaderType type, + const std::vector &transformFeedbackVaryings, + bool separatedOutputBuffers, const D3DCompilerWorkarounds &workarounds, + ShaderExecutableD3D **outExectuable) +{ + const char *profileType = NULL; + switch (type) + { + case SHADER_VERTEX: + profileType = "vs"; + break; + case SHADER_PIXEL: + profileType = "ps"; + break; + case SHADER_GEOMETRY: + profileType = "gs"; + break; + default: + UNREACHABLE(); + return gl::Error(GL_INVALID_OPERATION); + } + + std::string profile = FormatString("%s_%d_%d%s", profileType, getMajorShaderModel(), getMinorShaderModel(), getShaderModelSuffix().c_str()); + + UINT flags = D3DCOMPILE_OPTIMIZATION_LEVEL2; + + if (gl::DebugAnnotationsActive()) + { +#ifndef NDEBUG + flags = D3DCOMPILE_SKIP_OPTIMIZATION; +#endif + + flags |= D3DCOMPILE_DEBUG; + } + + if (workarounds.enableIEEEStrictness) + flags |= D3DCOMPILE_IEEE_STRICTNESS; + + // 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. + std::vector configs; + configs.push_back(CompileConfig(flags, "default" )); + configs.push_back(CompileConfig(flags | D3DCOMPILE_SKIP_VALIDATION, "skip validation" )); + configs.push_back(CompileConfig(flags | D3DCOMPILE_SKIP_OPTIMIZATION, "skip optimization")); + + D3D_SHADER_MACRO loopMacros[] = { {"ANGLE_ENABLE_LOOP_FLATTEN", "1"}, {0, 0} }; + + ID3DBlob *binary = NULL; + std::string debugInfo; + gl::Error error = mCompiler.compileToBinary(infoLog, shaderHLSL, profile, configs, loopMacros, &binary, &debugInfo); + if (error.isError()) + { + return error; + } + + // It's possible that binary is NULL if the compiler failed in all configurations. Set the executable to NULL + // and return GL_NO_ERROR to signify that there was a link error but the internal state is still OK. + if (!binary) + { + *outExectuable = NULL; + return gl::Error(GL_NO_ERROR); + } + + error = loadExecutable(binary->GetBufferPointer(), binary->GetBufferSize(), type, + transformFeedbackVaryings, separatedOutputBuffers, outExectuable); + + SafeRelease(binary); + if (error.isError()) + { + return error; + } + + if (!debugInfo.empty()) + { + (*outExectuable)->appendDebugInfo(debugInfo); + } + + return gl::Error(GL_NO_ERROR); +} + +UniformStorageD3D *Renderer11::createUniformStorage(size_t storageSize) +{ + return new UniformStorage11(this, storageSize); +} + +VertexBuffer *Renderer11::createVertexBuffer() +{ + return new VertexBuffer11(this); +} + +IndexBuffer *Renderer11::createIndexBuffer() +{ + return new IndexBuffer11(this); +} + +BufferImpl *Renderer11::createBuffer() +{ + return new Buffer11(this); +} + +VertexArrayImpl *Renderer11::createVertexArray() +{ + return new VertexArray11(this); +} + +QueryImpl *Renderer11::createQuery(GLenum type) +{ + return new Query11(this, type); +} + +FenceNVImpl *Renderer11::createFenceNV() +{ + return new FenceNV11(this); +} + +FenceSyncImpl *Renderer11::createFenceSync() +{ + return new FenceSync11(this); +} + +TransformFeedbackImpl* Renderer11::createTransformFeedback() +{ + return new TransformFeedbackD3D(); +} + +bool Renderer11::supportsFastCopyBufferToTexture(GLenum internalFormat) const +{ + ASSERT(getRendererExtensions().pixelBufferObject); + + const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat); + const d3d11::TextureFormat &d3d11FormatInfo = d3d11::GetTextureFormatInfo(internalFormat, mFeatureLevel); + const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(d3d11FormatInfo.texFormat); + + // sRGB formats do not work with D3D11 buffer SRVs + if (internalFormatInfo.colorEncoding == GL_SRGB) + { + return false; + } + + // We cannot support direct copies to non-color-renderable formats + if (d3d11FormatInfo.rtvFormat == DXGI_FORMAT_UNKNOWN) + { + return false; + } + + // We skip all 3-channel formats since sometimes format support is missing + if (internalFormatInfo.componentCount == 3) + { + return false; + } + + // We don't support formats which we can't represent without conversion + if (dxgiFormatInfo.internalFormat != internalFormat) + { + return false; + } + + return true; +} + +gl::Error Renderer11::fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTargetD3D *destRenderTarget, + GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea) +{ + ASSERT(supportsFastCopyBufferToTexture(destinationFormat)); + return mPixelTransfer->copyBufferToTexture(unpack, offset, destRenderTarget, destinationFormat, sourcePixelsType, destArea); +} + +ImageD3D *Renderer11::createImage() +{ + return new Image11(this); +} + +gl::Error Renderer11::generateMipmap(ImageD3D *dest, ImageD3D *src) +{ + Image11 *dest11 = Image11::makeImage11(dest); + Image11 *src11 = Image11::makeImage11(src); + return Image11::generateMipmap(dest11, src11); +} + +TextureStorage *Renderer11::createTextureStorage2D(SwapChainD3D *swapChain) +{ + SwapChain11 *swapChain11 = SwapChain11::makeSwapChain11(swapChain); + return new TextureStorage11_2D(this, swapChain11); +} + +TextureStorage *Renderer11::createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels, bool hintLevelZeroOnly) +{ + return new TextureStorage11_2D(this, internalformat, renderTarget, width, height, levels, hintLevelZeroOnly); +} + +TextureStorage *Renderer11::createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly) +{ + return new TextureStorage11_Cube(this, internalformat, renderTarget, size, levels, hintLevelZeroOnly); +} + +TextureStorage *Renderer11::createTextureStorage3D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) +{ + return new TextureStorage11_3D(this, internalformat, renderTarget, width, height, depth, levels); +} + +TextureStorage *Renderer11::createTextureStorage2DArray(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) +{ + return new TextureStorage11_2DArray(this, internalformat, renderTarget, width, height, depth, levels); +} + +TextureImpl *Renderer11::createTexture(GLenum target) +{ + switch(target) + { + case GL_TEXTURE_2D: return new TextureD3D_2D(this); + case GL_TEXTURE_CUBE_MAP: return new TextureD3D_Cube(this); + case GL_TEXTURE_3D: return new TextureD3D_3D(this); + case GL_TEXTURE_2D_ARRAY: return new TextureD3D_2DArray(this); + default: + UNREACHABLE(); + } + + return NULL; +} + +RenderbufferImpl *Renderer11::createRenderbuffer() +{ + RenderbufferD3D *renderbuffer = new RenderbufferD3D(this); + return renderbuffer; +} + +gl::Error Renderer11::readTextureData(ID3D11Texture2D *texture, unsigned int subResource, const gl::Rectangle &area, GLenum format, + GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, uint8_t *pixels) +{ + ASSERT(area.width >= 0); + ASSERT(area.height >= 0); + + D3D11_TEXTURE2D_DESC textureDesc; + texture->GetDesc(&textureDesc); + + // Clamp read region to the defined texture boundaries, preventing out of bounds reads + // and reads of uninitialized data. + gl::Rectangle safeArea; + safeArea.x = gl::clamp(area.x, 0, static_cast(textureDesc.Width)); + safeArea.y = gl::clamp(area.y, 0, static_cast(textureDesc.Height)); + safeArea.width = gl::clamp(area.width + std::min(area.x, 0), 0, + static_cast(textureDesc.Width) - safeArea.x); + safeArea.height = gl::clamp(area.height + std::min(area.y, 0), 0, + static_cast(textureDesc.Height) - safeArea.y); + + ASSERT(safeArea.x >= 0 && safeArea.y >= 0); + ASSERT(safeArea.x + safeArea.width <= static_cast(textureDesc.Width)); + ASSERT(safeArea.y + safeArea.height <= static_cast(textureDesc.Height)); + + if (safeArea.width == 0 || safeArea.height == 0) + { + // no work to do + return gl::Error(GL_NO_ERROR); + } + + D3D11_TEXTURE2D_DESC stagingDesc; + stagingDesc.Width = safeArea.width; + stagingDesc.Height = safeArea.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)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal staging texture for ReadPixels, HRESULT: 0x%X.", result); + } + + 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)) + { + SafeRelease(stagingTex); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal resolve texture for ReadPixels, HRESULT: 0x%X.", result); + } + + mDeviceContext->ResolveSubresource(srcTex, 0, texture, subResource, textureDesc.Format); + subResource = 0; + } + else + { + srcTex = texture; + srcTex->AddRef(); + } + + D3D11_BOX srcBox; + srcBox.left = static_cast(safeArea.x); + srcBox.right = static_cast(safeArea.x + safeArea.width); + srcBox.top = static_cast(safeArea.y); + srcBox.bottom = static_cast(safeArea.y + safeArea.height); + srcBox.front = 0; + srcBox.back = 1; + + mDeviceContext->CopySubresourceRegion(stagingTex, 0, 0, 0, 0, srcTex, subResource, &srcBox); + + SafeRelease(srcTex); + + PackPixelsParams packParams(safeArea, format, type, outputPitch, pack, 0); + gl::Error error = packPixels(stagingTex, packParams, pixels); + + SafeRelease(stagingTex); + + return error; +} + +gl::Error Renderer11::packPixels(ID3D11Texture2D *readTexture, const PackPixelsParams ¶ms, uint8_t *pixelsOut) +{ + D3D11_TEXTURE2D_DESC textureDesc; + readTexture->GetDesc(&textureDesc); + + D3D11_MAPPED_SUBRESOURCE mapping; + HRESULT hr = mDeviceContext->Map(readTexture, 0, D3D11_MAP_READ, 0, &mapping); + if (FAILED(hr)) + { + ASSERT(hr == E_OUTOFMEMORY); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal texture for reading, result: 0x%X.", hr); + } + + uint8_t *source; + int inputPitch; + if (params.pack.reverseRowOrder) + { + source = static_cast(mapping.pData) + mapping.RowPitch * (params.area.height - 1); + inputPitch = -static_cast(mapping.RowPitch); + } + else + { + source = static_cast(mapping.pData); + inputPitch = static_cast(mapping.RowPitch); + } + + const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(textureDesc.Format); + const gl::InternalFormat &sourceFormatInfo = gl::GetInternalFormatInfo(dxgiFormatInfo.internalFormat); + if (sourceFormatInfo.format == params.format && sourceFormatInfo.type == params.type) + { + uint8_t *dest = pixelsOut + params.offset; + for (int y = 0; y < params.area.height; y++) + { + memcpy(dest + y * params.outputPitch, source + y * inputPitch, params.area.width * sourceFormatInfo.pixelBytes); + } + } + else + { + const d3d11::DXGIFormat &sourceDXGIFormatInfo = d3d11::GetDXGIFormatInfo(textureDesc.Format); + ColorCopyFunction fastCopyFunc = sourceDXGIFormatInfo.getFastCopyFunction(params.format, params.type); + + GLenum sizedDestInternalFormat = gl::GetSizedInternalFormat(params.format, params.type); + const gl::InternalFormat &destFormatInfo = gl::GetInternalFormatInfo(sizedDestInternalFormat); + + if (fastCopyFunc) + { + // Fast copy is possible through some special function + for (int y = 0; y < params.area.height; y++) + { + for (int x = 0; x < params.area.width; x++) + { + uint8_t *dest = pixelsOut + params.offset + y * params.outputPitch + x * destFormatInfo.pixelBytes; + const uint8_t *src = source + y * inputPitch + x * sourceFormatInfo.pixelBytes; + + fastCopyFunc(src, dest); + } + } + } + else + { + ColorReadFunction colorReadFunction = sourceDXGIFormatInfo.colorReadFunction; + ColorWriteFunction colorWriteFunction = GetColorWriteFunction(params.format, params.type); + + uint8_t temp[16]; // Maximum size of any Color type used. + static_assert(sizeof(temp) >= sizeof(gl::ColorF) && + sizeof(temp) >= sizeof(gl::ColorUI) && + sizeof(temp) >= sizeof(gl::ColorI), + "Unexpected size of gl::Color struct."); + + for (int y = 0; y < params.area.height; y++) + { + for (int x = 0; x < params.area.width; x++) + { + uint8_t *dest = pixelsOut + params.offset + y * params.outputPitch + x * destFormatInfo.pixelBytes; + const uint8_t *src = source + y * inputPitch + x * sourceFormatInfo.pixelBytes; + + // readFunc and writeFunc will be using the same type of color, CopyTexImage + // will not allow the copy otherwise. + colorReadFunction(src, temp); + colorWriteFunction(temp, dest); + } + } + } + } + + mDeviceContext->Unmap(readTexture, 0); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const gl::Rectangle &drawRect, RenderTargetD3D *readRenderTarget, + RenderTargetD3D *drawRenderTarget, GLenum filter, const gl::Rectangle *scissor, + bool colorBlit, bool depthBlit, bool stencilBlit) +{ + // Since blitRenderbufferRect is called for each render buffer that needs to be blitted, + // it should never be the case that both color and depth/stencil need to be blitted at + // at the same time. + ASSERT(colorBlit != (depthBlit || stencilBlit)); + + RenderTarget11 *drawRenderTarget11 = RenderTarget11::makeRenderTarget11(drawRenderTarget); + if (!drawRenderTarget) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to retrieve the internal draw render target from the draw framebuffer."); + } + + ID3D11Resource *drawTexture = drawRenderTarget11->getTexture(); + unsigned int drawSubresource = drawRenderTarget11->getSubresourceIndex(); + ID3D11RenderTargetView *drawRTV = drawRenderTarget11->getRenderTargetView(); + ID3D11DepthStencilView *drawDSV = drawRenderTarget11->getDepthStencilView(); + + RenderTarget11 *readRenderTarget11 = RenderTarget11::makeRenderTarget11(readRenderTarget); + if (!readRenderTarget) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to retrieve the internal read render target from the read framebuffer."); + } + + ID3D11Resource *readTexture = NULL; + ID3D11ShaderResourceView *readSRV = NULL; + unsigned int readSubresource = 0; + if (readRenderTarget->getSamples() > 0) + { + ID3D11Resource *unresolvedResource = readRenderTarget11->getTexture(); + ID3D11Texture2D *unresolvedTexture = d3d11::DynamicCastComObject(unresolvedResource); + + if (unresolvedTexture) + { + readTexture = resolveMultisampledTexture(unresolvedTexture, readRenderTarget11->getSubresourceIndex()); + readSubresource = 0; + + SafeRelease(unresolvedTexture); + + HRESULT hresult = mDevice->CreateShaderResourceView(readTexture, NULL, &readSRV); + if (FAILED(hresult)) + { + SafeRelease(readTexture); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create shader resource view to resolve multisampled framebuffer."); + } + } + } + else + { + readTexture = readRenderTarget11->getTexture(); + readTexture->AddRef(); + readSubresource = readRenderTarget11->getSubresourceIndex(); + readSRV = readRenderTarget11->getShaderResourceView(); + readSRV->AddRef(); + } + + if (!readTexture || !readSRV) + { + SafeRelease(readTexture); + SafeRelease(readSRV); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to retrieve the internal read render target view from the read render target."); + } + + gl::Extents readSize(readRenderTarget->getWidth(), readRenderTarget->getHeight(), 1); + gl::Extents drawSize(drawRenderTarget->getWidth(), drawRenderTarget->getHeight(), 1); + + bool scissorNeeded = scissor && gl::ClipRectangle(drawRect, *scissor, NULL); + + bool wholeBufferCopy = !scissorNeeded && + readRect.x == 0 && readRect.width == readSize.width && + readRect.y == 0 && readRect.height == readSize.height && + drawRect.x == 0 && drawRect.width == drawSize.width && + drawRect.y == 0 && drawRect.height == drawSize.height; + + bool stretchRequired = readRect.width != drawRect.width || readRect.height != drawRect.height; + + bool flipRequired = readRect.width < 0 || readRect.height < 0 || drawRect.width < 0 || drawRect.height < 0; + + bool outOfBounds = readRect.x < 0 || readRect.x + readRect.width > readSize.width || + readRect.y < 0 || readRect.y + readRect.height > readSize.height || + drawRect.x < 0 || drawRect.x + drawRect.width > drawSize.width || + drawRect.y < 0 || drawRect.y + drawRect.height > drawSize.height; + + const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(drawRenderTarget11->getDXGIFormat()); + bool partialDSBlit = (dxgiFormatInfo.depthBits > 0 && depthBlit) != (dxgiFormatInfo.stencilBits > 0 && stencilBlit); + + gl::Error result(GL_NO_ERROR); + + if (readRenderTarget11->getDXGIFormat() == drawRenderTarget11->getDXGIFormat() && + !stretchRequired && !outOfBounds && !flipRequired && !partialDSBlit && + (!(depthBlit || stencilBlit) || wholeBufferCopy)) + { + UINT dstX = drawRect.x; + UINT dstY = drawRect.y; + + 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; + + if (scissorNeeded) + { + // drawRect is guaranteed to have positive width and height because stretchRequired is false. + ASSERT(drawRect.width >= 0 || drawRect.height >= 0); + + if (drawRect.x < scissor->x) + { + dstX = scissor->x; + readBox.left += (scissor->x - drawRect.x); + } + if (drawRect.y < scissor->y) + { + dstY = scissor->y; + readBox.top += (scissor->y - drawRect.y); + } + if (drawRect.x + drawRect.width > scissor->x + scissor->width) + { + readBox.right -= ((drawRect.x + drawRect.width) - (scissor->x + scissor->width)); + } + if (drawRect.y + drawRect.height > scissor->y + scissor->height) + { + readBox.bottom -= ((drawRect.y + drawRect.height) - (scissor->y + scissor->height)); + } + } + + // 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, dstX, dstY, 0, + readTexture, readSubresource, pSrcBox); + result = gl::Error(GL_NO_ERROR); + } + else + { + gl::Box readArea(readRect.x, readRect.y, 0, readRect.width, readRect.height, 1); + gl::Box drawArea(drawRect.x, drawRect.y, 0, drawRect.width, drawRect.height, 1); + + if (depthBlit && stencilBlit) + { + result = mBlit->copyDepthStencil(readTexture, readSubresource, readArea, readSize, + drawTexture, drawSubresource, drawArea, drawSize, + scissor); + } + else if (depthBlit) + { + result = mBlit->copyDepth(readSRV, readArea, readSize, drawDSV, drawArea, drawSize, + scissor); + } + else if (stencilBlit) + { + result = mBlit->copyStencil(readTexture, readSubresource, readArea, readSize, + drawTexture, drawSubresource, drawArea, drawSize, + scissor); + } + else + { + GLenum format = gl::GetInternalFormatInfo(drawRenderTarget->getInternalFormat()).format; + result = mBlit->copyTexture(readSRV, readArea, readSize, drawRTV, drawArea, drawSize, + scissor, format, filter); + } + } + + SafeRelease(readTexture); + SafeRelease(readSRV); + + return result; +} + +bool Renderer11::isES3Capable() const +{ + return (d3d11_gl::GetMaximumClientVersion(mFeatureLevel) > 2); +}; + +ID3D11Texture2D *Renderer11::resolveMultisampledTexture(ID3D11Texture2D *source, unsigned int subresource) +{ + D3D11_TEXTURE2D_DESC textureDesc; + source->GetDesc(&textureDesc); + + if (textureDesc.SampleDesc.Count > 1) + { + D3D11_TEXTURE2D_DESC resolveDesc; + resolveDesc.Width = textureDesc.Width; + resolveDesc.Height = textureDesc.Height; + resolveDesc.MipLevels = 1; + resolveDesc.ArraySize = 1; + resolveDesc.Format = textureDesc.Format; + resolveDesc.SampleDesc.Count = 1; + resolveDesc.SampleDesc.Quality = 0; + resolveDesc.Usage = textureDesc.Usage; + resolveDesc.BindFlags = textureDesc.BindFlags; + resolveDesc.CPUAccessFlags = 0; + resolveDesc.MiscFlags = 0; + + ID3D11Texture2D *resolveTexture = NULL; + HRESULT result = mDevice->CreateTexture2D(&resolveDesc, NULL, &resolveTexture); + if (FAILED(result)) + { + ERR("Failed to create a multisample resolve texture, HRESULT: 0x%X.", result); + return NULL; + } + + mDeviceContext->ResolveSubresource(resolveTexture, 0, source, subresource, textureDesc.Format); + return resolveTexture; + } + else + { + source->AddRef(); + return source; + } +} + +bool Renderer11::getLUID(LUID *adapterLuid) const +{ + adapterLuid->HighPart = 0; + adapterLuid->LowPart = 0; + + if (!mDxgiAdapter) + { + return false; + } + + DXGI_ADAPTER_DESC adapterDesc; + if (FAILED(mDxgiAdapter->GetDesc(&adapterDesc))) + { + return false; + } + + *adapterLuid = adapterDesc.AdapterLuid; + return true; +} + +VertexConversionType Renderer11::getVertexConversionType(const gl::VertexFormat &vertexFormat) const +{ + return d3d11::GetVertexFormatInfo(vertexFormat, mFeatureLevel).conversionType; +} + +GLenum Renderer11::getVertexComponentType(const gl::VertexFormat &vertexFormat) const +{ + return d3d11::GetDXGIFormatInfo(d3d11::GetVertexFormatInfo(vertexFormat, mFeatureLevel).nativeFormat).componentType; +} + +void Renderer11::generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureCaps, gl::Extensions *outExtensions) const +{ + d3d11_gl::GenerateCaps(mDevice, mDeviceContext, outCaps, outTextureCaps, outExtensions); +} + +Workarounds Renderer11::generateWorkarounds() const +{ + return d3d11::GenerateWorkarounds(mFeatureLevel); +} + +void Renderer11::setShaderResource(gl::SamplerType shaderType, UINT resourceSlot, ID3D11ShaderResourceView *srv) +{ + auto ¤tSRVs = (shaderType == gl::SAMPLER_VERTEX ? mCurVertexSRVs : mCurPixelSRVs); + + ASSERT(static_cast(resourceSlot) < currentSRVs.size()); + auto &record = currentSRVs[resourceSlot]; + + if (record.srv != reinterpret_cast(srv)) + { + if (shaderType == gl::SAMPLER_VERTEX) + { + mDeviceContext->VSSetShaderResources(resourceSlot, 1, &srv); + } + else + { + mDeviceContext->PSSetShaderResources(resourceSlot, 1, &srv); + } + + record.srv = reinterpret_cast(srv); + if (srv) + { + record.resource = reinterpret_cast(GetViewResource(srv)); + srv->GetDesc(&record.desc); + } + else + { + record.resource = 0; + } + } +} +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.h new file mode 100644 index 0000000000..cc7d6c237b --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.h @@ -0,0 +1,400 @@ +// +// Copyright (c) 2012-2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Renderer11.h: Defines a back-end specific class for the D3D11 renderer. + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_RENDERER11_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_RENDERER11_H_ + +#include "common/angleutils.h" +#include "common/mathutil.h" +#include "libANGLE/AttributeMap.h" +#include "libANGLE/angletypes.h" +#include "libANGLE/renderer/d3d/HLSLCompiler.h" +#include "libANGLE/renderer/d3d/RendererD3D.h" +#include "libANGLE/renderer/d3d/RenderTargetD3D.h" +#include "libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h" +#include "libANGLE/renderer/d3d/d3d11/InputLayoutCache.h" +#include "libANGLE/renderer/d3d/d3d11/RenderStateCache.h" + +struct ID3D11DeviceContext1; + +namespace gl +{ +class FramebufferAttachment; +struct ImageIndex; +} + +namespace rx +{ + +class VertexDataManager; +class IndexDataManager; +class StreamingIndexBufferInterface; +class Blit11; +class Clear11; +class PixelTransfer11; +class RenderTarget11; +class Trim11; +struct PackPixelsParams; + +enum +{ + MAX_VERTEX_UNIFORM_VECTORS_D3D11 = 1024, + MAX_FRAGMENT_UNIFORM_VECTORS_D3D11 = 1024 +}; + +// Possible reasons RendererD3D initialize can fail +enum D3D11InitError +{ + // The renderer loaded successfully + D3D11_INIT_SUCCESS = 0, + // Failed to load the ANGLE & D3D compiler libraries + D3D11_INIT_COMPILER_ERROR, + // Failed to load a necessary DLL (non-compiler) + D3D11_INIT_MISSING_DEP, + // CreateDevice returned E_INVALIDARG + D3D11_INIT_CREATEDEVICE_INVALIDARG, + // CreateDevice failed with an error other than invalid arg + D3D11_INIT_CREATEDEVICE_ERROR, + // DXGI 1.2 required but not found + D3D11_INIT_INCOMPATIBLE_DXGI, + // Other initialization error + D3D11_INIT_OTHER_ERROR, + NUM_D3D11_INIT_ERRORS +}; + +class Renderer11 : public RendererD3D +{ + public: + explicit Renderer11(egl::Display *display); + virtual ~Renderer11(); + + static Renderer11 *makeRenderer11(Renderer *renderer); + + egl::Error initialize() override; + virtual bool resetDevice(); + + egl::ConfigSet generateConfigs() const override; + + gl::Error flush() override; + gl::Error finish() override; + + virtual SwapChainD3D *createSwapChain(NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat); + + virtual gl::Error generateSwizzle(gl::Texture *texture); + virtual gl::Error setSamplerState(gl::SamplerType type, int index, gl::Texture *texture, const gl::SamplerState &sampler); + virtual gl::Error setTexture(gl::SamplerType type, int index, gl::Texture *texture); + + gl::Error setUniformBuffers(const gl::Data &data, + const GLint vertexUniformBuffers[], + const GLint fragmentUniformBuffers[]) override; + + virtual gl::Error setRasterizerState(const gl::RasterizerState &rasterState); + gl::Error setBlendState(const gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::ColorF &blendColor, + unsigned int sampleMask) override; + virtual gl::Error setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef, + int stencilBackRef, bool frontFaceCCW); + + virtual void setScissorRectangle(const gl::Rectangle &scissor, bool enabled); + virtual void setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace, + bool ignoreViewport); + + virtual bool applyPrimitiveType(GLenum mode, GLsizei count, bool usesPointSize); + gl::Error applyRenderTarget(const gl::Framebuffer *frameBuffer) override; + virtual gl::Error applyShaders(gl::Program *program, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer, + bool rasterizerDiscard, bool transformFeedbackActive); + + virtual gl::Error applyUniforms(const ProgramImpl &program, const std::vector &uniformArray); + virtual gl::Error applyVertexBuffer(const gl::State &state, GLenum mode, GLint first, GLsizei count, GLsizei instances); + virtual gl::Error applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo); + void applyTransformFeedbackBuffers(const gl::State &state) override; + + gl::Error drawArrays(const gl::Data &data, GLenum mode, GLsizei count, GLsizei instances, bool usesPointSize) override; + virtual gl::Error drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, + gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances); + + virtual void markAllStateDirty(); + + // lost device + bool testDeviceLost() override; + bool testDeviceResettable() override; + + VendorID getVendorId() const override; + std::string getRendererDescription() const override; + GUID getAdapterIdentifier() const override; + + virtual unsigned int getReservedVertexUniformVectors() const; + virtual unsigned int getReservedFragmentUniformVectors() const; + virtual unsigned int getReservedVertexUniformBuffers() const; + virtual unsigned int getReservedFragmentUniformBuffers() const; + virtual bool getShareHandleSupport() const; + virtual bool getPostSubBufferSupport() const; + + virtual int getMajorShaderModel() const; + int getMinorShaderModel() const override; + std::string getShaderModelSuffix() const override; + + // Pixel operations + virtual gl::Error copyImage2D(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + const gl::Offset &destOffset, TextureStorage *storage, GLint level); + virtual gl::Error copyImageCube(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + const gl::Offset &destOffset, TextureStorage *storage, GLenum target, GLint level); + virtual gl::Error copyImage3D(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + const gl::Offset &destOffset, TextureStorage *storage, GLint level); + virtual gl::Error copyImage2DArray(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + const gl::Offset &destOffset, TextureStorage *storage, GLint level); + + // RenderTarget creation + virtual gl::Error createRenderTarget(int width, int height, GLenum format, GLsizei samples, RenderTargetD3D **outRT); + + // Framebuffer creation + FramebufferImpl *createDefaultFramebuffer(const gl::Framebuffer::Data &data) override; + FramebufferImpl *createFramebuffer(const gl::Framebuffer::Data &data) override; + + // Shader creation + virtual CompilerImpl *createCompiler(const gl::Data &data); + virtual ShaderImpl *createShader(GLenum type); + virtual ProgramImpl *createProgram(); + + // Shader operations + virtual gl::Error loadExecutable(const void *function, size_t length, ShaderType type, + const std::vector &transformFeedbackVaryings, + bool separatedOutputBuffers, ShaderExecutableD3D **outExecutable); + virtual gl::Error compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, ShaderType type, + const std::vector &transformFeedbackVaryings, + bool separatedOutputBuffers, const D3DCompilerWorkarounds &workarounds, + ShaderExecutableD3D **outExectuable); + virtual UniformStorageD3D *createUniformStorage(size_t storageSize); + + // Image operations + virtual ImageD3D *createImage(); + gl::Error generateMipmap(ImageD3D *dest, ImageD3D *source) override; + virtual TextureStorage *createTextureStorage2D(SwapChainD3D *swapChain); + virtual TextureStorage *createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels, bool hintLevelZeroOnly); + virtual TextureStorage *createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly); + virtual TextureStorage *createTextureStorage3D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels); + virtual TextureStorage *createTextureStorage2DArray(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels); + + // Texture creation + virtual TextureImpl *createTexture(GLenum target); + + // Renderbuffer creation + virtual RenderbufferImpl *createRenderbuffer(); + + // Buffer creation + virtual BufferImpl *createBuffer(); + virtual VertexBuffer *createVertexBuffer(); + virtual IndexBuffer *createIndexBuffer(); + + // Vertex Array creation + virtual VertexArrayImpl *createVertexArray(); + + // Query and Fence creation + virtual QueryImpl *createQuery(GLenum type); + virtual FenceNVImpl *createFenceNV(); + virtual FenceSyncImpl *createFenceSync(); + + // Transform Feedback creation + virtual TransformFeedbackImpl* createTransformFeedback(); + + // D3D11-renderer specific methods + ID3D11Device *getDevice() { return mDevice; } + ID3D11DeviceContext *getDeviceContext() { return mDeviceContext; }; + ID3D11DeviceContext1 *getDeviceContext1IfSupported() { return mDeviceContext1; }; + DXGIFactory *getDxgiFactory() { return mDxgiFactory; }; + + Blit11 *getBlitter() { return mBlit; } + Clear11 *getClearer() { return mClear; } + + // Buffer-to-texture and Texture-to-buffer copies + virtual bool supportsFastCopyBufferToTexture(GLenum internalFormat) const; + virtual gl::Error fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTargetD3D *destRenderTarget, + GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea); + + void unapplyRenderTargets(); + void setOneTimeRenderTarget(ID3D11RenderTargetView *renderTargetView); + gl::Error packPixels(ID3D11Texture2D *readTexture, const PackPixelsParams ¶ms, uint8_t *pixelsOut); + + bool getLUID(LUID *adapterLuid) const override; + virtual VertexConversionType getVertexConversionType(const gl::VertexFormat &vertexFormat) const; + virtual GLenum getVertexComponentType(const gl::VertexFormat &vertexFormat) const; + + gl::Error readTextureData(ID3D11Texture2D *texture, unsigned int subResource, const gl::Rectangle &area, GLenum format, + GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, uint8_t *pixels); + + void setShaderResource(gl::SamplerType shaderType, UINT resourceSlot, ID3D11ShaderResourceView *srv); + + gl::Error blitRenderbufferRect(const gl::Rectangle &readRect, const gl::Rectangle &drawRect, RenderTargetD3D *readRenderTarget, + RenderTargetD3D *drawRenderTarget, GLenum filter, const gl::Rectangle *scissor, + bool colorBlit, bool depthBlit, bool stencilBlit); + + bool isES3Capable() const; + D3D_FEATURE_LEVEL getFeatureLevel() const { return mFeatureLevel; }; + + RendererClass getRendererClass() const override { return RENDERER_D3D11; } + + private: + void generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureCaps, gl::Extensions *outExtensions) const override; + Workarounds generateWorkarounds() const override; + + gl::Error drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer); + gl::Error drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer, int instances); + + ID3D11Texture2D *resolveMultisampledTexture(ID3D11Texture2D *source, unsigned int subresource); + void unsetConflictingSRVs(gl::SamplerType shaderType, uintptr_t resource, const gl::ImageIndex *index); + + HMODULE mD3d11Module; + HMODULE mDxgiModule; + std::vector mAvailableFeatureLevels; + D3D_DRIVER_TYPE mDriverType; + + HLSLCompiler mCompiler; + + void initializeDevice(); + void releaseDeviceResources(); + void release(); + + RenderStateCache mStateCache; + + // current render target states + uintptr_t mAppliedRTVs[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS]; + uintptr_t mAppliedDSV; + bool mDepthStencilInitialized; + bool mRenderTargetDescInitialized; + + struct RenderTargetDesc + { + size_t width; + size_t height; + DXGI_FORMAT format; + }; + RenderTargetDesc mRenderTargetDesc; + + // Currently applied sampler states + std::vector mForceSetVertexSamplerStates; + std::vector mCurVertexSamplerStates; + + std::vector mForceSetPixelSamplerStates; + std::vector mCurPixelSamplerStates; + + // Currently applied textures + struct SRVRecord + { + uintptr_t srv; + uintptr_t resource; + D3D11_SHADER_RESOURCE_VIEW_DESC desc; + }; + std::vector mCurVertexSRVs; + std::vector mCurPixelSRVs; + + // Currently applied blend state + bool mForceSetBlendState; + gl::BlendState mCurBlendState; + gl::ColorF mCurBlendColor; + unsigned int mCurSampleMask; + + // Currently applied rasterizer state + bool mForceSetRasterState; + gl::RasterizerState mCurRasterState; + + // Currently applied depth stencil state + bool mForceSetDepthStencilState; + gl::DepthStencilState mCurDepthStencilState; + int mCurStencilRef; + int mCurStencilBackRef; + + // Currently applied scissor rectangle + bool mForceSetScissor; + bool mScissorEnabled; + gl::Rectangle mCurScissor; + + // Currently applied viewport + bool mForceSetViewport; + gl::Rectangle mCurViewport; + float mCurNear; + float mCurFar; + + // Currently applied primitive topology + D3D11_PRIMITIVE_TOPOLOGY mCurrentPrimitiveTopology; + + // Currently applied index buffer + ID3D11Buffer *mAppliedIB; + DXGI_FORMAT mAppliedIBFormat; + unsigned int mAppliedIBOffset; + + // Currently applied transform feedback buffers + size_t mAppliedNumXFBBindings; + ID3D11Buffer *mAppliedTFBuffers[gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS]; // Tracks the current D3D buffers + // in use for streamout + GLintptr mAppliedTFOffsets[gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS]; // Tracks the current GL-specified + // buffer offsets to transform feedback + // buffers + UINT mCurrentD3DOffsets[gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS]; // Tracks the D3D buffer offsets, + // which may differ from GLs, due + // to different append behavior + + // Currently applied shaders + uintptr_t mAppliedVertexShader; + uintptr_t mAppliedGeometryShader; + uintptr_t mAppliedPixelShader; + + dx_VertexConstants mVertexConstants; + dx_VertexConstants mAppliedVertexConstants; + ID3D11Buffer *mDriverConstantBufferVS; + ID3D11Buffer *mCurrentVertexConstantBuffer; + unsigned int mCurrentConstantBufferVS[gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS]; + GLintptr mCurrentConstantBufferVSOffset[gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS]; + GLsizeiptr mCurrentConstantBufferVSSize[gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS]; + + dx_PixelConstants mPixelConstants; + dx_PixelConstants mAppliedPixelConstants; + ID3D11Buffer *mDriverConstantBufferPS; + ID3D11Buffer *mCurrentPixelConstantBuffer; + unsigned int mCurrentConstantBufferPS[gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS]; + GLintptr mCurrentConstantBufferPSOffset[gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS]; + GLsizeiptr mCurrentConstantBufferPSSize[gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS]; + + ID3D11Buffer *mCurrentGeometryConstantBuffer; + + // Vertex, index and input layouts + VertexDataManager *mVertexDataManager; + IndexDataManager *mIndexDataManager; + InputLayoutCache mInputLayoutCache; + + StreamingIndexBufferInterface *mLineLoopIB; + StreamingIndexBufferInterface *mTriangleFanIB; + + // Texture copy resources + Blit11 *mBlit; + PixelTransfer11 *mPixelTransfer; + + // Masked clear resources + Clear11 *mClear; + + // Perform trim for D3D resources + Trim11 *mTrim; + + // Sync query + ID3D11Query *mSyncQuery; + + // Constant buffer offset support + bool mSupportsConstantBufferOffsets; + + ID3D11Device *mDevice; + D3D_FEATURE_LEVEL mFeatureLevel; + ID3D11DeviceContext *mDeviceContext; + ID3D11DeviceContext1 *mDeviceContext1; + IDXGIAdapter *mDxgiAdapter; + DXGI_ADAPTER_DESC mAdapterDescription; + char mDescription[128]; + DXGIFactory *mDxgiFactory; + + DebugAnnotator11 mAnnotator; +}; + +} +#endif // LIBANGLE_RENDERER_D3D_D3D11_RENDERER11_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.cpp new file mode 100644 index 0000000000..7e64c3183d --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.cpp @@ -0,0 +1,110 @@ +// +// Copyright (c) 2012-2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// ShaderExecutable11.cpp: Implements a D3D11-specific class to contain shader +// executable implementation details. + +#include "libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" + +namespace rx +{ + +ShaderExecutable11::ShaderExecutable11(const void *function, size_t length, ID3D11PixelShader *executable) + : ShaderExecutableD3D(function, length) +{ + mPixelExecutable = executable; + mVertexExecutable = NULL; + mGeometryExecutable = NULL; + mStreamOutExecutable = NULL; +} + +ShaderExecutable11::ShaderExecutable11(const void *function, size_t length, ID3D11VertexShader *executable, ID3D11GeometryShader *streamOut) + : ShaderExecutableD3D(function, length) +{ + mVertexExecutable = executable; + mPixelExecutable = NULL; + mGeometryExecutable = NULL; + mStreamOutExecutable = streamOut; +} + +ShaderExecutable11::ShaderExecutable11(const void *function, size_t length, ID3D11GeometryShader *executable) + : ShaderExecutableD3D(function, length) +{ + mGeometryExecutable = executable; + mVertexExecutable = NULL; + mPixelExecutable = NULL; + mStreamOutExecutable = NULL; +} + +ShaderExecutable11::~ShaderExecutable11() +{ + SafeRelease(mVertexExecutable); + SafeRelease(mPixelExecutable); + SafeRelease(mGeometryExecutable); + SafeRelease(mStreamOutExecutable); +} + +ShaderExecutable11 *ShaderExecutable11::makeShaderExecutable11(ShaderExecutableD3D *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; +} + +ID3D11GeometryShader *ShaderExecutable11::getStreamOutShader() const +{ + return mStreamOutExecutable; +} + +UniformStorage11::UniformStorage11(Renderer11 *renderer, size_t initialSize) + : UniformStorageD3D(initialSize), + mConstantBuffer(NULL) +{ + ID3D11Device *d3d11Device = renderer->getDevice(); + + if (initialSize > 0) + { + D3D11_BUFFER_DESC constantBufferDescription = {0}; + constantBufferDescription.ByteWidth = initialSize; + 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 = d3d11Device->CreateBuffer(&constantBufferDescription, NULL, &mConstantBuffer); + UNUSED_ASSERTION_VARIABLE(result); + ASSERT(SUCCEEDED(result)); + } +} + +UniformStorage11::~UniformStorage11() +{ + SafeRelease(mConstantBuffer); +} + +const UniformStorage11 *UniformStorage11::makeUniformStorage11(const UniformStorageD3D *uniformStorage) +{ + ASSERT(HAS_DYNAMIC_TYPE(const UniformStorage11*, uniformStorage)); + return static_cast(uniformStorage); +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h new file mode 100644 index 0000000000..02558ee4dc --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h @@ -0,0 +1,59 @@ +// +// Copyright (c) 2012-2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// ShaderExecutable11.h: Defines a D3D11-specific class to contain shader +// executable implementation details. + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_SHADEREXECUTABLE11_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_SHADEREXECUTABLE11_H_ + +#include "libANGLE/renderer/d3d/ShaderExecutableD3D.h" + +namespace rx +{ +class Renderer11; +class UniformStorage11; + +class ShaderExecutable11 : public ShaderExecutableD3D +{ + public: + ShaderExecutable11(const void *function, size_t length, ID3D11PixelShader *executable); + ShaderExecutable11(const void *function, size_t length, ID3D11VertexShader *executable, ID3D11GeometryShader *streamOut); + ShaderExecutable11(const void *function, size_t length, ID3D11GeometryShader *executable); + + virtual ~ShaderExecutable11(); + + static ShaderExecutable11 *makeShaderExecutable11(ShaderExecutableD3D *executable); + + ID3D11PixelShader *getPixelShader() const; + ID3D11VertexShader *getVertexShader() const; + ID3D11GeometryShader *getGeometryShader() const; + ID3D11GeometryShader *getStreamOutShader() const; + + private: + ID3D11PixelShader *mPixelExecutable; + ID3D11VertexShader *mVertexExecutable; + ID3D11GeometryShader *mGeometryExecutable; + ID3D11GeometryShader *mStreamOutExecutable; +}; + +class UniformStorage11 : public UniformStorageD3D +{ + public: + UniformStorage11(Renderer11 *renderer, size_t initialSize); + virtual ~UniformStorage11(); + + static const UniformStorage11 *makeUniformStorage11(const UniformStorageD3D *uniformStorage); + + ID3D11Buffer *getConstantBuffer() const { return mConstantBuffer; } + + private: + ID3D11Buffer *mConstantBuffer; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_D3D11_SHADEREXECUTABLE11_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp new file mode 100644 index 0000000000..298f3ccbd2 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp @@ -0,0 +1,711 @@ +// +// Copyright (c) 2012-2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// SwapChain11.cpp: Implements a back-end specific class for the D3D11 swap chain. + +#include "libANGLE/renderer/d3d/d3d11/SwapChain11.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" +#include "libANGLE/renderer/d3d/d3d11/formatutils11.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" +#include "libANGLE/renderer/d3d/d3d11/NativeWindow.h" +#include "libANGLE/features.h" + +// Precompiled shaders +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough2d11vs.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2d11ps.h" + + +namespace rx +{ + +SwapChain11::SwapChain11(Renderer11 *renderer, NativeWindow nativeWindow, HANDLE shareHandle, + GLenum backBufferFormat, GLenum depthBufferFormat) + : mRenderer(renderer), + SwapChainD3D(nativeWindow, shareHandle, backBufferFormat, depthBufferFormat), + mColorRenderTarget(this, renderer, false), + mDepthStencilRenderTarget(this, renderer, true) +{ + mSwapChain = NULL; + mBackBufferTexture = NULL; + mBackBufferRTView = NULL; + mOffscreenTexture = NULL; + mOffscreenRTView = NULL; + mOffscreenSRView = NULL; + mDepthStencilTexture = NULL; + mDepthStencilDSView = NULL; + mDepthStencilSRView = NULL; + mQuadVB = NULL; + mPassThroughSampler = NULL; + mPassThroughIL = NULL; + mPassThroughVS = NULL; + mPassThroughPS = NULL; + mWidth = -1; + mHeight = -1; + mSwapInterval = 0; + mAppCreatedShareHandle = mShareHandle != NULL; + mPassThroughResourcesInit = false; +} + +SwapChain11::~SwapChain11() +{ + release(); +} + +void SwapChain11::release() +{ + SafeRelease(mSwapChain); + SafeRelease(mBackBufferTexture); + SafeRelease(mBackBufferRTView); + SafeRelease(mOffscreenTexture); + SafeRelease(mOffscreenRTView); + SafeRelease(mOffscreenSRView); + SafeRelease(mDepthStencilTexture); + SafeRelease(mDepthStencilDSView); + SafeRelease(mDepthStencilSRView); + SafeRelease(mQuadVB); + SafeRelease(mPassThroughSampler); + SafeRelease(mPassThroughIL); + SafeRelease(mPassThroughVS); + SafeRelease(mPassThroughPS); + + if (!mAppCreatedShareHandle) + { + mShareHandle = NULL; + } +} + +void SwapChain11::releaseOffscreenTexture() +{ + SafeRelease(mOffscreenTexture); + SafeRelease(mOffscreenRTView); + SafeRelease(mOffscreenSRView); + SafeRelease(mDepthStencilTexture); + SafeRelease(mDepthStencilDSView); + SafeRelease(mDepthStencilSRView); +} + +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(); + + const d3d11::TextureFormat &backbufferFormatInfo = d3d11::GetTextureFormatInfo(mBackBufferFormat, mRenderer->getFeatureLevel()); + + // 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); + SafeRelease(tempResource11); + + 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 != backbufferFormatInfo.texFormat || + 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 = !mNativeWindow.getNativeWindow() && mRenderer->getShareHandleSupport(); + + D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0}; +#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) + const int textureLength = std::max(backbufferWidth, backbufferHeight); + offscreenTextureDesc.Width = textureLength; + offscreenTextureDesc.Height = textureLength; +#else + offscreenTextureDesc.Width = backbufferWidth; + offscreenTextureDesc.Height = backbufferHeight; +#endif + offscreenTextureDesc.Format = backbufferFormatInfo.texFormat; + 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 back buffer 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); + SafeRelease(offscreenTextureResource); + + if (FAILED(result)) + { + mShareHandle = NULL; + ERR("Could not get offscreen texture shared handle: %08lX", result); + } + } + } + } + + + D3D11_RENDER_TARGET_VIEW_DESC offscreenRTVDesc; + offscreenRTVDesc.Format = backbufferFormatInfo.rtvFormat; + offscreenRTVDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; + offscreenRTVDesc.Texture2D.MipSlice = 0; + + HRESULT result = device->CreateRenderTargetView(mOffscreenTexture, &offscreenRTVDesc, &mOffscreenRTView); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mOffscreenRTView, "Offscreen back buffer render target"); + + D3D11_SHADER_RESOURCE_VIEW_DESC offscreenSRVDesc; + offscreenSRVDesc.Format = backbufferFormatInfo.srvFormat; + offscreenSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + offscreenSRVDesc.Texture2D.MostDetailedMip = 0; + offscreenSRVDesc.Texture2D.MipLevels = static_cast(-1); + + result = device->CreateShaderResourceView(mOffscreenTexture, &offscreenSRVDesc, &mOffscreenSRView); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mOffscreenSRView, "Offscreen back buffer shader resource"); + + const d3d11::TextureFormat &depthBufferFormatInfo = d3d11::GetTextureFormatInfo(mDepthBufferFormat, mRenderer->getFeatureLevel()); + + if (mDepthBufferFormat != GL_NONE) + { + D3D11_TEXTURE2D_DESC depthStencilTextureDesc; +#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) + const int textureLength = std::max(backbufferWidth, backbufferHeight); + depthStencilTextureDesc.Width = textureLength; + depthStencilTextureDesc.Height = textureLength; +#else + depthStencilTextureDesc.Width = backbufferWidth; + depthStencilTextureDesc.Height = backbufferHeight; +#endif + depthStencilTextureDesc.Format = depthBufferFormatInfo.texFormat; + depthStencilTextureDesc.MipLevels = 1; + depthStencilTextureDesc.ArraySize = 1; + depthStencilTextureDesc.SampleDesc.Count = 1; + depthStencilTextureDesc.SampleDesc.Quality = 0; + depthStencilTextureDesc.Usage = D3D11_USAGE_DEFAULT; + depthStencilTextureDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL; + + if (depthBufferFormatInfo.srvFormat != DXGI_FORMAT_UNKNOWN) + { + depthStencilTextureDesc.BindFlags |= D3D11_BIND_SHADER_RESOURCE; + } + + depthStencilTextureDesc.CPUAccessFlags = 0; + depthStencilTextureDesc.MiscFlags = 0; + + result = device->CreateTexture2D(&depthStencilTextureDesc, 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, "Offscreen depth stencil texture"); + + D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilDesc; + depthStencilDesc.Format = depthBufferFormatInfo.dsvFormat; + depthStencilDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; + depthStencilDesc.Flags = 0; + depthStencilDesc.Texture2D.MipSlice = 0; + + result = device->CreateDepthStencilView(mDepthStencilTexture, &depthStencilDesc, &mDepthStencilDSView); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mDepthStencilDSView, "Offscreen depth stencil view"); + + if (depthBufferFormatInfo.srvFormat != DXGI_FORMAT_UNKNOWN) + { + D3D11_SHADER_RESOURCE_VIEW_DESC depthStencilSRVDesc; + depthStencilSRVDesc.Format = depthBufferFormatInfo.srvFormat; + depthStencilSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + depthStencilSRVDesc.Texture2D.MostDetailedMip = 0; + depthStencilSRVDesc.Texture2D.MipLevels = static_cast(-1); + + result = device->CreateShaderResourceView(mDepthStencilTexture, &depthStencilSRVDesc, &mDepthStencilSRView); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mDepthStencilSRView, "Offscreen depth stencil shader resource"); + } + } + + 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); + + SafeRelease(previousOffscreenTexture); + + if (mSwapChain) + { + swapRect(0, 0, mWidth, mHeight); + } + } + + return EGL_SUCCESS; +} + +EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight) +{ + ID3D11Device *device = mRenderer->getDevice(); + + if (device == NULL) + { + return EGL_BAD_ACCESS; + } + + // EGL allows creating a surface with 0x0 dimension, however, DXGI does not like 0x0 swapchains + if (backbufferWidth < 1 || backbufferHeight < 1) + { + return EGL_SUCCESS; + } + +#if !defined(ANGLE_ENABLE_WINDOWS_STORE) || (WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP) + // Can only call resize if we have already created our swap buffer and resources + ASSERT(mSwapChain && mBackBufferTexture && mBackBufferRTView); + + SafeRelease(mBackBufferTexture); + SafeRelease(mBackBufferRTView); + + // Resize swap chain + DXGI_SWAP_CHAIN_DESC desc; + mSwapChain->GetDesc(&desc); + const d3d11::TextureFormat &backbufferFormatInfo = d3d11::GetTextureFormatInfo(mBackBufferFormat, mRenderer->getFeatureLevel()); + HRESULT result = mSwapChain->ResizeBuffers(desc.BufferCount, backbufferWidth, backbufferHeight, backbufferFormatInfo.texFormat, 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); +#else + // Do nothing on Windows Phone apart from updating the internal buffer/width height + mWidth = backbufferWidth; + mHeight = backbufferHeight; + return EGL_SUCCESS; +#endif +} + +EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swapInterval) +{ + ID3D11Device *device = mRenderer->getDevice(); + + if (device == NULL) + { + return EGL_BAD_ACCESS; + } + + // Release specific resources to free up memory for the new render target, while the + // old render target still exists for the purpose of preserving its contents. + SafeRelease(mSwapChain); + SafeRelease(mBackBufferTexture); + SafeRelease(mBackBufferRTView); + + mSwapInterval = static_cast(swapInterval); + if (mSwapInterval > 4) + { + // IDXGISwapChain::Present documentation states that valid sync intervals are in the [0,4] range + return EGL_BAD_PARAMETER; + } + + // EGL allows creating a surface with 0x0 dimension, however, DXGI does not like 0x0 swapchains + if (backbufferWidth < 1 || backbufferHeight < 1) + { + releaseOffscreenTexture(); + return EGL_SUCCESS; + } + + if (mNativeWindow.getNativeWindow()) + { + const d3d11::TextureFormat &backbufferFormatInfo = d3d11::GetTextureFormatInfo(mBackBufferFormat, mRenderer->getFeatureLevel()); + + HRESULT result = mNativeWindow.createSwapChain(device, mRenderer->getDxgiFactory(), + backbufferFormatInfo.texFormat, + backbufferWidth, backbufferHeight, &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_Passthrough2D, sizeof(g_VS_Passthrough2D), &mPassThroughIL); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mPassThroughIL, "Swap chain pass through layout"); + + result = device->CreateVertexShader(g_VS_Passthrough2D, sizeof(g_VS_Passthrough2D), NULL, &mPassThroughVS); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mPassThroughVS, "Swap chain pass through vertex shader"); + + result = device->CreatePixelShader(g_PS_PassthroughRGBA2D, sizeof(g_PS_PassthroughRGBA2D), 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; + +#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) + const float dim = std::max(mWidth, mHeight); + float u1 = x / dim; + float v1 = y / dim; + float u2 = (x + width) / dim; + float v2 = (y + height) / dim; + + const NativeWindow::RotationFlags flags = mNativeWindow.rotationFlags(); + const bool rotateL = flags == NativeWindow::RotateLeft; + const bool rotateR = flags == NativeWindow::RotateRight; + d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, rotateL ? u2 : u1, rotateR ? v2 : v1); + d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, rotateR ? u2 : u1, rotateL ? v1 : v2); + d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, rotateR ? u1 : u2, rotateL ? v2 : v1); + d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, rotateL ? u1 : u2, rotateR ? v1 : v2); +#else + 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); +#endif + + 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; +#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) + viewport.Width = (rotateL || rotateR) ? mHeight : mWidth; + viewport.Height = (rotateL || rotateR) ? mWidth : mHeight; +#else + viewport.Width = mWidth; + viewport.Height = mHeight; +#endif + viewport.MinDepth = 0.0f; + viewport.MaxDepth = 1.0f; + deviceContext->RSSetViewports(1, &viewport); + + // Apply textures + mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, mOffscreenSRView); + deviceContext->PSSetSamplers(0, 1, &mPassThroughSampler); + + // Draw + deviceContext->Draw(4, 0); + +#if ANGLE_VSYNC == ANGLE_DISABLED + result = mSwapChain->Present(0, 0); +#else + result = mSwapChain->Present(mSwapInterval, 0); +#endif + + if (result == DXGI_ERROR_DEVICE_REMOVED) + { + HRESULT removedReason = device->GetDeviceRemovedReason(); + UNUSED_TRACE_VARIABLE(removedReason); + 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 + mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, NULL); + + mRenderer->unapplyRenderTargets(); + mRenderer->markAllStateDirty(); + + return EGL_SUCCESS; +} + +ID3D11Texture2D *SwapChain11::getOffscreenTexture() +{ + return mOffscreenTexture; +} + +ID3D11RenderTargetView *SwapChain11::getRenderTarget() +{ + return mOffscreenRTView; +} + +ID3D11ShaderResourceView *SwapChain11::getRenderTargetShaderResource() +{ + return mOffscreenSRView; +} + +ID3D11DepthStencilView *SwapChain11::getDepthStencil() +{ + return mDepthStencilDSView; +} + +ID3D11ShaderResourceView * SwapChain11::getDepthStencilShaderResource() +{ + return mDepthStencilSRView; +} + +ID3D11Texture2D *SwapChain11::getDepthStencilTexture() +{ + return mDepthStencilTexture; +} + +SwapChain11 *SwapChain11::makeSwapChain11(SwapChainD3D *swapChain) +{ + ASSERT(HAS_DYNAMIC_TYPE(SwapChain11*, swapChain)); + return static_cast(swapChain); +} + +void SwapChain11::recreate() +{ + // possibly should use this method instead of reset +} + +void *rx::SwapChain11::getDevice() +{ + return mRenderer->getDevice(); +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h new file mode 100644 index 0000000000..48c808a261 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.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. +// + +// SwapChain11.h: Defines a back-end specific class for the D3D11 swap chain. + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_SWAPCHAIN11_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_SWAPCHAIN11_H_ + +#include "common/angleutils.h" +#include "libANGLE/renderer/d3d/SwapChainD3D.h" +#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h" + +namespace rx +{ +class Renderer11; + +class SwapChain11 : public SwapChainD3D +{ + public: + SwapChain11(Renderer11 *renderer, NativeWindow nativeWindow, 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(); + + RenderTargetD3D *getColorRenderTarget() override { return &mColorRenderTarget; } + RenderTargetD3D *getDepthStencilRenderTarget() override { return &mDepthStencilRenderTarget; } + + virtual ID3D11Texture2D *getOffscreenTexture(); + virtual ID3D11RenderTargetView *getRenderTarget(); + virtual ID3D11ShaderResourceView *getRenderTargetShaderResource(); + + virtual ID3D11Texture2D *getDepthStencilTexture(); + virtual ID3D11DepthStencilView *getDepthStencil(); + virtual ID3D11ShaderResourceView *getDepthStencilShaderResource(); + + EGLint getWidth() const { return mWidth; } + EGLint getHeight() const { return mHeight; } + + virtual void *getDevice(); + + static SwapChain11 *makeSwapChain11(SwapChainD3D *swapChain); + + private: + 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; + + DXGISwapChain *mSwapChain; + + ID3D11Texture2D *mBackBufferTexture; + ID3D11RenderTargetView *mBackBufferRTView; + + ID3D11Texture2D *mOffscreenTexture; + ID3D11RenderTargetView *mOffscreenRTView; + ID3D11ShaderResourceView *mOffscreenSRView; + + ID3D11Texture2D *mDepthStencilTexture; + ID3D11DepthStencilView *mDepthStencilDSView; + ID3D11ShaderResourceView *mDepthStencilSRView; + + ID3D11Buffer *mQuadVB; + ID3D11SamplerState *mPassThroughSampler; + ID3D11InputLayout *mPassThroughIL; + ID3D11VertexShader *mPassThroughVS; + ID3D11PixelShader *mPassThroughPS; + + SurfaceRenderTarget11 mColorRenderTarget; + SurfaceRenderTarget11 mDepthStencilRenderTarget; +}; + +} +#endif // LIBANGLE_RENDERER_D3D_D3D11_SWAPCHAIN11_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp new file mode 100644 index 0000000000..103e90fed3 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp @@ -0,0 +1,2676 @@ +// +// Copyright (c) 2012-2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// 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 "libANGLE/renderer/d3d/d3d11/TextureStorage11.h" + +#include + +#include "common/MemoryBuffer.h" +#include "common/utilities.h" +#include "libANGLE/ImageIndex.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/renderer/d3d/TextureD3D.h" +#include "libANGLE/renderer/d3d/d3d11/Blit11.h" +#include "libANGLE/renderer/d3d/d3d11/Image11.h" +#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" +#include "libANGLE/renderer/d3d/d3d11/SwapChain11.h" +#include "libANGLE/renderer/d3d/d3d11/formatutils11.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" + +namespace rx +{ + +TextureStorage11::SwizzleCacheValue::SwizzleCacheValue() + : swizzleRed(GL_NONE), swizzleGreen(GL_NONE), swizzleBlue(GL_NONE), swizzleAlpha(GL_NONE) +{ +} + +TextureStorage11::SwizzleCacheValue::SwizzleCacheValue(GLenum red, GLenum green, GLenum blue, GLenum alpha) + : swizzleRed(red), swizzleGreen(green), swizzleBlue(blue), swizzleAlpha(alpha) +{ +} + +bool TextureStorage11::SwizzleCacheValue::operator==(const SwizzleCacheValue &other) const +{ + return swizzleRed == other.swizzleRed && + swizzleGreen == other.swizzleGreen && + swizzleBlue == other.swizzleBlue && + swizzleAlpha == other.swizzleAlpha; +} + +bool TextureStorage11::SwizzleCacheValue::operator!=(const SwizzleCacheValue &other) const +{ + return !(*this == other); +} + +TextureStorage11::SRVKey::SRVKey(int baseLevel, int mipLevels, bool swizzle) + : baseLevel(baseLevel), mipLevels(mipLevels), swizzle(swizzle) +{ +} + +bool TextureStorage11::SRVKey::operator<(const SRVKey &rhs) const +{ + return std::tie(baseLevel, mipLevels, swizzle) < std::tie(rhs.baseLevel, rhs.mipLevels, rhs.swizzle); +} + +TextureStorage11::TextureStorage11(Renderer11 *renderer, UINT bindFlags) + : mBindFlags(bindFlags), + mTopLevel(0), + mMipLevels(0), + mInternalFormat(GL_NONE), + mTextureFormat(DXGI_FORMAT_UNKNOWN), + mShaderResourceFormat(DXGI_FORMAT_UNKNOWN), + mRenderTargetFormat(DXGI_FORMAT_UNKNOWN), + mDepthStencilFormat(DXGI_FORMAT_UNKNOWN), + mTextureWidth(0), + mTextureHeight(0), + mTextureDepth(0) +{ + mRenderer = Renderer11::makeRenderer11(renderer); + + for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) + { + mLevelSRVs[i] = NULL; + } +} + +TextureStorage11::~TextureStorage11() +{ + for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) + { + SafeRelease(mLevelSRVs[level]); + } + + for (SRVCache::iterator i = mSrvCache.begin(); i != mSrvCache.end(); i++) + { + SafeRelease(i->second); + } + mSrvCache.clear(); +} + +TextureStorage11 *TextureStorage11::makeTextureStorage11(TextureStorage *storage) +{ + ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11*, storage)); + return static_cast(storage); +} + +DWORD TextureStorage11::GetTextureBindFlags(GLenum internalFormat, D3D_FEATURE_LEVEL featureLevel, bool renderTarget) +{ + UINT bindFlags = 0; + + const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalFormat, featureLevel); + if (formatInfo.srvFormat != DXGI_FORMAT_UNKNOWN) + { + bindFlags |= D3D11_BIND_SHADER_RESOURCE; + } + if (formatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN) + { + bindFlags |= D3D11_BIND_DEPTH_STENCIL; + } + if (formatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN && renderTarget) + { + bindFlags |= D3D11_BIND_RENDER_TARGET; + } + + return bindFlags; +} + +UINT TextureStorage11::getBindFlags() const +{ + return mBindFlags; +} + +int TextureStorage11::getTopLevel() const +{ + return mTopLevel; +} + +bool TextureStorage11::isRenderTarget() const +{ + return (mBindFlags & (D3D11_BIND_RENDER_TARGET | D3D11_BIND_DEPTH_STENCIL)) != 0; +} + +bool TextureStorage11::isManaged() const +{ + return false; +} + +int TextureStorage11::getLevelCount() const +{ + return mMipLevels - mTopLevel; +} + +int TextureStorage11::getLevelWidth(int mipLevel) const +{ + return std::max(static_cast(mTextureWidth) >> mipLevel, 1); +} + +int TextureStorage11::getLevelHeight(int mipLevel) const +{ + return std::max(static_cast(mTextureHeight) >> mipLevel, 1); +} + +int TextureStorage11::getLevelDepth(int mipLevel) const +{ + return std::max(static_cast(mTextureDepth) >> mipLevel, 1); +} + +UINT TextureStorage11::getSubresourceIndex(const gl::ImageIndex &index) const +{ + UINT mipSlice = static_cast(index.mipIndex + mTopLevel); + UINT arraySlice = static_cast(index.hasLayer() ? index.layerIndex : 0); + UINT subresource = D3D11CalcSubresource(mipSlice, arraySlice, mMipLevels); + ASSERT(subresource != std::numeric_limits::max()); + return subresource; +} + +gl::Error TextureStorage11::getSRV(const gl::SamplerState &samplerState, ID3D11ShaderResourceView **outSRV) +{ + bool swizzleRequired = samplerState.swizzleRequired(); + bool mipmapping = gl::IsMipmapFiltered(samplerState); + unsigned int mipLevels = mipmapping ? (samplerState.maxLevel - samplerState.baseLevel + 1) : 1; + + // Make sure there's 'mipLevels' mipmap levels below the base level (offset by the top level, which corresponds to GL level 0) + mipLevels = std::min(mipLevels, mMipLevels - mTopLevel - samplerState.baseLevel); + + if (mRenderer->getFeatureLevel() <= D3D_FEATURE_LEVEL_9_3) + { + ASSERT(!swizzleRequired); + ASSERT(mipLevels == 1 || mipLevels == mMipLevels); + } + + if (mRenderer->getWorkarounds().zeroMaxLodWorkaround) + { + // We must ensure that the level zero texture is in sync with mipped texture. + gl::Error error = useLevelZeroWorkaroundTexture(mipLevels == 1); + if (error.isError()) + { + return error; + } + } + + if (swizzleRequired) + { + verifySwizzleExists(samplerState.swizzleRed, samplerState.swizzleGreen, samplerState.swizzleBlue, samplerState.swizzleAlpha); + } + + SRVKey key(samplerState.baseLevel, mipLevels, swizzleRequired); + SRVCache::const_iterator iter = mSrvCache.find(key); + if (iter != mSrvCache.end()) + { + *outSRV = iter->second; + } + else + { + ID3D11Resource *texture = NULL; + if (swizzleRequired) + { + gl::Error error = getSwizzleTexture(&texture); + if (error.isError()) + { + return error; + } + } + else + { + gl::Error error = getResource(&texture); + if (error.isError()) + { + return error; + } + } + + ID3D11ShaderResourceView *srv = NULL; + DXGI_FORMAT format = (swizzleRequired ? mSwizzleShaderResourceFormat : mShaderResourceFormat); + gl::Error error = createSRV(samplerState.baseLevel, mipLevels, format, texture, &srv); + if (error.isError()) + { + return error; + } + + mSrvCache.insert(std::make_pair(key, srv)); + *outSRV = srv; + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage11::getSRVLevel(int mipLevel, ID3D11ShaderResourceView **outSRV) +{ + ASSERT(mipLevel >= 0 && mipLevel < getLevelCount()); + + if (!mLevelSRVs[mipLevel]) + { + ID3D11Resource *resource = NULL; + gl::Error error = getResource(&resource); + if (error.isError()) + { + return error; + } + + error = createSRV(mipLevel, 1, mShaderResourceFormat, resource, &mLevelSRVs[mipLevel]); + if (error.isError()) + { + return error; + } + } + + *outSRV = mLevelSRVs[mipLevel]; + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage11::generateSwizzles(GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha) +{ + SwizzleCacheValue swizzleTarget(swizzleRed, swizzleGreen, swizzleBlue, swizzleAlpha); + for (int level = 0; level < getLevelCount(); level++) + { + // Check if the swizzle for this level is out of date + if (mSwizzleCache[level] != swizzleTarget) + { + // Need to re-render the swizzle for this level + ID3D11ShaderResourceView *sourceSRV = NULL; + gl::Error error = getSRVLevel(level, &sourceSRV); + if (error.isError()) + { + return error; + } + + ID3D11RenderTargetView *destRTV = NULL; + error = getSwizzleRenderTarget(level, &destRTV); + if (error.isError()) + { + return error; + } + + gl::Extents size(getLevelWidth(level), getLevelHeight(level), getLevelDepth(level)); + + Blit11 *blitter = mRenderer->getBlitter(); + + error = blitter->swizzleTexture(sourceSRV, destRTV, size, swizzleRed, swizzleGreen, swizzleBlue, swizzleAlpha); + if (error.isError()) + { + return error; + } + + mSwizzleCache[level] = swizzleTarget; + } + } + + return gl::Error(GL_NO_ERROR); +} + +void TextureStorage11::invalidateSwizzleCacheLevel(int mipLevel) +{ + if (mipLevel >= 0 && static_cast(mipLevel) < ArraySize(mSwizzleCache)) + { + // The default constructor of SwizzleCacheValue has GL_NONE for all channels which is not a + // valid swizzle combination + mSwizzleCache[mipLevel] = SwizzleCacheValue(); + } +} + +void TextureStorage11::invalidateSwizzleCache() +{ + for (unsigned int mipLevel = 0; mipLevel < ArraySize(mSwizzleCache); mipLevel++) + { + invalidateSwizzleCacheLevel(mipLevel); + } +} + +gl::Error TextureStorage11::updateSubresourceLevel(ID3D11Resource *srcTexture, unsigned int sourceSubresource, + const gl::ImageIndex &index, const gl::Box ©Area) +{ + ASSERT(srcTexture); + + GLint level = index.mipIndex; + + invalidateSwizzleCacheLevel(level); + + gl::Extents texSize(getLevelWidth(level), getLevelHeight(level), getLevelDepth(level)); + + bool fullCopy = copyArea.x == 0 && + copyArea.y == 0 && + copyArea.z == 0 && + copyArea.width == texSize.width && + copyArea.height == texSize.height && + copyArea.depth == texSize.depth; + + ID3D11Resource *dstTexture = NULL; + gl::Error error(GL_NO_ERROR); + + // If the zero-LOD workaround is active and we want to update a level greater than zero, then we should + // update the mipmapped texture, even if mapmaps are currently disabled. + if (index.mipIndex > 0 && mRenderer->getWorkarounds().zeroMaxLodWorkaround) + { + error = getMippedResource(&dstTexture); + } + else + { + error = getResource(&dstTexture); + } + + if (error.isError()) + { + return error; + } + + unsigned int dstSubresource = getSubresourceIndex(index); + + ASSERT(dstTexture); + + const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mTextureFormat); + if (!fullCopy && (dxgiFormatInfo.depthBits > 0 || dxgiFormatInfo.stencilBits > 0)) + { + // CopySubresourceRegion cannot copy partial depth stencils, use the blitter instead + Blit11 *blitter = mRenderer->getBlitter(); + + return blitter->copyDepthStencil(srcTexture, sourceSubresource, copyArea, texSize, + dstTexture, dstSubresource, copyArea, texSize, + NULL); + } + else + { + D3D11_BOX srcBox; + srcBox.left = copyArea.x; + srcBox.top = copyArea.y; + srcBox.right = copyArea.x + roundUp(static_cast(copyArea.width), dxgiFormatInfo.blockWidth); + srcBox.bottom = copyArea.y + roundUp(static_cast(copyArea.height), dxgiFormatInfo.blockHeight); + srcBox.front = copyArea.z; + srcBox.back = copyArea.z + copyArea.depth; + + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + + context->CopySubresourceRegion(dstTexture, dstSubresource, copyArea.x, copyArea.y, copyArea.z, + srcTexture, sourceSubresource, fullCopy ? NULL : &srcBox); + return gl::Error(GL_NO_ERROR); + } +} + +gl::Error TextureStorage11::copySubresourceLevel(ID3D11Resource* dstTexture, unsigned int dstSubresource, + const gl::ImageIndex &index, const gl::Box ®ion) +{ + ASSERT(dstTexture); + + ID3D11Resource *srcTexture = NULL; + gl::Error error(GL_NO_ERROR); + + // If the zero-LOD workaround is active and we want to update a level greater than zero, then we should + // update the mipmapped texture, even if mapmaps are currently disabled. + if (index.mipIndex > 0 && mRenderer->getWorkarounds().zeroMaxLodWorkaround) + { + error = getMippedResource(&srcTexture); + } + else + { + error = getResource(&srcTexture); + } + + if (error.isError()) + { + return error; + } + + ASSERT(srcTexture); + + unsigned int srcSubresource = getSubresourceIndex(index); + + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + + // D3D11 can't perform partial CopySubresourceRegion on depth/stencil textures, so pSrcBox should be NULL. + D3D11_BOX srcBox; + D3D11_BOX *pSrcBox = NULL; + if (mRenderer->getFeatureLevel() <= D3D_FEATURE_LEVEL_9_3) + { + // However, D3D10Level9 doesn't always perform CopySubresourceRegion correctly unless the source box + // is specified. This is okay, since we don't perform CopySubresourceRegion on depth/stencil + // textures on 9_3. + ASSERT(d3d11::GetDXGIFormatInfo(mTextureFormat).depthBits == 0); + ASSERT(d3d11::GetDXGIFormatInfo(mTextureFormat).stencilBits == 0); + srcBox.left = region.x; + srcBox.right = region.x + region.width; + srcBox.top = region.y; + srcBox.bottom = region.y + region.height; + srcBox.front = region.z; + srcBox.back = region.z + region.depth; + pSrcBox = &srcBox; + } + + context->CopySubresourceRegion(dstTexture, dstSubresource, region.x, region.y, region.z, + srcTexture, srcSubresource, pSrcBox); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage11::generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex) +{ + ASSERT(sourceIndex.layerIndex == destIndex.layerIndex); + + invalidateSwizzleCacheLevel(destIndex.mipIndex); + + RenderTargetD3D *source = NULL; + gl::Error error = getRenderTarget(sourceIndex, &source); + if (error.isError()) + { + return error; + } + + RenderTargetD3D *dest = NULL; + error = getRenderTarget(destIndex, &dest); + if (error.isError()) + { + return error; + } + + ID3D11ShaderResourceView *sourceSRV = RenderTarget11::makeRenderTarget11(source)->getShaderResourceView(); + ID3D11RenderTargetView *destRTV = RenderTarget11::makeRenderTarget11(dest)->getRenderTargetView(); + + gl::Box sourceArea(0, 0, 0, source->getWidth(), source->getHeight(), source->getDepth()); + gl::Extents sourceSize(source->getWidth(), source->getHeight(), source->getDepth()); + + gl::Box destArea(0, 0, 0, dest->getWidth(), dest->getHeight(), dest->getDepth()); + gl::Extents destSize(dest->getWidth(), dest->getHeight(), dest->getDepth()); + + Blit11 *blitter = mRenderer->getBlitter(); + return blitter->copyTexture(sourceSRV, sourceArea, sourceSize, destRTV, destArea, destSize, NULL, + gl::GetInternalFormatInfo(source->getInternalFormat()).format, GL_LINEAR); +} + +void TextureStorage11::verifySwizzleExists(GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha) +{ + SwizzleCacheValue swizzleTarget(swizzleRed, swizzleGreen, swizzleBlue, swizzleAlpha); + for (unsigned int level = 0; level < mMipLevels; level++) + { + ASSERT(mSwizzleCache[level] == swizzleTarget); + } +} + +gl::Error TextureStorage11::copyToStorage(TextureStorage *destStorage) +{ + ASSERT(destStorage); + + ID3D11Resource *sourceResouce = NULL; + gl::Error error = getResource(&sourceResouce); + if (error.isError()) + { + return error; + } + + TextureStorage11 *dest11 = TextureStorage11::makeTextureStorage11(destStorage); + ID3D11Resource *destResource = NULL; + error = dest11->getResource(&destResource); + if (error.isError()) + { + return error; + } + + ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext(); + immediateContext->CopyResource(destResource, sourceResouce); + + dest11->invalidateSwizzleCache(); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage11::setData(const gl::ImageIndex &index, ImageD3D *image, const gl::Box *destBox, GLenum type, + const gl::PixelUnpackState &unpack, const uint8_t *pixelData) +{ + ASSERT(!image->isDirty()); + + ID3D11Resource *resource = NULL; + gl::Error error = getResource(&resource); + if (error.isError()) + { + return error; + } + ASSERT(resource); + + UINT destSubresource = getSubresourceIndex(index); + + const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(image->getInternalFormat()); + + gl::Box levelBox(0, 0, 0, getLevelWidth(index.mipIndex), getLevelHeight(index.mipIndex), getLevelDepth(index.mipIndex)); + bool fullUpdate = (destBox == NULL || *destBox == levelBox); + ASSERT(internalFormatInfo.depthBits == 0 || fullUpdate); + + // TODO(jmadill): Handle compressed formats + // Compressed formats have different load syntax, so we'll have to handle them with slightly + // different logic. Will implemnent this in a follow-up patch, and ensure we do not use SetData + // with compressed formats in the calling logic. + ASSERT(!internalFormatInfo.compressed); + + int width = destBox ? destBox->width : static_cast(image->getWidth()); + int height = destBox ? destBox->height : static_cast(image->getHeight()); + int depth = destBox ? destBox->depth : static_cast(image->getDepth()); + UINT srcRowPitch = internalFormatInfo.computeRowPitch(type, width, unpack.alignment, unpack.rowLength); + UINT srcDepthPitch = internalFormatInfo.computeDepthPitch(type, width, height, unpack.alignment, unpack.rowLength); + + const d3d11::TextureFormat &d3d11Format = d3d11::GetTextureFormatInfo(image->getInternalFormat(), mRenderer->getFeatureLevel()); + const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(d3d11Format.texFormat); + + size_t outputPixelSize = dxgiFormatInfo.pixelBytes; + + UINT bufferRowPitch = outputPixelSize * width; + UINT bufferDepthPitch = bufferRowPitch * height; + + size_t neededSize = bufferDepthPitch * depth; + MemoryBuffer *conversionBuffer = NULL; + error = mRenderer->getScratchMemoryBuffer(neededSize, &conversionBuffer); + if (error.isError()) + { + return error; + } + + // TODO: fast path + LoadImageFunction loadFunction = d3d11Format.loadFunctions.at(type); + loadFunction(width, height, depth, + pixelData, srcRowPitch, srcDepthPitch, + conversionBuffer->data(), bufferRowPitch, bufferDepthPitch); + + ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext(); + + if (!fullUpdate) + { + ASSERT(destBox); + + D3D11_BOX destD3DBox; + destD3DBox.left = destBox->x; + destD3DBox.right = destBox->x + destBox->width; + destD3DBox.top = destBox->y; + destD3DBox.bottom = destBox->y + destBox->height; + destD3DBox.front = destBox->z; + destD3DBox.back = destBox->z + destBox->depth; + + immediateContext->UpdateSubresource(resource, destSubresource, + &destD3DBox, conversionBuffer->data(), + bufferRowPitch, bufferDepthPitch); + } + else + { + immediateContext->UpdateSubresource(resource, destSubresource, + NULL, conversionBuffer->data(), + bufferRowPitch, bufferDepthPitch); + } + + return gl::Error(GL_NO_ERROR); +} + +TextureStorage11_2D::TextureStorage11_2D(Renderer11 *renderer, SwapChain11 *swapchain) + : TextureStorage11(renderer, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE), + mTexture(swapchain->getOffscreenTexture()), + mSwizzleTexture(NULL), + mLevelZeroTexture(NULL), + mLevelZeroRenderTarget(NULL), + mUseLevelZeroTexture(false) +{ + mTexture->AddRef(); + + for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) + { + mAssociatedImages[i] = NULL; + mRenderTarget[i] = NULL; + mSwizzleRenderTargets[i] = NULL; + } + + D3D11_TEXTURE2D_DESC texDesc; + mTexture->GetDesc(&texDesc); + mMipLevels = texDesc.MipLevels; + mTextureFormat = texDesc.Format; + mTextureWidth = texDesc.Width; + mTextureHeight = texDesc.Height; + mTextureDepth = 1; + + mInternalFormat = swapchain->GetBackBufferInternalFormat(); + + ID3D11ShaderResourceView *srv = swapchain->getRenderTargetShaderResource(); + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; + srv->GetDesc(&srvDesc); + mShaderResourceFormat = srvDesc.Format; + + ID3D11RenderTargetView* offscreenRTV = swapchain->getRenderTarget(); + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + offscreenRTV->GetDesc(&rtvDesc); + mRenderTargetFormat = rtvDesc.Format; + + const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mTextureFormat); + const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(dxgiFormatInfo.internalFormat, mRenderer->getFeatureLevel()); + mSwizzleTextureFormat = formatInfo.swizzleTexFormat; + mSwizzleShaderResourceFormat = formatInfo.swizzleSRVFormat; + mSwizzleRenderTargetFormat = formatInfo.swizzleRTVFormat; + + mDepthStencilFormat = DXGI_FORMAT_UNKNOWN; + + initializeSerials(1, 1); +} + +TextureStorage11_2D::TextureStorage11_2D(Renderer11 *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels, bool hintLevelZeroOnly) + : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderer->getFeatureLevel(), renderTarget)), + mTexture(NULL), + mSwizzleTexture(NULL), + mLevelZeroTexture(NULL), + mLevelZeroRenderTarget(NULL), + mUseLevelZeroTexture(false) +{ + for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) + { + mAssociatedImages[i] = NULL; + mRenderTarget[i] = NULL; + mSwizzleRenderTargets[i] = NULL; + } + + mInternalFormat = internalformat; + + const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat, renderer->getFeatureLevel()); + mTextureFormat = formatInfo.texFormat; + mShaderResourceFormat = formatInfo.srvFormat; + mDepthStencilFormat = formatInfo.dsvFormat; + mRenderTargetFormat = formatInfo.rtvFormat; + mSwizzleTextureFormat = formatInfo.swizzleTexFormat; + mSwizzleShaderResourceFormat = formatInfo.swizzleSRVFormat; + mSwizzleRenderTargetFormat = formatInfo.swizzleRTVFormat; + + d3d11::MakeValidSize(false, mTextureFormat, &width, &height, &mTopLevel); + mMipLevels = mTopLevel + levels; + mTextureWidth = width; + mTextureHeight = height; + mTextureDepth = 1; + + if (hintLevelZeroOnly && levels > 1) + { + //The LevelZeroOnly hint should only be true if the zero max LOD workaround is active. + ASSERT(mRenderer->getWorkarounds().zeroMaxLodWorkaround); + mUseLevelZeroTexture = true; + } + + initializeSerials(getLevelCount(), 1); +} + +TextureStorage11_2D::~TextureStorage11_2D() +{ + for (unsigned i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) + { + if (mAssociatedImages[i] != NULL) + { + bool imageAssociationCorrect = mAssociatedImages[i]->isAssociatedStorageValid(this); + ASSERT(imageAssociationCorrect); + + if (imageAssociationCorrect) + { + // We must let the Images recover their data before we delete it from the TextureStorage. + gl::Error error = mAssociatedImages[i]->recoverFromAssociatedStorage(); + if (error.isError()) + { + // TODO: Find a way to report this back to the context + } + } + } + } + + SafeRelease(mTexture); + SafeRelease(mSwizzleTexture); + + SafeRelease(mLevelZeroTexture); + SafeDelete(mLevelZeroRenderTarget); + + for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) + { + SafeDelete(mRenderTarget[i]); + SafeRelease(mSwizzleRenderTargets[i]); + } +} + +TextureStorage11_2D *TextureStorage11_2D::makeTextureStorage11_2D(TextureStorage *storage) +{ + ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_2D*, storage)); + return static_cast(storage); +} + +gl::Error TextureStorage11_2D::copyToStorage(TextureStorage *destStorage) +{ + ASSERT(destStorage); + + TextureStorage11_2D *dest11 = TextureStorage11_2D::makeTextureStorage11_2D(destStorage); + + if (mRenderer->getWorkarounds().zeroMaxLodWorkaround) + { + ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext(); + + // If either mTexture or mLevelZeroTexture exist, then we need to copy them into the corresponding textures in destStorage. + if (mTexture) + { + gl::Error error = dest11->useLevelZeroWorkaroundTexture(false); + if (error.isError()) + { + return error; + } + + ID3D11Resource *destResource = NULL; + error = dest11->getResource(&destResource); + if (error.isError()) + { + return error; + } + + immediateContext->CopyResource(destResource, mTexture); + } + + if (mLevelZeroTexture) + { + gl::Error error = dest11->useLevelZeroWorkaroundTexture(true); + if (error.isError()) + { + return error; + } + + ID3D11Resource *destResource = NULL; + error = dest11->getResource(&destResource); + if (error.isError()) + { + return error; + } + + immediateContext->CopyResource(destResource, mLevelZeroTexture); + } + } + else + { + ID3D11Resource *sourceResouce = NULL; + gl::Error error = getResource(&sourceResouce); + if (error.isError()) + { + return error; + } + + ID3D11Resource *destResource = NULL; + error = dest11->getResource(&destResource); + if (error.isError()) + { + return error; + } + + ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext(); + immediateContext->CopyResource(destResource, sourceResouce); + } + + dest11->invalidateSwizzleCache(); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage11_2D::useLevelZeroWorkaroundTexture(bool useLevelZeroTexture) +{ + if (useLevelZeroTexture && mMipLevels > 1) + { + if (!mUseLevelZeroTexture && mTexture) + { + gl::Error error = ensureTextureExists(1); + if (error.isError()) + { + return error; + } + + // Pull data back from the mipped texture if necessary. + ASSERT(mLevelZeroTexture); + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + context->CopySubresourceRegion(mLevelZeroTexture, 0, 0, 0, 0, mTexture, 0, NULL); + } + + mUseLevelZeroTexture = true; + } + else + { + if (mUseLevelZeroTexture && mLevelZeroTexture) + { + gl::Error error = ensureTextureExists(mMipLevels); + if (error.isError()) + { + return error; + } + + // Pull data back from the level zero texture if necessary. + ASSERT(mTexture); + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + context->CopySubresourceRegion(mTexture, 0, 0, 0, 0, mLevelZeroTexture, 0, NULL); + } + + mUseLevelZeroTexture = false; + } + + return gl::Error(GL_NO_ERROR); +} + +void TextureStorage11_2D::associateImage(Image11* image, const gl::ImageIndex &index) +{ + GLint level = index.mipIndex; + + ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + + if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + { + mAssociatedImages[level] = image; + } +} + +bool TextureStorage11_2D::isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage) +{ + GLint level = index.mipIndex; + + if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + { + // This validation check should never return false. It means the Image/TextureStorage association is broken. + bool retValue = (mAssociatedImages[level] == expectedImage); + ASSERT(retValue); + return retValue; + } + + return false; +} + +// disassociateImage allows an Image to end its association with a Storage. +void TextureStorage11_2D::disassociateImage(const gl::ImageIndex &index, Image11* expectedImage) +{ + GLint level = index.mipIndex; + + ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + + if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + { + ASSERT(mAssociatedImages[level] == expectedImage); + + if (mAssociatedImages[level] == expectedImage) + { + mAssociatedImages[level] = NULL; + } + } +} + +// releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image recover its data before ending the association. +gl::Error TextureStorage11_2D::releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage) +{ + GLint level = index.mipIndex; + + ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + + if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + { + // No need to let the old Image recover its data, if it is also the incoming Image. + if (mAssociatedImages[level] != NULL && mAssociatedImages[level] != incomingImage) + { + // Ensure that the Image is still associated with this TextureStorage. This should be true. + bool imageAssociationCorrect = mAssociatedImages[level]->isAssociatedStorageValid(this); + ASSERT(imageAssociationCorrect); + + if (imageAssociationCorrect) + { + // Force the image to recover from storage before its data is overwritten. + // This will reset mAssociatedImages[level] to NULL too. + gl::Error error = mAssociatedImages[level]->recoverFromAssociatedStorage(); + if (error.isError()) + { + return error; + } + } + } + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage11_2D::getResource(ID3D11Resource **outResource) +{ + if (mUseLevelZeroTexture && mMipLevels > 1) + { + gl::Error error = ensureTextureExists(1); + if (error.isError()) + { + return error; + } + + *outResource = mLevelZeroTexture; + return gl::Error(GL_NO_ERROR); + } + else + { + gl::Error error = ensureTextureExists(mMipLevels); + if (error.isError()) + { + return error; + } + + *outResource = mTexture; + return gl::Error(GL_NO_ERROR); + } +} + +gl::Error TextureStorage11_2D::getMippedResource(ID3D11Resource **outResource) +{ + // This shouldn't be called unless the zero max LOD workaround is active. + ASSERT(mRenderer->getWorkarounds().zeroMaxLodWorkaround); + + gl::Error error = ensureTextureExists(mMipLevels); + if (error.isError()) + { + return error; + } + + *outResource = mTexture; + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage11_2D::ensureTextureExists(int mipLevels) +{ + // If mMipLevels = 1 then always use mTexture rather than mLevelZeroTexture. + bool useLevelZeroTexture = mRenderer->getWorkarounds().zeroMaxLodWorkaround ? (mipLevels == 1) && (mMipLevels > 1) : false; + ID3D11Texture2D **outputTexture = useLevelZeroTexture ? &mLevelZeroTexture : &mTexture; + + // 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 (*outputTexture == NULL && mTextureWidth > 0 && mTextureHeight > 0) + { + ASSERT(mipLevels > 0); + + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_TEXTURE2D_DESC desc; + desc.Width = mTextureWidth; // Compressed texture size constraints? + desc.Height = mTextureHeight; + desc.MipLevels = mipLevels; + 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, outputTexture); + + // this can happen from windows TDR + if (d3d11::isDeviceLostError(result)) + { + mRenderer->notifyDeviceLost(); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create 2D texture storage, result: 0x%X.", result); + } + else if (FAILED(result)) + { + ASSERT(result == E_OUTOFMEMORY); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create 2D texture storage, result: 0x%X.", result); + } + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage11_2D::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) +{ + ASSERT(!index.hasLayer()); + + int level = index.mipIndex; + ASSERT(level >= 0 && level < getLevelCount()); + + // In GL ES 2.0, the application can only render to level zero of the texture (Section 4.4.3 of the GLES 2.0 spec, page 113 of version 2.0.25). + // Other parts of TextureStorage11_2D could create RTVs on non-zero levels of the texture (e.g. generateMipmap). + // On Feature Level 9_3, this is unlikely to be useful. The renderer can't create SRVs on the individual levels of the texture, + // so methods like generateMipmap can't do anything useful with non-zero-level RTVs. + // Therefore if level > 0 on 9_3 then there's almost certainly something wrong. + ASSERT(!(mRenderer->getFeatureLevel() <= D3D_FEATURE_LEVEL_9_3 && level > 0)); + + if (!mRenderTarget[level]) + { + ID3D11Resource *texture = NULL; + gl::Error error = getResource(&texture); + if (error.isError()) + { + return error; + } + + ID3D11ShaderResourceView *srv = NULL; + error = getSRVLevel(level, &srv); + if (error.isError()) + { + return error; + } + + if (mUseLevelZeroTexture) + { + if (!mLevelZeroRenderTarget) + { + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = mRenderTargetFormat; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; + rtvDesc.Texture2D.MipSlice = mTopLevel + level; + + ID3D11RenderTargetView *rtv; + HRESULT result = device->CreateRenderTargetView(mLevelZeroTexture, &rtvDesc, &rtv); + + if (result == E_OUTOFMEMORY) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal render target view for texture storage, result: 0x%X.", result); + } + ASSERT(SUCCEEDED(result)); + + mLevelZeroRenderTarget = new TextureRenderTarget11(rtv, mLevelZeroTexture, NULL, mInternalFormat, getLevelWidth(level), getLevelHeight(level), 1, 0); + + // RenderTarget will take ownership of these resources + SafeRelease(rtv); + } + + ASSERT(outRT); + *outRT = mLevelZeroRenderTarget; + return gl::Error(GL_NO_ERROR); + } + + if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN) + { + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = mRenderTargetFormat; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; + rtvDesc.Texture2D.MipSlice = mTopLevel + level; + + ID3D11RenderTargetView *rtv; + HRESULT result = device->CreateRenderTargetView(texture, &rtvDesc, &rtv); + + ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal render target view for texture storage, result: 0x%X.", result); + } + + mRenderTarget[level] = new TextureRenderTarget11(rtv, texture, srv, mInternalFormat, getLevelWidth(level), getLevelHeight(level), 1, 0); + + // RenderTarget will take ownership of these resources + SafeRelease(rtv); + } + else if (mDepthStencilFormat != DXGI_FORMAT_UNKNOWN) + { + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; + dsvDesc.Format = mDepthStencilFormat; + dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; + dsvDesc.Texture2D.MipSlice = mTopLevel + level; + dsvDesc.Flags = 0; + + ID3D11DepthStencilView *dsv; + HRESULT result = device->CreateDepthStencilView(texture, &dsvDesc, &dsv); + + ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY,"Failed to create internal depth stencil view for texture storage, result: 0x%X.", result); + } + + mRenderTarget[level] = new TextureRenderTarget11(dsv, texture, srv, mInternalFormat, getLevelWidth(level), getLevelHeight(level), 1, 0); + + // RenderTarget will take ownership of these resources + SafeRelease(dsv); + } + else + { + UNREACHABLE(); + } + } + + ASSERT(outRT); + *outRT = mRenderTarget[level]; + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage11_2D::createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture, + ID3D11ShaderResourceView **outSRV) const +{ + ASSERT(outSRV); + + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; + srvDesc.Format = format; + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + srvDesc.Texture2D.MostDetailedMip = mTopLevel + baseLevel; + srvDesc.Texture2D.MipLevels = mipLevels; + + ID3D11Resource *srvTexture = texture; + + if (mRenderer->getWorkarounds().zeroMaxLodWorkaround) + { + ASSERT(mTopLevel == 0); + ASSERT(baseLevel == 0); + // This code also assumes that the incoming texture equals either mLevelZeroTexture or mTexture. + + if (mipLevels == 1 && mMipLevels > 1) + { + // We must use a SRV on the level-zero-only texture. + ASSERT(mLevelZeroTexture != NULL && texture == mLevelZeroTexture); + srvTexture = mLevelZeroTexture; + } + else + { + ASSERT(mipLevels == static_cast(mMipLevels)); + ASSERT(mTexture != NULL && texture == mTexture); + srvTexture = mTexture; + } + } + + ID3D11Device *device = mRenderer->getDevice(); + HRESULT result = device->CreateShaderResourceView(srvTexture, &srvDesc, outSRV); + + ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal texture storage SRV, result: 0x%X.", result); + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage11_2D::getSwizzleTexture(ID3D11Resource **outTexture) +{ + ASSERT(outTexture); + + if (!mSwizzleTexture) + { + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_TEXTURE2D_DESC desc; + desc.Width = mTextureWidth; + desc.Height = mTextureHeight; + desc.MipLevels = mMipLevels; + desc.ArraySize = 1; + desc.Format = mSwizzleTextureFormat; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET; + desc.CPUAccessFlags = 0; + desc.MiscFlags = 0; + + HRESULT result = device->CreateTexture2D(&desc, NULL, &mSwizzleTexture); + + ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal swizzle texture, result: 0x%X.", result); + } + } + + *outTexture = mSwizzleTexture; + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage11_2D::getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV) +{ + ASSERT(mipLevel >= 0 && mipLevel < getLevelCount()); + ASSERT(outRTV); + + if (!mSwizzleRenderTargets[mipLevel]) + { + ID3D11Resource *swizzleTexture = NULL; + gl::Error error = getSwizzleTexture(&swizzleTexture); + if (error.isError()) + { + return error; + } + + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = mSwizzleRenderTargetFormat; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; + rtvDesc.Texture2D.MipSlice = mTopLevel + mipLevel; + + HRESULT result = device->CreateRenderTargetView(mSwizzleTexture, &rtvDesc, &mSwizzleRenderTargets[mipLevel]); + + ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal swizzle render target view, result: 0x%X.", result); + } + } + + *outRTV = mSwizzleRenderTargets[mipLevel]; + return gl::Error(GL_NO_ERROR); +} + +TextureStorage11_Cube::TextureStorage11_Cube(Renderer11 *renderer, GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly) + : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderer->getFeatureLevel(), renderTarget)) +{ + mTexture = NULL; + mSwizzleTexture = NULL; + + for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) + { + mSwizzleRenderTargets[level] = NULL; + for (unsigned int face = 0; face < CUBE_FACE_COUNT; face++) + { + mAssociatedImages[face][level] = NULL; + mRenderTarget[face][level] = NULL; + } + } + + mLevelZeroTexture = NULL; + mUseLevelZeroTexture = false; + + for (unsigned int face = 0; face < CUBE_FACE_COUNT; face++) + { + mLevelZeroRenderTarget[face] = NULL; + } + + mInternalFormat = internalformat; + + const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat, renderer->getFeatureLevel()); + mTextureFormat = formatInfo.texFormat; + mShaderResourceFormat = formatInfo.srvFormat; + mDepthStencilFormat = formatInfo.dsvFormat; + mRenderTargetFormat = formatInfo.rtvFormat; + mSwizzleTextureFormat = formatInfo.swizzleTexFormat; + mSwizzleShaderResourceFormat = formatInfo.swizzleSRVFormat; + mSwizzleRenderTargetFormat = formatInfo.swizzleRTVFormat; + + // adjust size if needed for compressed textures + int height = size; + d3d11::MakeValidSize(false, mTextureFormat, &size, &height, &mTopLevel); + + mMipLevels = mTopLevel + levels; + mTextureWidth = size; + mTextureHeight = size; + mTextureDepth = 1; + + if (hintLevelZeroOnly && levels > 1) + { + //The LevelZeroOnly hint should only be true if the zero max LOD workaround is active. + ASSERT(mRenderer->getWorkarounds().zeroMaxLodWorkaround); + mUseLevelZeroTexture = true; + } + + initializeSerials(getLevelCount() * CUBE_FACE_COUNT, CUBE_FACE_COUNT); +} + +TextureStorage11_Cube::~TextureStorage11_Cube() +{ + for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) + { + for (unsigned int face = 0; face < CUBE_FACE_COUNT; face++) + { + if (mAssociatedImages[face][level] != NULL) + { + bool imageAssociationCorrect = mAssociatedImages[face][level]->isAssociatedStorageValid(this); + ASSERT(imageAssociationCorrect); + + if (imageAssociationCorrect) + { + // We must let the Images recover their data before we delete it from the TextureStorage. + mAssociatedImages[face][level]->recoverFromAssociatedStorage(); + } + } + } + } + + SafeRelease(mTexture); + SafeRelease(mSwizzleTexture); + SafeRelease(mLevelZeroTexture); + + for (unsigned int face = 0; face < CUBE_FACE_COUNT; face++) + { + SafeDelete(mLevelZeroRenderTarget[face]); + } + + for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) + { + SafeRelease(mSwizzleRenderTargets[level]); + for (unsigned int face = 0; face < CUBE_FACE_COUNT; face++) + { + SafeDelete(mRenderTarget[face][level]); + } + } +} + +TextureStorage11_Cube *TextureStorage11_Cube::makeTextureStorage11_Cube(TextureStorage *storage) +{ + ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_Cube*, storage)); + return static_cast(storage); +} + +UINT TextureStorage11_Cube::getSubresourceIndex(const gl::ImageIndex &index) const +{ + if (mRenderer->getWorkarounds().zeroMaxLodWorkaround && mUseLevelZeroTexture && index.mipIndex == 0) + { + UINT arraySlice = static_cast(index.hasLayer() ? index.layerIndex : 0); + UINT subresource = D3D11CalcSubresource(0, arraySlice, 1); + ASSERT(subresource != std::numeric_limits::max()); + return subresource; + } + else + { + UINT mipSlice = static_cast(index.mipIndex + mTopLevel); + UINT arraySlice = static_cast(index.hasLayer() ? index.layerIndex : 0); + UINT subresource = D3D11CalcSubresource(mipSlice, arraySlice, mMipLevels); + ASSERT(subresource != std::numeric_limits::max()); + return subresource; + } +} + +gl::Error TextureStorage11_Cube::copyToStorage(TextureStorage *destStorage) +{ + ASSERT(destStorage); + + TextureStorage11_Cube *dest11 = TextureStorage11_Cube::makeTextureStorage11_Cube(destStorage); + + if (mRenderer->getWorkarounds().zeroMaxLodWorkaround) + { + ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext(); + + // If either mTexture or mLevelZeroTexture exist, then we need to copy them into the corresponding textures in destStorage. + if (mTexture) + { + gl::Error error = dest11->useLevelZeroWorkaroundTexture(false); + if (error.isError()) + { + return error; + } + + ID3D11Resource *destResource = NULL; + error = dest11->getResource(&destResource); + if (error.isError()) + { + return error; + } + + immediateContext->CopyResource(destResource, mTexture); + } + + if (mLevelZeroTexture) + { + gl::Error error = dest11->useLevelZeroWorkaroundTexture(true); + if (error.isError()) + { + return error; + } + + ID3D11Resource *destResource = NULL; + error = dest11->getResource(&destResource); + if (error.isError()) + { + return error; + } + + immediateContext->CopyResource(destResource, mLevelZeroTexture); + } + } + else + { + ID3D11Resource *sourceResouce = NULL; + gl::Error error = getResource(&sourceResouce); + if (error.isError()) + { + return error; + } + + ID3D11Resource *destResource = NULL; + error = dest11->getResource(&destResource); + if (error.isError()) + { + return error; + } + + ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext(); + immediateContext->CopyResource(destResource, sourceResouce); + } + + dest11->invalidateSwizzleCache(); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage11_Cube::useLevelZeroWorkaroundTexture(bool useLevelZeroTexture) +{ + if (useLevelZeroTexture && mMipLevels > 1) + { + if (!mUseLevelZeroTexture && mTexture) + { + gl::Error error = ensureTextureExists(1); + if (error.isError()) + { + return error; + } + + // Pull data back from the mipped texture if necessary. + ASSERT(mLevelZeroTexture); + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + + for (int face = 0; face < 6; face++) + { + context->CopySubresourceRegion(mLevelZeroTexture, D3D11CalcSubresource(0, face, 1), 0, 0, 0, mTexture, face * mMipLevels, NULL); + } + } + + mUseLevelZeroTexture = true; + } + else + { + if (mUseLevelZeroTexture && mLevelZeroTexture) + { + gl::Error error = ensureTextureExists(mMipLevels); + if (error.isError()) + { + return error; + } + + // Pull data back from the level zero texture if necessary. + ASSERT(mTexture); + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + + for (int face = 0; face < 6; face++) + { + context->CopySubresourceRegion(mTexture, D3D11CalcSubresource(0, face, mMipLevels), 0, 0, 0, mLevelZeroTexture, face, NULL); + } + } + + mUseLevelZeroTexture = false; + } + + return gl::Error(GL_NO_ERROR); +} + +void TextureStorage11_Cube::associateImage(Image11* image, const gl::ImageIndex &index) +{ + GLint level = index.mipIndex; + GLint layerTarget = index.layerIndex; + + ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + ASSERT(0 <= layerTarget && layerTarget < CUBE_FACE_COUNT); + + if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + { + if (0 <= layerTarget && layerTarget < CUBE_FACE_COUNT) + { + mAssociatedImages[layerTarget][level] = image; + } + } +} + +bool TextureStorage11_Cube::isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage) +{ + GLint level = index.mipIndex; + GLint layerTarget = index.layerIndex; + + if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + { + if (0 <= layerTarget && layerTarget < CUBE_FACE_COUNT) + { + // This validation check should never return false. It means the Image/TextureStorage association is broken. + bool retValue = (mAssociatedImages[layerTarget][level] == expectedImage); + ASSERT(retValue); + return retValue; + } + } + + return false; +} + +// disassociateImage allows an Image to end its association with a Storage. +void TextureStorage11_Cube::disassociateImage(const gl::ImageIndex &index, Image11* expectedImage) +{ + GLint level = index.mipIndex; + GLint layerTarget = index.layerIndex; + + ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + ASSERT(0 <= layerTarget && layerTarget < CUBE_FACE_COUNT); + + if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + { + if (0 <= layerTarget && layerTarget < CUBE_FACE_COUNT) + { + ASSERT(mAssociatedImages[layerTarget][level] == expectedImage); + + if (mAssociatedImages[layerTarget][level] == expectedImage) + { + mAssociatedImages[layerTarget][level] = NULL; + } + } + } +} + +// releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image recover its data before ending the association. +gl::Error TextureStorage11_Cube::releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage) +{ + GLint level = index.mipIndex; + GLint layerTarget = index.layerIndex; + + ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + ASSERT(0 <= layerTarget && layerTarget < CUBE_FACE_COUNT); + + if ((0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)) + { + if (0 <= layerTarget && layerTarget < CUBE_FACE_COUNT) + { + // No need to let the old Image recover its data, if it is also the incoming Image. + if (mAssociatedImages[layerTarget][level] != NULL && mAssociatedImages[layerTarget][level] != incomingImage) + { + // Ensure that the Image is still associated with this TextureStorage. This should be true. + bool imageAssociationCorrect = mAssociatedImages[layerTarget][level]->isAssociatedStorageValid(this); + ASSERT(imageAssociationCorrect); + + if (imageAssociationCorrect) + { + // Force the image to recover from storage before its data is overwritten. + // This will reset mAssociatedImages[level] to NULL too. + gl::Error error = mAssociatedImages[layerTarget][level]->recoverFromAssociatedStorage(); + if (error.isError()) + { + return error; + } + } + } + } + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage11_Cube::getResource(ID3D11Resource **outResource) +{ + if (mUseLevelZeroTexture && mMipLevels > 1) + { + gl::Error error = ensureTextureExists(1); + if (error.isError()) + { + return error; + } + + *outResource = mLevelZeroTexture; + return gl::Error(GL_NO_ERROR); + } + else + { + gl::Error error = ensureTextureExists(mMipLevels); + if (error.isError()) + { + return error; + } + + *outResource = mTexture; + return gl::Error(GL_NO_ERROR); + } +} + +gl::Error TextureStorage11_Cube::getMippedResource(ID3D11Resource **outResource) +{ + // This shouldn't be called unless the zero max LOD workaround is active. + ASSERT(mRenderer->getWorkarounds().zeroMaxLodWorkaround); + + gl::Error error = ensureTextureExists(mMipLevels); + if (error.isError()) + { + return error; + } + + *outResource = mTexture; + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage11_Cube::ensureTextureExists(int mipLevels) +{ + // If mMipLevels = 1 then always use mTexture rather than mLevelZeroTexture. + bool useLevelZeroTexture = mRenderer->getWorkarounds().zeroMaxLodWorkaround ? (mipLevels == 1) && (mMipLevels > 1) : false; + ID3D11Texture2D **outputTexture = useLevelZeroTexture ? &mLevelZeroTexture : &mTexture; + + // 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 (*outputTexture == NULL && mTextureWidth > 0 && mTextureHeight > 0) + { + ASSERT(mMipLevels > 0); + + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_TEXTURE2D_DESC desc; + desc.Width = mTextureWidth; + desc.Height = mTextureHeight; + desc.MipLevels = mipLevels; + desc.ArraySize = CUBE_FACE_COUNT; + 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, outputTexture); + + // this can happen from windows TDR + if (d3d11::isDeviceLostError(result)) + { + mRenderer->notifyDeviceLost(); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create cube texture storage, result: 0x%X.", result); + } + else if (FAILED(result)) + { + ASSERT(result == E_OUTOFMEMORY); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create cube texture storage, result: 0x%X.", result); + } + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage11_Cube::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) +{ + int faceIndex = index.layerIndex; + int level = index.mipIndex; + + ASSERT(level >= 0 && level < getLevelCount()); + ASSERT(faceIndex >= 0 && faceIndex < CUBE_FACE_COUNT); + + if (!mRenderTarget[faceIndex][level]) + { + ID3D11Device *device = mRenderer->getDevice(); + HRESULT result; + + ID3D11Resource *texture = NULL; + gl::Error error = getResource(&texture); + if (error.isError()) + { + return error; + } + + if (mUseLevelZeroTexture) + { + if (!mLevelZeroRenderTarget[faceIndex]) + { + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = mRenderTargetFormat; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; + rtvDesc.Texture2DArray.MipSlice = mTopLevel + level; + rtvDesc.Texture2DArray.FirstArraySlice = faceIndex; + rtvDesc.Texture2DArray.ArraySize = 1; + + ID3D11RenderTargetView *rtv; + result = device->CreateRenderTargetView(mLevelZeroTexture, &rtvDesc, &rtv); + + if (result == E_OUTOFMEMORY) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal render target view for texture storage, result: 0x%X.", result); + } + ASSERT(SUCCEEDED(result)); + + mLevelZeroRenderTarget[faceIndex] = new TextureRenderTarget11(rtv, mLevelZeroTexture, NULL, mInternalFormat, getLevelWidth(level), getLevelHeight(level), 1, 0); + + // RenderTarget will take ownership of these resources + SafeRelease(rtv); + } + + ASSERT(outRT); + *outRT = mLevelZeroRenderTarget[faceIndex]; + return gl::Error(GL_NO_ERROR); + } + + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; + srvDesc.Format = mShaderResourceFormat; + srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + level; + srvDesc.Texture2DArray.MipLevels = 1; + srvDesc.Texture2DArray.FirstArraySlice = faceIndex; + srvDesc.Texture2DArray.ArraySize = 1; + + if (mRenderer->getFeatureLevel() <= D3D_FEATURE_LEVEL_9_3) + { + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE; + } + else + { + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; // Will be used with Texture2D sampler, not TextureCube + } + + ID3D11ShaderResourceView *srv; + result = device->CreateShaderResourceView(texture, &srvDesc, &srv); + + ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal shader resource view for texture storage, result: 0x%X.", result); + } + + if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN) + { + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = mRenderTargetFormat; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; + rtvDesc.Texture2DArray.MipSlice = mTopLevel + level; + rtvDesc.Texture2DArray.FirstArraySlice = faceIndex; + rtvDesc.Texture2DArray.ArraySize = 1; + + ID3D11RenderTargetView *rtv; + result = device->CreateRenderTargetView(texture, &rtvDesc, &rtv); + + ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); + if (FAILED(result)) + { + SafeRelease(srv); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal render target view for texture storage, result: 0x%X.", result); + } + + mRenderTarget[faceIndex][level] = new TextureRenderTarget11(rtv, texture, srv, mInternalFormat, getLevelWidth(level), getLevelHeight(level), 1, 0); + + // RenderTarget will take ownership of these resources + SafeRelease(rtv); + SafeRelease(srv); + } + else if (mDepthStencilFormat != DXGI_FORMAT_UNKNOWN) + { + D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; + dsvDesc.Format = mDepthStencilFormat; + dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY; + dsvDesc.Flags = 0; + dsvDesc.Texture2DArray.MipSlice = mTopLevel + level; + dsvDesc.Texture2DArray.FirstArraySlice = faceIndex; + dsvDesc.Texture2DArray.ArraySize = 1; + + ID3D11DepthStencilView *dsv; + result = device->CreateDepthStencilView(texture, &dsvDesc, &dsv); + + ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); + if (FAILED(result)) + { + SafeRelease(srv); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal depth stencil view for texture storage, result: 0x%X.", result); + } + + mRenderTarget[faceIndex][level] = new TextureRenderTarget11(dsv, texture, srv, mInternalFormat, getLevelWidth(level), getLevelHeight(level), 1, 0); + + // RenderTarget will take ownership of these resources + SafeRelease(dsv); + SafeRelease(srv); + } + else + { + UNREACHABLE(); + } + } + + ASSERT(outRT); + *outRT = mRenderTarget[faceIndex][level]; + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage11_Cube::createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture, + ID3D11ShaderResourceView **outSRV) const +{ + ASSERT(outSRV); + + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; + srvDesc.Format = format; + + // Unnormalized integer cube maps are not supported by DX11; we emulate them as an array of six 2D textures + const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(format); + if (dxgiFormatInfo.componentType == GL_INT || dxgiFormatInfo.componentType == GL_UNSIGNED_INT) + { + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; + srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + baseLevel; + srvDesc.Texture2DArray.MipLevels = 1; + srvDesc.Texture2DArray.FirstArraySlice = 0; + srvDesc.Texture2DArray.ArraySize = CUBE_FACE_COUNT; + } + else + { + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE; + srvDesc.TextureCube.MipLevels = mipLevels; + srvDesc.TextureCube.MostDetailedMip = mTopLevel + baseLevel; + } + + ID3D11Resource *srvTexture = texture; + + if (mRenderer->getWorkarounds().zeroMaxLodWorkaround) + { + ASSERT(mTopLevel == 0); + ASSERT(baseLevel == 0); + // This code also assumes that the incoming texture equals either mLevelZeroTexture or mTexture. + + if (mipLevels == 1 && mMipLevels > 1) + { + // We must use a SRV on the level-zero-only texture. + ASSERT(mLevelZeroTexture != NULL && texture == mLevelZeroTexture); + srvTexture = mLevelZeroTexture; + } + else + { + ASSERT(mipLevels == static_cast(mMipLevels)); + ASSERT(mTexture != NULL && texture == mTexture); + srvTexture = mTexture; + } + } + + ID3D11Device *device = mRenderer->getDevice(); + HRESULT result = device->CreateShaderResourceView(srvTexture, &srvDesc, outSRV); + + ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal texture storage SRV, result: 0x%X.", result); + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage11_Cube::getSwizzleTexture(ID3D11Resource **outTexture) +{ + ASSERT(outTexture); + + if (!mSwizzleTexture) + { + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_TEXTURE2D_DESC desc; + desc.Width = mTextureWidth; + desc.Height = mTextureHeight; + desc.MipLevels = mMipLevels; + desc.ArraySize = CUBE_FACE_COUNT; + desc.Format = mSwizzleTextureFormat; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET; + desc.CPUAccessFlags = 0; + desc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE; + + HRESULT result = device->CreateTexture2D(&desc, NULL, &mSwizzleTexture); + + ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal swizzle texture, result: 0x%X.", result); + } + } + + *outTexture = mSwizzleTexture; + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage11_Cube::getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV) +{ + ASSERT(mipLevel >= 0 && mipLevel < getLevelCount()); + ASSERT(outRTV); + + if (!mSwizzleRenderTargets[mipLevel]) + { + ID3D11Resource *swizzleTexture = NULL; + gl::Error error = getSwizzleTexture(&swizzleTexture); + if (error.isError()) + { + return error; + } + + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = mSwizzleRenderTargetFormat; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; + rtvDesc.Texture2DArray.MipSlice = mTopLevel + mipLevel; + rtvDesc.Texture2DArray.FirstArraySlice = 0; + rtvDesc.Texture2DArray.ArraySize = CUBE_FACE_COUNT; + + HRESULT result = device->CreateRenderTargetView(mSwizzleTexture, &rtvDesc, &mSwizzleRenderTargets[mipLevel]); + + ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal swizzle render target view, result: 0x%X.", result); + } + } + + *outRTV = mSwizzleRenderTargets[mipLevel]; + return gl::Error(GL_NO_ERROR); +} + +TextureStorage11_3D::TextureStorage11_3D(Renderer11 *renderer, GLenum internalformat, bool renderTarget, + GLsizei width, GLsizei height, GLsizei depth, int levels) + : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderer->getFeatureLevel(), renderTarget)) +{ + mTexture = NULL; + mSwizzleTexture = NULL; + + for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) + { + mAssociatedImages[i] = NULL; + mLevelRenderTargets[i] = NULL; + mSwizzleRenderTargets[i] = NULL; + } + + mInternalFormat = internalformat; + + const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat, renderer->getFeatureLevel()); + mTextureFormat = formatInfo.texFormat; + mShaderResourceFormat = formatInfo.srvFormat; + mDepthStencilFormat = formatInfo.dsvFormat; + mRenderTargetFormat = formatInfo.rtvFormat; + mSwizzleTextureFormat = formatInfo.swizzleTexFormat; + mSwizzleShaderResourceFormat = formatInfo.swizzleSRVFormat; + mSwizzleRenderTargetFormat = formatInfo.swizzleRTVFormat; + + // adjust size if needed for compressed textures + d3d11::MakeValidSize(false, mTextureFormat, &width, &height, &mTopLevel); + + mMipLevels = mTopLevel + levels; + mTextureWidth = width; + mTextureHeight = height; + mTextureDepth = depth; + + initializeSerials(getLevelCount() * depth, depth); +} + +TextureStorage11_3D::~TextureStorage11_3D() +{ + for (unsigned i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) + { + if (mAssociatedImages[i] != NULL) + { + bool imageAssociationCorrect = mAssociatedImages[i]->isAssociatedStorageValid(this); + ASSERT(imageAssociationCorrect); + + if (imageAssociationCorrect) + { + // We must let the Images recover their data before we delete it from the TextureStorage. + mAssociatedImages[i]->recoverFromAssociatedStorage(); + } + } + } + + SafeRelease(mTexture); + SafeRelease(mSwizzleTexture); + + for (RenderTargetMap::iterator i = mLevelLayerRenderTargets.begin(); i != mLevelLayerRenderTargets.end(); i++) + { + SafeDelete(i->second); + } + mLevelLayerRenderTargets.clear(); + + for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) + { + SafeDelete(mLevelRenderTargets[i]); + SafeRelease(mSwizzleRenderTargets[i]); + } +} + +TextureStorage11_3D *TextureStorage11_3D::makeTextureStorage11_3D(TextureStorage *storage) +{ + ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_3D*, storage)); + return static_cast(storage); +} + +void TextureStorage11_3D::associateImage(Image11* image, const gl::ImageIndex &index) +{ + GLint level = index.mipIndex; + + ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + + if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + { + mAssociatedImages[level] = image; + } +} + +bool TextureStorage11_3D::isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage) +{ + GLint level = index.mipIndex; + + if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + { + // This validation check should never return false. It means the Image/TextureStorage association is broken. + bool retValue = (mAssociatedImages[level] == expectedImage); + ASSERT(retValue); + return retValue; + } + + return false; +} + +// disassociateImage allows an Image to end its association with a Storage. +void TextureStorage11_3D::disassociateImage(const gl::ImageIndex &index, Image11* expectedImage) +{ + GLint level = index.mipIndex; + + ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + + if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + { + ASSERT(mAssociatedImages[level] == expectedImage); + + if (mAssociatedImages[level] == expectedImage) + { + mAssociatedImages[level] = NULL; + } + } +} + +// releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image recover its data before ending the association. +gl::Error TextureStorage11_3D::releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage) +{ + GLint level = index.mipIndex; + + ASSERT((0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)); + + if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + { + // No need to let the old Image recover its data, if it is also the incoming Image. + if (mAssociatedImages[level] != NULL && mAssociatedImages[level] != incomingImage) + { + // Ensure that the Image is still associated with this TextureStorage. This should be true. + bool imageAssociationCorrect = mAssociatedImages[level]->isAssociatedStorageValid(this); + ASSERT(imageAssociationCorrect); + + if (imageAssociationCorrect) + { + // Force the image to recover from storage before its data is overwritten. + // This will reset mAssociatedImages[level] to NULL too. + gl::Error error = mAssociatedImages[level]->recoverFromAssociatedStorage(); + if (error.isError()) + { + return error; + } + } + } + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage11_3D::getResource(ID3D11Resource **outResource) +{ + // If the width, height or depth are not positive this should be treated as an incomplete texture + // we handle that here by skipping the d3d texture creation + if (mTexture == NULL && mTextureWidth > 0 && mTextureHeight > 0 && mTextureDepth > 0) + { + ASSERT(mMipLevels > 0); + + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_TEXTURE3D_DESC desc; + desc.Width = mTextureWidth; + desc.Height = mTextureHeight; + desc.Depth = mTextureDepth; + desc.MipLevels = mMipLevels; + desc.Format = mTextureFormat; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = getBindFlags(); + desc.CPUAccessFlags = 0; + desc.MiscFlags = 0; + + HRESULT result = device->CreateTexture3D(&desc, NULL, &mTexture); + + // this can happen from windows TDR + if (d3d11::isDeviceLostError(result)) + { + mRenderer->notifyDeviceLost(); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create 3D texture storage, result: 0x%X.", result); + } + else if (FAILED(result)) + { + ASSERT(result == E_OUTOFMEMORY); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create 3D texture storage, result: 0x%X.", result); + } + } + + *outResource = mTexture; + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage11_3D::createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture, + ID3D11ShaderResourceView **outSRV) const +{ + ASSERT(outSRV); + + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; + srvDesc.Format = format; + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D; + srvDesc.Texture3D.MostDetailedMip = baseLevel; + srvDesc.Texture3D.MipLevels = mipLevels; + + ID3D11Device *device = mRenderer->getDevice(); + HRESULT result = device->CreateShaderResourceView(texture, &srvDesc, outSRV); + + ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal texture storage SRV, result: 0x%X.", result); + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage11_3D::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) +{ + int mipLevel = index.mipIndex; + ASSERT(mipLevel >= 0 && mipLevel < getLevelCount()); + + ASSERT(mRenderTargetFormat != DXGI_FORMAT_UNKNOWN); + + if (!index.hasLayer()) + { + if (!mLevelRenderTargets[mipLevel]) + { + ID3D11Resource *texture = NULL; + gl::Error error = getResource(&texture); + if (error.isError()) + { + return error; + } + + ID3D11ShaderResourceView *srv = NULL; + error = getSRVLevel(mipLevel, &srv); + if (error.isError()) + { + return error; + } + + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = mRenderTargetFormat; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D; + rtvDesc.Texture3D.MipSlice = mTopLevel + mipLevel; + rtvDesc.Texture3D.FirstWSlice = 0; + rtvDesc.Texture3D.WSize = static_cast(-1); + + ID3D11RenderTargetView *rtv; + HRESULT result = device->CreateRenderTargetView(texture, &rtvDesc, &rtv); + + ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); + if (FAILED(result)) + { + SafeRelease(srv); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal render target view for texture storage, result: 0x%X.", result); + } + + mLevelRenderTargets[mipLevel] = new TextureRenderTarget11(rtv, texture, srv, mInternalFormat, getLevelWidth(mipLevel), getLevelHeight(mipLevel), getLevelDepth(mipLevel), 0); + + // RenderTarget will take ownership of these resources + SafeRelease(rtv); + } + + ASSERT(outRT); + *outRT = mLevelRenderTargets[mipLevel]; + return gl::Error(GL_NO_ERROR); + } + else + { + int layer = index.layerIndex; + + LevelLayerKey key(mipLevel, layer); + if (mLevelLayerRenderTargets.find(key) == mLevelLayerRenderTargets.end()) + { + ID3D11Device *device = mRenderer->getDevice(); + HRESULT result; + + ID3D11Resource *texture = NULL; + gl::Error error = getResource(&texture); + if (error.isError()) + { + return error; + } + + // TODO, what kind of SRV is expected here? + ID3D11ShaderResourceView *srv = NULL; + + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = mRenderTargetFormat; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D; + rtvDesc.Texture3D.MipSlice = mTopLevel + mipLevel; + rtvDesc.Texture3D.FirstWSlice = layer; + rtvDesc.Texture3D.WSize = 1; + + ID3D11RenderTargetView *rtv; + result = device->CreateRenderTargetView(texture, &rtvDesc, &rtv); + + ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); + if (FAILED(result)) + { + SafeRelease(srv); return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal render target view for texture storage, result: 0x%X.", result); + } + ASSERT(SUCCEEDED(result)); + + mLevelLayerRenderTargets[key] = new TextureRenderTarget11(rtv, texture, srv, mInternalFormat, getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1, 0); + + // RenderTarget will take ownership of these resources + SafeRelease(rtv); + } + + ASSERT(outRT); + *outRT = mLevelLayerRenderTargets[key]; + return gl::Error(GL_NO_ERROR); + } +} + +gl::Error TextureStorage11_3D::getSwizzleTexture(ID3D11Resource **outTexture) +{ + ASSERT(outTexture); + + if (!mSwizzleTexture) + { + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_TEXTURE3D_DESC desc; + desc.Width = mTextureWidth; + desc.Height = mTextureHeight; + desc.Depth = mTextureDepth; + desc.MipLevels = mMipLevels; + desc.Format = mSwizzleTextureFormat; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET; + desc.CPUAccessFlags = 0; + desc.MiscFlags = 0; + + HRESULT result = device->CreateTexture3D(&desc, NULL, &mSwizzleTexture); + + ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal swizzle texture, result: 0x%X.", result); + } + } + + *outTexture = mSwizzleTexture; + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage11_3D::getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV) +{ + ASSERT(mipLevel >= 0 && mipLevel < getLevelCount()); + ASSERT(outRTV); + + if (!mSwizzleRenderTargets[mipLevel]) + { + ID3D11Resource *swizzleTexture = NULL; + gl::Error error = getSwizzleTexture(&swizzleTexture); + if (error.isError()) + { + return error; + } + + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = mSwizzleRenderTargetFormat; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D; + rtvDesc.Texture3D.MipSlice = mTopLevel + mipLevel; + rtvDesc.Texture3D.FirstWSlice = 0; + rtvDesc.Texture3D.WSize = static_cast(-1); + + HRESULT result = device->CreateRenderTargetView(mSwizzleTexture, &rtvDesc, &mSwizzleRenderTargets[mipLevel]); + + ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal swizzle render target view, result: 0x%X.", result); + } + } + + *outRTV = mSwizzleRenderTargets[mipLevel]; + return gl::Error(GL_NO_ERROR); +} + +TextureStorage11_2DArray::TextureStorage11_2DArray(Renderer11 *renderer, GLenum internalformat, bool renderTarget, + GLsizei width, GLsizei height, GLsizei depth, int levels) + : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderer->getFeatureLevel(), renderTarget)) +{ + mTexture = NULL; + mSwizzleTexture = NULL; + + for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) + { + mSwizzleRenderTargets[level] = NULL; + } + + mInternalFormat = internalformat; + + const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat, renderer->getFeatureLevel()); + mTextureFormat = formatInfo.texFormat; + mShaderResourceFormat = formatInfo.srvFormat; + mDepthStencilFormat = formatInfo.dsvFormat; + mRenderTargetFormat = formatInfo.rtvFormat; + mSwizzleTextureFormat = formatInfo.swizzleTexFormat; + mSwizzleShaderResourceFormat = formatInfo.swizzleSRVFormat; + mSwizzleRenderTargetFormat = formatInfo.swizzleRTVFormat; + + // adjust size if needed for compressed textures + d3d11::MakeValidSize(false, mTextureFormat, &width, &height, &mTopLevel); + + mMipLevels = mTopLevel + levels; + mTextureWidth = width; + mTextureHeight = height; + mTextureDepth = depth; + + initializeSerials(getLevelCount() * depth, depth); +} + +TextureStorage11_2DArray::~TextureStorage11_2DArray() +{ + for (ImageMap::iterator i = mAssociatedImages.begin(); i != mAssociatedImages.end(); i++) + { + if (i->second) + { + bool imageAssociationCorrect = i->second->isAssociatedStorageValid(this); + ASSERT(imageAssociationCorrect); + + if (imageAssociationCorrect) + { + // We must let the Images recover their data before we delete it from the TextureStorage. + i->second->recoverFromAssociatedStorage(); + } + } + } + mAssociatedImages.clear(); + + SafeRelease(mTexture); + SafeRelease(mSwizzleTexture); + + for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) + { + SafeRelease(mSwizzleRenderTargets[level]); + } + + for (RenderTargetMap::iterator i = mRenderTargets.begin(); i != mRenderTargets.end(); i++) + { + SafeDelete(i->second); + } + mRenderTargets.clear(); +} + +TextureStorage11_2DArray *TextureStorage11_2DArray::makeTextureStorage11_2DArray(TextureStorage *storage) +{ + ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_2DArray*, storage)); + return static_cast(storage); +} + +void TextureStorage11_2DArray::associateImage(Image11* image, const gl::ImageIndex &index) +{ + GLint level = index.mipIndex; + GLint layerTarget = index.layerIndex; + + ASSERT(0 <= level && level < getLevelCount()); + + if (0 <= level && level < getLevelCount()) + { + LevelLayerKey key(level, layerTarget); + mAssociatedImages[key] = image; + } +} + +bool TextureStorage11_2DArray::isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage) +{ + GLint level = index.mipIndex; + GLint layerTarget = index.layerIndex; + + LevelLayerKey key(level, layerTarget); + + // This validation check should never return false. It means the Image/TextureStorage association is broken. + bool retValue = (mAssociatedImages.find(key) != mAssociatedImages.end() && (mAssociatedImages[key] == expectedImage)); + ASSERT(retValue); + return retValue; +} + +// disassociateImage allows an Image to end its association with a Storage. +void TextureStorage11_2DArray::disassociateImage(const gl::ImageIndex &index, Image11* expectedImage) +{ + GLint level = index.mipIndex; + GLint layerTarget = index.layerIndex; + + LevelLayerKey key(level, layerTarget); + + bool imageAssociationCorrect = (mAssociatedImages.find(key) != mAssociatedImages.end() && (mAssociatedImages[key] == expectedImage)); + ASSERT(imageAssociationCorrect); + + if (imageAssociationCorrect) + { + mAssociatedImages[key] = NULL; + } +} + +// releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image recover its data before ending the association. +gl::Error TextureStorage11_2DArray::releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage) +{ + GLint level = index.mipIndex; + GLint layerTarget = index.layerIndex; + + LevelLayerKey key(level, layerTarget); + + if (mAssociatedImages.find(key) != mAssociatedImages.end()) + { + if (mAssociatedImages[key] != NULL && mAssociatedImages[key] != incomingImage) + { + // Ensure that the Image is still associated with this TextureStorage. This should be true. + bool imageAssociationCorrect = mAssociatedImages[key]->isAssociatedStorageValid(this); + ASSERT(imageAssociationCorrect); + + if (imageAssociationCorrect) + { + // Force the image to recover from storage before its data is overwritten. + // This will reset mAssociatedImages[level] to NULL too. + gl::Error error = mAssociatedImages[key]->recoverFromAssociatedStorage(); + if (error.isError()) + { + return error; + } + } + } + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage11_2DArray::getResource(ID3D11Resource **outResource) +{ + // if the width, height or depth is not positive this should be treated as an incomplete texture + // we handle that here by skipping the d3d texture creation + if (mTexture == NULL && mTextureWidth > 0 && mTextureHeight > 0 && mTextureDepth > 0) + { + ASSERT(mMipLevels > 0); + + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_TEXTURE2D_DESC desc; + desc.Width = mTextureWidth; + desc.Height = mTextureHeight; + desc.MipLevels = mMipLevels; + desc.ArraySize = mTextureDepth; + 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(); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create 2D array texture storage, result: 0x%X.", result); + } + else if (FAILED(result)) + { + ASSERT(result == E_OUTOFMEMORY); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create 2D array texture storage, result: 0x%X.", result); + } + } + + *outResource = mTexture; + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage11_2DArray::createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture, + ID3D11ShaderResourceView **outSRV) const +{ + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; + srvDesc.Format = format; + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; + srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + baseLevel; + srvDesc.Texture2DArray.MipLevels = mipLevels; + srvDesc.Texture2DArray.FirstArraySlice = 0; + srvDesc.Texture2DArray.ArraySize = mTextureDepth; + + ID3D11Device *device = mRenderer->getDevice(); + HRESULT result = device->CreateShaderResourceView(texture, &srvDesc, outSRV); + + ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal texture storage SRV, result: 0x%X.", result); + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage11_2DArray::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) +{ + ASSERT(index.hasLayer()); + + int mipLevel = index.mipIndex; + int layer = index.layerIndex; + + ASSERT(mipLevel >= 0 && mipLevel < getLevelCount()); + + LevelLayerKey key(mipLevel, layer); + if (mRenderTargets.find(key) == mRenderTargets.end()) + { + ID3D11Device *device = mRenderer->getDevice(); + HRESULT result; + + ID3D11Resource *texture = NULL; + gl::Error error = getResource(&texture); + if (error.isError()) + { + return error; + } + + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; + srvDesc.Format = mShaderResourceFormat; + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; + srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + mipLevel; + srvDesc.Texture2DArray.MipLevels = 1; + srvDesc.Texture2DArray.FirstArraySlice = layer; + srvDesc.Texture2DArray.ArraySize = 1; + + ID3D11ShaderResourceView *srv; + result = device->CreateShaderResourceView(texture, &srvDesc, &srv); + + ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal shader resource view for texture storage, result: 0x%X.", result); + } + + if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN) + { + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = mRenderTargetFormat; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; + rtvDesc.Texture2DArray.MipSlice = mTopLevel + mipLevel; + rtvDesc.Texture2DArray.FirstArraySlice = layer; + rtvDesc.Texture2DArray.ArraySize = 1; + + ID3D11RenderTargetView *rtv; + result = device->CreateRenderTargetView(texture, &rtvDesc, &rtv); + + ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); + if (FAILED(result)) + { + SafeRelease(srv); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal render target view for texture storage, result: 0x%X.", result); + } + + mRenderTargets[key] = new TextureRenderTarget11(rtv, texture, srv, mInternalFormat, getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1, 0); + + // RenderTarget will take ownership of these resources + SafeRelease(rtv); + SafeRelease(srv); + } + else + { + UNREACHABLE(); + } + } + + ASSERT(outRT); + *outRT = mRenderTargets[key]; + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage11_2DArray::getSwizzleTexture(ID3D11Resource **outTexture) +{ + if (!mSwizzleTexture) + { + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_TEXTURE2D_DESC desc; + desc.Width = mTextureWidth; + desc.Height = mTextureHeight; + desc.MipLevels = mMipLevels; + desc.ArraySize = mTextureDepth; + desc.Format = mSwizzleTextureFormat; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET; + desc.CPUAccessFlags = 0; + desc.MiscFlags = 0; + + HRESULT result = device->CreateTexture2D(&desc, NULL, &mSwizzleTexture); + + ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal swizzle texture, result: 0x%X.", result); + } + } + + *outTexture = mSwizzleTexture; + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage11_2DArray::getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV) +{ + ASSERT(mipLevel >= 0 && mipLevel < getLevelCount()); + ASSERT(outRTV); + + if (!mSwizzleRenderTargets[mipLevel]) + { + ID3D11Resource *swizzleTexture = NULL; + gl::Error error = getSwizzleTexture(&swizzleTexture); + if (error.isError()) + { + return error; + } + + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = mSwizzleRenderTargetFormat; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; + rtvDesc.Texture2DArray.MipSlice = mTopLevel + mipLevel; + rtvDesc.Texture2DArray.FirstArraySlice = 0; + rtvDesc.Texture2DArray.ArraySize = mTextureDepth; + + HRESULT result = device->CreateRenderTargetView(mSwizzleTexture, &rtvDesc, &mSwizzleRenderTargets[mipLevel]); + + ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal swizzle render target view, result: 0x%X.", result); + } + } + + *outRTV = mSwizzleRenderTargets[mipLevel]; + return gl::Error(GL_NO_ERROR); +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.h new file mode 100644 index 0000000000..456e2660f9 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.h @@ -0,0 +1,326 @@ +// +// 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. +// + +// 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 LIBANGLE_RENDERER_D3D_D3D11_TEXTURESTORAGE11_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_TEXTURESTORAGE11_H_ + +#include "libANGLE/Texture.h" +#include "libANGLE/Error.h" +#include "libANGLE/renderer/d3d/TextureStorage.h" + +#include + +namespace gl +{ +struct ImageIndex; +} + +namespace rx +{ +class RenderTargetD3D; +class RenderTarget11; +class Renderer11; +class SwapChain11; +class Image11; + +class TextureStorage11 : public TextureStorage +{ + public: + virtual ~TextureStorage11(); + + static TextureStorage11 *makeTextureStorage11(TextureStorage *storage); + + static DWORD GetTextureBindFlags(GLenum internalFormat, D3D_FEATURE_LEVEL featureLevel, bool renderTarget); + + UINT getBindFlags() const; + + virtual gl::Error getResource(ID3D11Resource **outResource) = 0; + virtual gl::Error getSRV(const gl::SamplerState &samplerState, ID3D11ShaderResourceView **outSRV); + virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) = 0; + + virtual gl::Error generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex); + + virtual int getTopLevel() const; + virtual bool isRenderTarget() const; + virtual bool isManaged() const; + virtual int getLevelCount() const; + virtual UINT getSubresourceIndex(const gl::ImageIndex &index) const; + + gl::Error generateSwizzles(GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha); + void invalidateSwizzleCacheLevel(int mipLevel); + void invalidateSwizzleCache(); + + gl::Error updateSubresourceLevel(ID3D11Resource *texture, unsigned int sourceSubresource, + const gl::ImageIndex &index, const gl::Box ©Area); + + gl::Error copySubresourceLevel(ID3D11Resource* dstTexture, unsigned int dstSubresource, + const gl::ImageIndex &index, const gl::Box ®ion); + + virtual void associateImage(Image11* image, const gl::ImageIndex &index) = 0; + virtual void disassociateImage(const gl::ImageIndex &index, Image11* expectedImage) = 0; + virtual bool isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage) = 0; + virtual gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage) = 0; + + virtual gl::Error copyToStorage(TextureStorage *destStorage); + virtual gl::Error setData(const gl::ImageIndex &index, ImageD3D *image, const gl::Box *destBox, GLenum type, + const gl::PixelUnpackState &unpack, const uint8_t *pixelData); + + protected: + TextureStorage11(Renderer11 *renderer, UINT bindFlags); + int getLevelWidth(int mipLevel) const; + int getLevelHeight(int mipLevel) const; + int getLevelDepth(int mipLevel) const; + + // Some classes (e.g. TextureStorage11_2D) will override getMippedResource. + virtual gl::Error getMippedResource(ID3D11Resource **outResource) { return getResource(outResource); } + + virtual gl::Error getSwizzleTexture(ID3D11Resource **outTexture) = 0; + virtual gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV) = 0; + gl::Error getSRVLevel(int mipLevel, ID3D11ShaderResourceView **outSRV); + + virtual gl::Error createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture, + ID3D11ShaderResourceView **outSRV) const = 0; + + void verifySwizzleExists(GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha); + + Renderer11 *mRenderer; + int mTopLevel; + unsigned int mMipLevels; + + GLenum mInternalFormat; + DXGI_FORMAT mTextureFormat; + DXGI_FORMAT mShaderResourceFormat; + DXGI_FORMAT mRenderTargetFormat; + DXGI_FORMAT mDepthStencilFormat; + DXGI_FORMAT mSwizzleTextureFormat; + DXGI_FORMAT mSwizzleShaderResourceFormat; + DXGI_FORMAT mSwizzleRenderTargetFormat; + unsigned int mTextureWidth; + unsigned int mTextureHeight; + unsigned int mTextureDepth; + + struct SwizzleCacheValue + { + GLenum swizzleRed; + GLenum swizzleGreen; + GLenum swizzleBlue; + GLenum swizzleAlpha; + + SwizzleCacheValue(); + SwizzleCacheValue(GLenum red, GLenum green, GLenum blue, GLenum alpha); + + bool operator ==(const SwizzleCacheValue &other) const; + bool operator !=(const SwizzleCacheValue &other) const; + }; + SwizzleCacheValue mSwizzleCache[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + + private: + const UINT mBindFlags; + + struct SRVKey + { + SRVKey(int baseLevel = 0, int mipLevels = 0, bool swizzle = false); + + bool operator<(const SRVKey &rhs) const; + + int baseLevel; + int mipLevels; + bool swizzle; + }; + typedef std::map SRVCache; + + SRVCache mSrvCache; + ID3D11ShaderResourceView *mLevelSRVs[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; +}; + +class TextureStorage11_2D : public TextureStorage11 +{ + public: + TextureStorage11_2D(Renderer11 *renderer, SwapChain11 *swapchain); + TextureStorage11_2D(Renderer11 *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels, bool hintLevelZeroOnly = false); + virtual ~TextureStorage11_2D(); + + static TextureStorage11_2D *makeTextureStorage11_2D(TextureStorage *storage); + + virtual gl::Error getResource(ID3D11Resource **outResource); + virtual gl::Error getMippedResource(ID3D11Resource **outResource); + virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT); + + virtual gl::Error copyToStorage(TextureStorage *destStorage); + + virtual void associateImage(Image11* image, const gl::ImageIndex &index); + virtual void disassociateImage(const gl::ImageIndex &index, Image11* expectedImage); + virtual bool isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage); + virtual gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage); + + virtual gl::Error useLevelZeroWorkaroundTexture(bool useLevelZeroTexture); + + protected: + virtual gl::Error getSwizzleTexture(ID3D11Resource **outTexture); + virtual gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV); + + gl::Error ensureTextureExists(int mipLevels); + + private: + virtual gl::Error createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture, + ID3D11ShaderResourceView **outSRV) const; + + ID3D11Texture2D *mTexture; + RenderTarget11 *mRenderTarget[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + + // These are members related to the zero max-LOD workaround. + // D3D11 Feature Level 9_3 can't disable mipmaps on a mipmapped texture (i.e. solely sample from level zero). + // These members are used to work around this limitation. + // Usually only mTexture XOR mLevelZeroTexture will exist. + // For example, if an app creates a texture with only one level, then 9_3 will only create mLevelZeroTexture. + // However, in some scenarios, both textures have to be created. This incurs additional memory overhead. + // One example of this is an application that creates a texture, calls glGenerateMipmap, and then disables mipmaps on the texture. + // A more likely example is an app that creates an empty texture, renders to it, and then calls glGenerateMipmap + // TODO: In this rendering scenario, release the mLevelZeroTexture after mTexture has been created to save memory. + ID3D11Texture2D *mLevelZeroTexture; + RenderTarget11 *mLevelZeroRenderTarget; + bool mUseLevelZeroTexture; + + // Swizzle-related variables + ID3D11Texture2D *mSwizzleTexture; + ID3D11RenderTargetView *mSwizzleRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + + Image11 *mAssociatedImages[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; +}; + +class TextureStorage11_Cube : public TextureStorage11 +{ + public: + TextureStorage11_Cube(Renderer11 *renderer, GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly); + virtual ~TextureStorage11_Cube(); + + static TextureStorage11_Cube *makeTextureStorage11_Cube(TextureStorage *storage); + + virtual UINT getSubresourceIndex(const gl::ImageIndex &index) const; + + virtual gl::Error getResource(ID3D11Resource **outResource); + virtual gl::Error getMippedResource(ID3D11Resource **outResource); + virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT); + + virtual gl::Error copyToStorage(TextureStorage *destStorage); + + virtual void associateImage(Image11* image, const gl::ImageIndex &index); + virtual void disassociateImage(const gl::ImageIndex &index, Image11* expectedImage); + virtual bool isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage); + virtual gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage); + + virtual gl::Error useLevelZeroWorkaroundTexture(bool useLevelZeroTexture); + + protected: + virtual gl::Error getSwizzleTexture(ID3D11Resource **outTexture); + virtual gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV); + + gl::Error ensureTextureExists(int mipLevels); + + private: + virtual gl::Error createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture, + ID3D11ShaderResourceView **outSRV) const; + + static const size_t CUBE_FACE_COUNT = 6; + + ID3D11Texture2D *mTexture; + RenderTarget11 *mRenderTarget[CUBE_FACE_COUNT][gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + + // Level-zero workaround members. See TextureStorage11_2D's workaround members for a description. + ID3D11Texture2D *mLevelZeroTexture; + RenderTarget11 *mLevelZeroRenderTarget[CUBE_FACE_COUNT]; + bool mUseLevelZeroTexture; + + ID3D11Texture2D *mSwizzleTexture; + ID3D11RenderTargetView *mSwizzleRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + + Image11 *mAssociatedImages[CUBE_FACE_COUNT][gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; +}; + +class TextureStorage11_3D : public TextureStorage11 +{ + public: + TextureStorage11_3D(Renderer11 *renderer, GLenum internalformat, bool renderTarget, + GLsizei width, GLsizei height, GLsizei depth, int levels); + virtual ~TextureStorage11_3D(); + + static TextureStorage11_3D *makeTextureStorage11_3D(TextureStorage *storage); + + virtual gl::Error getResource(ID3D11Resource **outResource); + + // Handles both layer and non-layer RTs + virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT); + + virtual void associateImage(Image11* image, const gl::ImageIndex &index); + virtual void disassociateImage(const gl::ImageIndex &index, Image11* expectedImage); + virtual bool isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage); + virtual gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage); + + protected: + virtual gl::Error getSwizzleTexture(ID3D11Resource **outTexture); + virtual gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV); + + private: + virtual gl::Error createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture, + ID3D11ShaderResourceView **outSRV) const; + + typedef std::pair LevelLayerKey; + typedef std::map RenderTargetMap; + RenderTargetMap mLevelLayerRenderTargets; + + RenderTarget11 *mLevelRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + + ID3D11Texture3D *mTexture; + ID3D11Texture3D *mSwizzleTexture; + ID3D11RenderTargetView *mSwizzleRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + + Image11 *mAssociatedImages[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; +}; + +class TextureStorage11_2DArray : public TextureStorage11 +{ + public: + TextureStorage11_2DArray(Renderer11 *renderer, GLenum internalformat, bool renderTarget, + GLsizei width, GLsizei height, GLsizei depth, int levels); + virtual ~TextureStorage11_2DArray(); + + static TextureStorage11_2DArray *makeTextureStorage11_2DArray(TextureStorage *storage); + + virtual gl::Error getResource(ID3D11Resource **outResource); + virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT); + + virtual void associateImage(Image11* image, const gl::ImageIndex &index); + virtual void disassociateImage(const gl::ImageIndex &index, Image11* expectedImage); + virtual bool isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage); + virtual gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage); + + protected: + virtual gl::Error getSwizzleTexture(ID3D11Resource **outTexture); + virtual gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV); + + private: + virtual gl::Error createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture, + ID3D11ShaderResourceView **outSRV) const; + + typedef std::pair LevelLayerKey; + typedef std::map RenderTargetMap; + RenderTargetMap mRenderTargets; + + ID3D11Texture2D *mTexture; + + ID3D11Texture2D *mSwizzleTexture; + ID3D11RenderTargetView *mSwizzleRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + + typedef std::map ImageMap; + ImageMap mAssociatedImages; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_D3D11_TEXTURESTORAGE11_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Trim11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Trim11.cpp new file mode 100644 index 0000000000..213ce31817 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Trim11.cpp @@ -0,0 +1,95 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Trim11.cpp: Trim support utility class. + +#include "libANGLE/renderer/d3d/d3d11/Trim11.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" + +#if defined (ANGLE_ENABLE_WINDOWS_STORE) +using namespace ABI::Windows::Foundation; +using namespace ABI::Windows::ApplicationModel; +using namespace ABI::Windows::ApplicationModel::Core; +#endif + +namespace rx +{ + +Trim11::Trim11(rx::Renderer11 *renderer) + : mRenderer(renderer) +{ + bool result = true; + result = registerForRendererTrimRequest(); + ASSERT(result); +} + +Trim11::~Trim11() +{ + unregisterForRendererTrimRequest(); +} + +void Trim11::trim() +{ + if (!mRenderer) + { + return; + } + +#if defined (ANGLE_ENABLE_WINDOWS_STORE) + ID3D11Device* device = mRenderer->getDevice(); + // IDXGIDevice3 is only supported on Windows 8.1 and Windows Phone 8.1 and above. + IDXGIDevice3 *dxgiDevice3 = d3d11::DynamicCastComObject(device); + if (dxgiDevice3) + { + dxgiDevice3->Trim(); + } + SafeRelease(dxgiDevice3); +#endif +} + +bool Trim11::registerForRendererTrimRequest() +{ +#if defined (ANGLE_ENABLE_WINDOWS_STORE) + ICoreApplication* coreApplication = nullptr; + HRESULT result = GetActivationFactory(HStringReference(RuntimeClass_Windows_ApplicationModel_Core_CoreApplication).Get(), &coreApplication); + if (SUCCEEDED(result)) + { + auto suspendHandler = Callback>( + [this](IInspectable*, ISuspendingEventArgs*) -> HRESULT + { + trim(); + return S_OK; + }); + result = coreApplication->add_Suspending(suspendHandler.Get(), &mApplicationSuspendedEventToken); + } + SafeRelease(coreApplication); + + if (FAILED(result)) + { + return false; + } +#endif + return true; +} + +void Trim11::unregisterForRendererTrimRequest() +{ +#if defined (ANGLE_ENABLE_WINDOWS_STORE) + if (mApplicationSuspendedEventToken.value != 0) + { + ICoreApplication* coreApplication = nullptr; + if (SUCCEEDED(GetActivationFactory(HStringReference(RuntimeClass_Windows_ApplicationModel_Core_CoreApplication).Get(), &coreApplication))) + { + coreApplication->remove_Suspending(mApplicationSuspendedEventToken); + } + mApplicationSuspendedEventToken.value = 0; + SafeRelease(coreApplication); + } +#endif +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Trim11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Trim11.h new file mode 100644 index 0000000000..f232ad7e8e --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Trim11.h @@ -0,0 +1,43 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Trim11.h: Trim support utility class. + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_TRIM11_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_TRIM11_H_ + +#include "common/angleutils.h" +#include "libANGLE/angletypes.h" +#include "libANGLE/Error.h" + +#if !defined(ANGLE_ENABLE_WINDOWS_STORE) +typedef void* EventRegistrationToken; +#else +#include +#endif + +namespace rx +{ +class Renderer11; + +class Trim11 : angle::NonCopyable +{ + public: + explicit Trim11(Renderer11 *renderer); + ~Trim11(); + + private: + Renderer11 *mRenderer; + EventRegistrationToken mApplicationSuspendedEventToken; + + void trim(); + bool registerForRendererTrimRequest(); + void unregisterForRendererTrimRequest(); +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_D3D11_TRIM11_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexArray11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexArray11.h new file mode 100644 index 0000000000..78aad7d106 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexArray11.h @@ -0,0 +1,40 @@ +// +// Copyright 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// VertexArray11.h: Defines the rx::VertexArray11 class which implements rx::VertexArrayImpl. + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_VERTEXARRAY11_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_VERTEXARRAY11_H_ + +#include "libANGLE/renderer/VertexArrayImpl.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" + +namespace rx +{ +class Renderer11; + +class VertexArray11 : public VertexArrayImpl +{ + public: + VertexArray11(Renderer11 *renderer) + : VertexArrayImpl(), + mRenderer(renderer) + { + } + virtual ~VertexArray11() { } + + virtual void setElementArrayBuffer(const gl::Buffer *buffer) { } + virtual void setAttribute(size_t idx, const gl::VertexAttribute &attr) { } + virtual void setAttributeDivisor(size_t idx, GLuint divisor) { } + virtual void enableAttribute(size_t idx, bool enabledState) { } + + private: + Renderer11 *mRenderer; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_D3D11_VERTEXARRAY11_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.cpp new file mode 100644 index 0000000000..adc64cef5e --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.cpp @@ -0,0 +1,244 @@ +// +// 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 "libANGLE/renderer/d3d/d3d11/VertexBuffer11.h" +#include "libANGLE/renderer/d3d/d3d11/Buffer11.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" +#include "libANGLE/renderer/d3d/d3d11/formatutils11.h" +#include "libANGLE/Buffer.h" +#include "libANGLE/VertexAttribute.h" + +namespace rx +{ + +VertexBuffer11::VertexBuffer11(Renderer11 *const renderer) : mRenderer(renderer) +{ + mBuffer = NULL; + mBufferSize = 0; + mDynamicUsage = false; + mMappedResourceData = NULL; +} + +VertexBuffer11::~VertexBuffer11() +{ + ASSERT(mMappedResourceData == NULL); + SafeRelease(mBuffer); +} + +gl::Error VertexBuffer11::initialize(unsigned int size, bool dynamicUsage) +{ + SafeRelease(mBuffer); + + 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 gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal vertex buffer of size, %lu.", size); + } + } + + mBufferSize = size; + mDynamicUsage = dynamicUsage; + + return gl::Error(GL_NO_ERROR); +} + +VertexBuffer11 *VertexBuffer11::makeVertexBuffer11(VertexBuffer *vetexBuffer) +{ + ASSERT(HAS_DYNAMIC_TYPE(VertexBuffer11*, vetexBuffer)); + return static_cast(vetexBuffer); +} + +gl::Error VertexBuffer11::mapResource() +{ + if (mMappedResourceData == NULL) + { + ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); + + D3D11_MAPPED_SUBRESOURCE mappedResource; + + HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mappedResource); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal vertex buffer, HRESULT: 0x%08x.", result); + } + + mMappedResourceData = reinterpret_cast(mappedResource.pData); + } + + return gl::Error(GL_NO_ERROR); +} + +void VertexBuffer11::hintUnmapResource() +{ + if (mMappedResourceData != NULL) + { + ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); + dxContext->Unmap(mBuffer, 0); + + mMappedResourceData = NULL; + } +} + +gl::Error VertexBuffer11::storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData ¤tValue, + GLint start, GLsizei count, GLsizei instances, unsigned int offset) +{ + if (!mBuffer) + { + return gl::Error(GL_OUT_OF_MEMORY, "Internal vertex buffer is not initialized."); + } + + gl::Buffer *buffer = attrib.buffer.get(); + int inputStride = ComputeVertexAttributeStride(attrib); + + // This will map the resource if it isn't already mapped. + gl::Error error = mapResource(); + if (error.isError()) + { + return error; + } + + uint8_t *output = mMappedResourceData + offset; + + const uint8_t *input = NULL; + if (attrib.enabled) + { + if (buffer) + { + BufferD3D *storage = GetImplAs(buffer); + error = storage->getData(&input); + if (error.isError()) + { + return error; + } + input += static_cast(attrib.offset); + } + else + { + input = static_cast(attrib.pointer); + } + } + else + { + input = reinterpret_cast(currentValue.FloatValues); + } + + if (instances == 0 || attrib.divisor == 0) + { + input += inputStride * start; + } + + gl::VertexFormat vertexFormat(attrib, currentValue.Type); + const d3d11::VertexFormat &vertexFormatInfo = d3d11::GetVertexFormatInfo(vertexFormat, mRenderer->getFeatureLevel()); + ASSERT(vertexFormatInfo.copyFunction != NULL); + vertexFormatInfo.copyFunction(input, inputStride, count, output); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error VertexBuffer11::getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, + GLsizei instances, unsigned int *outSpaceRequired) const +{ + unsigned int elementCount = 0; + if (attrib.enabled) + { + if (instances == 0 || attrib.divisor == 0) + { + elementCount = count; + } + else + { + // Round up to divisor, if possible + elementCount = UnsignedCeilDivide(static_cast(instances), attrib.divisor); + } + + gl::VertexFormat vertexFormat(attrib); + const d3d11::VertexFormat &vertexFormatInfo = d3d11::GetVertexFormatInfo(vertexFormat, mRenderer->getFeatureLevel()); + const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(vertexFormatInfo.nativeFormat); + unsigned int elementSize = dxgiFormatInfo.pixelBytes; + if (elementSize <= std::numeric_limits::max() / elementCount) + { + if (outSpaceRequired) + { + *outSpaceRequired = elementSize * elementCount; + } + return gl::Error(GL_NO_ERROR); + } + else + { + return gl::Error(GL_OUT_OF_MEMORY, "New vertex buffer size would result in an overflow."); + } + } + else + { + const unsigned int elementSize = 4; + if (outSpaceRequired) + { + *outSpaceRequired = elementSize * 4; + } + return gl::Error(GL_NO_ERROR); + } +} + +unsigned int VertexBuffer11::getBufferSize() const +{ + return mBufferSize; +} + +gl::Error VertexBuffer11::setBufferSize(unsigned int size) +{ + if (size > mBufferSize) + { + return initialize(size, mDynamicUsage); + } + else + { + return gl::Error(GL_NO_ERROR); + } +} + +gl::Error VertexBuffer11::discard() +{ + if (!mBuffer) + { + return gl::Error(GL_OUT_OF_MEMORY, "Internal vertex buffer is not initialized."); + } + + ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); + + D3D11_MAPPED_SUBRESOURCE mappedResource; + HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal buffer for discarding, HRESULT: 0x%08x", result); + } + + dxContext->Unmap(mBuffer, 0); + + return gl::Error(GL_NO_ERROR); +} + +ID3D11Buffer *VertexBuffer11::getBuffer() const +{ + return mBuffer; +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.h new file mode 100644 index 0000000000..2450e8955c --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.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. +// + +// VertexBuffer11.h: Defines the D3D11 VertexBuffer implementation. + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_VERTEXBUFFER11_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_VERTEXBUFFER11_H_ + +#include + +#include "libANGLE/renderer/d3d/VertexBuffer.h" + +namespace rx +{ +class Renderer11; + +class VertexBuffer11 : public VertexBuffer +{ + public: + explicit VertexBuffer11(Renderer11 *const renderer); + virtual ~VertexBuffer11(); + + virtual gl::Error initialize(unsigned int size, bool dynamicUsage); + + static VertexBuffer11 *makeVertexBuffer11(VertexBuffer *vetexBuffer); + + virtual gl::Error storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData ¤tValue, + GLint start, GLsizei count, GLsizei instances, unsigned int offset); + + virtual gl::Error getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances, + unsigned int *outSpaceRequired) const; + + virtual unsigned int getBufferSize() const; + virtual gl::Error setBufferSize(unsigned int size); + virtual gl::Error discard(); + + virtual void hintUnmapResource(); + + ID3D11Buffer *getBuffer() const; + + private: + gl::Error mapResource(); + + Renderer11 *const mRenderer; + + ID3D11Buffer *mBuffer; + unsigned int mBufferSize; + bool mDynamicUsage; + + uint8_t *mMappedResourceData; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_D3D11_VERTEXBUFFER11_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/copyvertex.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/copyvertex.h new file mode 100644 index 0000000000..5501e361f1 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/copyvertex.h @@ -0,0 +1,40 @@ +// +// Copyright (c) 2013-2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// copyvertex.h: Defines D3D11 vertex buffer copying and conversion functions + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_COPYVERTEX_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_COPYVERTEX_H_ + +#include "common/mathutil.h" + +namespace rx +{ + +// 'alphaDefaultValueBits' gives the default value for the alpha channel (4th component) +template +inline void CopyNativeVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output); + +template +inline void Copy8SintTo16SintVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output); + +template +inline void Copy8SnormTo16SnormVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output); + +template +inline void Copy32FixedTo32FVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output); + +template +inline void CopyTo32FVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output); + +template +inline void CopyXYZ10W2ToXYZW32FVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output); + +} + +#include "copyvertex.inl" + +#endif // LIBANGLE_RENDERER_D3D_D3D11_COPYVERTEX_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/copyvertex.inl b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/copyvertex.inl new file mode 100644 index 0000000000..60678d7b9f --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/copyvertex.inl @@ -0,0 +1,377 @@ +// +// Copyright (c) 2014-2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +namespace rx +{ + +template +inline void CopyNativeVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output) +{ + const size_t attribSize = sizeof(T)* inputComponentCount; + + if (attribSize == stride && inputComponentCount == outputComponentCount) + { + memcpy(output, input, count * attribSize); + } + else + { + const T defaultAlphaValue = gl::bitCast(alphaDefaultValueBits); + const size_t lastNonAlphaOutputComponent = std::min(outputComponentCount, 3); + + for (size_t i = 0; i < count; i++) + { + const T *offsetInput = reinterpret_cast(input + (i * stride)); + T *offsetOutput = reinterpret_cast(output) + i * outputComponentCount; + + for (size_t j = 0; j < inputComponentCount; j++) + { + offsetOutput[j] = offsetInput[j]; + } + + for (size_t j = inputComponentCount; j < lastNonAlphaOutputComponent; j++) + { + // Set the remaining G/B channels to 0. + offsetOutput[j] = 0; + } + + if (inputComponentCount < outputComponentCount && outputComponentCount == 4) + { + // Set the remaining alpha channel to the defaultAlphaValue. + offsetOutput[3] = defaultAlphaValue; + } + } + } +} + +template +inline void Copy8SintTo16SintVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output) +{ + const size_t lastNonAlphaOutputComponent = std::min(outputComponentCount, 3); + + for (size_t i = 0; i < count; i++) + { + const GLbyte *offsetInput = reinterpret_cast(input + i * stride); + GLshort *offsetOutput = reinterpret_cast(output)+i * outputComponentCount; + + for (size_t j = 0; j < inputComponentCount; j++) + { + offsetOutput[j] = static_cast(offsetInput[j]); + } + + for (size_t j = inputComponentCount; j < lastNonAlphaOutputComponent; j++) + { + // Set remaining G/B channels to 0. + offsetOutput[j] = 0; + } + + if (inputComponentCount < outputComponentCount && outputComponentCount == 4) + { + // On integer formats, we must set the Alpha channel to 1 if it's unused. + offsetOutput[3] = 1; + } + } +} + +template +inline void Copy8SnormTo16SnormVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output) +{ + for (size_t i = 0; i < count; i++) + { + const GLbyte *offsetInput = reinterpret_cast(input + i * stride); + GLshort *offsetOutput = reinterpret_cast(output) + i * outputComponentCount; + + for (size_t j = 0; j < inputComponentCount; j++) + { + // The original GLbyte value ranges from -128 to +127 (INT8_MAX). + // When converted to GLshort, the value must be scaled to between -32768 and +32767 (INT16_MAX). + if (offsetInput[j] > 0) + { + offsetOutput[j] = offsetInput[j] << 8 | offsetInput[j] << 1 | ((offsetInput[j] & 0x40) >> 6); + } + else + { + offsetOutput[j] = offsetInput[j] << 8; + } + } + + for (size_t j = inputComponentCount; j < std::min(outputComponentCount, 3); j++) + { + // Set remaining G/B channels to 0. + offsetOutput[j] = 0; + } + + if (inputComponentCount < outputComponentCount && outputComponentCount == 4) + { + // On normalized formats, we must set the Alpha channel to the max value if it's unused. + offsetOutput[3] = INT16_MAX; + } + } +} + +template +inline void Copy32FixedTo32FVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output) +{ + static const float divisor = 1.0f / (1 << 16); + + for (size_t i = 0; i < count; i++) + { + const GLfixed* offsetInput = reinterpret_cast(input + (stride * i)); + float* offsetOutput = reinterpret_cast(output) + i * outputComponentCount; + + for (size_t j = 0; j < inputComponentCount; j++) + { + offsetOutput[j] = static_cast(offsetInput[j]) * divisor; + } + + // 4-component output formats would need special padding in the alpha channel. + static_assert(!(inputComponentCount < 4 && outputComponentCount == 4), + "An inputComponentCount less than 4 and an outputComponentCount equal to 4 is not supported."); + + for (size_t j = inputComponentCount; j < outputComponentCount; j++) + { + offsetOutput[j] = 0.0f; + } + } +} + +template +inline void CopyTo32FVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output) +{ + typedef std::numeric_limits NL; + + for (size_t i = 0; i < count; i++) + { + const T *offsetInput = reinterpret_cast(input + (stride * i)); + float *offsetOutput = reinterpret_cast(output) + i * outputComponentCount; + + for (size_t j = 0; j < inputComponentCount; 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]); + } + } + + // This would require special padding. + static_assert(!(inputComponentCount < 4 && outputComponentCount == 4), + "An inputComponentCount less than 4 and an outputComponentCount equal to 4 is not supported."); + + for (size_t j = inputComponentCount; j < outputComponentCount; j++) + { + offsetOutput[j] = 0.0f; + } + } +} + +namespace priv +{ + +template +static inline void CopyPackedRGB(uint32_t data, uint8_t *output) +{ + const uint32_t rgbSignMask = 0x200; // 1 set at the 9 bit + const uint32_t negativeMask = 0xFFFFFC00; // All bits from 10 to 31 set to 1 + + if (toFloat) + { + GLfloat *floatOutput = reinterpret_cast(output); + if (isSigned) + { + GLfloat finalValue = 0; + if (data & rgbSignMask) + { + int negativeNumber = data | negativeMask; + finalValue = static_cast(negativeNumber); + } + else + { + finalValue = static_cast(data); + } + + if (normalized) + { + const int32_t maxValue = 0x1FF; // 1 set in bits 0 through 8 + const int32_t minValue = 0xFFFFFE01; // Inverse of maxValue + + // A 10-bit two's complement number has the possibility of being minValue - 1 but + // OpenGL's normalization rules dictate that it should be clamped to minValue in this + // case. + if (finalValue < minValue) + { + finalValue = minValue; + } + + const int32_t halfRange = (maxValue - minValue) >> 1; + *floatOutput = ((finalValue - minValue) / halfRange) - 1.0f; + } + else + { + *floatOutput = finalValue; + } + } + else + { + if (normalized) + { + const uint32_t maxValue = 0x3FF; // 1 set in bits 0 through 9 + *floatOutput = static_cast(data) / static_cast(maxValue); + } + else + { + *floatOutput = static_cast(data); + } + } + } + else + { + if (isSigned) + { + GLshort *intOutput = reinterpret_cast(output); + + if (data & rgbSignMask) + { + *intOutput = data | negativeMask; + } + else + { + *intOutput = data; + } + } + else + { + GLushort *uintOutput = reinterpret_cast(output); + *uintOutput = data; + } + } +} + +template +inline void CopyPackedAlpha(uint32_t data, uint8_t *output) +{ + if (toFloat) + { + GLfloat *floatOutput = reinterpret_cast(output); + if (isSigned) + { + if (normalized) + { + switch (data) + { + case 0x0: *floatOutput = 0.0f; break; + case 0x1: *floatOutput = 1.0f; break; + case 0x2: *floatOutput = -1.0f; break; + case 0x3: *floatOutput = -1.0f; break; + default: UNREACHABLE(); + } + } + else + { + switch (data) + { + case 0x0: *floatOutput = 0.0f; break; + case 0x1: *floatOutput = 1.0f; break; + case 0x2: *floatOutput = -2.0f; break; + case 0x3: *floatOutput = -1.0f; break; + default: UNREACHABLE(); + } + } + } + else + { + if (normalized) + { + switch (data) + { + case 0x0: *floatOutput = 0.0f / 3.0f; break; + case 0x1: *floatOutput = 1.0f / 3.0f; break; + case 0x2: *floatOutput = 2.0f / 3.0f; break; + case 0x3: *floatOutput = 3.0f / 3.0f; break; + default: UNREACHABLE(); + } + } + else + { + switch (data) + { + case 0x0: *floatOutput = 0.0f; break; + case 0x1: *floatOutput = 1.0f; break; + case 0x2: *floatOutput = 2.0f; break; + case 0x3: *floatOutput = 3.0f; break; + default: UNREACHABLE(); + } + } + } + } + else + { + if (isSigned) + { + GLshort *intOutput = reinterpret_cast(output); + switch (data) + { + case 0x0: *intOutput = 0; break; + case 0x1: *intOutput = 1; break; + case 0x2: *intOutput = -2; break; + case 0x3: *intOutput = -1; break; + default: UNREACHABLE(); + } + } + else + { + GLushort *uintOutput = reinterpret_cast(output); + switch (data) + { + case 0x0: *uintOutput = 0; break; + case 0x1: *uintOutput = 1; break; + case 0x2: *uintOutput = 2; break; + case 0x3: *uintOutput = 3; break; + default: UNREACHABLE(); + } + } + } +} + +} + +template +inline void CopyXYZ10W2ToXYZW32FVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output) +{ + const size_t outputComponentSize = toFloat ? 4 : 2; + const size_t componentCount = 4; + + const uint32_t rgbMask = 0x3FF; // 1 set in bits 0 through 9 + const size_t redShift = 0; // red is bits 0 through 9 + const size_t greenShift = 10; // green is bits 10 through 19 + const size_t blueShift = 20; // blue is bits 20 through 29 + + const uint32_t alphaMask = 0x3; // 1 set in bits 0 and 1 + const size_t alphaShift = 30; // Alpha is the 30 and 31 bits + + for (size_t i = 0; i < count; i++) + { + GLuint packedValue = *reinterpret_cast(input + (i * stride)); + uint8_t *offsetOutput = output + (i * outputComponentSize * componentCount); + + priv::CopyPackedRGB( (packedValue >> redShift) & rgbMask, offsetOutput + (0 * outputComponentSize)); + priv::CopyPackedRGB( (packedValue >> greenShift) & rgbMask, offsetOutput + (1 * outputComponentSize)); + priv::CopyPackedRGB( (packedValue >> blueShift) & rgbMask, offsetOutput + (2 * outputComponentSize)); + priv::CopyPackedAlpha((packedValue >> alphaShift) & alphaMask, offsetOutput + (3 * outputComponentSize)); + } +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.cpp new file mode 100644 index 0000000000..2f81d6d608 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.cpp @@ -0,0 +1,1328 @@ +// +// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// formatutils11.cpp: Queries for GL image formats and their translations to D3D11 +// formats. + +#include "libANGLE/renderer/d3d/d3d11/formatutils11.h" + +#include "libANGLE/formatutils.h" +#include "libANGLE/renderer/Renderer.h" +#include "libANGLE/renderer/d3d/copyimage.h" +#include "libANGLE/renderer/d3d/generatemip.h" +#include "libANGLE/renderer/d3d/loadimage.h" +#include "libANGLE/renderer/d3d/d3d11/copyvertex.h" + +namespace rx +{ + +namespace d3d11 +{ + +typedef std::map DXGIToESFormatMap; + +inline void AddDXGIToESEntry(DXGIToESFormatMap *map, DXGI_FORMAT key, GLenum value) +{ + map->insert(std::make_pair(key, value)); +} + +static DXGIToESFormatMap BuildDXGIToESFormatMap() +{ + DXGIToESFormatMap map; + + AddDXGIToESEntry(&map, DXGI_FORMAT_UNKNOWN, GL_NONE); + + AddDXGIToESEntry(&map, DXGI_FORMAT_A8_UNORM, GL_ALPHA8_EXT); + AddDXGIToESEntry(&map, DXGI_FORMAT_R8_UNORM, GL_R8); + AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8_UNORM, GL_RG8); + AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8B8A8_UNORM, GL_RGBA8); + AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, GL_SRGB8_ALPHA8); + AddDXGIToESEntry(&map, DXGI_FORMAT_B8G8R8A8_UNORM, GL_BGRA8_EXT); + + AddDXGIToESEntry(&map, DXGI_FORMAT_R8_SNORM, GL_R8_SNORM); + AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8_SNORM, GL_RG8_SNORM); + AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8B8A8_SNORM, GL_RGBA8_SNORM); + + AddDXGIToESEntry(&map, DXGI_FORMAT_R8_UINT, GL_R8UI); + AddDXGIToESEntry(&map, DXGI_FORMAT_R16_UINT, GL_R16UI); + AddDXGIToESEntry(&map, DXGI_FORMAT_R32_UINT, GL_R32UI); + AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8_UINT, GL_RG8UI); + AddDXGIToESEntry(&map, DXGI_FORMAT_R16G16_UINT, GL_RG16UI); + AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32_UINT, GL_RG32UI); + AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32B32_UINT, GL_RGB32UI); + AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8B8A8_UINT, GL_RGBA8UI); + AddDXGIToESEntry(&map, DXGI_FORMAT_R16G16B16A16_UINT, GL_RGBA16UI); + AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32B32A32_UINT, GL_RGBA32UI); + + AddDXGIToESEntry(&map, DXGI_FORMAT_R8_SINT, GL_R8I); + AddDXGIToESEntry(&map, DXGI_FORMAT_R16_SINT, GL_R16I); + AddDXGIToESEntry(&map, DXGI_FORMAT_R32_SINT, GL_R32I); + AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8_SINT, GL_RG8I); + AddDXGIToESEntry(&map, DXGI_FORMAT_R16G16_SINT, GL_RG16I); + AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32_SINT, GL_RG32I); + AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32B32_SINT, GL_RGB32I); + AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8B8A8_SINT, GL_RGBA8I); + AddDXGIToESEntry(&map, DXGI_FORMAT_R16G16B16A16_SINT, GL_RGBA16I); + AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32B32A32_SINT, GL_RGBA32I); + + AddDXGIToESEntry(&map, DXGI_FORMAT_R10G10B10A2_UNORM, GL_RGB10_A2); + AddDXGIToESEntry(&map, DXGI_FORMAT_R10G10B10A2_UINT, GL_RGB10_A2UI); + + AddDXGIToESEntry(&map, DXGI_FORMAT_R16_FLOAT, GL_R16F); + AddDXGIToESEntry(&map, DXGI_FORMAT_R16G16_FLOAT, GL_RG16F); + AddDXGIToESEntry(&map, DXGI_FORMAT_R16G16B16A16_FLOAT, GL_RGBA16F); + + AddDXGIToESEntry(&map, DXGI_FORMAT_R32_FLOAT, GL_R32F); + AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32_FLOAT, GL_RG32F); + AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32B32_FLOAT, GL_RGB32F); + AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32B32A32_FLOAT, GL_RGBA32F); + + AddDXGIToESEntry(&map, DXGI_FORMAT_R9G9B9E5_SHAREDEXP, GL_RGB9_E5); + AddDXGIToESEntry(&map, DXGI_FORMAT_R11G11B10_FLOAT, GL_R11F_G11F_B10F); + + AddDXGIToESEntry(&map, DXGI_FORMAT_R16_TYPELESS, GL_DEPTH_COMPONENT16); + AddDXGIToESEntry(&map, DXGI_FORMAT_R16_UNORM, GL_DEPTH_COMPONENT16); + AddDXGIToESEntry(&map, DXGI_FORMAT_D16_UNORM, GL_DEPTH_COMPONENT16); + AddDXGIToESEntry(&map, DXGI_FORMAT_R24G8_TYPELESS, GL_DEPTH24_STENCIL8_OES); + AddDXGIToESEntry(&map, DXGI_FORMAT_R24_UNORM_X8_TYPELESS, GL_DEPTH24_STENCIL8_OES); + AddDXGIToESEntry(&map, DXGI_FORMAT_D24_UNORM_S8_UINT, GL_DEPTH24_STENCIL8_OES); + AddDXGIToESEntry(&map, DXGI_FORMAT_R32G8X24_TYPELESS, GL_DEPTH32F_STENCIL8); + AddDXGIToESEntry(&map, DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS, GL_DEPTH32F_STENCIL8); + AddDXGIToESEntry(&map, DXGI_FORMAT_D32_FLOAT_S8X24_UINT, GL_DEPTH32F_STENCIL8); + AddDXGIToESEntry(&map, DXGI_FORMAT_R32_TYPELESS, GL_DEPTH_COMPONENT32F); + AddDXGIToESEntry(&map, DXGI_FORMAT_D32_FLOAT, GL_DEPTH_COMPONENT32F); + + AddDXGIToESEntry(&map, DXGI_FORMAT_BC1_UNORM, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT); + AddDXGIToESEntry(&map, DXGI_FORMAT_BC2_UNORM, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE); + AddDXGIToESEntry(&map, DXGI_FORMAT_BC3_UNORM, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE); + + return map; +} + +struct D3D11FastCopyFormat +{ + GLenum destFormat; + GLenum destType; + ColorCopyFunction copyFunction; + + D3D11FastCopyFormat(GLenum destFormat, GLenum destType, ColorCopyFunction copyFunction) + : destFormat(destFormat), destType(destType), copyFunction(copyFunction) + { } + + bool operator<(const D3D11FastCopyFormat& other) const + { + return memcmp(this, &other, sizeof(D3D11FastCopyFormat)) < 0; + } +}; + +typedef std::multimap D3D11FastCopyMap; + +static D3D11FastCopyMap BuildFastCopyMap() +{ + D3D11FastCopyMap map; + + map.insert(std::make_pair(DXGI_FORMAT_B8G8R8A8_UNORM, D3D11FastCopyFormat(GL_RGBA, GL_UNSIGNED_BYTE, CopyBGRA8ToRGBA8))); + + return map; +} + +struct DXGIColorFormatInfo +{ + size_t redBits; + size_t greenBits; + size_t blueBits; + + size_t luminanceBits; + + size_t alphaBits; + size_t sharedBits; +}; + +typedef std::map ColorFormatInfoMap; +typedef std::pair ColorFormatInfoPair; + +static inline void InsertDXGIColorFormatInfo(ColorFormatInfoMap *map, DXGI_FORMAT format, size_t redBits, size_t greenBits, + size_t blueBits, size_t alphaBits, size_t sharedBits) +{ + DXGIColorFormatInfo info; + info.redBits = redBits; + info.greenBits = greenBits; + info.blueBits = blueBits; + info.alphaBits = alphaBits; + info.sharedBits = sharedBits; + + map->insert(std::make_pair(format, info)); +} + +static ColorFormatInfoMap BuildColorFormatInfoMap() +{ + ColorFormatInfoMap map; + + // | DXGI format | R | G | B | A | S | + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_A8_UNORM, 0, 0, 0, 8, 0); + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8_UNORM, 8, 0, 0, 0, 0); + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8G8_UNORM, 8, 8, 0, 0, 0); + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8G8B8A8_UNORM, 8, 8, 8, 8, 0); + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, 8, 8, 8, 8, 0); + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_B8G8R8A8_UNORM, 8, 8, 8, 8, 0); + + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8_SNORM, 8, 0, 0, 0, 0); + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8G8_SNORM, 8, 8, 0, 0, 0); + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8G8B8A8_SNORM, 8, 8, 8, 8, 0); + + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8_UINT, 8, 0, 0, 0, 0); + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R16_UINT, 16, 0, 0, 0, 0); + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R32_UINT, 32, 0, 0, 0, 0); + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8G8_UINT, 8, 8, 0, 0, 0); + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R16G16_UINT, 16, 16, 0, 0, 0); + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R32G32_UINT, 32, 32, 0, 0, 0); + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R32G32B32_UINT, 32, 32, 32, 0, 0); + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8G8B8A8_UINT, 8, 8, 8, 8, 0); + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R16G16B16A16_UINT, 16, 16, 16, 16, 0); + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R32G32B32A32_UINT, 32, 32, 32, 32, 0); + + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8_SINT, 8, 0, 0, 0, 0); + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R16_SINT, 16, 0, 0, 0, 0); + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R32_SINT, 32, 0, 0, 0, 0); + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8G8_SINT, 8, 8, 0, 0, 0); + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R16G16_SINT, 16, 16, 0, 0, 0); + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R32G32_SINT, 32, 32, 0, 0, 0); + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R32G32B32_SINT, 32, 32, 32, 0, 0); + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8G8B8A8_SINT, 8, 8, 8, 8, 0); + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R16G16B16A16_SINT, 16, 16, 16, 16, 0); + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R32G32B32A32_SINT, 32, 32, 32, 32, 0); + + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R10G10B10A2_UNORM, 10, 10, 10, 2, 0); + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R10G10B10A2_UINT, 10, 10, 10, 2, 0); + + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R16_FLOAT, 16, 0, 0, 0, 0); + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R16G16_FLOAT, 16, 16, 0, 0, 0); + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R16G16B16A16_FLOAT, 16, 16, 16, 16, 0); + + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R32_FLOAT, 32, 0, 0, 0, 0); + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R32G32_FLOAT, 32, 32, 0, 0, 0); + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R32G32B32_FLOAT, 32, 32, 32, 0, 0); + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R32G32B32A32_FLOAT, 32, 32, 32, 32, 0); + + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R9G9B9E5_SHAREDEXP, 9, 9, 9, 0, 5); + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R11G11B10_FLOAT, 11, 11, 10, 0, 0); + + return map; +} + +struct DXGIDepthStencilInfo +{ + unsigned int depthBits; + unsigned int depthOffset; + unsigned int stencilBits; + unsigned int stencilOffset; +}; + +typedef std::map DepthStencilInfoMap; +typedef std::pair DepthStencilInfoPair; + +static inline void InsertDXGIDepthStencilInfo(DepthStencilInfoMap *map, DXGI_FORMAT format, unsigned int depthBits, + unsigned int depthOffset, unsigned int stencilBits, unsigned int stencilOffset) +{ + DXGIDepthStencilInfo info; + info.depthBits = depthBits; + info.depthOffset = depthOffset; + info.stencilBits = stencilBits; + info.stencilOffset = stencilOffset; + + map->insert(std::make_pair(format, info)); +} + +static DepthStencilInfoMap BuildDepthStencilInfoMap() +{ + DepthStencilInfoMap map; + + InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_R16_TYPELESS, 16, 0, 0, 0); + InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_R16_UNORM, 16, 0, 0, 0); + InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_D16_UNORM, 16, 0, 0, 0); + + InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_R24G8_TYPELESS, 24, 0, 8, 24); + InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_R24_UNORM_X8_TYPELESS, 24, 0, 8, 24); + InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_D24_UNORM_S8_UINT, 24, 0, 8, 24); + + InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_R32_TYPELESS, 32, 0, 0, 0); + InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_R32_FLOAT, 32, 0, 0, 0); + InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_D32_FLOAT, 32, 0, 0, 0); + + InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_R32G8X24_TYPELESS, 32, 0, 8, 32); + InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS, 32, 0, 8, 32); + InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_D32_FLOAT_S8X24_UINT, 32, 0, 8, 32); + + return map; +} + +typedef std::map DXGIFormatInfoMap; + +DXGIFormat::DXGIFormat() + : pixelBytes(0), + blockWidth(0), + blockHeight(0), + redBits(0), + greenBits(0), + blueBits(0), + alphaBits(0), + sharedBits(0), + depthBits(0), + depthOffset(0), + stencilBits(0), + stencilOffset(0), + internalFormat(GL_NONE), + componentType(GL_NONE), + mipGenerationFunction(NULL), + colorReadFunction(NULL), + fastCopyFunctions() +{ +} + +ColorCopyFunction DXGIFormat::getFastCopyFunction(GLenum format, GLenum type) const +{ + FastCopyFunctionMap::const_iterator iter = fastCopyFunctions.find(std::make_pair(format, type)); + return (iter != fastCopyFunctions.end()) ? iter->second : NULL; +} + +void AddDXGIFormat(DXGIFormatInfoMap *map, DXGI_FORMAT dxgiFormat, GLuint pixelBits, GLuint blockWidth, GLuint blockHeight, + GLenum componentType, MipGenerationFunction mipFunc, ColorReadFunction readFunc) +{ + DXGIFormat info; + info.pixelBytes = pixelBits / 8; + info.blockWidth = blockWidth; + info.blockHeight = blockHeight; + + static const ColorFormatInfoMap colorInfoMap = BuildColorFormatInfoMap(); + ColorFormatInfoMap::const_iterator colorInfoIter = colorInfoMap.find(dxgiFormat); + if (colorInfoIter != colorInfoMap.end()) + { + const DXGIColorFormatInfo &colorInfo = colorInfoIter->second; + info.redBits = colorInfo.redBits; + info.greenBits = colorInfo.greenBits; + info.blueBits = colorInfo.blueBits; + info.alphaBits = colorInfo.alphaBits; + info.sharedBits = colorInfo.sharedBits; + } + + static const DepthStencilInfoMap dsInfoMap = BuildDepthStencilInfoMap(); + DepthStencilInfoMap::const_iterator dsInfoIter = dsInfoMap.find(dxgiFormat); + if (dsInfoIter != dsInfoMap.end()) + { + const DXGIDepthStencilInfo &dsInfo = dsInfoIter->second; + info.depthBits = dsInfo.depthBits; + info.depthOffset = dsInfo.depthOffset; + info.stencilBits = dsInfo.stencilBits; + info.stencilOffset = dsInfo.stencilOffset; + } + + static const DXGIToESFormatMap dxgiToESMap = BuildDXGIToESFormatMap(); + DXGIToESFormatMap::const_iterator dxgiToESIter = dxgiToESMap.find(dxgiFormat); + info.internalFormat = (dxgiToESIter != dxgiToESMap.end()) ? dxgiToESIter->second : GL_NONE; + + info.componentType = componentType; + + info.mipGenerationFunction = mipFunc; + info.colorReadFunction = readFunc; + + static const D3D11FastCopyMap fastCopyMap = BuildFastCopyMap(); + std::pair fastCopyIter = fastCopyMap.equal_range(dxgiFormat); + for (D3D11FastCopyMap::const_iterator i = fastCopyIter.first; i != fastCopyIter.second; i++) + { + info.fastCopyFunctions.insert(std::make_pair(std::make_pair(i->second.destFormat, i->second.destType), i->second.copyFunction)); + } + + map->insert(std::make_pair(dxgiFormat, info)); +} + +// A map to determine the pixel size and mipmap generation function of a given DXGI format +static DXGIFormatInfoMap BuildDXGIFormatInfoMap() +{ + DXGIFormatInfoMap map; + + // | DXGI format |S |W |H |Component Type | Mip generation function | Color read function + AddDXGIFormat(&map, DXGI_FORMAT_UNKNOWN, 0, 0, 0, GL_NONE, NULL, NULL); + + AddDXGIFormat(&map, DXGI_FORMAT_A8_UNORM, 8, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R8_UNORM, 8, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R8G8_UNORM, 16, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R8G8B8A8_UNORM, 32, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, 32, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_B8G8R8A8_UNORM, 32, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip, ReadColor); + + AddDXGIFormat(&map, DXGI_FORMAT_R8_SNORM, 8, 1, 1, GL_SIGNED_NORMALIZED, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R8G8_SNORM, 16, 1, 1, GL_SIGNED_NORMALIZED, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R8G8B8A8_SNORM, 32, 1, 1, GL_SIGNED_NORMALIZED, GenerateMip, ReadColor); + + AddDXGIFormat(&map, DXGI_FORMAT_R8_UINT, 8, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R16_UINT, 16, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R32_UINT, 32, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R8G8_UINT, 16, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R16G16_UINT, 32, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R32G32_UINT, 64, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R32G32B32_UINT, 96, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R8G8B8A8_UINT, 32, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R16G16B16A16_UINT, 64, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R32G32B32A32_UINT, 128, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor); + + AddDXGIFormat(&map, DXGI_FORMAT_R8_SINT, 8, 1, 1, GL_INT, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R16_SINT, 16, 1, 1, GL_INT, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R32_SINT, 32, 1, 1, GL_INT, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R8G8_SINT, 16, 1, 1, GL_INT, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R16G16_SINT, 32, 1, 1, GL_INT, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R32G32_SINT, 64, 1, 1, GL_INT, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R32G32B32_SINT, 96, 1, 1, GL_INT, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R8G8B8A8_SINT, 32, 1, 1, GL_INT, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R16G16B16A16_SINT, 64, 1, 1, GL_INT, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R32G32B32A32_SINT, 128, 1, 1, GL_INT, GenerateMip, ReadColor); + + AddDXGIFormat(&map, DXGI_FORMAT_R10G10B10A2_UNORM, 32, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R10G10B10A2_UINT, 32, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor); + + AddDXGIFormat(&map, DXGI_FORMAT_R16_FLOAT, 16, 1, 1, GL_FLOAT, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R16G16_FLOAT, 32, 1, 1, GL_FLOAT, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R16G16B16A16_FLOAT, 64, 1, 1, GL_FLOAT, GenerateMip, ReadColor); + + AddDXGIFormat(&map, DXGI_FORMAT_R32_FLOAT, 32, 1, 1, GL_FLOAT, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R32G32_FLOAT, 64, 1, 1, GL_FLOAT, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R32G32B32_FLOAT, 96, 1, 1, GL_FLOAT, NULL, NULL); + AddDXGIFormat(&map, DXGI_FORMAT_R32G32B32A32_FLOAT, 128, 1, 1, GL_FLOAT, GenerateMip, ReadColor); + + AddDXGIFormat(&map, DXGI_FORMAT_R9G9B9E5_SHAREDEXP, 32, 1, 1, GL_FLOAT, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R11G11B10_FLOAT, 32, 1, 1, GL_FLOAT, GenerateMip, ReadColor); + + AddDXGIFormat(&map, DXGI_FORMAT_R16_TYPELESS, 16, 1, 1, GL_NONE, NULL, NULL); + AddDXGIFormat(&map, DXGI_FORMAT_R16_UNORM, 16, 1, 1, GL_UNSIGNED_NORMALIZED, NULL, NULL); + AddDXGIFormat(&map, DXGI_FORMAT_D16_UNORM, 16, 1, 1, GL_UNSIGNED_NORMALIZED, NULL, NULL); + AddDXGIFormat(&map, DXGI_FORMAT_R24G8_TYPELESS, 32, 1, 1, GL_NONE, NULL, NULL); + AddDXGIFormat(&map, DXGI_FORMAT_R24_UNORM_X8_TYPELESS, 32, 1, 1, GL_NONE, NULL, NULL); + AddDXGIFormat(&map, DXGI_FORMAT_D24_UNORM_S8_UINT, 32, 1, 1, GL_UNSIGNED_INT, NULL, NULL); + AddDXGIFormat(&map, DXGI_FORMAT_R32G8X24_TYPELESS, 64, 1, 1, GL_NONE, NULL, NULL); + AddDXGIFormat(&map, DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS, 64, 1, 1, GL_NONE, NULL, NULL); + AddDXGIFormat(&map, DXGI_FORMAT_D32_FLOAT_S8X24_UINT, 64, 1, 1, GL_UNSIGNED_INT, NULL, NULL); + AddDXGIFormat(&map, DXGI_FORMAT_R32_TYPELESS, 32, 1, 1, GL_NONE, NULL, NULL); + AddDXGIFormat(&map, DXGI_FORMAT_D32_FLOAT, 32, 1, 1, GL_FLOAT, NULL, NULL); + + AddDXGIFormat(&map, DXGI_FORMAT_BC1_UNORM, 64, 4, 4, GL_UNSIGNED_NORMALIZED, NULL, NULL); + AddDXGIFormat(&map, DXGI_FORMAT_BC2_UNORM, 128, 4, 4, GL_UNSIGNED_NORMALIZED, NULL, NULL); + AddDXGIFormat(&map, DXGI_FORMAT_BC3_UNORM, 128, 4, 4, GL_UNSIGNED_NORMALIZED, NULL, NULL); + + // Useful formats for vertex buffers + AddDXGIFormat(&map, DXGI_FORMAT_R16_UNORM, 16, 1, 1, GL_UNSIGNED_NORMALIZED, NULL, NULL); + AddDXGIFormat(&map, DXGI_FORMAT_R16_SNORM, 16, 1, 1, GL_SIGNED_NORMALIZED, NULL, NULL); + AddDXGIFormat(&map, DXGI_FORMAT_R16G16_UNORM, 32, 1, 1, GL_UNSIGNED_NORMALIZED, NULL, NULL); + AddDXGIFormat(&map, DXGI_FORMAT_R16G16_SNORM, 32, 1, 1, GL_SIGNED_NORMALIZED, NULL, NULL); + AddDXGIFormat(&map, DXGI_FORMAT_R16G16B16A16_UNORM, 64, 1, 1, GL_UNSIGNED_NORMALIZED, NULL, NULL); + AddDXGIFormat(&map, DXGI_FORMAT_R16G16B16A16_SNORM, 64, 1, 1, GL_SIGNED_NORMALIZED, NULL, NULL); + + return map; +} + +const DXGIFormat &GetDXGIFormatInfo(DXGI_FORMAT format) +{ + static const DXGIFormatInfoMap infoMap = BuildDXGIFormatInfoMap(); + DXGIFormatInfoMap::const_iterator iter = infoMap.find(format); + if (iter != infoMap.end()) + { + return iter->second; + } + else + { + static DXGIFormat defaultInfo; + return defaultInfo; + } +} + +struct SwizzleSizeType +{ + size_t maxComponentSize; + GLenum componentType; + + SwizzleSizeType() + : maxComponentSize(0), componentType(GL_NONE) + { } + + SwizzleSizeType(size_t maxComponentSize, GLenum componentType) + : maxComponentSize(maxComponentSize), componentType(componentType) + { } + + bool operator<(const SwizzleSizeType& other) const + { + return (maxComponentSize != other.maxComponentSize) ? (maxComponentSize < other.maxComponentSize) + : (componentType < other.componentType); + } +}; + +struct SwizzleFormatInfo +{ + DXGI_FORMAT mTexFormat; + DXGI_FORMAT mSRVFormat; + DXGI_FORMAT mRTVFormat; + + SwizzleFormatInfo() + : mTexFormat(DXGI_FORMAT_UNKNOWN), mSRVFormat(DXGI_FORMAT_UNKNOWN), mRTVFormat(DXGI_FORMAT_UNKNOWN) + { } + + SwizzleFormatInfo(DXGI_FORMAT texFormat, DXGI_FORMAT srvFormat, DXGI_FORMAT rtvFormat) + : mTexFormat(texFormat), mSRVFormat(srvFormat), mRTVFormat(rtvFormat) + { } +}; + +typedef std::map SwizzleInfoMap; +typedef std::pair SwizzleInfoPair; + +static SwizzleInfoMap BuildSwizzleInfoMap() +{ + SwizzleInfoMap map; + + map.insert(SwizzleInfoPair(SwizzleSizeType( 8, GL_UNSIGNED_NORMALIZED), SwizzleFormatInfo(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM ))); + map.insert(SwizzleInfoPair(SwizzleSizeType(16, GL_UNSIGNED_NORMALIZED), SwizzleFormatInfo(DXGI_FORMAT_R16G16B16A16_UNORM, DXGI_FORMAT_R16G16B16A16_UNORM, DXGI_FORMAT_R16G16B16A16_UNORM))); + map.insert(SwizzleInfoPair(SwizzleSizeType(24, GL_UNSIGNED_NORMALIZED), SwizzleFormatInfo(DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT))); + map.insert(SwizzleInfoPair(SwizzleSizeType(32, GL_UNSIGNED_NORMALIZED), SwizzleFormatInfo(DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT))); + + map.insert(SwizzleInfoPair(SwizzleSizeType( 8, GL_SIGNED_NORMALIZED ), SwizzleFormatInfo(DXGI_FORMAT_R8G8B8A8_SNORM, DXGI_FORMAT_R8G8B8A8_SNORM, DXGI_FORMAT_R8G8B8A8_SNORM ))); + + map.insert(SwizzleInfoPair(SwizzleSizeType(16, GL_FLOAT ), SwizzleFormatInfo(DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT))); + map.insert(SwizzleInfoPair(SwizzleSizeType(32, GL_FLOAT ), SwizzleFormatInfo(DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT))); + + map.insert(SwizzleInfoPair(SwizzleSizeType( 8, GL_UNSIGNED_INT ), SwizzleFormatInfo(DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_R8G8B8A8_UINT ))); + map.insert(SwizzleInfoPair(SwizzleSizeType(16, GL_UNSIGNED_INT ), SwizzleFormatInfo(DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_R16G16B16A16_UINT ))); + map.insert(SwizzleInfoPair(SwizzleSizeType(32, GL_UNSIGNED_INT ), SwizzleFormatInfo(DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_R32G32B32A32_UINT ))); + + map.insert(SwizzleInfoPair(SwizzleSizeType( 8, GL_INT ), SwizzleFormatInfo(DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_R8G8B8A8_SINT ))); + map.insert(SwizzleInfoPair(SwizzleSizeType(16, GL_INT ), SwizzleFormatInfo(DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_R16G16B16A16_SINT ))); + map.insert(SwizzleInfoPair(SwizzleSizeType(32, GL_INT ), SwizzleFormatInfo(DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_R32G32B32A32_SINT ))); + + return map; +} + +typedef std::pair InternalFormatInitializerPair; +typedef std::map InternalFormatInitializerMap; + +static InternalFormatInitializerMap BuildInternalFormatInitializerMap() +{ + InternalFormatInitializerMap map; + + map.insert(InternalFormatInitializerPair(GL_RGB8, Initialize4ComponentData )); + map.insert(InternalFormatInitializerPair(GL_RGB565, Initialize4ComponentData )); + map.insert(InternalFormatInitializerPair(GL_SRGB8, Initialize4ComponentData )); + map.insert(InternalFormatInitializerPair(GL_RGB16F, Initialize4ComponentData)); + map.insert(InternalFormatInitializerPair(GL_RGB32F, Initialize4ComponentData)); + map.insert(InternalFormatInitializerPair(GL_RGB8UI, Initialize4ComponentData )); + map.insert(InternalFormatInitializerPair(GL_RGB8I, Initialize4ComponentData )); + map.insert(InternalFormatInitializerPair(GL_RGB16UI, Initialize4ComponentData )); + map.insert(InternalFormatInitializerPair(GL_RGB16I, Initialize4ComponentData )); + map.insert(InternalFormatInitializerPair(GL_RGB32UI, Initialize4ComponentData )); + map.insert(InternalFormatInitializerPair(GL_RGB32I, Initialize4ComponentData )); + + return map; +} + +// ES3 image loading functions vary based on the internal format and data type given, +// this map type determines the loading function from the internal format and type supplied +// to glTex*Image*D and the destination DXGI_FORMAT. Source formats and types are taken from +// Tables 3.2 and 3.3 of the ES 3 spec. +typedef std::pair TypeLoadFunctionPair; +typedef std::map > D3D11LoadFunctionMap; + +static void UnimplementedLoadFunction(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + UNIMPLEMENTED(); +} + +static void UnreachableLoadFunction(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + UNREACHABLE(); +} + +// A helper function to insert data into the D3D11LoadFunctionMap with fewer characters. +static inline void InsertLoadFunction(D3D11LoadFunctionMap *map, GLenum internalFormat, GLenum type, + LoadImageFunction loadFunc) +{ + (*map)[internalFormat].push_back(TypeLoadFunctionPair(type, loadFunc)); +} + +D3D11LoadFunctionMap BuildD3D11_FL9_3_LoadFunctionMap() +{ + D3D11LoadFunctionMap map; + + // From GL_EXT_texture_storage. Also used by GL_ALPHA8 + // On feature level 9_3, A8_UNORM doesn't support mipmaps, so we must use RGBA8 instead + InsertLoadFunction(&map, GL_ALPHA8_EXT, GL_UNSIGNED_BYTE, LoadA8ToRGBA8); + + return map; +} + +D3D11LoadFunctionMap BuildD3D11_FL10_0Plus_LoadFunctionMap() +{ + D3D11LoadFunctionMap map; + + // From GL_EXT_texture_storage. Also used by GL_ALPHA8 + InsertLoadFunction(&map, GL_ALPHA8_EXT, GL_UNSIGNED_BYTE, LoadToNative); + + return map; +} + +D3D11LoadFunctionMap BuildBaseD3D11LoadFunctionMap() +{ + D3D11LoadFunctionMap map; + + // | Internal format | Type | Load function | + InsertLoadFunction(&map, GL_RGBA8, GL_UNSIGNED_BYTE, LoadToNative ); + InsertLoadFunction(&map, GL_RGB5_A1, GL_UNSIGNED_BYTE, LoadToNative ); + InsertLoadFunction(&map, GL_RGBA4, GL_UNSIGNED_BYTE, LoadToNative ); + InsertLoadFunction(&map, GL_SRGB8_ALPHA8, GL_UNSIGNED_BYTE, LoadToNative ); + InsertLoadFunction(&map, GL_RGBA8_SNORM, GL_BYTE, LoadToNative ); + InsertLoadFunction(&map, GL_RGBA4, GL_UNSIGNED_SHORT_4_4_4_4, LoadRGBA4ToRGBA8 ); + InsertLoadFunction(&map, GL_RGB10_A2, GL_UNSIGNED_INT_2_10_10_10_REV, LoadToNative ); + InsertLoadFunction(&map, GL_RGB5_A1, GL_UNSIGNED_SHORT_5_5_5_1, LoadRGB5A1ToRGBA8 ); + InsertLoadFunction(&map, GL_RGB5_A1, GL_UNSIGNED_INT_2_10_10_10_REV, LoadRGB10A2ToRGBA8 ); + InsertLoadFunction(&map, GL_RGBA16F, GL_HALF_FLOAT, LoadToNative ); + InsertLoadFunction(&map, GL_RGBA16F, GL_HALF_FLOAT_OES, LoadToNative ); + InsertLoadFunction(&map, GL_RGBA32F, GL_FLOAT, LoadToNative ); + InsertLoadFunction(&map, GL_RGBA16F, GL_FLOAT, Load32FTo16F<4> ); + InsertLoadFunction(&map, GL_RGBA8UI, GL_UNSIGNED_BYTE, LoadToNative ); + InsertLoadFunction(&map, GL_RGBA8I, GL_BYTE, LoadToNative ); + InsertLoadFunction(&map, GL_RGBA16UI, GL_UNSIGNED_SHORT, LoadToNative ); + InsertLoadFunction(&map, GL_RGBA16I, GL_SHORT, LoadToNative ); + InsertLoadFunction(&map, GL_RGBA32UI, GL_UNSIGNED_INT, LoadToNative ); + InsertLoadFunction(&map, GL_RGBA32I, GL_INT, LoadToNative ); + InsertLoadFunction(&map, GL_RGB10_A2UI, GL_UNSIGNED_INT_2_10_10_10_REV, LoadToNative ); + InsertLoadFunction(&map, GL_RGB8, GL_UNSIGNED_BYTE, LoadToNative3To4 ); + InsertLoadFunction(&map, GL_RGB565, GL_UNSIGNED_BYTE, LoadToNative3To4 ); + InsertLoadFunction(&map, GL_SRGB8, GL_UNSIGNED_BYTE, LoadToNative3To4 ); + InsertLoadFunction(&map, GL_RGB8_SNORM, GL_BYTE, LoadToNative3To4 ); + InsertLoadFunction(&map, GL_RGB565, GL_UNSIGNED_SHORT_5_6_5, LoadR5G6B5ToRGBA8 ); + InsertLoadFunction(&map, GL_R11F_G11F_B10F, GL_UNSIGNED_INT_10F_11F_11F_REV, LoadToNative ); + InsertLoadFunction(&map, GL_RGB9_E5, GL_UNSIGNED_INT_5_9_9_9_REV, LoadToNative ); + InsertLoadFunction(&map, GL_RGB16F, GL_HALF_FLOAT, LoadToNative3To4); + InsertLoadFunction(&map, GL_RGB16F, GL_HALF_FLOAT_OES, LoadToNative3To4); + InsertLoadFunction(&map, GL_R11F_G11F_B10F, GL_HALF_FLOAT, LoadRGB16FToRG11B10F ); + InsertLoadFunction(&map, GL_R11F_G11F_B10F, GL_HALF_FLOAT_OES, LoadRGB16FToRG11B10F ); + InsertLoadFunction(&map, GL_RGB9_E5, GL_HALF_FLOAT, LoadRGB16FToRGB9E5 ); + InsertLoadFunction(&map, GL_RGB9_E5, GL_HALF_FLOAT_OES, LoadRGB16FToRGB9E5 ); + InsertLoadFunction(&map, GL_RGB32F, GL_FLOAT, LoadToNative3To4); + InsertLoadFunction(&map, GL_RGB16F, GL_FLOAT, LoadRGB32FToRGBA16F ); + InsertLoadFunction(&map, GL_R11F_G11F_B10F, GL_FLOAT, LoadRGB32FToRG11B10F ); + InsertLoadFunction(&map, GL_RGB9_E5, GL_FLOAT, LoadRGB32FToRGB9E5 ); + InsertLoadFunction(&map, GL_RGB8UI, GL_UNSIGNED_BYTE, LoadToNative3To4 ); + InsertLoadFunction(&map, GL_RGB8I, GL_BYTE, LoadToNative3To4 ); + InsertLoadFunction(&map, GL_RGB16UI, GL_UNSIGNED_SHORT, LoadToNative3To4 ); + InsertLoadFunction(&map, GL_RGB16I, GL_SHORT, LoadToNative3To4 ); + InsertLoadFunction(&map, GL_RGB32UI, GL_UNSIGNED_INT, LoadToNative3To4 ); + InsertLoadFunction(&map, GL_RGB32I, GL_INT, LoadToNative3To4 ); + InsertLoadFunction(&map, GL_RG8, GL_UNSIGNED_BYTE, LoadToNative ); + InsertLoadFunction(&map, GL_RG8_SNORM, GL_BYTE, LoadToNative ); + InsertLoadFunction(&map, GL_RG16F, GL_HALF_FLOAT, LoadToNative ); + InsertLoadFunction(&map, GL_RG16F, GL_HALF_FLOAT_OES, LoadToNative ); + InsertLoadFunction(&map, GL_RG32F, GL_FLOAT, LoadToNative ); + InsertLoadFunction(&map, GL_RG16F, GL_FLOAT, Load32FTo16F<2> ); + InsertLoadFunction(&map, GL_RG8UI, GL_UNSIGNED_BYTE, LoadToNative ); + InsertLoadFunction(&map, GL_RG8I, GL_BYTE, LoadToNative ); + InsertLoadFunction(&map, GL_RG16UI, GL_UNSIGNED_SHORT, LoadToNative ); + InsertLoadFunction(&map, GL_RG16I, GL_SHORT, LoadToNative ); + InsertLoadFunction(&map, GL_RG32UI, GL_UNSIGNED_INT, LoadToNative ); + InsertLoadFunction(&map, GL_RG32I, GL_INT, LoadToNative ); + InsertLoadFunction(&map, GL_R8, GL_UNSIGNED_BYTE, LoadToNative ); + InsertLoadFunction(&map, GL_R8_SNORM, GL_BYTE, LoadToNative ); + InsertLoadFunction(&map, GL_R16F, GL_HALF_FLOAT, LoadToNative ); + InsertLoadFunction(&map, GL_R16F, GL_HALF_FLOAT_OES, LoadToNative ); + InsertLoadFunction(&map, GL_R32F, GL_FLOAT, LoadToNative ); + InsertLoadFunction(&map, GL_R16F, GL_FLOAT, Load32FTo16F<1> ); + InsertLoadFunction(&map, GL_R8UI, GL_UNSIGNED_BYTE, LoadToNative ); + InsertLoadFunction(&map, GL_R8I, GL_BYTE, LoadToNative ); + InsertLoadFunction(&map, GL_R16UI, GL_UNSIGNED_SHORT, LoadToNative ); + InsertLoadFunction(&map, GL_R16I, GL_SHORT, LoadToNative ); + InsertLoadFunction(&map, GL_R32UI, GL_UNSIGNED_INT, LoadToNative ); + InsertLoadFunction(&map, GL_R32I, GL_INT, LoadToNative ); + InsertLoadFunction(&map, GL_DEPTH_COMPONENT16, GL_UNSIGNED_SHORT, LoadToNative ); + InsertLoadFunction(&map, GL_DEPTH_COMPONENT24, GL_UNSIGNED_INT, LoadR32ToR24G8 ); + InsertLoadFunction(&map, GL_DEPTH_COMPONENT16, GL_UNSIGNED_INT, LoadR32ToR16 ); + InsertLoadFunction(&map, GL_DEPTH_COMPONENT32F, GL_FLOAT, LoadToNative ); + InsertLoadFunction(&map, GL_DEPTH24_STENCIL8, GL_UNSIGNED_INT_24_8, LoadR32ToR24G8 ); + InsertLoadFunction(&map, GL_DEPTH32F_STENCIL8, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, LoadToNative ); + + // Unsized formats + // Load functions are unreachable because they are converted to sized internal formats based on + // the format and type before loading takes place. + InsertLoadFunction(&map, GL_RGBA, GL_UNSIGNED_BYTE, UnreachableLoadFunction ); + InsertLoadFunction(&map, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, UnreachableLoadFunction ); + InsertLoadFunction(&map, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, UnreachableLoadFunction ); + InsertLoadFunction(&map, GL_RGB, GL_UNSIGNED_BYTE, UnreachableLoadFunction ); + InsertLoadFunction(&map, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, UnreachableLoadFunction ); + InsertLoadFunction(&map, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, UnreachableLoadFunction ); + InsertLoadFunction(&map, GL_LUMINANCE, GL_UNSIGNED_BYTE, UnreachableLoadFunction ); + InsertLoadFunction(&map, GL_ALPHA, GL_UNSIGNED_BYTE, UnreachableLoadFunction ); + + // From GL_OES_texture_float + InsertLoadFunction(&map, GL_LUMINANCE_ALPHA, GL_FLOAT, LoadLA32FToRGBA32F ); + InsertLoadFunction(&map, GL_LUMINANCE, GL_FLOAT, LoadL32FToRGBA32F ); + InsertLoadFunction(&map, GL_ALPHA, GL_FLOAT, LoadA32FToRGBA32F ); + + // From GL_OES_texture_half_float + InsertLoadFunction(&map, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT, LoadLA16FToRGBA16F ); + InsertLoadFunction(&map, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES, LoadLA16FToRGBA16F ); + InsertLoadFunction(&map, GL_LUMINANCE, GL_HALF_FLOAT, LoadL16FToRGBA16F ); + InsertLoadFunction(&map, GL_LUMINANCE, GL_HALF_FLOAT_OES, LoadL16FToRGBA16F ); + InsertLoadFunction(&map, GL_ALPHA, GL_HALF_FLOAT, LoadA16FToRGBA16F ); + InsertLoadFunction(&map, GL_ALPHA, GL_HALF_FLOAT_OES, LoadA16FToRGBA16F ); + + // From GL_EXT_texture_storage + // GL_ALPHA8_EXT GL_UNSIGNED_BYTE is in the feature-level-specific load function maps, due to differences between 9_3 and 10_0+ + InsertLoadFunction(&map, GL_LUMINANCE8_EXT, GL_UNSIGNED_BYTE, LoadL8ToRGBA8 ); + InsertLoadFunction(&map, GL_LUMINANCE8_ALPHA8_EXT, GL_UNSIGNED_BYTE, LoadLA8ToRGBA8 ); + InsertLoadFunction(&map, GL_ALPHA32F_EXT, GL_FLOAT, LoadA32FToRGBA32F ); + InsertLoadFunction(&map, GL_LUMINANCE32F_EXT, GL_FLOAT, LoadL32FToRGBA32F ); + InsertLoadFunction(&map, GL_LUMINANCE_ALPHA32F_EXT, GL_FLOAT, LoadLA32FToRGBA32F ); + InsertLoadFunction(&map, GL_ALPHA16F_EXT, GL_HALF_FLOAT, LoadA16FToRGBA16F ); + InsertLoadFunction(&map, GL_ALPHA16F_EXT, GL_HALF_FLOAT_OES, LoadA16FToRGBA16F ); + InsertLoadFunction(&map, GL_LUMINANCE16F_EXT, GL_HALF_FLOAT, LoadL16FToRGBA16F ); + InsertLoadFunction(&map, GL_LUMINANCE16F_EXT, GL_HALF_FLOAT_OES, LoadL16FToRGBA16F ); + InsertLoadFunction(&map, GL_LUMINANCE_ALPHA16F_EXT, GL_HALF_FLOAT, LoadLA16FToRGBA16F ); + InsertLoadFunction(&map, GL_LUMINANCE_ALPHA16F_EXT, GL_HALF_FLOAT_OES, LoadLA16FToRGBA16F ); + + // From GL_ANGLE_depth_texture + InsertLoadFunction(&map, GL_DEPTH_COMPONENT32_OES, GL_UNSIGNED_INT, LoadR32ToR24G8 ); + + // From GL_EXT_texture_format_BGRA8888 + InsertLoadFunction(&map, GL_BGRA8_EXT, GL_UNSIGNED_BYTE, LoadToNative ); + InsertLoadFunction(&map, GL_BGRA4_ANGLEX, GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT, LoadRGBA4ToRGBA8 ); + InsertLoadFunction(&map, GL_BGRA4_ANGLEX, GL_UNSIGNED_BYTE, LoadToNative ); + InsertLoadFunction(&map, GL_BGR5_A1_ANGLEX, GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT, LoadRGB5A1ToRGBA8 ); + InsertLoadFunction(&map, GL_BGR5_A1_ANGLEX, GL_UNSIGNED_BYTE, LoadToNative ); + + // Compressed formats + // From ES 3.0.1 spec, table 3.16 + // | Internal format | Type | Load function | + InsertLoadFunction(&map, GL_COMPRESSED_R11_EAC, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); + InsertLoadFunction(&map, GL_COMPRESSED_R11_EAC, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); + InsertLoadFunction(&map, GL_COMPRESSED_SIGNED_R11_EAC, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); + InsertLoadFunction(&map, GL_COMPRESSED_RG11_EAC, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); + InsertLoadFunction(&map, GL_COMPRESSED_SIGNED_RG11_EAC, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); + InsertLoadFunction(&map, GL_COMPRESSED_RGB8_ETC2, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); + InsertLoadFunction(&map, GL_COMPRESSED_SRGB8_ETC2, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); + InsertLoadFunction(&map, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); + InsertLoadFunction(&map, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); + InsertLoadFunction(&map, GL_COMPRESSED_RGBA8_ETC2_EAC, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); + InsertLoadFunction(&map, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); + + // From GL_EXT_texture_compression_dxt1 + InsertLoadFunction(&map, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, LoadCompressedToNative<4, 4, 8>); + InsertLoadFunction(&map, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, LoadCompressedToNative<4, 4, 8>); + + // From GL_ANGLE_texture_compression_dxt3 + InsertLoadFunction(&map, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, GL_UNSIGNED_BYTE, LoadCompressedToNative<4, 4, 16>); + + // From GL_ANGLE_texture_compression_dxt5 + InsertLoadFunction(&map, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, GL_UNSIGNED_BYTE, LoadCompressedToNative<4, 4, 16>); + + return map; +} + +// For sized GL internal formats, there is only one corresponding D3D11 format. This map type allows +// querying for the DXGI texture formats to use for textures, SRVs, RTVs and DSVs given a GL internal +// format. +typedef std::map D3D11ES3FormatMap; + +TextureFormat::TextureFormat() + : texFormat(DXGI_FORMAT_UNKNOWN), + srvFormat(DXGI_FORMAT_UNKNOWN), + rtvFormat(DXGI_FORMAT_UNKNOWN), + dsvFormat(DXGI_FORMAT_UNKNOWN), + renderFormat(DXGI_FORMAT_UNKNOWN), + swizzleTexFormat(DXGI_FORMAT_UNKNOWN), + swizzleSRVFormat(DXGI_FORMAT_UNKNOWN), + swizzleRTVFormat(DXGI_FORMAT_UNKNOWN), + dataInitializerFunction(NULL), + loadFunctions() +{ +} + +static inline void InsertD3D11FormatInfoBase(D3D11ES3FormatMap *formatMap, const D3D11LoadFunctionMap &flLoadFunctions, GLenum internalFormat, DXGI_FORMAT texFormat, + DXGI_FORMAT srvFormat, DXGI_FORMAT rtvFormat, DXGI_FORMAT dsvFormat) +{ + TextureFormat info; + info.texFormat = texFormat; + info.srvFormat = srvFormat; + info.rtvFormat = rtvFormat; + info.dsvFormat = dsvFormat; + + // Given a GL internal format, the renderFormat is the DSV format if it is depth- or stencil-renderable, + // the RTV format if it is color-renderable, and the (nonrenderable) texture format otherwise. + if (dsvFormat != DXGI_FORMAT_UNKNOWN) + { + info.renderFormat = dsvFormat; + } + else if (rtvFormat != DXGI_FORMAT_UNKNOWN) + { + info.renderFormat = rtvFormat; + } + else if (texFormat != DXGI_FORMAT_UNKNOWN) + { + info.renderFormat = texFormat; + } + else + { + info.renderFormat = DXGI_FORMAT_UNKNOWN; + } + + // Compute the swizzle formats + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat); + if (internalFormat != GL_NONE && formatInfo.pixelBytes > 0) + { + if (formatInfo.componentCount != 4 || texFormat == DXGI_FORMAT_UNKNOWN || + srvFormat == DXGI_FORMAT_UNKNOWN || rtvFormat == DXGI_FORMAT_UNKNOWN) + { + // Get the maximum sized component + unsigned int maxBits = 1; + if (formatInfo.compressed) + { + unsigned int compressedBitsPerBlock = formatInfo.pixelBytes * 8; + unsigned int blockSize = formatInfo.compressedBlockWidth * formatInfo.compressedBlockHeight; + maxBits = std::max(compressedBitsPerBlock / blockSize, maxBits); + } + else + { + maxBits = std::max(maxBits, formatInfo.alphaBits); + maxBits = std::max(maxBits, formatInfo.redBits); + maxBits = std::max(maxBits, formatInfo.greenBits); + maxBits = std::max(maxBits, formatInfo.blueBits); + maxBits = std::max(maxBits, formatInfo.luminanceBits); + maxBits = std::max(maxBits, formatInfo.depthBits); + } + + maxBits = roundUp(maxBits, 8U); + + static const SwizzleInfoMap swizzleMap = BuildSwizzleInfoMap(); + SwizzleInfoMap::const_iterator swizzleIter = swizzleMap.find(SwizzleSizeType(maxBits, formatInfo.componentType)); + ASSERT(swizzleIter != swizzleMap.end()); + + const SwizzleFormatInfo &swizzleInfo = swizzleIter->second; + info.swizzleTexFormat = swizzleInfo.mTexFormat; + info.swizzleSRVFormat = swizzleInfo.mSRVFormat; + info.swizzleRTVFormat = swizzleInfo.mRTVFormat; + } + else + { + // The original texture format is suitable for swizzle operations + info.swizzleTexFormat = texFormat; + info.swizzleSRVFormat = srvFormat; + info.swizzleRTVFormat = rtvFormat; + } + } + else + { + // Not possible to swizzle with this texture format since it is either unsized or GL_NONE + info.swizzleTexFormat = DXGI_FORMAT_UNKNOWN; + info.swizzleSRVFormat = DXGI_FORMAT_UNKNOWN; + info.swizzleRTVFormat = DXGI_FORMAT_UNKNOWN; + } + + // Check if there is an initialization function for this texture format + static const InternalFormatInitializerMap initializerMap = BuildInternalFormatInitializerMap(); + InternalFormatInitializerMap::const_iterator initializerIter = initializerMap.find(internalFormat); + info.dataInitializerFunction = (initializerIter != initializerMap.end()) ? initializerIter->second : NULL; + + // Gather all the load functions for this internal format from the base list + static const D3D11LoadFunctionMap loadFunctions = BuildBaseD3D11LoadFunctionMap(); + D3D11LoadFunctionMap::const_iterator loadFunctionIter = loadFunctions.find(internalFormat); + if (loadFunctionIter != loadFunctions.end()) + { + const std::vector &loadFunctionVector = loadFunctionIter->second; + for (size_t i = 0; i < loadFunctionVector.size(); i++) + { + GLenum type = loadFunctionVector[i].first; + LoadImageFunction function = loadFunctionVector[i].second; + info.loadFunctions.insert(std::make_pair(type, function)); + } + } + + // Gather load functions for this internal format from the feature-level-specific list + D3D11LoadFunctionMap::const_iterator flLoadFunctionIter = flLoadFunctions.find(internalFormat); + if (flLoadFunctionIter != flLoadFunctions.end()) + { + const std::vector &flLoadFunctionVector = flLoadFunctionIter->second; + for (size_t i = 0; i < flLoadFunctionVector.size(); i++) + { + GLenum type = flLoadFunctionVector[i].first; + LoadImageFunction function = flLoadFunctionVector[i].second; + info.loadFunctions.insert(std::make_pair(type, function)); + } + } + + formatMap->insert(std::make_pair(internalFormat, info)); +} + +static inline void InsertD3D11_FL9_3_FormatInfo(D3D11ES3FormatMap *map, GLenum internalFormat, DXGI_FORMAT texFormat, + DXGI_FORMAT srvFormat, DXGI_FORMAT rtvFormat, DXGI_FORMAT dsvFormat) +{ + static const D3D11LoadFunctionMap flLoadFunctions = BuildD3D11_FL9_3_LoadFunctionMap(); + InsertD3D11FormatInfoBase(map, flLoadFunctions, internalFormat, texFormat, srvFormat, rtvFormat, dsvFormat); +} + +static inline void InsertD3D11FormatInfo(D3D11ES3FormatMap *map, GLenum internalFormat, DXGI_FORMAT texFormat, + DXGI_FORMAT srvFormat, DXGI_FORMAT rtvFormat, DXGI_FORMAT dsvFormat) +{ + static const D3D11LoadFunctionMap flLoadFunctions = BuildD3D11_FL10_0Plus_LoadFunctionMap(); + InsertD3D11FormatInfoBase(map, flLoadFunctions, internalFormat, texFormat, srvFormat, rtvFormat, dsvFormat); +} + +static D3D11ES3FormatMap BuildD3D11_FL9_3FormatOverrideMap() +{ + // D3D11 Feature Level 9_3 doesn't support as many texture formats as Feature Level 10_0+. + // In particular, it doesn't support: + // - mipmaps on DXGI_FORMAT_A8_NORM + // - *_TYPELESS formats + // - DXGI_FORMAT_D32_FLOAT_S8X24_UINT or DXGI_FORMAT_D32_FLOAT + + D3D11ES3FormatMap map; + + // | GL internal format | D3D11 texture format | D3D11 SRV format | D3D11 RTV format | D3D11 DSV format + InsertD3D11_FL9_3_FormatInfo(&map, GL_ALPHA, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN); + InsertD3D11_FL9_3_FormatInfo(&map, GL_ALPHA8_EXT, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN); + InsertD3D11_FL9_3_FormatInfo(&map, GL_DEPTH_COMPONENT16, DXGI_FORMAT_D16_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D16_UNORM); + InsertD3D11_FL9_3_FormatInfo(&map, GL_DEPTH_COMPONENT24, DXGI_FORMAT_D24_UNORM_S8_UINT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D24_UNORM_S8_UINT); + InsertD3D11_FL9_3_FormatInfo(&map, GL_DEPTH_COMPONENT32F, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); + InsertD3D11_FL9_3_FormatInfo(&map, GL_DEPTH24_STENCIL8, DXGI_FORMAT_D24_UNORM_S8_UINT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D24_UNORM_S8_UINT); + InsertD3D11_FL9_3_FormatInfo(&map, GL_DEPTH32F_STENCIL8, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); + InsertD3D11_FL9_3_FormatInfo(&map, GL_STENCIL_INDEX8, DXGI_FORMAT_D24_UNORM_S8_UINT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D24_UNORM_S8_UINT); + + return map; +} + +static D3D11ES3FormatMap BuildD3D11FormatMap() +{ + D3D11ES3FormatMap map; + + // | GL internal format | D3D11 texture format | D3D11 SRV format | D3D11 RTV format | D3D11 DSV format | + InsertD3D11FormatInfo(&map, GL_NONE, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_R8, DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_R8_SNORM, DXGI_FORMAT_R8_SNORM, DXGI_FORMAT_R8_SNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RG8, DXGI_FORMAT_R8G8_UNORM, DXGI_FORMAT_R8G8_UNORM, DXGI_FORMAT_R8G8_UNORM, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RG8_SNORM, DXGI_FORMAT_R8G8_SNORM, DXGI_FORMAT_R8G8_SNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RGB8, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RGB8_SNORM, DXGI_FORMAT_R8G8B8A8_SNORM, DXGI_FORMAT_R8G8B8A8_SNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RGB565, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RGBA4, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RGB5_A1, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RGBA8, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RGBA8_SNORM, DXGI_FORMAT_R8G8B8A8_SNORM, DXGI_FORMAT_R8G8B8A8_SNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RGB10_A2, DXGI_FORMAT_R10G10B10A2_UNORM, DXGI_FORMAT_R10G10B10A2_UNORM, DXGI_FORMAT_R10G10B10A2_UNORM, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RGB10_A2UI, DXGI_FORMAT_R10G10B10A2_UINT, DXGI_FORMAT_R10G10B10A2_UINT, DXGI_FORMAT_R10G10B10A2_UINT, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_SRGB8, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_SRGB8_ALPHA8, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_R16F, DXGI_FORMAT_R16_FLOAT, DXGI_FORMAT_R16_FLOAT, DXGI_FORMAT_R16_FLOAT, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RG16F, DXGI_FORMAT_R16G16_FLOAT, DXGI_FORMAT_R16G16_FLOAT, DXGI_FORMAT_R16G16_FLOAT, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RGB16F, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RGBA16F, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_R32F, DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RG32F, DXGI_FORMAT_R32G32_FLOAT, DXGI_FORMAT_R32G32_FLOAT, DXGI_FORMAT_R32G32_FLOAT, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RGB32F, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RGBA32F, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_R11F_G11F_B10F, DXGI_FORMAT_R11G11B10_FLOAT, DXGI_FORMAT_R11G11B10_FLOAT, DXGI_FORMAT_R11G11B10_FLOAT, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RGB9_E5, DXGI_FORMAT_R9G9B9E5_SHAREDEXP, DXGI_FORMAT_R9G9B9E5_SHAREDEXP, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_R8I, DXGI_FORMAT_R8_SINT, DXGI_FORMAT_R8_SINT, DXGI_FORMAT_R8_SINT, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_R8UI, DXGI_FORMAT_R8_UINT, DXGI_FORMAT_R8_UINT, DXGI_FORMAT_R8_UINT, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_R16I, DXGI_FORMAT_R16_SINT, DXGI_FORMAT_R16_SINT, DXGI_FORMAT_R16_SINT, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_R16UI, DXGI_FORMAT_R16_UINT, DXGI_FORMAT_R16_UINT, DXGI_FORMAT_R16_UINT, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_R32I, DXGI_FORMAT_R32_SINT, DXGI_FORMAT_R32_SINT, DXGI_FORMAT_R32_SINT, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_R32UI, DXGI_FORMAT_R32_UINT, DXGI_FORMAT_R32_UINT, DXGI_FORMAT_R32_UINT, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RG8I, DXGI_FORMAT_R8G8_SINT, DXGI_FORMAT_R8G8_SINT, DXGI_FORMAT_R8G8_SINT, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RG8UI, DXGI_FORMAT_R8G8_UINT, DXGI_FORMAT_R8G8_UINT, DXGI_FORMAT_R8G8_UINT, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RG16I, DXGI_FORMAT_R16G16_SINT, DXGI_FORMAT_R16G16_SINT, DXGI_FORMAT_R16G16_SINT, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RG16UI, DXGI_FORMAT_R16G16_UINT, DXGI_FORMAT_R16G16_UINT, DXGI_FORMAT_R16G16_UINT, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RG32I, DXGI_FORMAT_R32G32_SINT, DXGI_FORMAT_R32G32_SINT, DXGI_FORMAT_R32G32_SINT, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RG32UI, DXGI_FORMAT_R32G32_UINT, DXGI_FORMAT_R32G32_UINT, DXGI_FORMAT_R32G32_UINT, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RGB8I, DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RGB8UI, DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RGB16I, DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RGB16UI, DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RGB32I, DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RGB32UI, DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RGBA8I, DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RGBA8UI, DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RGBA16I, DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RGBA16UI, DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RGBA32I, DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RGBA32UI, DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_UNKNOWN); + + // Unsized formats, TODO: Are types of float and half float allowed for the unsized types? Would it change the DXGI format? + InsertD3D11FormatInfo(&map, GL_ALPHA, DXGI_FORMAT_A8_UNORM, DXGI_FORMAT_A8_UNORM, DXGI_FORMAT_A8_UNORM, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_LUMINANCE, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_LUMINANCE_ALPHA, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RGB, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_RGBA, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_BGRA_EXT, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_UNKNOWN); + + // From GL_EXT_texture_storage + // | GL internal format | D3D11 texture format | D3D11 SRV format | D3D11 RTV format | D3D11 DSV format | + InsertD3D11FormatInfo(&map, GL_ALPHA8_EXT, DXGI_FORMAT_A8_UNORM, DXGI_FORMAT_A8_UNORM, DXGI_FORMAT_A8_UNORM, DXGI_FORMAT_UNKNOWN ); + InsertD3D11FormatInfo(&map, GL_LUMINANCE8_EXT, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN ); + InsertD3D11FormatInfo(&map, GL_ALPHA32F_EXT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_UNKNOWN ); + InsertD3D11FormatInfo(&map, GL_LUMINANCE32F_EXT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_UNKNOWN ); + InsertD3D11FormatInfo(&map, GL_ALPHA16F_EXT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_UNKNOWN ); + InsertD3D11FormatInfo(&map, GL_LUMINANCE16F_EXT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_UNKNOWN ); + InsertD3D11FormatInfo(&map, GL_LUMINANCE8_ALPHA8_EXT, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN ); + InsertD3D11FormatInfo(&map, GL_LUMINANCE_ALPHA32F_EXT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_UNKNOWN ); + InsertD3D11FormatInfo(&map, GL_LUMINANCE_ALPHA16F_EXT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_UNKNOWN ); + InsertD3D11FormatInfo(&map, GL_BGRA8_EXT, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_UNKNOWN ); + InsertD3D11FormatInfo(&map, GL_BGRA4_ANGLEX, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_UNKNOWN ); + InsertD3D11FormatInfo(&map, GL_BGR5_A1_ANGLEX, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_UNKNOWN ); + + // Depth stencil formats + InsertD3D11FormatInfo(&map, GL_DEPTH_COMPONENT16, DXGI_FORMAT_R16_TYPELESS, DXGI_FORMAT_R16_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D16_UNORM ); + InsertD3D11FormatInfo(&map, GL_DEPTH_COMPONENT24, DXGI_FORMAT_R24G8_TYPELESS, DXGI_FORMAT_R24_UNORM_X8_TYPELESS, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D24_UNORM_S8_UINT ); + InsertD3D11FormatInfo(&map, GL_DEPTH_COMPONENT32F, DXGI_FORMAT_R32_TYPELESS, DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D32_FLOAT ); + InsertD3D11FormatInfo(&map, GL_DEPTH24_STENCIL8, DXGI_FORMAT_R24G8_TYPELESS, DXGI_FORMAT_R24_UNORM_X8_TYPELESS, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D24_UNORM_S8_UINT ); + InsertD3D11FormatInfo(&map, GL_DEPTH32F_STENCIL8, DXGI_FORMAT_R32G8X24_TYPELESS, DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D32_FLOAT_S8X24_UINT); + InsertD3D11FormatInfo(&map, GL_STENCIL_INDEX8, DXGI_FORMAT_R24G8_TYPELESS, DXGI_FORMAT_X24_TYPELESS_G8_UINT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D24_UNORM_S8_UINT ); + + // From GL_ANGLE_depth_texture + // Since D3D11 doesn't have a D32_UNORM format, use D24S8 which has comparable precision and matches the ES3 format. + InsertD3D11FormatInfo(&map, GL_DEPTH_COMPONENT32_OES, DXGI_FORMAT_R24G8_TYPELESS, DXGI_FORMAT_R24_UNORM_X8_TYPELESS, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D24_UNORM_S8_UINT); + + // Compressed formats, From ES 3.0.1 spec, table 3.16 + // | GL internal format | D3D11 texture format | D3D11 SRV format | D3D11 RTV format | D3D11 DSV format | + InsertD3D11FormatInfo(&map, GL_COMPRESSED_R11_EAC, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_COMPRESSED_SIGNED_R11_EAC, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_COMPRESSED_RG11_EAC, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_COMPRESSED_SIGNED_RG11_EAC, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_COMPRESSED_RGB8_ETC2, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_COMPRESSED_SRGB8_ETC2, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_COMPRESSED_RGBA8_ETC2_EAC, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); + + // From GL_EXT_texture_compression_dxt1 + InsertD3D11FormatInfo(&map, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, DXGI_FORMAT_BC1_UNORM, DXGI_FORMAT_BC1_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); + InsertD3D11FormatInfo(&map, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, DXGI_FORMAT_BC1_UNORM, DXGI_FORMAT_BC1_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); + + // From GL_ANGLE_texture_compression_dxt3 + InsertD3D11FormatInfo(&map, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, DXGI_FORMAT_BC2_UNORM, DXGI_FORMAT_BC2_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); + + // From GL_ANGLE_texture_compression_dxt5 + InsertD3D11FormatInfo(&map, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, DXGI_FORMAT_BC3_UNORM, DXGI_FORMAT_BC3_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); + + return map; +} + +const TextureFormat &GetTextureFormatInfo(GLenum internalFormat, D3D_FEATURE_LEVEL featureLevel) +{ + static const D3D11ES3FormatMap formatMap = BuildD3D11FormatMap(); + static const D3D11ES3FormatMap formatMapFL9_3Override = BuildD3D11_FL9_3FormatOverrideMap(); + + if (featureLevel == D3D_FEATURE_LEVEL_9_3) + { + // First see if the internalFormat has a special map for FL9_3 + D3D11ES3FormatMap::const_iterator fl9_3Iter = formatMapFL9_3Override.find(internalFormat); + if (fl9_3Iter != formatMapFL9_3Override.end()) + { + return fl9_3Iter->second; + } + } + + D3D11ES3FormatMap::const_iterator iter = formatMap.find(internalFormat); + if (iter != formatMap.end()) + { + return iter->second; + } + else + { + static const TextureFormat defaultInfo; + return defaultInfo; + } +} + +typedef std::map D3D11VertexFormatInfoMap; +typedef std::pair D3D11VertexFormatPair; + +VertexFormat::VertexFormat() + : conversionType(VERTEX_CONVERT_NONE), + nativeFormat(DXGI_FORMAT_UNKNOWN), + copyFunction(NULL) +{ +} + +static void AddVertexFormatInfo(D3D11VertexFormatInfoMap *map, GLenum inputType, GLboolean normalized, GLuint componentCount, + VertexConversionType conversionType, DXGI_FORMAT nativeFormat, VertexCopyFunction copyFunction) +{ + gl::VertexFormat inputFormat(inputType, normalized, componentCount, false); + + VertexFormat info; + info.conversionType = conversionType; + info.nativeFormat = nativeFormat; + info.copyFunction = copyFunction; + + map->insert(D3D11VertexFormatPair(inputFormat, info)); +} + +static void AddIntegerVertexFormatInfo(D3D11VertexFormatInfoMap *map, GLenum inputType, GLuint componentCount, + VertexConversionType conversionType, DXGI_FORMAT nativeFormat, VertexCopyFunction copyFunction) +{ + gl::VertexFormat inputFormat(inputType, GL_FALSE, componentCount, true); + + VertexFormat info; + info.conversionType = conversionType; + info.nativeFormat = nativeFormat; + info.copyFunction = copyFunction; + + map->insert(D3D11VertexFormatPair(inputFormat, info)); +} + +static D3D11VertexFormatInfoMap BuildD3D11_FL9_3VertexFormatInfoOverrideMap() +{ + // D3D11 Feature Level 9_3 doesn't support as many formats for vertex buffer resource as Feature Level 10_0+. + // http://msdn.microsoft.com/en-us/library/windows/desktop/ff471324(v=vs.85).aspx + + D3D11VertexFormatInfoMap map; + + // GL_BYTE -- unnormalized + AddVertexFormatInfo(&map, GL_BYTE, GL_FALSE, 1, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16_SINT, &Copy8SintTo16SintVertexData<1, 2>); + AddVertexFormatInfo(&map, GL_BYTE, GL_FALSE, 2, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16_SINT, &Copy8SintTo16SintVertexData<2, 2>); + AddVertexFormatInfo(&map, GL_BYTE, GL_FALSE, 3, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16B16A16_SINT, &Copy8SintTo16SintVertexData<3, 4>); + AddVertexFormatInfo(&map, GL_BYTE, GL_FALSE, 4, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16B16A16_SINT, &Copy8SintTo16SintVertexData<4, 4>); + + // GL_BYTE -- normalized + AddVertexFormatInfo(&map, GL_BYTE, GL_TRUE, 1, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16_SNORM, &Copy8SnormTo16SnormVertexData<1, 2>); + AddVertexFormatInfo(&map, GL_BYTE, GL_TRUE, 2, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16_SNORM, &Copy8SnormTo16SnormVertexData<2, 2>); + AddVertexFormatInfo(&map, GL_BYTE, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SNORM, &Copy8SnormTo16SnormVertexData<3, 4>); + AddVertexFormatInfo(&map, GL_BYTE, GL_TRUE, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SNORM, &Copy8SnormTo16SnormVertexData<4, 4>); + + // GL_UNSIGNED_BYTE -- unnormalized + AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_FALSE, 1, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R8G8B8A8_UINT, &CopyNativeVertexData); + AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_FALSE, 2, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R8G8B8A8_UINT, &CopyNativeVertexData); + // NOTE: 3 and 4 component unnormalized GL_UNSIGNED_BYTE should use the default format table. + + // GL_UNSIGNED_BYTE -- normalized + AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_TRUE, 1, VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_UNORM, &CopyNativeVertexData); + AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_TRUE, 2, VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_UNORM, &CopyNativeVertexData); + // NOTE: 3 and 4 component normalized GL_UNSIGNED_BYTE should use the default format table. + + // GL_SHORT -- unnormalized + AddVertexFormatInfo(&map, GL_SHORT, GL_FALSE, 1, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16_SINT, &CopyNativeVertexData); + // NOTE: 2, 3 and 4 component unnormalized GL_SHORT should use the default format table. + + // GL_SHORT -- normalized + AddVertexFormatInfo(&map, GL_SHORT, GL_TRUE, 1, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16_SNORM, &CopyNativeVertexData); + // NOTE: 2, 3 and 4 component normalized GL_SHORT should use the default format table. + + // GL_UNSIGNED_SHORT -- unnormalized + AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_FALSE, 1, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, &CopyTo32FVertexData); + AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_FALSE, 2, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, &CopyTo32FVertexData); + AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_FALSE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT, &CopyTo32FVertexData); + AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_FALSE, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyTo32FVertexData); + + // GL_UNSIGNED_SHORT -- normalized + AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_TRUE, 1, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, &CopyTo32FVertexData); + AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_TRUE, 2, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, &CopyTo32FVertexData); + AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT, &CopyTo32FVertexData); + AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_TRUE, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyTo32FVertexData); + + // GL_FIXED + // TODO: Add test to verify that this works correctly. + AddVertexFormatInfo(&map, GL_FIXED, GL_FALSE, 1, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, &Copy32FixedTo32FVertexData<1, 2>); + // NOTE: 2, 3 and 4 component GL_FIXED should use the default format table. + + // GL_FLOAT + // TODO: Add test to verify that this works correctly. + AddVertexFormatInfo(&map, GL_FLOAT, GL_FALSE, 1, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, &CopyNativeVertexData); + // NOTE: 2, 3 and 4 component GL_FLOAT should use the default format table. + + return map; +} + +static D3D11VertexFormatInfoMap BuildD3D11VertexFormatInfoMap() +{ + D3D11VertexFormatInfoMap map; + + // TODO: column legend + + // + // Float formats + // + + // GL_BYTE -- un-normalized + AddVertexFormatInfo(&map, GL_BYTE, GL_FALSE, 1, VERTEX_CONVERT_GPU, DXGI_FORMAT_R8_SINT, &CopyNativeVertexData); + AddVertexFormatInfo(&map, GL_BYTE, GL_FALSE, 2, VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8_SINT, &CopyNativeVertexData); + AddVertexFormatInfo(&map, GL_BYTE, GL_FALSE, 3, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R8G8B8A8_SINT, &CopyNativeVertexData); + AddVertexFormatInfo(&map, GL_BYTE, GL_FALSE, 4, VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8B8A8_SINT, &CopyNativeVertexData); + + // GL_BYTE -- normalized + AddVertexFormatInfo(&map, GL_BYTE, GL_TRUE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_SNORM, &CopyNativeVertexData); + AddVertexFormatInfo(&map, GL_BYTE, GL_TRUE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_SNORM, &CopyNativeVertexData); + AddVertexFormatInfo(&map, GL_BYTE, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_SNORM, &CopyNativeVertexData); + AddVertexFormatInfo(&map, GL_BYTE, GL_TRUE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_SNORM, &CopyNativeVertexData); + + // GL_UNSIGNED_BYTE -- un-normalized + AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_FALSE, 1, VERTEX_CONVERT_GPU, DXGI_FORMAT_R8_UINT, &CopyNativeVertexData); + AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_FALSE, 2, VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8_UINT, &CopyNativeVertexData); + AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_FALSE, 3, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R8G8B8A8_UINT, &CopyNativeVertexData); + AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_FALSE, 4, VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8B8A8_UINT, &CopyNativeVertexData); + + // GL_UNSIGNED_BYTE -- normalized + AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_TRUE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_UNORM, &CopyNativeVertexData); + AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_TRUE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_UNORM, &CopyNativeVertexData); + AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_UNORM, &CopyNativeVertexData); + AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_TRUE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_UNORM, &CopyNativeVertexData); + + // GL_SHORT -- un-normalized + AddVertexFormatInfo(&map, GL_SHORT, GL_FALSE, 1, VERTEX_CONVERT_GPU, DXGI_FORMAT_R16_SINT, &CopyNativeVertexData); + AddVertexFormatInfo(&map, GL_SHORT, GL_FALSE, 2, VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16_SINT, &CopyNativeVertexData); + AddVertexFormatInfo(&map, GL_SHORT, GL_FALSE, 3, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16B16A16_SINT, &CopyNativeVertexData); + AddVertexFormatInfo(&map, GL_SHORT, GL_FALSE, 4, VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16B16A16_SINT, &CopyNativeVertexData); + + // GL_SHORT -- normalized + AddVertexFormatInfo(&map, GL_SHORT, GL_TRUE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_SNORM, &CopyNativeVertexData); + AddVertexFormatInfo(&map, GL_SHORT, GL_TRUE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_SNORM, &CopyNativeVertexData); + AddVertexFormatInfo(&map, GL_SHORT, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SNORM, &CopyNativeVertexData); + AddVertexFormatInfo(&map, GL_SHORT, GL_TRUE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_SNORM, &CopyNativeVertexData); + + // GL_UNSIGNED_SHORT -- un-normalized + AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_FALSE, 1, VERTEX_CONVERT_GPU, DXGI_FORMAT_R16_UINT, &CopyNativeVertexData); + AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_FALSE, 2, VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16_UINT, &CopyNativeVertexData); + AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_FALSE, 3, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16B16A16_UINT, &CopyNativeVertexData); + AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_FALSE, 4, VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16B16A16_UINT, &CopyNativeVertexData); + + // GL_UNSIGNED_SHORT -- normalized + AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_TRUE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_UNORM, &CopyNativeVertexData); + AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_TRUE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_UNORM, &CopyNativeVertexData); + AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_UNORM, &CopyNativeVertexData); + AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_TRUE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_UNORM, &CopyNativeVertexData); + + // GL_INT -- un-normalized + AddVertexFormatInfo(&map, GL_INT, GL_FALSE, 1, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32_SINT, &CopyNativeVertexData); + AddVertexFormatInfo(&map, GL_INT, GL_FALSE, 2, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32_SINT, &CopyNativeVertexData); + AddVertexFormatInfo(&map, GL_INT, GL_FALSE, 3, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32_SINT, &CopyNativeVertexData); + AddVertexFormatInfo(&map, GL_INT, GL_FALSE, 4, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32A32_SINT, &CopyNativeVertexData); + + // GL_INT -- normalized + AddVertexFormatInfo(&map, GL_INT, GL_TRUE, 1, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32_FLOAT, &CopyTo32FVertexData); + AddVertexFormatInfo(&map, GL_INT, GL_TRUE, 2, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, &CopyTo32FVertexData); + AddVertexFormatInfo(&map, GL_INT, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT, &CopyTo32FVertexData); + AddVertexFormatInfo(&map, GL_INT, GL_TRUE, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyTo32FVertexData); + + // GL_UNSIGNED_INT -- un-normalized + AddVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_FALSE, 1, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32_UINT, &CopyNativeVertexData); + AddVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_FALSE, 2, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32_UINT, &CopyNativeVertexData); + AddVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_FALSE, 3, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32_UINT, &CopyNativeVertexData); + AddVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_FALSE, 4, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32A32_UINT, &CopyNativeVertexData); + + // GL_UNSIGNED_INT -- normalized + AddVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_TRUE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32_FLOAT, &CopyTo32FVertexData); + AddVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_TRUE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_FLOAT, &CopyTo32FVertexData); + AddVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT, &CopyTo32FVertexData); + AddVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_TRUE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyTo32FVertexData); + + // GL_FIXED + AddVertexFormatInfo(&map, GL_FIXED, GL_FALSE, 1, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32_FLOAT, &Copy32FixedTo32FVertexData<1, 1>); + AddVertexFormatInfo(&map, GL_FIXED, GL_FALSE, 2, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, &Copy32FixedTo32FVertexData<2, 2>); + AddVertexFormatInfo(&map, GL_FIXED, GL_FALSE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT, &Copy32FixedTo32FVertexData<3, 3>); + AddVertexFormatInfo(&map, GL_FIXED, GL_FALSE, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, &Copy32FixedTo32FVertexData<4, 4>); + + // GL_HALF_FLOAT + AddVertexFormatInfo(&map, GL_HALF_FLOAT, GL_FALSE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_FLOAT, &CopyNativeVertexData); + AddVertexFormatInfo(&map, GL_HALF_FLOAT, GL_FALSE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_FLOAT, &CopyNativeVertexData); + AddVertexFormatInfo(&map, GL_HALF_FLOAT, GL_FALSE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_FLOAT, &CopyNativeVertexData); + AddVertexFormatInfo(&map, GL_HALF_FLOAT, GL_FALSE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_FLOAT, &CopyNativeVertexData); + + // GL_FLOAT + AddVertexFormatInfo(&map, GL_FLOAT, GL_FALSE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32_FLOAT, &CopyNativeVertexData); + AddVertexFormatInfo(&map, GL_FLOAT, GL_FALSE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_FLOAT, &CopyNativeVertexData); + AddVertexFormatInfo(&map, GL_FLOAT, GL_FALSE, 3, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32_FLOAT, &CopyNativeVertexData); + AddVertexFormatInfo(&map, GL_FLOAT, GL_FALSE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyNativeVertexData); + + // GL_INT_2_10_10_10_REV + AddVertexFormatInfo(&map, GL_INT_2_10_10_10_REV, GL_FALSE, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyXYZ10W2ToXYZW32FVertexData); + AddVertexFormatInfo(&map, GL_INT_2_10_10_10_REV, GL_TRUE, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyXYZ10W2ToXYZW32FVertexData); + + // GL_UNSIGNED_INT_2_10_10_10_REV + AddVertexFormatInfo(&map, GL_UNSIGNED_INT_2_10_10_10_REV, GL_FALSE, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyXYZ10W2ToXYZW32FVertexData); + AddVertexFormatInfo(&map, GL_UNSIGNED_INT_2_10_10_10_REV, GL_TRUE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R10G10B10A2_UNORM, &CopyNativeVertexData); + + // + // Integer Formats + // + + // GL_BYTE + AddIntegerVertexFormatInfo(&map, GL_BYTE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_SINT, &CopyNativeVertexData); + AddIntegerVertexFormatInfo(&map, GL_BYTE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_SINT, &CopyNativeVertexData); + AddIntegerVertexFormatInfo(&map, GL_BYTE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_SINT, &CopyNativeVertexData); + AddIntegerVertexFormatInfo(&map, GL_BYTE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_SINT, &CopyNativeVertexData); + + // GL_UNSIGNED_BYTE + AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_BYTE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_UINT, &CopyNativeVertexData); + AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_BYTE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_UINT, &CopyNativeVertexData); + AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_BYTE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_UINT, &CopyNativeVertexData); + AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_BYTE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_UINT, &CopyNativeVertexData); + + // GL_SHORT + AddIntegerVertexFormatInfo(&map, GL_SHORT, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_SINT, &CopyNativeVertexData); + AddIntegerVertexFormatInfo(&map, GL_SHORT, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_SINT, &CopyNativeVertexData); + AddIntegerVertexFormatInfo(&map, GL_SHORT, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SINT, &CopyNativeVertexData); + AddIntegerVertexFormatInfo(&map, GL_SHORT, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_SINT, &CopyNativeVertexData); + + // GL_UNSIGNED_SHORT + AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_SHORT, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_UINT, &CopyNativeVertexData); + AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_SHORT, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_UINT, &CopyNativeVertexData); + AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_SHORT, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_UINT, &CopyNativeVertexData); + AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_SHORT, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_UINT, &CopyNativeVertexData); + + // GL_INT + AddIntegerVertexFormatInfo(&map, GL_INT, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32_SINT, &CopyNativeVertexData); + AddIntegerVertexFormatInfo(&map, GL_INT, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_SINT, &CopyNativeVertexData); + AddIntegerVertexFormatInfo(&map, GL_INT, 3, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32_SINT, &CopyNativeVertexData); + AddIntegerVertexFormatInfo(&map, GL_INT, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32A32_SINT, &CopyNativeVertexData); + + // GL_UNSIGNED_INT + AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_INT, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32_SINT, &CopyNativeVertexData); + AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_INT, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_SINT, &CopyNativeVertexData); + AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_INT, 3, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32_SINT, &CopyNativeVertexData); + AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_INT, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32A32_SINT, &CopyNativeVertexData); + + // GL_INT_2_10_10_10_REV + AddIntegerVertexFormatInfo(&map, GL_INT_2_10_10_10_REV, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SINT, &CopyXYZ10W2ToXYZW32FVertexData); + + // GL_UNSIGNED_INT_2_10_10_10_REV + AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_INT_2_10_10_10_REV, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R10G10B10A2_UINT, &CopyNativeVertexData); + + return map; +} + +const VertexFormat &GetVertexFormatInfo(const gl::VertexFormat &vertexFormat, D3D_FEATURE_LEVEL featureLevel) +{ + static const D3D11VertexFormatInfoMap vertexFormatMap = BuildD3D11VertexFormatInfoMap(); + static const D3D11VertexFormatInfoMap vertexFormatMapFL9_3Override = BuildD3D11_FL9_3VertexFormatInfoOverrideMap(); + + if (featureLevel == D3D_FEATURE_LEVEL_9_3) + { + // First see if the format has a special mapping for FL9_3 + D3D11VertexFormatInfoMap::const_iterator iter = vertexFormatMapFL9_3Override.find(vertexFormat); + if (iter != vertexFormatMapFL9_3Override.end()) + { + return iter->second; + } + } + + D3D11VertexFormatInfoMap::const_iterator iter = vertexFormatMap.find(vertexFormat); + if (iter != vertexFormatMap.end()) + { + return iter->second; + } + else + { + static const VertexFormat defaultInfo; + return defaultInfo; + } +} + +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.h new file mode 100644 index 0000000000..33fe29dc39 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.h @@ -0,0 +1,93 @@ +// +// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// formatutils11.h: Queries for GL image formats and their translations to D3D11 +// formats. + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_FORMATUTILS11_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_FORMATUTILS11_H_ + +#include "libANGLE/renderer/d3d/formatutilsD3D.h" +#include "libANGLE/angletypes.h" + +#include "common/platform.h" + +#include + +namespace rx +{ + +namespace d3d11 +{ + +typedef std::map, ColorCopyFunction> FastCopyFunctionMap; + +struct DXGIFormat +{ + DXGIFormat(); + + GLuint pixelBytes; + GLuint blockWidth; + GLuint blockHeight; + + GLuint redBits; + GLuint greenBits; + GLuint blueBits; + GLuint alphaBits; + GLuint sharedBits; + + GLuint depthBits; + GLuint depthOffset; + GLuint stencilBits; + GLuint stencilOffset; + + GLenum internalFormat; + GLenum componentType; + + MipGenerationFunction mipGenerationFunction; + ColorReadFunction colorReadFunction; + + FastCopyFunctionMap fastCopyFunctions; + ColorCopyFunction getFastCopyFunction(GLenum format, GLenum type) const; +}; +const DXGIFormat &GetDXGIFormatInfo(DXGI_FORMAT format); + +struct TextureFormat +{ + TextureFormat(); + + DXGI_FORMAT texFormat; + DXGI_FORMAT srvFormat; + DXGI_FORMAT rtvFormat; + DXGI_FORMAT dsvFormat; + DXGI_FORMAT renderFormat; + + DXGI_FORMAT swizzleTexFormat; + DXGI_FORMAT swizzleSRVFormat; + DXGI_FORMAT swizzleRTVFormat; + + InitializeTextureDataFunction dataInitializerFunction; + + typedef std::map LoadFunctionMap; + LoadFunctionMap loadFunctions; +}; +const TextureFormat &GetTextureFormatInfo(GLenum internalFormat, D3D_FEATURE_LEVEL featureLevel); + +struct VertexFormat +{ + VertexFormat(); + + VertexConversionType conversionType; + DXGI_FORMAT nativeFormat; + VertexCopyFunction copyFunction; +}; +const VertexFormat &GetVertexFormatInfo(const gl::VertexFormat &vertexFormat, D3D_FEATURE_LEVEL featureLevel); + +} + +} + +#endif // LIBANGLE_RENDERER_D3D_D3D11_FORMATUTILS11_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp new file mode 100644 index 0000000000..63085f497f --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp @@ -0,0 +1,1378 @@ +// +// Copyright (c) 2012-2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// renderer11_utils.cpp: Conversion functions and other utility routines +// specific to the D3D11 renderer. + +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" +#include "libANGLE/renderer/d3d/d3d11/formatutils11.h" +#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h" +#include "libANGLE/renderer/d3d/FramebufferD3D.h" +#include "libANGLE/renderer/Workarounds.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/Program.h" +#include "libANGLE/Framebuffer.h" + +#include "common/debug.h" + +#include + +#ifndef D3D_FL9_1_DEFAULT_MAX_ANISOTROPY +# define D3D_FL9_1_DEFAULT_MAX_ANISOTROPY 2 +#endif +#ifndef D3D_FL9_1_SIMULTANEOUS_RENDER_TARGET_COUNT +# define D3D_FL9_1_SIMULTANEOUS_RENDER_TARGET_COUNT 1 +#endif +#ifndef D3D_FL9_3_SIMULTANEOUS_RENDER_TARGET_COUNT +# define D3D_FL9_3_SIMULTANEOUS_RENDER_TARGET_COUNT 4 +#endif +#ifndef D3D_FL9_1_IA_PRIMITIVE_MAX_COUNT +# define D3D_FL9_1_IA_PRIMITIVE_MAX_COUNT 65535 +#endif +#ifndef D3D_FL9_2_IA_PRIMITIVE_MAX_COUNT +# define D3D_FL9_2_IA_PRIMITIVE_MAX_COUNT 1048575 +#endif +#ifndef D3D_FL9_1_REQ_TEXTURECUBE_DIMENSION +# define D3D_FL9_1_REQ_TEXTURECUBE_DIMENSION 512 +#endif +#ifndef D3D_FL9_3_REQ_TEXTURECUBE_DIMENSION +# define D3D_FL9_3_REQ_TEXTURECUBE_DIMENSION 4096 +#endif +#ifndef D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION +# define D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION 2048 +#endif +#ifndef D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION +# define D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION 256 +#endif +#ifndef D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION +# define D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION 4096 +#endif +#ifndef D3D11_REQ_TEXTURECUBE_DIMENSION +# define D3D11_REQ_TEXTURECUBE_DIMENSION 16384 +#endif +#ifndef D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION +# define D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION 2048 +#endif +#ifndef D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION +# define D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION 2048 +#endif +#ifndef D3D11_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP +# define D3D11_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP 32 +#endif +#ifndef D3D11_REQ_DRAW_VERTEX_COUNT_2_TO_EXP +# define D3D11_REQ_DRAW_VERTEX_COUNT_2_TO_EXP 32 +#endif +#ifndef D3D10_1_STANDARD_VERTEX_ELEMENT_COUNT +# define D3D10_1_STANDARD_VERTEX_ELEMENT_COUNT 32 +#endif +#ifndef D3D11_STANDARD_VERTEX_ELEMENT_COUNT +# define D3D11_STANDARD_VERTEX_ELEMENT_COUNT 32 +#endif +#ifndef D3D10_1_SO_BUFFER_SLOT_COUNT +# define D3D10_1_SO_BUFFER_SLOT_COUNT 4 +#endif +#ifndef D3D11_SO_BUFFER_SLOT_COUNT +# define D3D11_SO_BUFFER_SLOT_COUNT 4 +#endif +#ifndef D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT +# define D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT 14 +#endif +#ifndef D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT +# define D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT 16 +#endif +#ifndef D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE +# define D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE -8 +#endif +#ifndef D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE +# define D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE 7 +#endif +#ifndef D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT +# define D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT 4096 +#endif +#ifndef D3D11_PS_INPUT_REGISTER_COUNT +# define D3D11_PS_INPUT_REGISTER_COUNT 32 +#endif +#ifndef D3D10_1_VS_OUTPUT_REGISTER_COUNT +# define D3D10_1_VS_OUTPUT_REGISTER_COUNT 32 +#endif +#if defined(ANGLE_MINGW32_COMPAT) +static const IID WKPDID_D3DDebugObjectName = { 0x429b8c22, 0x9188, 0x4b0c, 0x87, 0x42, 0xac, 0xb0, 0xbf, 0x85, 0xc2, 0x00 }; +#endif + +namespace rx +{ + +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; + case GL_MIN: d3dBlendOp = D3D11_BLEND_OP_MIN; break; + case GL_MAX: d3dBlendOp = D3D11_BLEND_OP_MAX; 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, GLenum comparisonMode) +{ + bool comparison = comparisonMode != GL_NONE; + + if (maxAnisotropy > 1.0f) + { + return D3D11_ENCODE_ANISOTROPIC_FILTER(static_cast(comparison)); + } + 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, static_cast(comparison)); + } +} + +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; +} + +D3D11_QUERY ConvertQueryType(GLenum queryType) +{ + switch (queryType) + { + case GL_ANY_SAMPLES_PASSED_EXT: + case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT: return D3D11_QUERY_OCCLUSION; + case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: return D3D11_QUERY_SO_STATISTICS; + default: UNREACHABLE(); return D3D11_QUERY_EVENT; + } +} + +} + + +namespace d3d11_gl +{ + +GLint GetMaximumClientVersion(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { +#if defined(ANGLE_ENABLE_D3D11_1) + case D3D_FEATURE_LEVEL_11_1: +#endif + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return 3; + + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return 2; + + default: UNREACHABLE(); return 0; + } +} + +static gl::TextureCaps GenerateTextureFormatCaps(GLint maxClientVersion, GLenum internalFormat, ID3D11Device *device) +{ + gl::TextureCaps textureCaps; + + const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalFormat, device->GetFeatureLevel()); + + UINT formatSupport; + if (SUCCEEDED(device->CheckFormatSupport(formatInfo.texFormat, &formatSupport))) + { + const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat); + if (internalFormatInfo.depthBits > 0 || internalFormatInfo.stencilBits > 0) + { + textureCaps.texturable = ((formatSupport & D3D11_FORMAT_SUPPORT_TEXTURE2D) != 0); + } + else + { + UINT formatSupportMask = D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_TEXTURECUBE; + if (maxClientVersion > 2) + { + formatSupportMask |= D3D11_FORMAT_SUPPORT_TEXTURE3D; + } + textureCaps.texturable = ((formatSupport & formatSupportMask) == formatSupportMask); + } + } + + if (SUCCEEDED(device->CheckFormatSupport(formatInfo.renderFormat, &formatSupport)) && + ((formatSupport & D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET) != 0)) + { + for (size_t sampleCount = 1; sampleCount <= D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT; sampleCount++) + { + UINT qualityCount = 0; + if (SUCCEEDED(device->CheckMultisampleQualityLevels(formatInfo.renderFormat, sampleCount, &qualityCount)) && + qualityCount > 0) + { + textureCaps.sampleCounts.insert(sampleCount); + } + } + } + + textureCaps.filterable = SUCCEEDED(device->CheckFormatSupport(formatInfo.srvFormat, &formatSupport)) && + ((formatSupport & D3D11_FORMAT_SUPPORT_SHADER_SAMPLE)) != 0; + textureCaps.renderable = (SUCCEEDED(device->CheckFormatSupport(formatInfo.rtvFormat, &formatSupport)) && + ((formatSupport & D3D11_FORMAT_SUPPORT_RENDER_TARGET)) != 0) || + (SUCCEEDED(device->CheckFormatSupport(formatInfo.dsvFormat, &formatSupport)) && + ((formatSupport & D3D11_FORMAT_SUPPORT_DEPTH_STENCIL) != 0)); + + return textureCaps; +} + +static bool GetNPOTTextureSupport(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { +#if defined(ANGLE_ENABLE_D3D11_1) + case D3D_FEATURE_LEVEL_11_1: +#endif + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return true; + + // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876.aspx + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return false; + + default: UNREACHABLE(); return false; + } +} + +static float GetMaximumAnisotropy(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { +#if defined(ANGLE_ENABLE_D3D11_1) + case D3D_FEATURE_LEVEL_11_1: +#endif + 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; + + // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876.aspx + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: return 16; + + case D3D_FEATURE_LEVEL_9_1: return D3D_FL9_1_DEFAULT_MAX_ANISOTROPY; + + default: UNREACHABLE(); return 0; + } +} + +static bool GetOcclusionQuerySupport(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { +#if defined(ANGLE_ENABLE_D3D11_1) + case D3D_FEATURE_LEVEL_11_1: +#endif + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return true; + + // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx ID3D11Device::CreateQuery + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: return true; + case D3D_FEATURE_LEVEL_9_1: return false; + + default: UNREACHABLE(); return false; + } +} + +static bool GetEventQuerySupport(D3D_FEATURE_LEVEL featureLevel) +{ + // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx ID3D11Device::CreateQuery + + switch (featureLevel) + { +#if defined(ANGLE_ENABLE_D3D11_1) + case D3D_FEATURE_LEVEL_11_1: +#endif + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return true; + + default: UNREACHABLE(); return false; + } +} + +static bool GetInstancingSupport(D3D_FEATURE_LEVEL featureLevel) +{ + // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx ID3D11Device::CreateInputLayout + + switch (featureLevel) + { +#if defined(ANGLE_ENABLE_D3D11_1) + case D3D_FEATURE_LEVEL_11_1: +#endif + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return true; + + // Feature Level 9_3 supports instancing, but slot 0 in the input layout must not be instanced. + // D3D9 has a similar restriction, where stream 0 must not be instanced. + // This restriction can be worked around by remapping any non-instanced slot to slot 0. + // This works because HLSL uses shader semantics to match the vertex inputs to the elements in the input layout, rather than the slots. + // Note that we only support instancing via ANGLE_instanced_array on 9_3, since 9_3 doesn't support OpenGL ES 3.0 + case D3D_FEATURE_LEVEL_9_3: return true; + + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return false; + + default: UNREACHABLE(); return false; + } +} + +static bool GetFramebufferMultisampleSupport(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { +#if defined(ANGLE_ENABLE_D3D11_1) + case D3D_FEATURE_LEVEL_11_1: +#endif + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return true; + + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return false; + + default: UNREACHABLE(); return false; + } +} + +static bool GetFramebufferBlitSupport(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { +#if defined(ANGLE_ENABLE_D3D11_1) + case D3D_FEATURE_LEVEL_11_1: +#endif + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return true; + + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return false; + + default: UNREACHABLE(); return false; + } +} + +static bool GetDerivativeInstructionSupport(D3D_FEATURE_LEVEL featureLevel) +{ + // http://msdn.microsoft.com/en-us/library/windows/desktop/bb509588.aspx states that shader model + // ps_2_x is required for the ddx (and other derivative functions). + + // http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876.aspx states that feature level + // 9.3 supports shader model ps_2_x. + + switch (featureLevel) + { +#if defined(ANGLE_ENABLE_D3D11_1) + case D3D_FEATURE_LEVEL_11_1: +#endif + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + case D3D_FEATURE_LEVEL_9_3: return true; + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return false; + + default: UNREACHABLE(); return false; + } +} + +static bool GetShaderTextureLODSupport(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { +#if defined(ANGLE_ENABLE_D3D11_1) + case D3D_FEATURE_LEVEL_11_1: +#endif + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return true; + + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return false; + + default: UNREACHABLE(); return false; + } +} + +static size_t GetMaximumSimultaneousRenderTargets(D3D_FEATURE_LEVEL featureLevel) +{ + // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx ID3D11Device::CreateInputLayout + + switch (featureLevel) + { +#if defined(ANGLE_ENABLE_D3D11_1) + case D3D_FEATURE_LEVEL_11_1: +#endif + case D3D_FEATURE_LEVEL_11_0: return D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; + + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return D3D10_SIMULTANEOUS_RENDER_TARGET_COUNT; + + case D3D_FEATURE_LEVEL_9_3: return D3D_FL9_3_SIMULTANEOUS_RENDER_TARGET_COUNT; + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return D3D_FL9_1_SIMULTANEOUS_RENDER_TARGET_COUNT; + + default: UNREACHABLE(); return 0; + } +} + +static size_t GetMaximum2DTextureSize(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { +#if defined(ANGLE_ENABLE_D3D11_1) + case D3D_FEATURE_LEVEL_11_1: +#endif + case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; + + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION; + + case D3D_FEATURE_LEVEL_9_3: return D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION; + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION; + + default: UNREACHABLE(); return 0; + } +} + +static size_t GetMaximumCubeMapTextureSize(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { +#if defined(ANGLE_ENABLE_D3D11_1) + case D3D_FEATURE_LEVEL_11_1: +#endif + case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURECUBE_DIMENSION; + + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURECUBE_DIMENSION; + + case D3D_FEATURE_LEVEL_9_3: return D3D_FL9_3_REQ_TEXTURECUBE_DIMENSION; + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return D3D_FL9_1_REQ_TEXTURECUBE_DIMENSION; + + default: UNREACHABLE(); return 0; + } +} + +static size_t GetMaximum2DTextureArraySize(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { +#if defined(ANGLE_ENABLE_D3D11_1) + case D3D_FEATURE_LEVEL_11_1: +#endif + case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION; + + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION; + + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return 0; + + default: UNREACHABLE(); return 0; + } +} + +static size_t GetMaximum3DTextureSize(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { +#if defined(ANGLE_ENABLE_D3D11_1) + case D3D_FEATURE_LEVEL_11_1: +#endif + case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION; + + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE3D_U_V_OR_W_DIMENSION; + + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION; + + default: UNREACHABLE(); return 0; + } +} + +static size_t GetMaximumViewportSize(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { +#if defined(ANGLE_ENABLE_D3D11_1) + case D3D_FEATURE_LEVEL_11_1: +#endif + case D3D_FEATURE_LEVEL_11_0: return D3D11_VIEWPORT_BOUNDS_MAX; + + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return D3D10_VIEWPORT_BOUNDS_MAX; + + // No constants for D3D11 Feature Level 9 viewport size limits, use the maximum texture sizes + case D3D_FEATURE_LEVEL_9_3: return D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION; + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION; + + default: UNREACHABLE(); return 0; + } +} + +static size_t GetMaximumDrawIndexedIndexCount(D3D_FEATURE_LEVEL featureLevel) +{ + // D3D11 allows up to 2^32 elements, but we report max signed int for convenience since that's what's + // returned from glGetInteger + static_assert(D3D11_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP == 32, "Unexpected D3D11 constant value."); + static_assert(D3D10_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP == 32, "Unexpected D3D11 constant value."); + + switch (featureLevel) + { +#if defined(ANGLE_ENABLE_D3D11_1) + case D3D_FEATURE_LEVEL_11_1: +#endif + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return std::numeric_limits::max(); + + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: return D3D_FL9_2_IA_PRIMITIVE_MAX_COUNT; + case D3D_FEATURE_LEVEL_9_1: return D3D_FL9_1_IA_PRIMITIVE_MAX_COUNT; + + default: UNREACHABLE(); return 0; + } +} + +static size_t GetMaximumDrawVertexCount(D3D_FEATURE_LEVEL featureLevel) +{ + // D3D11 allows up to 2^32 elements, but we report max signed int for convenience since that's what's + // returned from glGetInteger + static_assert(D3D11_REQ_DRAW_VERTEX_COUNT_2_TO_EXP == 32, "Unexpected D3D11 constant value."); + static_assert(D3D10_REQ_DRAW_VERTEX_COUNT_2_TO_EXP == 32, "Unexpected D3D11 constant value."); + + switch (featureLevel) + { +#if defined(ANGLE_ENABLE_D3D11_1) + case D3D_FEATURE_LEVEL_11_1: +#endif + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return std::numeric_limits::max(); + + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: return D3D_FL9_2_IA_PRIMITIVE_MAX_COUNT; + case D3D_FEATURE_LEVEL_9_1: return D3D_FL9_1_IA_PRIMITIVE_MAX_COUNT; + + default: UNREACHABLE(); return 0; + } +} + +static size_t GetMaximumVertexInputSlots(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { +#if defined(ANGLE_ENABLE_D3D11_1) + case D3D_FEATURE_LEVEL_11_1: +#endif + case D3D_FEATURE_LEVEL_11_0: return D3D11_STANDARD_VERTEX_ELEMENT_COUNT; + + case D3D_FEATURE_LEVEL_10_1: return D3D10_1_STANDARD_VERTEX_ELEMENT_COUNT; + case D3D_FEATURE_LEVEL_10_0: return D3D10_STANDARD_VERTEX_ELEMENT_COUNT; + + // From http://http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876.aspx "Max Input Slots" + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return 16; + + default: UNREACHABLE(); return 0; + } +} + +static size_t GetMaximumVertexUniformVectors(D3D_FEATURE_LEVEL featureLevel) +{ + // TODO(geofflang): Remove hard-coded limit once the gl-uniform-arrays test can pass + switch (featureLevel) + { +#if defined(ANGLE_ENABLE_D3D11_1) + case D3D_FEATURE_LEVEL_11_1: +#endif + case D3D_FEATURE_LEVEL_11_0: return 1024; // D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT; + + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return 1024; // D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT; + + // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476149.aspx ID3D11DeviceContext::VSSetConstantBuffers + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return 255; + + default: UNREACHABLE(); return 0; + } +} + +static size_t GetReservedVertexUniformBuffers() +{ + // Reserve one buffer for the application uniforms, and one for driver uniforms + return 2; +} + +static size_t GetMaximumVertexUniformBlocks(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { +#if defined(ANGLE_ENABLE_D3D11_1) + case D3D_FEATURE_LEVEL_11_1: +#endif + case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - GetReservedVertexUniformBuffers(); + + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return D3D10_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - GetReservedVertexUniformBuffers(); + + // Uniform blocks not supported on D3D11 Feature Level 9 + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return 0; + + default: UNREACHABLE(); return 0; + } +} + +static size_t GetReservedVertexOutputVectors(D3D_FEATURE_LEVEL featureLevel) +{ + // According to The OpenGL ES Shading Language specifications + // (Language Version 1.00 section 10.16, Language Version 3.10 section 12.21) + // built-in special variables (e.g. gl_FragCoord, or gl_PointCoord) + // which are statically used in the shader should be included in the variable packing algorithm. + // Therefore, we should not reserve output vectors for them. + + switch (featureLevel) + { + // We must reserve one output vector for dx_Position. + // We also reserve one for gl_Position, which we unconditionally output on Feature Levels 10_0+, + // even if it's unused in the shader (e.g. for transform feedback). TODO: This could be improved. +#if defined(ANGLE_ENABLE_D3D11_1) + case D3D_FEATURE_LEVEL_11_1: +#endif + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return 2; + + // Just reserve dx_Position on Feature Level 9, since we don't ever need to output gl_Position. + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return 1; + + default: UNREACHABLE(); return 0; + } + + return 1; +} + +static size_t GetMaximumVertexOutputVectors(D3D_FEATURE_LEVEL featureLevel) +{ + static_assert(gl::IMPLEMENTATION_MAX_VARYING_VECTORS == D3D11_VS_OUTPUT_REGISTER_COUNT, "Unexpected D3D11 constant value."); + + switch (featureLevel) + { +#if defined(ANGLE_ENABLE_D3D11_1) + case D3D_FEATURE_LEVEL_11_1: +#endif + case D3D_FEATURE_LEVEL_11_0: return D3D11_VS_OUTPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(featureLevel); + + case D3D_FEATURE_LEVEL_10_1: return D3D10_1_VS_OUTPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(featureLevel); + case D3D_FEATURE_LEVEL_10_0: return D3D10_VS_OUTPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(featureLevel); + + // Use Shader Model 2.X limits + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return 8 - GetReservedVertexOutputVectors(featureLevel); + + default: UNREACHABLE(); return 0; + } +} + +static size_t GetMaximumVertexTextureUnits(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { +#if defined(ANGLE_ENABLE_D3D11_1) + case D3D_FEATURE_LEVEL_11_1: +#endif + case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT; + + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return D3D10_COMMONSHADER_SAMPLER_SLOT_COUNT; + + // Vertex textures not supported on D3D11 Feature Level 9 according to + // http://msdn.microsoft.com/en-us/library/windows/desktop/ff476149.aspx + // ID3D11DeviceContext::VSSetSamplers and ID3D11DeviceContext::VSSetShaderResources + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return 0; + + default: UNREACHABLE(); return 0; + } +} + +static size_t GetMaximumPixelUniformVectors(D3D_FEATURE_LEVEL featureLevel) +{ + // TODO(geofflang): Remove hard-coded limit once the gl-uniform-arrays test can pass + switch (featureLevel) + { +#if defined(ANGLE_ENABLE_D3D11_1) + case D3D_FEATURE_LEVEL_11_1: +#endif + case D3D_FEATURE_LEVEL_11_0: return 1024; // D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT; + + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return 1024; // D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT; + + // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476149.aspx ID3D11DeviceContext::PSSetConstantBuffers + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return 32; + + default: UNREACHABLE(); return 0; + } +} + +static size_t GetReservedPixelUniformBuffers() +{ + // Reserve one buffer for the application uniforms, and one for driver uniforms + return 2; +} + +static size_t GetMaximumPixelUniformBlocks(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { +#if defined(ANGLE_ENABLE_D3D11_1) + case D3D_FEATURE_LEVEL_11_1: +#endif + case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - GetReservedPixelUniformBuffers(); + + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return D3D10_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - GetReservedPixelUniformBuffers(); + + // Uniform blocks not supported on D3D11 Feature Level 9 + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return 0; + + default: UNREACHABLE(); return 0; + } +} + +static size_t GetMaximumPixelInputVectors(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { +#if defined(ANGLE_ENABLE_D3D11_1) + case D3D_FEATURE_LEVEL_11_1: +#endif + case D3D_FEATURE_LEVEL_11_0: return D3D11_PS_INPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(featureLevel); + + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return D3D10_PS_INPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(featureLevel); + + // Use Shader Model 2.X limits + case D3D_FEATURE_LEVEL_9_3: return 8 - GetReservedVertexOutputVectors(featureLevel); + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return 8 - GetReservedVertexOutputVectors(featureLevel); + + default: UNREACHABLE(); return 0; + } +} + +static size_t GetMaximumPixelTextureUnits(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { +#if defined(ANGLE_ENABLE_D3D11_1) + case D3D_FEATURE_LEVEL_11_1: +#endif + case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT; + + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return D3D10_COMMONSHADER_SAMPLER_SLOT_COUNT; + + // http://msdn.microsoft.com/en-us/library/windows/desktop/ff476149.aspx ID3D11DeviceContext::PSSetShaderResources + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return 16; + + default: UNREACHABLE(); return 0; + } +} + +static int GetMinimumTexelOffset(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { +#if defined(ANGLE_ENABLE_D3D11_1) + case D3D_FEATURE_LEVEL_11_1: +#endif + case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE; + + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return D3D10_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE; + + // Sampling functions with offsets are not available below shader model 4.0. + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return 0; + + default: UNREACHABLE(); return 0; + } +} + +static int GetMaximumTexelOffset(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { +#if defined(ANGLE_ENABLE_D3D11_1) + case D3D_FEATURE_LEVEL_11_1: +#endif + case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE; + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE; + + // Sampling functions with offsets are not available below shader model 4.0. + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return 0; + + default: UNREACHABLE(); return 0; + } +} + +static size_t GetMaximumConstantBufferSize(D3D_FEATURE_LEVEL featureLevel) +{ + // Returns a size_t despite the limit being a GLuint64 because size_t is the maximum size of + // any buffer that could be allocated. + + const size_t bytesPerComponent = 4 * sizeof(float); + + switch (featureLevel) + { +#if defined(ANGLE_ENABLE_D3D11_1) + case D3D_FEATURE_LEVEL_11_1: +#endif + case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * bytesPerComponent; + + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * bytesPerComponent; + + // Limits from http://msdn.microsoft.com/en-us/library/windows/desktop/ff476501.aspx remarks section + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return 4096 * bytesPerComponent; + + default: UNREACHABLE(); return 0; + } +} + +static size_t GetMaximumStreamOutputBuffers(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { +#if defined(ANGLE_ENABLE_D3D11_1) + case D3D_FEATURE_LEVEL_11_1: +#endif + case D3D_FEATURE_LEVEL_11_0: return D3D11_SO_BUFFER_SLOT_COUNT; + + case D3D_FEATURE_LEVEL_10_1: return D3D10_1_SO_BUFFER_SLOT_COUNT; + case D3D_FEATURE_LEVEL_10_0: return D3D10_SO_BUFFER_SLOT_COUNT; + + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return 0; + + default: UNREACHABLE(); return 0; + } +} + +static size_t GetMaximumStreamOutputInterleavedComponents(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { +#if defined(ANGLE_ENABLE_D3D11_1) + case D3D_FEATURE_LEVEL_11_1: +#endif + case D3D_FEATURE_LEVEL_11_0: + + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return GetMaximumVertexOutputVectors(featureLevel) * 4; + + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return 0; + + default: UNREACHABLE(); return 0; + } +} + +static size_t GetMaximumStreamOutputSeparateComponents(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { +#if defined(ANGLE_ENABLE_D3D11_1) + case D3D_FEATURE_LEVEL_11_1: +#endif + case D3D_FEATURE_LEVEL_11_0: return GetMaximumStreamOutputInterleavedComponents(featureLevel) / + GetMaximumStreamOutputBuffers(featureLevel); + + + // D3D 10 and 10.1 only allow one output per output slot if an output slot other than zero is used. + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return 4; + + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return 0; + + default: UNREACHABLE(); return 0; + } +} + +void GenerateCaps(ID3D11Device *device, ID3D11DeviceContext *deviceContext, gl::Caps *caps, gl::TextureCapsMap *textureCapsMap, gl::Extensions *extensions) +{ + D3D_FEATURE_LEVEL featureLevel = device->GetFeatureLevel(); + + GLuint maxSamples = 0; + const gl::FormatSet &allFormats = gl::GetAllSizedInternalFormats(); + for (gl::FormatSet::const_iterator internalFormat = allFormats.begin(); internalFormat != allFormats.end(); ++internalFormat) + { + gl::TextureCaps textureCaps = GenerateTextureFormatCaps(GetMaximumClientVersion(featureLevel), *internalFormat, device); + textureCapsMap->insert(*internalFormat, textureCaps); + + maxSamples = std::max(maxSamples, textureCaps.getMaxSamples()); + + if (gl::GetInternalFormatInfo(*internalFormat).compressed) + { + caps->compressedTextureFormats.push_back(*internalFormat); + } + } + + // GL core feature limits + caps->maxElementIndex = static_cast(std::numeric_limits::max()); + caps->max3DTextureSize = GetMaximum3DTextureSize(featureLevel); + caps->max2DTextureSize = GetMaximum2DTextureSize(featureLevel); + caps->maxCubeMapTextureSize = GetMaximumCubeMapTextureSize(featureLevel); + caps->maxArrayTextureLayers = GetMaximum2DTextureArraySize(featureLevel); + + // Unimplemented, set to minimum required + caps->maxLODBias = 2.0f; + + // No specific limits on render target size, maximum 2D texture size is equivalent + caps->maxRenderbufferSize = caps->max2DTextureSize; + + // Maximum draw buffers and color attachments are the same, max color attachments could eventually be + // increased to 16 + caps->maxDrawBuffers = GetMaximumSimultaneousRenderTargets(featureLevel); + caps->maxColorAttachments = GetMaximumSimultaneousRenderTargets(featureLevel); + + // D3D11 has the same limit for viewport width and height + caps->maxViewportWidth = GetMaximumViewportSize(featureLevel); + caps->maxViewportHeight = caps->maxViewportWidth; + + // Choose a reasonable maximum, enforced in the shader. + caps->minAliasedPointSize = 1.0f; + caps->maxAliasedPointSize = 1024.0f; + + // Wide lines not supported + caps->minAliasedLineWidth = 1.0f; + caps->maxAliasedLineWidth = 1.0f; + + // Primitive count limits + caps->maxElementsIndices = GetMaximumDrawIndexedIndexCount(featureLevel); + caps->maxElementsVertices = GetMaximumDrawVertexCount(featureLevel); + + // Program and shader binary formats (no supported shader binary formats) + caps->programBinaryFormats.push_back(GL_PROGRAM_BINARY_ANGLE); + + caps->vertexHighpFloat.setIEEEFloat(); + caps->vertexMediumpFloat.setIEEEFloat(); + caps->vertexLowpFloat.setIEEEFloat(); + caps->fragmentHighpFloat.setIEEEFloat(); + caps->fragmentMediumpFloat.setIEEEFloat(); + caps->fragmentLowpFloat.setIEEEFloat(); + + // 32-bit integers are natively supported + caps->vertexHighpInt.setTwosComplementInt(32); + caps->vertexMediumpInt.setTwosComplementInt(32); + caps->vertexLowpInt.setTwosComplementInt(32); + caps->fragmentHighpInt.setTwosComplementInt(32); + caps->fragmentMediumpInt.setTwosComplementInt(32); + caps->fragmentLowpInt.setTwosComplementInt(32); + + // We do not wait for server fence objects internally, so report a max timeout of zero. + caps->maxServerWaitTimeout = 0; + + // Vertex shader limits + caps->maxVertexAttributes = GetMaximumVertexInputSlots(featureLevel); + caps->maxVertexUniformComponents = GetMaximumVertexUniformVectors(featureLevel) * 4; + caps->maxVertexUniformVectors = GetMaximumVertexUniformVectors(featureLevel); + caps->maxVertexUniformBlocks = GetMaximumVertexUniformBlocks(featureLevel); + caps->maxVertexOutputComponents = GetMaximumVertexOutputVectors(featureLevel) * 4; + caps->maxVertexTextureImageUnits = GetMaximumVertexTextureUnits(featureLevel); + + // Fragment shader limits + caps->maxFragmentUniformComponents = GetMaximumPixelUniformVectors(featureLevel) * 4; + caps->maxFragmentUniformVectors = GetMaximumPixelUniformVectors(featureLevel); + caps->maxFragmentUniformBlocks = GetMaximumPixelUniformBlocks(featureLevel); + caps->maxFragmentInputComponents = GetMaximumPixelInputVectors(featureLevel) * 4; + caps->maxTextureImageUnits = GetMaximumPixelTextureUnits(featureLevel); + caps->minProgramTexelOffset = GetMinimumTexelOffset(featureLevel); + caps->maxProgramTexelOffset = GetMaximumTexelOffset(featureLevel); + + // Aggregate shader limits + caps->maxUniformBufferBindings = caps->maxVertexUniformBlocks + caps->maxFragmentUniformBlocks; + caps->maxUniformBlockSize = GetMaximumConstantBufferSize(featureLevel); + + // Setting a large alignment forces uniform buffers to bind with zero offset + caps->uniformBufferOffsetAlignment = static_cast(std::numeric_limits::max()); +#if defined(ANGLE_ENABLE_D3D11_1) + ID3D11DeviceContext1 *deviceContext1 = d3d11::DynamicCastComObject(deviceContext); + + if (deviceContext1) + { + D3D11_FEATURE_DATA_D3D11_OPTIONS d3d11Options; + device->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS, &d3d11Options, sizeof(D3D11_FEATURE_DATA_D3D11_OPTIONS)); + + if (d3d11Options.ConstantBufferOffsetting) + { + // With DirectX 11.1, constant buffer offset and size must be a multiple of 16 constants of 16 bytes each. + // https://msdn.microsoft.com/en-us/library/windows/desktop/hh404649%28v=vs.85%29.aspx + caps->uniformBufferOffsetAlignment = 256; + } + + SafeRelease(deviceContext1); + } +#endif + + caps->maxCombinedUniformBlocks = caps->maxVertexUniformBlocks + caps->maxFragmentUniformBlocks; + caps->maxCombinedVertexUniformComponents = (static_cast(caps->maxVertexUniformBlocks) * static_cast(caps->maxUniformBlockSize / 4)) + + static_cast(caps->maxVertexUniformComponents); + caps->maxCombinedFragmentUniformComponents = (static_cast(caps->maxFragmentUniformBlocks) * static_cast(caps->maxUniformBlockSize / 4)) + + static_cast(caps->maxFragmentUniformComponents); + caps->maxVaryingComponents = GetMaximumVertexOutputVectors(featureLevel) * 4; + caps->maxVaryingVectors = GetMaximumVertexOutputVectors(featureLevel); + caps->maxCombinedTextureImageUnits = caps->maxVertexTextureImageUnits + caps->maxTextureImageUnits; + + // Transform feedback limits + caps->maxTransformFeedbackInterleavedComponents = GetMaximumStreamOutputInterleavedComponents(featureLevel); + caps->maxTransformFeedbackSeparateAttributes = GetMaximumStreamOutputBuffers(featureLevel); + caps->maxTransformFeedbackSeparateComponents = GetMaximumStreamOutputSeparateComponents(featureLevel); + + // GL extension support + extensions->setTextureExtensionSupport(*textureCapsMap); + extensions->elementIndexUint = true; + extensions->packedDepthStencil = true; + extensions->getProgramBinary = true; + extensions->rgb8rgba8 = true; + extensions->readFormatBGRA = true; + extensions->pixelBufferObject = true; + extensions->mapBuffer = true; + extensions->mapBufferRange = true; + extensions->textureNPOT = GetNPOTTextureSupport(featureLevel); + extensions->drawBuffers = GetMaximumSimultaneousRenderTargets(featureLevel) > 1; + extensions->textureStorage = true; + extensions->textureFilterAnisotropic = true; + extensions->maxTextureAnisotropy = GetMaximumAnisotropy(featureLevel); + extensions->occlusionQueryBoolean = GetOcclusionQuerySupport(featureLevel); + extensions->fence = GetEventQuerySupport(featureLevel); + extensions->timerQuery = false; // Unimplemented + extensions->robustness = true; + extensions->blendMinMax = true; + extensions->framebufferBlit = GetFramebufferBlitSupport(featureLevel); + extensions->framebufferMultisample = GetFramebufferMultisampleSupport(featureLevel); + extensions->maxSamples = maxSamples; + extensions->instancedArrays = GetInstancingSupport(featureLevel); + extensions->packReverseRowOrder = true; + extensions->standardDerivatives = GetDerivativeInstructionSupport(featureLevel); + extensions->shaderTextureLOD = GetShaderTextureLODSupport(featureLevel); + extensions->fragDepth = true; + extensions->textureUsage = true; // This could be false since it has no effect in D3D11 + extensions->translatedShaderSource = true; +} + +} + +namespace d3d11 +{ + +void MakeValidSize(bool isImage, DXGI_FORMAT format, GLsizei *requestWidth, GLsizei *requestHeight, int *levelOffset) +{ + const DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(format); + + int upsampleCount = 0; + // Don't expand the size of full textures that are at least (blockWidth x blockHeight) already. + if (isImage || *requestWidth < static_cast(dxgiFormatInfo.blockWidth) || + *requestHeight < static_cast(dxgiFormatInfo.blockHeight)) + { + while (*requestWidth % dxgiFormatInfo.blockWidth != 0 || *requestHeight % dxgiFormatInfo.blockHeight != 0) + { + *requestWidth <<= 1; + *requestHeight <<= 1; + upsampleCount++; + } + } + *levelOffset = upsampleCount; +} + +void GenerateInitialTextureData(GLint internalFormat, D3D_FEATURE_LEVEL featureLevel, GLuint width, GLuint height, GLuint depth, + GLuint mipLevels, std::vector *outSubresourceData, + std::vector< std::vector > *outData) +{ + const d3d11::TextureFormat &d3dFormatInfo = d3d11::GetTextureFormatInfo(internalFormat, featureLevel); + ASSERT(d3dFormatInfo.dataInitializerFunction != NULL); + + const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(d3dFormatInfo.texFormat); + + outSubresourceData->resize(mipLevels); + outData->resize(mipLevels); + + for (unsigned int i = 0; i < mipLevels; i++) + { + unsigned int mipWidth = std::max(width >> i, 1U); + unsigned int mipHeight = std::max(height >> i, 1U); + unsigned int mipDepth = std::max(depth >> i, 1U); + + unsigned int rowWidth = dxgiFormatInfo.pixelBytes * mipWidth; + unsigned int imageSize = rowWidth * height; + + outData->at(i).resize(rowWidth * mipHeight * mipDepth); + d3dFormatInfo.dataInitializerFunction(mipWidth, mipHeight, mipDepth, outData->at(i).data(), rowWidth, imageSize); + + outSubresourceData->at(i).pSysMem = outData->at(i).data(); + outSubresourceData->at(i).SysMemPitch = rowWidth; + outSubresourceData->at(i).SysMemSlicePitch = imageSize; + } +} + +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 SetPositionLayerTexCoord3DVertex(PositionLayerTexCoord3DVertex* vertex, float x, float y, + unsigned int layer, float u, float v, float s) +{ + vertex->x = x; + vertex->y = y; + vertex->l = layer; + vertex->u = u; + vertex->v = v; + vertex->s = s; +} + +HRESULT SetDebugName(ID3D11DeviceChild *resource, const char *name) +{ +#if defined(_DEBUG) + return resource->SetPrivateData(WKPDID_D3DDebugObjectName, strlen(name), name); +#else + return S_OK; +#endif +} + +gl::Error GetAttachmentRenderTarget(const gl::FramebufferAttachment *attachment, RenderTarget11 **outRT) +{ + RenderTargetD3D *renderTarget = NULL; + gl::Error error = rx::GetAttachmentRenderTarget(attachment, &renderTarget); + if (error.isError()) + { + return error; + } + *outRT = RenderTarget11::makeRenderTarget11(renderTarget); + return gl::Error(GL_NO_ERROR); +} + +Workarounds GenerateWorkarounds(D3D_FEATURE_LEVEL featureLevel) +{ + Workarounds workarounds; + workarounds.mrtPerfWorkaround = true; + workarounds.setDataFasterThanImageUpload = true; + workarounds.zeroMaxLodWorkaround = (featureLevel <= D3D_FEATURE_LEVEL_9_3); + workarounds.useInstancedPointSpriteEmulation = (featureLevel <= D3D_FEATURE_LEVEL_9_3); + return workarounds; +} + +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.h new file mode 100644 index 0000000000..207e6b5404 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.h @@ -0,0 +1,190 @@ +// +// Copyright (c) 2012-2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// renderer11_utils.h: Conversion functions and other utility routines +// specific to the D3D11 renderer. + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_RENDERER11_UTILS_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_RENDERER11_UTILS_H_ + +#include "libANGLE/angletypes.h" +#include "libANGLE/Caps.h" +#include "libANGLE/Error.h" + +#include + +namespace gl +{ +class FramebufferAttachment; +} + +namespace rx +{ +class RenderTarget11; +struct Workarounds; + +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, GLenum comparisonMode); +D3D11_TEXTURE_ADDRESS_MODE ConvertTextureWrap(GLenum wrap); + +D3D11_QUERY ConvertQueryType(GLenum queryType); + +} + +namespace d3d11_gl +{ + +GLint GetMaximumClientVersion(D3D_FEATURE_LEVEL featureLevel); +void GenerateCaps(ID3D11Device *device, ID3D11DeviceContext *deviceContext, gl::Caps *caps, gl::TextureCapsMap *textureCapsMap, gl::Extensions *extensions); + +} + +namespace d3d11 +{ + +void MakeValidSize(bool isImage, DXGI_FORMAT format, GLsizei *requestWidth, GLsizei *requestHeight, int *levelOffset); + +void GenerateInitialTextureData(GLint internalFormat, D3D_FEATURE_LEVEL featureLevel, GLuint width, GLuint height, GLuint depth, + GLuint mipLevels, std::vector *outSubresourceData, + std::vector< std::vector > *outData); + +struct PositionTexCoordVertex +{ + float x, y; + float u, v; +}; +void SetPositionTexCoordVertex(PositionTexCoordVertex* vertex, float x, float y, float u, float v); + +struct PositionLayerTexCoord3DVertex +{ + float x, y; + unsigned int l; + float u, v, s; +}; +void SetPositionLayerTexCoord3DVertex(PositionLayerTexCoord3DVertex* vertex, float x, float y, + unsigned int layer, float u, float v, float s); + +template +struct PositionDepthColorVertex +{ + float x, y, z; + T r, g, b, a; +}; + +template +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; +} + +HRESULT SetDebugName(ID3D11DeviceChild *resource, const char *name); + +template +outType* DynamicCastComObject(IUnknown* object) +{ + outType *outObject = NULL; + HRESULT result = object->QueryInterface(__uuidof(outType), reinterpret_cast(&outObject)); + if (SUCCEEDED(result)) + { + return outObject; + } + else + { + SafeRelease(outObject); + return NULL; + } +} + +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; + } +} + +template +inline ID3D11VertexShader *CompileVS(ID3D11Device *device, const BYTE (&byteCode)[N], const char *name) +{ + ID3D11VertexShader *vs = NULL; + HRESULT result = device->CreateVertexShader(byteCode, N, NULL, &vs); + UNUSED_ASSERTION_VARIABLE(result); + ASSERT(SUCCEEDED(result)); + SetDebugName(vs, name); + return vs; +} + +template +inline ID3D11GeometryShader *CompileGS(ID3D11Device *device, const BYTE (&byteCode)[N], const char *name) +{ + ID3D11GeometryShader *gs = NULL; + HRESULT result = device->CreateGeometryShader(byteCode, N, NULL, &gs); + UNUSED_ASSERTION_VARIABLE(result); + ASSERT(SUCCEEDED(result)); + SetDebugName(gs, name); + return gs; +} + +template +inline ID3D11PixelShader *CompilePS(ID3D11Device *device, const BYTE (&byteCode)[N], const char *name) +{ + ID3D11PixelShader *ps = NULL; + HRESULT result = device->CreatePixelShader(byteCode, N, NULL, &ps); + UNUSED_ASSERTION_VARIABLE(result); + ASSERT(SUCCEEDED(result)); + SetDebugName(ps, name); + return ps; +} + +// Copy data to small D3D11 buffers, such as for small constant buffers, which use one struct to +// represent an entire buffer. +template +inline void SetBufferData(ID3D11DeviceContext *context, ID3D11Buffer *constantBuffer, const T &value) +{ + D3D11_MAPPED_SUBRESOURCE mappedResource; + context->Map(constantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + + memcpy(mappedResource.pData, &value, sizeof(T)); + + context->Unmap(constantBuffer, 0); +} + +gl::Error GetAttachmentRenderTarget(const gl::FramebufferAttachment *attachment, RenderTarget11 **outRT); + +Workarounds GenerateWorkarounds(D3D_FEATURE_LEVEL featureLevel); + +} + +} + +#endif // LIBANGLE_RENDERER_D3D_D3D11_RENDERER11_UTILS_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/BufferToTexture11.hlsl b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/BufferToTexture11.hlsl new file mode 100644 index 0000000000..c43734f6a3 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/BufferToTexture11.hlsl @@ -0,0 +1,77 @@ +Buffer Buffer4F : register(t0); +Buffer Buffer4I : register(t0); +Buffer Buffer4UI : register(t0); + +struct VS_OUTPUT +{ + float4 position : SV_Position; + uint index : TEXCOORD0; + uint slice : LAYER; +}; + +struct GS_OUTPUT +{ + float4 position : SV_Position; + uint index : TEXCOORD0; + uint slice : SV_RenderTargetArrayIndex; +}; + +cbuffer BufferCopyParams : register(b0) +{ + uint FirstPixelOffset; + uint PixelsPerRow; + uint RowStride; + uint RowsPerSlice; + float2 PositionOffset; + float2 PositionScale; + int2 TexLocationOffset; + int2 TexLocationScale; + uint FirstSlice; +} + +void ComputePositionAndIndex(uint vertexID, out VS_OUTPUT outVertex) +{ + uint PixelsPerSlice = PixelsPerRow * RowsPerSlice; + uint SliceStride = RowStride * RowsPerSlice; + + uint slice = vertexID / PixelsPerSlice; + uint sliceOffset = slice * PixelsPerSlice; + uint row = (vertexID - sliceOffset) / PixelsPerRow; + uint col = vertexID - sliceOffset - (row * PixelsPerRow); + + float2 coords = float2(float(col), float(row)); + + outVertex.position = float4(PositionOffset + PositionScale * coords, 0.0f, 1.0f); + outVertex.index = FirstPixelOffset + slice * SliceStride + row * RowStride + col; + outVertex.slice = FirstSlice + slice; +} + +void VS_BufferToTexture(in uint vertexID : SV_VertexID, out VS_OUTPUT outVertex) +{ + ComputePositionAndIndex(vertexID, outVertex); +} + +[maxvertexcount(1)] +void GS_BufferToTexture(point VS_OUTPUT inVertex[1], inout PointStream outStream) +{ + GS_OUTPUT outVertex; + outVertex.position = inVertex[0].position; + outVertex.index = inVertex[0].index; + outVertex.slice = inVertex[0].slice; + outStream.Append(outVertex); +} + +float4 PS_BufferToTexture_4F(in float4 inPosition : SV_Position, in uint inIndex : TEXCOORD0) : SV_Target +{ + return Buffer4F.Load(inIndex); +} + +int4 PS_BufferToTexture_4I(in float4 inPosition : SV_Position, in uint inIndex : TEXCOORD0) : SV_Target +{ + return Buffer4I.Load(inIndex); +} + +uint4 PS_BufferToTexture_4UI(in float4 inPosition : SV_Position, in uint inIndex : TEXCOORD0) : SV_Target +{ + return Buffer4UI.Load(inIndex); +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Clear11.hlsl b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Clear11.hlsl new file mode 100644 index 0000000000..2b3e1ebe4c --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Clear11.hlsl @@ -0,0 +1,119 @@ +// Assume we are in SM4+, which has 8 color outputs + +void VS_ClearFloat( in float3 inPosition : POSITION, in float4 inColor : COLOR, + out float4 outPosition : SV_POSITION, out float4 outColor : COLOR) +{ + outPosition = float4(inPosition, 1.0f); + outColor = inColor; +} + +struct PS_OutputFloat +{ + 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_OutputFloat PS_ClearFloat(in float4 inPosition : SV_POSITION, in float4 inColor : COLOR) +{ + PS_OutputFloat 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; +} + +struct PS_OutputFloat_FL9 +{ + float4 color0 : SV_TARGET0; + float4 color1 : SV_TARGET1; + float4 color2 : SV_TARGET2; + float4 color3 : SV_TARGET3; +}; + +PS_OutputFloat_FL9 PS_ClearFloat_FL9(in float4 inPosition : SV_POSITION, in float4 inColor : COLOR) +{ + PS_OutputFloat_FL9 outColor; + outColor.color0 = inColor; + outColor.color1 = inColor; + outColor.color2 = inColor; + outColor.color3 = inColor; + return outColor; +} + +void VS_ClearUint( in float3 inPosition : POSITION, in uint4 inColor : COLOR, + out float4 outPosition : SV_POSITION, out uint4 outColor : COLOR) +{ + outPosition = float4(inPosition, 1.0f); + outColor = inColor; +} + +struct PS_OutputUint +{ + uint4 color0 : SV_TARGET0; + uint4 color1 : SV_TARGET1; + uint4 color2 : SV_TARGET2; + uint4 color3 : SV_TARGET3; + uint4 color4 : SV_TARGET4; + uint4 color5 : SV_TARGET5; + uint4 color6 : SV_TARGET6; + uint4 color7 : SV_TARGET7; +}; + +PS_OutputUint PS_ClearUint(in float4 inPosition : SV_POSITION, in uint4 inColor : COLOR) +{ + PS_OutputUint 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; +} + + +void VS_ClearSint( in float3 inPosition : POSITION, in int4 inColor : COLOR, + out float4 outPosition : SV_POSITION, out int4 outColor : COLOR) +{ + outPosition = float4(inPosition, 1.0f); + outColor = inColor; +} + +struct PS_OutputSint +{ + int4 color0 : SV_TARGET0; + int4 color1 : SV_TARGET1; + int4 color2 : SV_TARGET2; + int4 color3 : SV_TARGET3; + int4 color4 : SV_TARGET4; + int4 color5 : SV_TARGET5; + int4 color6 : SV_TARGET6; + int4 color7 : SV_TARGET7; +}; + +PS_OutputSint PS_ClearSint(in float4 inPosition : SV_POSITION, in int4 inColor : COLOR) +{ + PS_OutputSint 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/libANGLE/renderer/d3d/d3d11/shaders/Passthrough2D11.hlsl b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Passthrough2D11.hlsl new file mode 100644 index 0000000000..8671c39fb7 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Passthrough2D11.hlsl @@ -0,0 +1,111 @@ +Texture2D TextureF : register(t0); +Texture2D TextureUI : register(t0); +Texture2D TextureI : register(t0); + +SamplerState Sampler : register(s0); + +void VS_Passthrough2D( 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; +} + +float PS_PassthroughDepth2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_DEPTH +{ + return TextureF.Sample(Sampler, inTexCoord).r; +} + +float4 PS_PassthroughRGBA2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + return TextureF.Sample(Sampler, inTexCoord).rgba; +} + +uint4 PS_PassthroughRGBA2DUI(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + uint2 size; + TextureUI.GetDimensions(size.x, size.y); + + return TextureUI.Load(int3(size * inTexCoord, 0)).rgba; +} + +int4 PS_PassthroughRGBA2DI(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + uint2 size; + TextureI.GetDimensions(size.x, size.y); + + return TextureI.Load(int3(size * inTexCoord, 0)).rgba; +} + +float4 PS_PassthroughRGB2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + return float4(TextureF.Sample(Sampler, inTexCoord).rgb, 1.0f); +} + +uint4 PS_PassthroughRGB2DUI(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + uint2 size; + TextureUI.GetDimensions(size.x, size.y); + + return uint4(TextureUI.Load(int3(size * inTexCoord, 0)).rgb, 0); +} + +int4 PS_PassthroughRGB2DI(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + uint2 size; + TextureI.GetDimensions(size.x, size.y); + + return int4(TextureI.Load(int3(size * inTexCoord, 0)).rgb, 0); +} + +float4 PS_PassthroughRG2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + return float4(TextureF.Sample(Sampler, inTexCoord).rg, 0.0f, 1.0f); +} + +uint4 PS_PassthroughRG2DUI(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + uint2 size; + TextureUI.GetDimensions(size.x, size.y); + + return uint4(TextureUI.Load(int3(size * inTexCoord, 0)).rg, 0, 0); +} + +int4 PS_PassthroughRG2DI(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + uint2 size; + TextureI.GetDimensions(size.x, size.y); + + return int4(TextureI.Load(int3(size * inTexCoord, 0)).rg, 0, 0); +} + +float4 PS_PassthroughR2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + return float4(TextureF.Sample(Sampler, inTexCoord).r, 0.0f, 0.0f, 1.0f); +} + +uint4 PS_PassthroughR2DUI(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + uint2 size; + TextureUI.GetDimensions(size.x, size.y); + + return uint4(TextureUI.Load(int3(size * inTexCoord, 0)).r, 0, 0, 0); +} + +int4 PS_PassthroughR2DI(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + uint2 size; + TextureI.GetDimensions(size.x, size.y); + + return int4(TextureI.Load(int3(size * inTexCoord, 0)).r, 0, 0, 0); +} + +float4 PS_PassthroughLum2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + return float4(TextureF.Sample(Sampler, inTexCoord).rrr, 1.0f); +} + +float4 PS_PassthroughLumAlpha2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + return TextureF.Sample(Sampler, inTexCoord).rrra; +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Passthrough3D11.hlsl b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Passthrough3D11.hlsl new file mode 100644 index 0000000000..c23c9032ec --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Passthrough3D11.hlsl @@ -0,0 +1,146 @@ +Texture3D TextureF : register(t0); +Texture3D TextureUI : register(t0); +Texture3D TextureI : register(t0); + +SamplerState Sampler : register(s0); + +struct VS_INPUT +{ + float2 Position : POSITION; + uint Layer : LAYER; + float3 TexCoord : TEXCOORD; +}; + +struct VS_OUTPUT +{ + float4 Position : SV_POSITION; + uint Layer : LAYER; + float3 TexCoord : TEXCOORD; +}; + +struct GS_OUTPUT +{ + float4 Position : SV_POSITION; + uint Layer : SV_RENDERTARGETARRAYINDEX; + float3 TexCoord : TEXCOORD; +}; + +VS_OUTPUT VS_Passthrough3D(VS_INPUT input) +{ + VS_OUTPUT output; + + output.Position = float4(input.Position, 0.0f, 1.0f); + output.Layer = input.Layer; + output.TexCoord = input.TexCoord; + + return output; +} + +[maxvertexcount(3)] +void GS_Passthrough3D(triangle VS_OUTPUT input[3], inout TriangleStream outputStream) +{ + GS_OUTPUT output; + + for (int i = 0; i < 3; i++) + { + output.Position = input[i].Position; + output.Layer = input[i].Layer; + output.TexCoord = input[i].TexCoord; + + outputStream.Append(output); + } +} + +float4 PS_PassthroughRGBA3D(GS_OUTPUT input) : SV_TARGET0 +{ + return TextureF.Sample(Sampler, input.TexCoord).rgba; +} + +uint4 PS_PassthroughRGBA3DUI(GS_OUTPUT input) : SV_TARGET0 +{ + uint3 size; + TextureUI.GetDimensions(size.x, size.y, size.z); + + return TextureUI.Load(int4(size * input.TexCoord, 0)).rgba; +} + +int4 PS_PassthroughRGBA3DI(GS_OUTPUT input) : SV_TARGET0 +{ + uint3 size; + TextureI.GetDimensions(size.x, size.y, size.z); + + return TextureI.Load(int4(size * input.TexCoord, 0)).rgba; +} + +float4 PS_PassthroughRGB3D(GS_OUTPUT input) : SV_TARGET0 +{ + return float4(TextureF.Sample(Sampler, input.TexCoord).rgb, 1.0f); +} + +uint4 PS_PassthroughRGB3DUI(GS_OUTPUT input) : SV_TARGET0 +{ + uint3 size; + TextureUI.GetDimensions(size.x, size.y, size.z); + + return uint4(TextureUI.Load(int4(size * input.TexCoord, 0)).rgb, 0); +} + +int4 PS_PassthroughRGB3DI(GS_OUTPUT input) : SV_TARGET0 +{ + uint3 size; + TextureI.GetDimensions(size.x, size.y, size.z); + + return int4(TextureI.Load(int4(size * input.TexCoord, 0)).rgb, 0); +} + +float4 PS_PassthroughRG3D(GS_OUTPUT input) : SV_TARGET0 +{ + return float4(TextureF.Sample(Sampler, input.TexCoord).rg, 0.0f, 1.0f); +} + +uint4 PS_PassthroughRG3DUI(GS_OUTPUT input) : SV_TARGET0 +{ + uint3 size; + TextureUI.GetDimensions(size.x, size.y, size.z); + + return uint4(TextureUI.Load(int4(size * input.TexCoord, 0)).rg, 0, 0); +} + +int4 PS_PassthroughRG3DI(GS_OUTPUT input) : SV_TARGET0 +{ + uint3 size; + TextureI.GetDimensions(size.x, size.y, size.z); + + return int4(TextureI.Load(int4(size * input.TexCoord, 0)).rg, 0, 0); +} + +float4 PS_PassthroughR3D(GS_OUTPUT input) : SV_TARGET0 +{ + return float4(TextureF.Sample(Sampler, input.TexCoord).r, 0.0f, 0.0f, 1.0f); +} + +uint4 PS_PassthroughR3DUI(GS_OUTPUT input) : SV_TARGET0 +{ + uint3 size; + TextureUI.GetDimensions(size.x, size.y, size.z); + + return uint4(TextureUI.Load(int4(size * input.TexCoord, 0)).r, 0, 0, 0); +} + +int4 PS_PassthroughR3DI(GS_OUTPUT input) : SV_TARGET0 +{ + uint3 size; + TextureI.GetDimensions(size.x, size.y, size.z); + + return int4(TextureI.Load(int4(size * input.TexCoord, 0)).r, 0, 0, 0); +} + +float4 PS_PassthroughLum3D(GS_OUTPUT input) : SV_TARGET0 +{ + return float4(TextureF.Sample(Sampler, input.TexCoord).rrr, 1.0f); +} + +float4 PS_PassthroughLumAlpha3D(GS_OUTPUT input) : SV_TARGET0 +{ + return TextureF.Sample(Sampler, input.TexCoord).rrra; +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Swizzle11.hlsl b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Swizzle11.hlsl new file mode 100644 index 0000000000..505e222137 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Swizzle11.hlsl @@ -0,0 +1,99 @@ +Texture2D TextureF2D : register(t0); +Texture2D TextureUI2D : register(t0); +Texture2D TextureI2D : register(t0); + +Texture3D TextureF3D : register(t0); +Texture3D TextureUI3D : register(t0); +Texture3D TextureI3D : register(t0); + +Texture2DArray TextureF2DArray : register(t0); +Texture2DArray TextureUI2DArray : register(t0); +Texture2DArray TextureI2DArray : register(t0); + +SamplerState Sampler : register(s0); + +cbuffer SwizzleProperties : register(b0) +{ + uint4 SwizzleIndices : packoffset(c0); +} + +float4 SwizzleLookup(in float4 sample) +{ + float lookup[6] = { sample[0], sample[1], sample[2], sample[3], 0.0f, 1.0f }; + return float4(lookup[SwizzleIndices[0]], lookup[SwizzleIndices[1]], lookup[SwizzleIndices[2]], lookup[SwizzleIndices[3]]); +} + +int4 SwizzleLookup(in int4 sample) +{ + int lookup[6] = { sample[0], sample[1], sample[2], sample[3], 0.0f, 1.0f }; + return int4(lookup[SwizzleIndices[0]], lookup[SwizzleIndices[1]], lookup[SwizzleIndices[2]], lookup[SwizzleIndices[3]]); +} + +uint4 SwizzleLookup(in uint4 sample) +{ + uint lookup[6] = { sample[0], sample[1], sample[2], sample[3], 0.0f, 1.0f }; + return uint4(lookup[SwizzleIndices[0]], lookup[SwizzleIndices[1]], lookup[SwizzleIndices[2]], lookup[SwizzleIndices[3]]); +} + +float4 PS_SwizzleF2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + return SwizzleLookup(TextureF2D.Sample(Sampler, inTexCoord)); +} + +int4 PS_SwizzleI2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + uint2 size; + TextureI2D.GetDimensions(size.x, size.y); + + return SwizzleLookup(TextureI2D.Load(int3(size * inTexCoord, 0))); +} + +uint4 PS_SwizzleUI2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + uint2 size; + TextureUI2D.GetDimensions(size.x, size.y); + + return SwizzleLookup(TextureUI2D.Load(int3(size * inTexCoord, 0))); +} + +float4 PS_SwizzleF3D(in float4 inPosition : SV_POSITION, in uint inLayer : SV_RENDERTARGETARRAYINDEX, in float3 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + return SwizzleLookup(TextureF3D.Sample(Sampler, inTexCoord)); +} + +int4 PS_SwizzleI3D(in float4 inPosition : SV_POSITION, in uint inLayer : SV_RENDERTARGETARRAYINDEX, in float3 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + uint3 size; + TextureI3D.GetDimensions(size.x, size.y, size.z); + + return SwizzleLookup(TextureI3D.Load(int4(size * inTexCoord, 0))); +} + +uint4 PS_SwizzleUI3D(in float4 inPosition : SV_POSITION, in uint inLayer : SV_RENDERTARGETARRAYINDEX, in float3 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + uint3 size; + TextureUI3D.GetDimensions(size.x, size.y, size.z); + + return SwizzleLookup(TextureUI3D.Load(int4(size * inTexCoord, 0))); +} + +float4 PS_SwizzleF2DArray(in float4 inPosition : SV_POSITION, in uint inLayer : SV_RENDERTARGETARRAYINDEX, in float3 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + return SwizzleLookup(TextureF2DArray.Sample(Sampler, float3(inTexCoord.xy, inLayer))); +} + +int4 PS_SwizzleI2DArray(in float4 inPosition : SV_POSITION, in uint inLayer : SV_RENDERTARGETARRAYINDEX, in float3 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + uint3 size; + TextureI2DArray.GetDimensions(size.x, size.y, size.z); + + return SwizzleLookup(TextureI2DArray.Load(int4(size.xy * inTexCoord.xy, inLayer, 0))); +} + +uint4 PS_SwizzleUI2DArray(in float4 inPosition : SV_POSITION, in uint inLayer : SV_RENDERTARGETARRAYINDEX, in float3 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + uint3 size; + TextureUI2DArray.GetDimensions(size.x, size.y, size.z); + + return SwizzleLookup(TextureUI2DArray.Load(int4(size.xy * inTexCoord.xy, inLayer, 0))); +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow.cpp new file mode 100644 index 0000000000..9d8f0bb96c --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow.cpp @@ -0,0 +1,68 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// NativeWindow.cpp: Handler for managing HWND native window types. + +#include "libANGLE/renderer/d3d/d3d11/NativeWindow.h" + +#include "common/debug.h" + +namespace rx +{ + +NativeWindow::NativeWindow(EGLNativeWindowType window) : mWindow(window) +{ +} + +bool NativeWindow::initialize() +{ + return true; +} + +bool NativeWindow::getClientRect(LPRECT rect) +{ + return GetClientRect(mWindow, rect) == TRUE; +} + +bool NativeWindow::isIconic() +{ + return IsIconic(mWindow) == TRUE; +} + +bool NativeWindow::isValidNativeWindow(EGLNativeWindowType window) +{ + return IsWindow(window) == TRUE; +} + +HRESULT NativeWindow::createSwapChain(ID3D11Device* device, DXGIFactory* factory, + DXGI_FORMAT format, unsigned int width, unsigned int height, + DXGISwapChain** swapChain) +{ + if (device == NULL || factory == NULL || swapChain == NULL || width == 0 || height == 0) + { + return E_INVALIDARG; + } + + DXGI_SWAP_CHAIN_DESC swapChainDesc = { 0 }; + swapChainDesc.BufferCount = 1; + swapChainDesc.BufferDesc.Format = format; + swapChainDesc.BufferDesc.Width = width; + swapChainDesc.BufferDesc.Height = height; + 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 | DXGI_USAGE_BACK_BUFFER; + swapChainDesc.Flags = 0; + swapChainDesc.OutputWindow = mWindow; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.Windowed = TRUE; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; + + return factory->CreateSwapChain(device, &swapChainDesc, swapChain); +} +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp new file mode 100644 index 0000000000..350526c867 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp @@ -0,0 +1,214 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// CoreWindowNativeWindow.cpp: NativeWindow for managing ICoreWindow native window types. + +#include "libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h" + +using namespace ABI::Windows::Foundation::Collections; + +namespace rx +{ +CoreWindowNativeWindow::~CoreWindowNativeWindow() +{ + unregisterForSizeChangeEvents(); +} + +bool CoreWindowNativeWindow::initialize(EGLNativeWindowType window, IPropertySet *propertySet) +{ + mOrientationChangedEventToken.value = 0; + ComPtr props = propertySet; + ComPtr win = window; + SIZE swapChainSize = {}; + bool swapChainSizeSpecified = false; + HRESULT result = S_OK; + + // IPropertySet is an optional parameter and can be null. + // If one is specified, cache as an IMap and read the properties + // used for initial host initialization. + if (propertySet) + { + result = props.As(&mPropertyMap); + if (SUCCEEDED(result)) + { + // The EGLRenderSurfaceSizeProperty is optional and may be missing. The IPropertySet + // was prevalidated to contain the EGLNativeWindowType before being passed to + // this host. + result = GetOptionalSizePropertyValue(mPropertyMap, EGLRenderSurfaceSizeProperty, &swapChainSize, &swapChainSizeSpecified); + } + } + + if (SUCCEEDED(result)) + { + result = win.As(&mCoreWindow); + } + + if (SUCCEEDED(result)) + { + // If a swapchain size is specfied, then the automatic resize + // behaviors implemented by the host should be disabled. The swapchain + // will be still be scaled when being rendered to fit the bounds + // of the host. + // Scaling of the swapchain output occurs automatically because if + // the scaling mode setting DXGI_SCALING_STRETCH on the swapchain. + if (swapChainSizeSpecified) + { + mClientRect = { 0, 0, swapChainSize.cx, swapChainSize.cy }; + mSupportsSwapChainResize = false; + } + else + { + result = GetCoreWindowSizeInPixels(mCoreWindow, &mClientRect); + } + } + + if (SUCCEEDED(result)) + { + ComPtr displayInformation; + result = GetActivationFactory(HStringReference(RuntimeClass_Windows_Graphics_Display_DisplayInformation).Get(), &displayInformation); + if (SUCCEEDED(result)) + { + result = displayInformation->GetForCurrentView(&mDisplayInformation); + } + } + + if (SUCCEEDED(result)) + { + mNewClientRect = mClientRect; + mClientRectChanged = false; + return registerForSizeChangeEvents(); + } + + return false; +} + +bool CoreWindowNativeWindow::registerForSizeChangeEvents() +{ + ComPtr sizeChangedHandler; + HRESULT result = Microsoft::WRL::MakeAndInitialize(sizeChangedHandler.ReleaseAndGetAddressOf(), this->shared_from_this()); + if (SUCCEEDED(result)) + { + result = mCoreWindow->add_SizeChanged(sizeChangedHandler.Get(), &mSizeChangedEventToken); + } + +#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) + ComPtr orientationChangedHandler; + result = sizeChangedHandler.As(&orientationChangedHandler); + if (SUCCEEDED(result)) + { + result = mDisplayInformation->add_OrientationChanged(orientationChangedHandler.Get(), &mOrientationChangedEventToken); + } +#endif + + if (SUCCEEDED(result)) + { + return true; + } + + return false; +} + +void CoreWindowNativeWindow::unregisterForSizeChangeEvents() +{ + if (mCoreWindow) + { + (void)mCoreWindow->remove_SizeChanged(mSizeChangedEventToken); + } +#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) + if (mDisplayInformation) + { + (void)mDisplayInformation->remove_OrientationChanged(mOrientationChangedEventToken); + } +#endif + mSizeChangedEventToken.value = 0; + mOrientationChangedEventToken.value = 0; +} + +HRESULT CoreWindowNativeWindow::createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain) +{ + if (device == NULL || factory == NULL || swapChain == NULL || width == 0 || height == 0) + { + return E_INVALIDARG; + } + + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = { 0 }; + swapChainDesc.Width = width; + swapChainDesc.Height = height; + swapChainDesc.Format = format; + swapChainDesc.Stereo = FALSE; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_BACK_BUFFER; + swapChainDesc.BufferCount = 2; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; + swapChainDesc.Scaling = DXGI_SCALING_STRETCH; + + *swapChain = nullptr; + + ComPtr newSwapChain; + HRESULT result = factory->CreateSwapChainForCoreWindow(device, mCoreWindow.Get(), &swapChainDesc, nullptr, newSwapChain.ReleaseAndGetAddressOf()); + if (SUCCEEDED(result)) + { + +#if 0 //(WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) // Qt: allow Windows Phone to resize, but don't modify the backing texture in the swap chain. + // Test if swapchain supports resize. On Windows Phone devices, this will return DXGI_ERROR_UNSUPPORTED. On + // other devices DXGI_ERROR_INVALID_CALL should be returned because the combination of flags passed + // (DXGI_SWAP_CHAIN_FLAG_NONPREROTATED | DXGI_SWAP_CHAIN_FLAG_GDI_COMPATIBLE) are invalid flag combinations. + if (newSwapChain->ResizeBuffers(swapChainDesc.BufferCount, swapChainDesc.Width, swapChainDesc.Height, swapChainDesc.Format, DXGI_SWAP_CHAIN_FLAG_NONPREROTATED | DXGI_SWAP_CHAIN_FLAG_GDI_COMPATIBLE) == DXGI_ERROR_UNSUPPORTED) + { + mSupportsSwapChainResize = false; + } +#endif // (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) + + result = newSwapChain.CopyTo(swapChain); + } + + if (SUCCEEDED(result)) + { + // If automatic swapchain resize behaviors have been disabled, then + // unregister for the resize change events. + if (mSupportsSwapChainResize == false) + { + unregisterForSizeChangeEvents(); + } + } + + return result; +} + +HRESULT GetCoreWindowSizeInPixels(const ComPtr& coreWindow, RECT *windowSize) +{ + ABI::Windows::Foundation::Rect bounds; + HRESULT result = coreWindow->get_Bounds(&bounds); + if (SUCCEEDED(result)) + { + *windowSize = { 0, 0, ConvertDipsToPixels(bounds.Width), ConvertDipsToPixels(bounds.Height) }; + } + + return result; +} + +static float GetLogicalDpi() +{ + ComPtr displayProperties; + float dpi = 96.0f; + + if (SUCCEEDED(GetActivationFactory(HStringReference(RuntimeClass_Windows_Graphics_Display_DisplayProperties).Get(), displayProperties.GetAddressOf()))) + { + if (SUCCEEDED(displayProperties->get_LogicalDpi(&dpi))) + { + return dpi; + } + } + return dpi; +} + +long ConvertDipsToPixels(float dips) +{ + static const float dipsPerInch = 96.0f; + return lround((dips * GetLogicalDpi() / dipsPerInch)); +} +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h new file mode 100644 index 0000000000..59df9d5a6c --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h @@ -0,0 +1,110 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// CoreWindowNativeWindow.h: NativeWindow for managing ICoreWindow native window types. + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_WINRT_COREWINDOWNATIVEWINDOW_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_WINRT_COREWINDOWNATIVEWINDOW_H_ + +#include "libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h" + +#include +#include + +typedef ABI::Windows::Foundation::__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CWindowSizeChangedEventArgs_t IWindowSizeChangedEventHandler; +typedef ABI::Windows::Foundation::__FITypedEventHandler_2_Windows__CGraphics__CDisplay__CDisplayInformation_IInspectable_t IDisplayOrientationEventHandler; + +namespace rx +{ +long ConvertDipsToPixels(float dips); + +class CoreWindowNativeWindow : public InspectableNativeWindow, public std::enable_shared_from_this +{ + public: + ~CoreWindowNativeWindow(); + + bool initialize(EGLNativeWindowType window, IPropertySet *propertySet); + bool registerForSizeChangeEvents(); + void unregisterForSizeChangeEvents(); + HRESULT createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain); + + private: + ComPtr mCoreWindow; + ComPtr> mPropertyMap; + ComPtr mDisplayInformation; + EventRegistrationToken mOrientationChangedEventToken; +}; + +[uuid(7F924F66-EBAE-40E5-A10B-B8F35E245190)] +class CoreWindowSizeChangedHandler : + public Microsoft::WRL::RuntimeClass, IWindowSizeChangedEventHandler, IDisplayOrientationEventHandler> +{ + public: + CoreWindowSizeChangedHandler() { } + HRESULT RuntimeClassInitialize(std::shared_ptr host) + { + if (!host) + { + return E_INVALIDARG; + } + + mHost = host; + return S_OK; + } + + // IWindowSizeChangedEventHandler + IFACEMETHOD(Invoke)(ABI::Windows::UI::Core::ICoreWindow *sender, ABI::Windows::UI::Core::IWindowSizeChangedEventArgs *sizeChangedEventArgs) + { + std::shared_ptr host = mHost.lock(); + if (host) + { + ABI::Windows::Foundation::Size windowSize; + if (SUCCEEDED(sizeChangedEventArgs->get_Size(&windowSize))) + { + SIZE windowSizeInPixels = { ConvertDipsToPixels(windowSize.Width), ConvertDipsToPixels(windowSize.Height) }; + host->setNewClientSize(windowSizeInPixels); + } + } + + return S_OK; + } + + IFACEMETHOD(Invoke)(ABI::Windows::Graphics::Display::IDisplayInformation *displayInformation, IInspectable *) + { +#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) + NativeWindow::RotationFlags flags = NativeWindow::RotateNone; + ABI::Windows::Graphics::Display::DisplayOrientations orientation; + if (SUCCEEDED(displayInformation->get_CurrentOrientation(&orientation))) + { + switch (orientation) + { + case ABI::Windows::Graphics::Display::DisplayOrientations_Landscape: + flags = NativeWindow::RotateLeft; + break; + case ABI::Windows::Graphics::Display::DisplayOrientations_LandscapeFlipped: + flags = NativeWindow::RotateRight; + break; + default: + break; + } + } + std::shared_ptr host = mHost.lock(); + if (host) + { + host->setRotationFlags(flags); + } +#endif + return S_OK; + } + + private: + std::weak_ptr mHost; +}; + +HRESULT GetCoreWindowSizeInPixels(const ComPtr& coreWindow, RECT *windowSize); +} + +#endif // LIBANGLE_RENDERER_D3D_D3D11_WINRT_COREWINDOWNATIVEWINDOW_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.cpp new file mode 100644 index 0000000000..2bf48c5d94 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.cpp @@ -0,0 +1,291 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// InspectableNativeWindow.cpp: NativeWindow base class for managing IInspectable native window types. + +#include "libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h" +#include "libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.h" + +namespace rx +{ +NativeWindow::NativeWindow(EGLNativeWindowType window) +{ + mWindow = window; +} + +bool NativeWindow::initialize() +{ + // If the native window type is a IPropertySet, extract the + // EGLNativeWindowType (IInspectable) and initialize the + // proper host with this IPropertySet. + ComPtr propertySet; + ComPtr eglNativeWindow; + if (IsEGLConfiguredPropertySet(mWindow, &propertySet, &eglNativeWindow)) + { + // A property set was found and the EGLNativeWindowType was + // retrieved. The mWindow member of the host to must be updated + // to use the EGLNativeWindowType specified in the property set. + // mWindow is treated as a raw pointer not an AddRef'd interface, so + // the old mWindow does not need a Release() before this assignment. + mWindow = eglNativeWindow.Get(); + } + + ComPtr coreWindow; + ComPtr swapChainPanel; + if (IsCoreWindow(mWindow, &coreWindow)) + { + mImpl = std::make_shared(); + if (mImpl) + { + return mImpl->initialize(mWindow, propertySet.Get()); + } + } + else if (IsSwapChainPanel(mWindow, &swapChainPanel)) + { + mImpl = std::make_shared(); + if (mImpl) + { + return mImpl->initialize(mWindow, propertySet.Get()); + } + } + else + { + ERR("Invalid IInspectable EGLNativeWindowType detected. Valid IInspectables include ICoreWindow, ISwapChainPanel and IPropertySet"); + } + + return false; +} + +bool NativeWindow::getClientRect(RECT *rect) +{ + if (mImpl) + { + return mImpl->getClientRect(rect); + } + + return false; +} + +#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) +NativeWindow::RotationFlags NativeWindow::rotationFlags() const +{ + if (mImpl) + { + return mImpl->rotationFlags(); + } + + return NativeWindow::RotateNone; +} +#endif + +bool NativeWindow::isIconic() +{ + return false; +} + +bool NativeWindow::isValidNativeWindow(EGLNativeWindowType window) +{ + return IsValidEGLNativeWindowType(window); +} + +HRESULT NativeWindow::createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain) +{ + if (mImpl) + { + return mImpl->createSwapChain(device, factory, format, width, height, swapChain); + } + + return E_UNEXPECTED; +} + +bool IsCoreWindow(EGLNativeWindowType window, ComPtr *coreWindow) +{ + if (!window) + { + return false; + } + + ComPtr win = window; + ComPtr coreWin; + if (SUCCEEDED(win.As(&coreWin))) + { + if (coreWindow != nullptr) + { + *coreWindow = coreWin.Detach(); + } + return true; + } + + return false; +} + +bool IsSwapChainPanel(EGLNativeWindowType window, ComPtr *swapChainPanel) +{ + if (!window) + { + return false; + } + + ComPtr win = window; + ComPtr panel; + if (SUCCEEDED(win.As(&panel))) + { + if (swapChainPanel != nullptr) + { + *swapChainPanel = panel.Detach(); + } + return true; + } + + return false; +} + +bool IsEGLConfiguredPropertySet(EGLNativeWindowType window, ABI::Windows::Foundation::Collections::IPropertySet **propertySet, IInspectable **eglNativeWindow) +{ + if (!window) + { + return false; + } + + ComPtr props = window; + ComPtr propSet; + ComPtr nativeWindow; + ComPtr> propMap; + boolean hasEglNativeWindowPropertyKey = false; + + HRESULT result = props.As(&propSet); + if (SUCCEEDED(result)) + { + result = propSet.As(&propMap); + } + + // Look for the presence of the EGLNativeWindowType in the property set + if (SUCCEEDED(result)) + { + result = propMap->HasKey(HStringReference(EGLNativeWindowTypeProperty).Get(), &hasEglNativeWindowPropertyKey); + } + + // If the IPropertySet does not contain the required EglNativeWindowType key, the property set is + // considered invalid. + if (SUCCEEDED(result) && !hasEglNativeWindowPropertyKey) + { + ERR("Could not find EGLNativeWindowTypeProperty in IPropertySet. Valid EGLNativeWindowTypeProperty values include ICoreWindow"); + return false; + } + + // The EglNativeWindowType property exists, so retreive the IInspectable that represents the EGLNativeWindowType + if (SUCCEEDED(result) && hasEglNativeWindowPropertyKey) + { + result = propMap->Lookup(HStringReference(EGLNativeWindowTypeProperty).Get(), &nativeWindow); + } + + if (SUCCEEDED(result)) + { + if (propertySet != nullptr) + { + result = propSet.CopyTo(propertySet); + } + } + + if (SUCCEEDED(result)) + { + if (eglNativeWindow != nullptr) + { + result = nativeWindow.CopyTo(eglNativeWindow); + } + } + + if (SUCCEEDED(result)) + { + return true; + } + + return false; +} + +// A Valid EGLNativeWindowType IInspectable can only be: +// +// ICoreWindow +// IPropertySet +// +// Anything else will be rejected as an invalid IInspectable. +bool IsValidEGLNativeWindowType(EGLNativeWindowType window) +{ + return IsCoreWindow(window) || IsSwapChainPanel(window) || IsEGLConfiguredPropertySet(window); +} + +// Attempts to read an optional SIZE property value that is assumed to be in the form of +// an ABI::Windows::Foundation::Size. This function validates the Size value before returning +// it to the caller. +// +// Possible return values are: +// S_OK, valueExists == true - optional SIZE value was successfully retrieved and validated +// S_OK, valueExists == false - optional SIZE value was not found +// E_INVALIDARG, valueExists = false - optional SIZE value was malformed in the property set. +// * Incorrect property type ( must be PropertyType_Size) +// * Invalid property value (width/height must be > 0) +// Additional errors may be returned from IMap or IPropertyValue +// +HRESULT GetOptionalSizePropertyValue(const ComPtr>& propertyMap, const wchar_t *propertyName, SIZE *value, bool *valueExists) +{ + if (!propertyMap || !propertyName || !value || !valueExists) + { + return false; + } + + // Assume that the value does not exist + *valueExists = false; + *value = { 0, 0 }; + + ComPtr propertyValue; + ABI::Windows::Foundation::PropertyType propertyType = ABI::Windows::Foundation::PropertyType::PropertyType_Empty; + Size sizeValue = { 0, 0 }; + boolean hasKey = false; + + HRESULT result = propertyMap->HasKey(HStringReference(propertyName).Get(), &hasKey); + if (SUCCEEDED(result) && !hasKey) + { + // Value does not exist, so return S_OK and set the exists parameter to false to indicate + // that a the optional property does not exist. + *valueExists = false; + return S_OK; + } + + if (SUCCEEDED(result)) + { + result = propertyMap->Lookup(HStringReference(propertyName).Get(), &propertyValue); + } + + if (SUCCEEDED(result)) + { + result = propertyValue->get_Type(&propertyType); + } + + // Check if the expected Size property is of PropertyType_Size type. + if (SUCCEEDED(result) && propertyType == ABI::Windows::Foundation::PropertyType::PropertyType_Size) + { + if (SUCCEEDED(propertyValue->GetSize(&sizeValue)) && (sizeValue.Width > 0 && sizeValue.Height > 0)) + { + // A valid property value exists + *value = { static_cast(sizeValue.Width), static_cast(sizeValue.Height) }; + *valueExists = true; + result = S_OK; + } + else + { + // An invalid Size property was detected. Width/Height values must > 0 + result = E_INVALIDARG; + } + } + else + { + // An invalid property type was detected. Size property must be of PropertyType_Size + result = E_INVALIDARG; + } + + return result; +} +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h new file mode 100644 index 0000000000..575bdf8a58 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h @@ -0,0 +1,105 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// InspectableNativeWindow.h: Host specific implementation interface for +// managing IInspectable native window types. + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_WINRT_INSPECTABLENATIVEWINDOW_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_WINRT_INSPECTABLENATIVEWINDOW_H_ + +#include "libANGLE/renderer/d3d/d3d11/NativeWindow.h" + +#include "common/platform.h" + +#include "angle_windowsstore.h" + +#include +#include + +using namespace Microsoft::WRL; +using namespace Microsoft::WRL::Wrappers; +using namespace ABI::Windows::Foundation; +using namespace ABI::Windows::Foundation::Collections; + +namespace rx +{ +class InspectableNativeWindow +{ + public: + InspectableNativeWindow() : + mSupportsSwapChainResize(true), + mRequiresSwapChainScaling(false), + mClientRectChanged(false), + mClientRect({0,0,0,0}), + mNewClientRect({0,0,0,0}), + mRotationFlags(NativeWindow::RotateNone) + { + mSizeChangedEventToken.value = 0; + } + virtual ~InspectableNativeWindow(){} + + virtual bool initialize(EGLNativeWindowType window, IPropertySet *propertySet) = 0; + virtual HRESULT createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain) = 0; + virtual bool registerForSizeChangeEvents() = 0; + virtual void unregisterForSizeChangeEvents() = 0; + virtual HRESULT scaleSwapChain(const SIZE& newSize) { return S_OK; } + + bool getClientRect(RECT *rect) + { + if (mClientRectChanged && mSupportsSwapChainResize) + { + mClientRect = mNewClientRect; + } + + *rect = mClientRect; + + return true; + } + + void setNewClientSize(const SIZE &newSize) + { + if (mSupportsSwapChainResize && !mRequiresSwapChainScaling) + { + mNewClientRect = { 0, 0, newSize.cx, newSize.cy }; + mClientRectChanged = true; + } + + if (mRequiresSwapChainScaling) + { + scaleSwapChain(newSize); + } + } + + NativeWindow::RotationFlags rotationFlags() const + { + return mRotationFlags; + } + + void setRotationFlags(NativeWindow::RotationFlags flags) + { + mRotationFlags = flags; + } + +protected: + bool mSupportsSwapChainResize; + bool mRequiresSwapChainScaling; + RECT mClientRect; + RECT mNewClientRect; + bool mClientRectChanged; + NativeWindow::RotationFlags mRotationFlags; + + EventRegistrationToken mSizeChangedEventToken; +}; + +bool IsValidEGLNativeWindowType(EGLNativeWindowType window); +bool IsCoreWindow(EGLNativeWindowType window, ComPtr *coreWindow = nullptr); +bool IsSwapChainPanel(EGLNativeWindowType window, ComPtr *swapChainPanel = nullptr); +bool IsEGLConfiguredPropertySet(EGLNativeWindowType window, ABI::Windows::Foundation::Collections::IPropertySet **propertySet = nullptr, IInspectable **inspectable = nullptr); +HRESULT GetOptionalSizePropertyValue(const ComPtr>& propertyMap, const wchar_t *propertyName, SIZE *value, bool *valueExists); + +} + +#endif // LIBANGLE_RENDERER_D3D_D3D11_WINRT_INSPECTABLENATIVEWINDOW_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.cpp new file mode 100644 index 0000000000..53899dbb30 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.cpp @@ -0,0 +1,228 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// SwapChainPanelNativeWindow.cpp: NativeWindow for managing ISwapChainPanel native window types. + +#include "libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.h" + +#include +#include + +using namespace ABI::Windows::Foundation::Collections; + +namespace rx +{ +SwapChainPanelNativeWindow::~SwapChainPanelNativeWindow() +{ + unregisterForSizeChangeEvents(); +} + +bool SwapChainPanelNativeWindow::initialize(EGLNativeWindowType window, IPropertySet *propertySet) +{ + ComPtr props = propertySet; + ComPtr win = window; + SIZE swapChainSize = {}; + bool swapChainSizeSpecified = false; + HRESULT result = S_OK; + + // IPropertySet is an optional parameter and can be null. + // If one is specified, cache as an IMap and read the properties + // used for initial host initialization. + if (propertySet) + { + result = props.As(&mPropertyMap); + if (SUCCEEDED(result)) + { + // The EGLRenderSurfaceSizeProperty is optional and may be missing. The IPropertySet + // was prevalidated to contain the EGLNativeWindowType before being passed to + // this host. + result = GetOptionalSizePropertyValue(mPropertyMap, EGLRenderSurfaceSizeProperty, &swapChainSize, &swapChainSizeSpecified); + } + } + + if (SUCCEEDED(result)) + { + result = win.As(&mSwapChainPanel); + } + + if (SUCCEEDED(result)) + { + // If a swapchain size is specfied, then the automatic resize + // behaviors implemented by the host should be disabled. The swapchain + // will be still be scaled when being rendered to fit the bounds + // of the host. + // Scaling of the swapchain output needs to be handled by the + // host for swapchain panels even though the scaling mode setting + // DXGI_SCALING_STRETCH is configured on the swapchain. + if (swapChainSizeSpecified) + { + mClientRect = { 0, 0, swapChainSize.cx, swapChainSize.cy }; + + // Enable host swapchain scaling + mRequiresSwapChainScaling = true; + } + else + { + result = GetSwapChainPanelSize(mSwapChainPanel, &mClientRect); + } + } + + if (SUCCEEDED(result)) + { + mNewClientRect = mClientRect; + mClientRectChanged = false; + return registerForSizeChangeEvents(); + } + + return false; +} + +bool SwapChainPanelNativeWindow::registerForSizeChangeEvents() +{ + ComPtr sizeChangedHandler; + ComPtr frameworkElement; + HRESULT result = Microsoft::WRL::MakeAndInitialize(sizeChangedHandler.ReleaseAndGetAddressOf(), this->shared_from_this()); + + if (SUCCEEDED(result)) + { + result = mSwapChainPanel.As(&frameworkElement); + } + + if (SUCCEEDED(result)) + { + result = frameworkElement->add_SizeChanged(sizeChangedHandler.Get(), &mSizeChangedEventToken); + } + + if (SUCCEEDED(result)) + { + return true; + } + + return false; +} + +void SwapChainPanelNativeWindow::unregisterForSizeChangeEvents() +{ + ComPtr frameworkElement; + if (SUCCEEDED(mSwapChainPanel.As(&frameworkElement))) + { + (void)frameworkElement->remove_SizeChanged(mSizeChangedEventToken); + } + + mSizeChangedEventToken.value = 0; +} + +HRESULT SwapChainPanelNativeWindow::createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain) +{ + if (device == NULL || factory == NULL || swapChain == NULL || width == 0 || height == 0) + { + return E_INVALIDARG; + } + + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = { 0 }; + swapChainDesc.Width = width; + swapChainDesc.Height = height; + swapChainDesc.Format = format; + swapChainDesc.Stereo = FALSE; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_BACK_BUFFER; + swapChainDesc.BufferCount = 2; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; + swapChainDesc.Scaling = DXGI_SCALING_STRETCH; + swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE; + + *swapChain = nullptr; + + ComPtr newSwapChain; + ComPtr swapChainPanelNative; + RECT currentPanelSize = {}; + + HRESULT result = factory->CreateSwapChainForComposition(device, &swapChainDesc, nullptr, newSwapChain.ReleaseAndGetAddressOf()); + + if (SUCCEEDED(result)) + { + result = mSwapChainPanel.As(&swapChainPanelNative); + } + + if (SUCCEEDED(result)) + { + result = swapChainPanelNative->SetSwapChain(newSwapChain.Get()); + } + + if (SUCCEEDED(result)) + { + // The swapchain panel host requires an instance of the swapchain set on the SwapChainPanel + // to perform the runtime-scale behavior. This swapchain is cached here because there are + // no methods for retreiving the currently configured on from ISwapChainPanelNative. + mSwapChain = newSwapChain; + result = newSwapChain.CopyTo(swapChain); + } + + // If the host is responsible for scaling the output of the swapchain, then + // scale it now before returning an instance to the caller. This is done by + // first reading the current size of the swapchain panel, then scaling + if (SUCCEEDED(result) && mRequiresSwapChainScaling) + { + result = GetSwapChainPanelSize(mSwapChainPanel, ¤tPanelSize); + } + + // Scale the swapchain to fit inside the contents of the panel. + if (SUCCEEDED(result) && mRequiresSwapChainScaling) + { + SIZE currentSize = { currentPanelSize.right, currentPanelSize.bottom }; + result = scaleSwapChain(currentSize); + } + + if (SUCCEEDED(result)) + { + // If automatic swapchain resize behaviors have been disabled, then + // unregister for the resize change events. + if (mSupportsSwapChainResize == false) + { + unregisterForSizeChangeEvents(); + } + } + + return result; +} + +HRESULT SwapChainPanelNativeWindow::scaleSwapChain(const SIZE &newSize) +{ + ABI::Windows::Foundation::Size renderScale = { (float)newSize.cx/(float)mClientRect.right, (float)newSize.cy/(float)mClientRect.bottom }; + // Setup a scale matrix for the swap chain + DXGI_MATRIX_3X2_F scaleMatrix = {}; + scaleMatrix._11 = renderScale.Width; + scaleMatrix._22 = renderScale.Height; + + ComPtr swapChain2; + HRESULT result = mSwapChain.As(&swapChain2); + if (SUCCEEDED(result)) + { + result = swapChain2->SetMatrixTransform(&scaleMatrix); + } + + return result; +} + +HRESULT GetSwapChainPanelSize(const ComPtr &swapChainPanel, RECT *windowSize) +{ + ComPtr uiElement; + ABI::Windows::Foundation::Size renderSize = { 0, 0 }; + HRESULT result = swapChainPanel.As(&uiElement); + if (SUCCEEDED(result)) + { + result = uiElement->get_RenderSize(&renderSize); + } + + if (SUCCEEDED(result)) + { + *windowSize = { 0, 0, lround(renderSize.Width), lround(renderSize.Height) }; + } + + return result; +} +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.h new file mode 100644 index 0000000000..caf327d913 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.h @@ -0,0 +1,79 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// SwapChainPanelNativeWindow.h: NativeWindow for managing ISwapChainPanel native window types. + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_WINRT_SWAPCHAINPANELNATIVEWINDOW_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_WINRT_SWAPCHAINPANELNATIVEWINDOW_H_ + +#include "libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h" + +namespace rx +{ +class SwapChainPanelNativeWindow : public InspectableNativeWindow, public std::enable_shared_from_this +{ + public: + ~SwapChainPanelNativeWindow(); + + bool initialize(EGLNativeWindowType window, IPropertySet *propertySet); + bool registerForSizeChangeEvents(); + void unregisterForSizeChangeEvents(); + HRESULT createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain); + HRESULT scaleSwapChain(const SIZE &newSize); + + private: + ComPtr mSwapChainPanel; + ComPtr> mPropertyMap; + ComPtr mSwapChain; +}; + +[uuid(8ACBD974-8187-4508-AD80-AEC77F93CF36)] +class SwapChainPanelSizeChangedHandler : + public Microsoft::WRL::RuntimeClass, ABI::Windows::UI::Xaml::ISizeChangedEventHandler> +{ + public: + SwapChainPanelSizeChangedHandler() { } + HRESULT RuntimeClassInitialize(std::shared_ptr host) + { + if (!host) + { + return E_INVALIDARG; + } + + mHost = host; + return S_OK; + } + + // ISizeChangedEventHandler + IFACEMETHOD(Invoke)(IInspectable *sender, ABI::Windows::UI::Xaml::ISizeChangedEventArgs *sizeChangedEventArgs) + { + std::shared_ptr host = mHost.lock(); + if (host) + { + // The size of the ISwapChainPanel control is returned in DIPs. + // We are keeping these in dips because the swapchain created for composition + // also uses dip units. This keeps dimensions, viewports, etc in the same unit. + // XAML Clients of the ISwapChainPanel are required to use dips to define their + // layout sizes as well. + ABI::Windows::Foundation::Size newSize; + HRESULT result = sizeChangedEventArgs->get_NewSize(&newSize); + if (SUCCEEDED(result)) + { + SIZE windowSize = { lround(newSize.Width), lround(newSize.Height) }; + host->setNewClientSize(windowSize); + } + } + + return S_OK; + } + + private: + std::weak_ptr mHost; +}; + +HRESULT GetSwapChainPanelSize(const ComPtr &swapChainPanel, RECT *windowSize); +} +#endif // LIBANGLE_RENDERER_D3D_D3D11_WINRT_SWAPCHAINPANELNATIVEWINDOW_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Blit9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Blit9.cpp new file mode 100644 index 0000000000..a0bc2960b7 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Blit9.cpp @@ -0,0 +1,679 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Blit9.cpp: Surface copy utility class. + +#include "libANGLE/renderer/d3d/d3d9/Blit9.h" +#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h" +#include "libANGLE/renderer/d3d/d3d9/formatutils9.h" +#include "libANGLE/renderer/d3d/d3d9/TextureStorage9.h" +#include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h" +#include "libANGLE/renderer/d3d/d3d9/Renderer9.h" +#include "libANGLE/angletypes.h" +#include "libANGLE/Framebuffer.h" +#include "libANGLE/FramebufferAttachment.h" + +namespace +{ +// Precompiled shaders +#include "libANGLE/renderer/d3d/d3d9/shaders/compiled/standardvs.h" +#include "libANGLE/renderer/d3d/d3d9/shaders/compiled/flipyvs.h" +#include "libANGLE/renderer/d3d/d3d9/shaders/compiled/passthroughps.h" +#include "libANGLE/renderer/d3d/d3d9/shaders/compiled/luminanceps.h" +#include "libANGLE/renderer/d3d/d3d9/shaders/compiled/componentmaskps.h" + +const BYTE* const g_shaderCode[] = +{ + g_vs20_standardvs, + g_vs20_flipyvs, + g_ps20_passthroughps, + g_ps20_luminanceps, + g_ps20_componentmaskps +}; + +const size_t g_shaderSize[] = +{ + sizeof(g_vs20_standardvs), + sizeof(g_vs20_flipyvs), + sizeof(g_ps20_passthroughps), + sizeof(g_ps20_luminanceps), + sizeof(g_ps20_componentmaskps) +}; +} + +namespace rx +{ + +Blit9::Blit9(Renderer9 *renderer) + : mRenderer(renderer), + mGeometryLoaded(false), + mQuadVertexBuffer(NULL), + mQuadVertexDeclaration(NULL), + mSavedStateBlock(NULL), + mSavedRenderTarget(NULL), + mSavedDepthStencil(NULL) +{ + memset(mCompiledShaders, 0, sizeof(mCompiledShaders)); +} + +Blit9::~Blit9() +{ + SafeRelease(mSavedStateBlock); + SafeRelease(mQuadVertexBuffer); + SafeRelease(mQuadVertexDeclaration); + + for (int i = 0; i < SHADER_COUNT; i++) + { + SafeRelease(mCompiledShaders[i]); + } +} + +gl::Error Blit9::initialize() +{ + if (mGeometryLoaded) + { + return gl::Error(GL_NO_ERROR); + } + + 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, "Failed to create internal blit vertex shader, result: 0x%X.", result); + } + + void *lockPtr = NULL; + result = mQuadVertexBuffer->Lock(0, 0, &lockPtr, 0); + + if (FAILED(result) || lockPtr == NULL) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + SafeRelease(mQuadVertexBuffer); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock internal blit vertex shader, result: 0x%X.", result); + } + + 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); + SafeRelease(mQuadVertexBuffer); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock internal blit vertex declaration, result: 0x%X.", result); + } + + mGeometryLoaded = true; + return gl::Error(GL_NO_ERROR); +} + +template +gl::Error Blit9::setShader(ShaderId source, const char *profile, + gl::Error (Renderer9::*createShader)(const DWORD *, size_t length, D3DShaderType **outShader), + 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]; + + gl::Error error = (mRenderer->*createShader)(reinterpret_cast(shaderCode), shaderSize, &shader); + if (error.isError()) + { + return error; + } + + mCompiledShaders[source] = shader; + } + + HRESULT hr = (device->*setShader)(shader); + if (FAILED(hr)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to set shader for blit operation, result: 0x%X.", hr); + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Blit9::setVertexShader(ShaderId shader) +{ + return setShader(shader, "vs_2_0", &Renderer9::createVertexShader, &IDirect3DDevice9::SetVertexShader); +} + +gl::Error Blit9::setPixelShader(ShaderId shader) +{ + return setShader(shader, "ps_2_0", &Renderer9::createPixelShader, &IDirect3DDevice9::SetPixelShader); +} + +RECT Blit9::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; +} + +gl::Error Blit9::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest) +{ + gl::Error error = initialize(); + if (error.isError()) + { + return error; + } + + IDirect3DTexture9 *texture = NULL; + error = copySurfaceToTexture(source, getSurfaceRect(source), &texture); + if (error.isError()) + { + return error; + } + + 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), gl::Offset(0, 0, 0)); + + render(); + + SafeRelease(texture); + + restoreState(); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Blit9::copy2D(const gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, const gl::Offset &destOffset, TextureStorage *storage, GLint level) +{ + gl::Error error = initialize(); + if (error.isError()) + { + return error; + } + + gl::FramebufferAttachment *colorbuffer = framebuffer->getColorbuffer(0); + ASSERT(colorbuffer); + + RenderTarget9 *renderTarget9 = NULL; + error = d3d9::GetAttachmentRenderTarget(colorbuffer, &renderTarget9); + if (error.isError()) + { + return error; + } + ASSERT(renderTarget9); + + IDirect3DSurface9 *source = renderTarget9->getSurface(); + ASSERT(source); + + IDirect3DSurface9 *destSurface = NULL; + TextureStorage9_2D *storage9 = TextureStorage9_2D::makeTextureStorage9_2D(storage); + error = storage9->getSurfaceLevel(level, true, &destSurface); + if (error.isError()) + { + return error; + } + ASSERT(destSurface); + + gl::Error result = copy(source, sourceRect, destFormat, destOffset, destSurface); + + SafeRelease(destSurface); + SafeRelease(source); + + return result; +} + +gl::Error Blit9::copyCube(const gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, const gl::Offset &destOffset, TextureStorage *storage, GLenum target, GLint level) +{ + gl::Error error = initialize(); + if (error.isError()) + { + return error; + } + + gl::FramebufferAttachment *colorbuffer = framebuffer->getColorbuffer(0); + ASSERT(colorbuffer); + + RenderTarget9 *renderTarget9 = NULL; + error = d3d9::GetAttachmentRenderTarget(colorbuffer, &renderTarget9); + if (error.isError()) + { + return error; + } + ASSERT(renderTarget9); + + IDirect3DSurface9 *source = renderTarget9->getSurface(); + ASSERT(source); + + IDirect3DSurface9 *destSurface = NULL; + TextureStorage9_Cube *storage9 = TextureStorage9_Cube::makeTextureStorage9_Cube(storage); + error = storage9->getCubeMapSurface(target, level, true, &destSurface); + if (error.isError()) + { + return error; + } + ASSERT(destSurface); + + gl::Error result = copy(source, sourceRect, destFormat, destOffset, destSurface); + + SafeRelease(destSurface); + SafeRelease(source); + + return result; +} + +gl::Error Blit9::copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, const gl::Offset &destOffset, IDirect3DSurface9 *dest) +{ + ASSERT(source != NULL && dest != NULL); + + 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 = { destOffset.x, destOffset.y, destOffset.x + (sourceRect.right - sourceRect.left), destOffset.y + (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, "Failed to blit between textures, StretchRect result: 0x%X.", result); + } + + return gl::Error(GL_NO_ERROR); + } + else + { + return formatConvert(source, sourceRect, destFormat, destOffset, dest); + } +} + +gl::Error Blit9::formatConvert(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, const gl::Offset &destOffset, IDirect3DSurface9 *dest) +{ + gl::Error error = initialize(); + if (error.isError()) + { + return error; + } + + IDirect3DTexture9 *texture = NULL; + error = copySurfaceToTexture(source, sourceRect, &texture); + if (error.isError()) + { + return error; + } + + IDirect3DDevice9 *device = mRenderer->getDevice(); + + saveState(); + + device->SetTexture(0, texture); + device->SetRenderTarget(0, dest); + + setViewport(sourceRect, destOffset); + + setCommonBlitState(); + + error = setFormatConvertShaders(destFormat); + if (!error.isError()) + { + render(); + } + + SafeRelease(texture); + + restoreState(); + + return error; +} + +gl::Error Blit9::setFormatConvertShaders(GLenum destFormat) +{ + gl::Error error = setVertexShader(SHADER_VS_STANDARD); + if (error.isError()) + { + return error; + } + + switch (destFormat) + { + default: UNREACHABLE(); + case GL_RGBA: + case GL_BGRA_EXT: + case GL_RGB: + case GL_RG_EXT: + case GL_RED_EXT: + case GL_ALPHA: + error = setPixelShader(SHADER_PS_COMPONENTMASK); + break; + + case GL_LUMINANCE: + case GL_LUMINANCE_ALPHA: + error = setPixelShader(SHADER_PS_LUMINANCE); + break; + } + + if (error.isError()) + { + return error; + } + + 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. + // Allocate one array for both registers and split it into two float4's. + float psConst[8] = { 0 }; + float *multConst = &psConst[0]; + float *addConst = &psConst[4]; + + switch (destFormat) + { + default: UNREACHABLE(); + case GL_RGBA: + case GL_BGRA_EXT: + multConst[X] = 1; + multConst[Y] = 1; + multConst[Z] = 1; + multConst[W] = 1; + addConst[X] = 0; + addConst[Y] = 0; + addConst[Z] = 0; + addConst[W] = 0; + break; + + case GL_RGB: + multConst[X] = 1; + multConst[Y] = 1; + multConst[Z] = 1; + multConst[W] = 0; + addConst[X] = 0; + addConst[Y] = 0; + addConst[Z] = 0; + addConst[W] = 1; + break; + + case GL_RG_EXT: + multConst[X] = 1; + multConst[Y] = 1; + multConst[Z] = 0; + multConst[W] = 0; + addConst[X] = 0; + addConst[Y] = 0; + addConst[Z] = 0; + addConst[W] = 1; + break; + + case GL_RED_EXT: + multConst[X] = 1; + multConst[Y] = 0; + multConst[Z] = 0; + multConst[W] = 0; + addConst[X] = 0; + addConst[Y] = 0; + addConst[Z] = 0; + addConst[W] = 1; + break; + + case GL_ALPHA: + multConst[X] = 0; + multConst[Y] = 0; + multConst[Z] = 0; + multConst[W] = 1; + addConst[X] = 0; + addConst[Y] = 0; + addConst[Z] = 0; + addConst[W] = 0; + break; + + case GL_LUMINANCE: + multConst[X] = 1; + multConst[Y] = 0; + multConst[Z] = 0; + multConst[W] = 0; + addConst[X] = 0; + addConst[Y] = 0; + addConst[Z] = 0; + addConst[W] = 1; + break; + + case GL_LUMINANCE_ALPHA: + multConst[X] = 1; + multConst[Y] = 0; + multConst[Z] = 0; + multConst[W] = 1; + addConst[X] = 0; + addConst[Y] = 0; + addConst[Z] = 0; + addConst[W] = 0; + break; + } + + mRenderer->getDevice()->SetPixelShaderConstantF(0, psConst, 2); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Blit9::copySurfaceToTexture(IDirect3DSurface9 *surface, const RECT &sourceRect, IDirect3DTexture9 **outTexture) +{ + ASSERT(surface); + + 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, "Failed to allocate internal texture for blit, result: 0x%X.", result); + } + + IDirect3DSurface9 *textureSurface; + result = texture->GetSurfaceLevel(0, &textureSurface); + + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + SafeRelease(texture); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to query surface of internal blit texture, result: 0x%X.", result); + } + + mRenderer->endScene(); + result = device->StretchRect(surface, &sourceRect, textureSurface, NULL, D3DTEXF_NONE); + + SafeRelease(textureSurface); + + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + SafeRelease(texture); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to copy between internal blit textures, result: 0x%X.", result); + } + + *outTexture = texture; + return gl::Error(GL_NO_ERROR); +} + +void Blit9::setViewport(const RECT &sourceRect, const gl::Offset &offset) +{ + IDirect3DDevice9 *device = mRenderer->getDevice(); + + D3DVIEWPORT9 vp; + vp.X = offset.x; + vp.Y = offset.y; + 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 Blit9::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 Blit9::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 Blit9::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[8] = { 0 }; + + device->SetVertexShader(NULL); + device->SetVertexShaderConstantF(0, dummyConst, 2); + device->SetPixelShader(NULL); + device->SetPixelShaderConstantF(0, dummyConst, 2); + + 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 Blit9::restoreState() +{ + IDirect3DDevice9 *device = mRenderer->getDevice(); + + device->SetDepthStencilSurface(mSavedDepthStencil); + SafeRelease(mSavedDepthStencil); + + device->SetRenderTarget(0, mSavedRenderTarget); + SafeRelease(mSavedRenderTarget); + + ASSERT(mSavedStateBlock != NULL); + + if (mSavedStateBlock != NULL) + { + mSavedStateBlock->Apply(); + } +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Blit9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Blit9.h new file mode 100644 index 0000000000..586abd2580 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Blit9.h @@ -0,0 +1,97 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Blit9.cpp: Surface copy utility class. + +#ifndef LIBANGLE_RENDERER_D3D_D3D9_BLIT9_H_ +#define LIBANGLE_RENDERER_D3D_D3D9_BLIT9_H_ + +#include "common/angleutils.h" +#include "libANGLE/Error.h" + +#include + +namespace gl +{ +class Framebuffer; +struct Offset; +} + +namespace rx +{ +class Renderer9; +class TextureStorage; + +class Blit9 : angle::NonCopyable +{ + public: + explicit Blit9(Renderer9 *renderer); + ~Blit9(); + + gl::Error initialize(); + + // Copy from source surface to dest surface. + // sourceRect, xoffset, yoffset are in D3D coordinates (0,0 in upper-left) + gl::Error copy2D(const gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, const gl::Offset &destOffset, TextureStorage *storage, GLint level); + gl::Error copyCube(const gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, const gl::Offset &destOffset, TextureStorage *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. + gl::Error formatConvert(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, const gl::Offset &destOffset, IDirect3DSurface9 *dest); + + // 2x2 box filter sample from source to dest. + // Requires that source is RGB(A) and dest has the same format as source. + gl::Error boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest); + + private: + Renderer9 *mRenderer; + + bool mGeometryLoaded; + IDirect3DVertexBuffer9 *mQuadVertexBuffer; + IDirect3DVertexDeclaration9 *mQuadVertexDeclaration; + + gl::Error setFormatConvertShaders(GLenum destFormat); + + gl::Error copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, const gl::Offset &destOffset, IDirect3DSurface9 *dest); + gl::Error copySurfaceToTexture(IDirect3DSurface9 *surface, const RECT &sourceRect, IDirect3DTexture9 **outTexture); + void setViewport(const RECT &sourceRect, const gl::Offset &offset); + 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 + gl::Error setShader(ShaderId source, const char *profile, + gl::Error (Renderer9::*createShader)(const DWORD *, size_t length, D3DShaderType **outShader), + HRESULT (WINAPI IDirect3DDevice9::*setShader)(D3DShaderType*)); + + gl::Error setVertexShader(ShaderId shader); + gl::Error setPixelShader(ShaderId shader); + void render(); + + void saveState(); + void restoreState(); + IDirect3DStateBlock9 *mSavedStateBlock; + IDirect3DSurface9 *mSavedRenderTarget; + IDirect3DSurface9 *mSavedDepthStencil; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_D3D9_BLIT9_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.cpp new file mode 100644 index 0000000000..b051c81aa8 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.cpp @@ -0,0 +1,116 @@ +// +// Copyright 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Buffer9.cpp Defines the Buffer9 class. + +#include "libANGLE/renderer/d3d/d3d9/Buffer9.h" +#include "libANGLE/renderer/d3d/d3d9/Renderer9.h" + +namespace rx +{ + +Buffer9::Buffer9(Renderer9 *renderer) + : BufferD3D(renderer), + mRenderer(renderer), + mSize(0) +{} + +Buffer9::~Buffer9() +{ + mSize = 0; +} + +Buffer9 *Buffer9::makeBuffer9(BufferImpl *buffer) +{ + ASSERT(HAS_DYNAMIC_TYPE(Buffer9*, buffer)); + return static_cast(buffer); +} + +gl::Error Buffer9::setData(const void* data, size_t size, GLenum usage) +{ + if (size > mMemory.size()) + { + if (!mMemory.resize(size)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to resize internal buffer."); + } + } + + mSize = size; + if (data && size > 0) + { + memcpy(mMemory.data(), data, size); + } + + invalidateStaticData(); + + if (usage == GL_STATIC_DRAW) + { + initializeStaticData(); + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Buffer9::getData(const uint8_t **outData) +{ + *outData = mMemory.data(); + return gl::Error(GL_NO_ERROR); +} + +gl::Error Buffer9::setSubData(const void* data, size_t size, size_t offset) +{ + if (offset + size > mMemory.size()) + { + if (!mMemory.resize(offset + size)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to resize internal buffer."); + } + } + + mSize = std::max(mSize, offset + size); + if (data && size > 0) + { + memcpy(mMemory.data() + offset, data, size); + } + + invalidateStaticData(); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Buffer9::copySubData(BufferImpl* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size) +{ + // Note: this method is currently unreachable + Buffer9* sourceBuffer = makeBuffer9(source); + ASSERT(sourceBuffer); + + memcpy(mMemory.data() + destOffset, sourceBuffer->mMemory.data() + sourceOffset, size); + + invalidateStaticData(); + + return gl::Error(GL_NO_ERROR); +} + +// We do not support buffer mapping in D3D9 +gl::Error Buffer9::map(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr) +{ + UNREACHABLE(); + return gl::Error(GL_INVALID_OPERATION); +} + +gl::Error Buffer9::unmap() +{ + UNREACHABLE(); + return gl::Error(GL_INVALID_OPERATION); +} + +void Buffer9::markTransformFeedbackUsage() +{ + UNREACHABLE(); +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.h new file mode 100644 index 0000000000..c1984146fc --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.h @@ -0,0 +1,49 @@ +// +// Copyright 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Buffer9.h: Defines the rx::Buffer9 class which implements rx::BufferImpl via rx::BufferD3D. + +#ifndef LIBANGLE_RENDERER_D3D_D3D9_BUFFER9_H_ +#define LIBANGLE_RENDERER_D3D_D3D9_BUFFER9_H_ + +#include "common/MemoryBuffer.h" +#include "libANGLE/angletypes.h" +#include "libANGLE/renderer/d3d/BufferD3D.h" + +namespace rx +{ +class Renderer9; + +class Buffer9 : public BufferD3D +{ + public: + Buffer9(Renderer9 *renderer); + virtual ~Buffer9(); + + static Buffer9 *makeBuffer9(BufferImpl *buffer); + + // BufferD3D implementation + virtual size_t getSize() const { return mSize; } + virtual bool supportsDirectBinding() const { return false; } + + // BufferImpl implementation + virtual gl::Error setData(const void* data, size_t size, GLenum usage); + gl::Error getData(const uint8_t **outData) override; + virtual gl::Error setSubData(const void* data, size_t size, size_t offset); + virtual gl::Error copySubData(BufferImpl* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size); + virtual gl::Error map(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr); + virtual gl::Error unmap(); + virtual void markTransformFeedbackUsage(); + + private: + Renderer9 *mRenderer; + MemoryBuffer mMemory; + size_t mSize; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_D3D9_BUFFER9_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/DebugAnnotator9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/DebugAnnotator9.cpp new file mode 100644 index 0000000000..09b229bcb1 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/DebugAnnotator9.cpp @@ -0,0 +1,36 @@ +// +// Copyright 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// DebugAnnotator9.h: D3D9 helpers for adding trace annotations. +// + +#include "libANGLE/renderer/d3d/d3d9/DebugAnnotator9.h" + +#include "common/platform.h" + +namespace rx +{ + +void DebugAnnotator9::beginEvent(const std::wstring &eventName) +{ + D3DPERF_BeginEvent(0, eventName.c_str()); +} + +void DebugAnnotator9::endEvent() +{ + D3DPERF_EndEvent(); +} + +void DebugAnnotator9::setMarker(const std::wstring &markerName) +{ + D3DPERF_SetMarker(0, markerName.c_str()); +} + +bool DebugAnnotator9::getStatus() +{ + return !!D3DPERF_GetStatus(); +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/DebugAnnotator9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/DebugAnnotator9.h new file mode 100644 index 0000000000..02956f7183 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/DebugAnnotator9.h @@ -0,0 +1,29 @@ +// +// Copyright 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// DebugAnnotator9.h: D3D9 helpers for adding trace annotations. +// + +#ifndef LIBANGLE_RENDERER_D3D_D3D9_DEBUGANNOTATOR9_H_ +#define LIBANGLE_RENDERER_D3D_D3D9_DEBUGANNOTATOR9_H_ + +#include "common/debug.h" + +namespace rx +{ + +class DebugAnnotator9 : public gl::DebugAnnotator +{ + public: + DebugAnnotator9() {} + void beginEvent(const std::wstring &eventName) override; + void endEvent() override; + void setMarker(const std::wstring &markerName) override; + bool getStatus() override; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_D3D9_DEBUGANNOTATOR9_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Fence9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Fence9.cpp new file mode 100644 index 0000000000..27c265e28d --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Fence9.cpp @@ -0,0 +1,90 @@ +// +// 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::FenceNV9 class. + +#include "libANGLE/renderer/d3d/d3d9/Fence9.h" +#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h" +#include "libANGLE/renderer/d3d/d3d9/Renderer9.h" + +namespace rx +{ + +FenceNV9::FenceNV9(Renderer9 *renderer) + : FenceNVImpl(), + mRenderer(renderer), + mQuery(NULL) +{ +} + +FenceNV9::~FenceNV9() +{ + SafeRelease(mQuery); +} + +gl::Error FenceNV9::set() +{ + if (!mQuery) + { + gl::Error error = mRenderer->allocateEventQuery(&mQuery); + if (error.isError()) + { + return error; + } + } + + HRESULT result = mQuery->Issue(D3DISSUE_END); + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + SafeRelease(mQuery); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to end event query, result: 0x%X.", result); + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error FenceNV9::test(bool flushCommandBuffer, GLboolean *outFinished) +{ + ASSERT(mQuery); + + DWORD getDataFlags = (flushCommandBuffer ? D3DGETDATA_FLUSH : 0); + HRESULT result = mQuery->GetData(NULL, 0, getDataFlags); + + if (d3d9::isDeviceLostError(result)) + { + mRenderer->notifyDeviceLost(); + return gl::Error(GL_OUT_OF_MEMORY, "Device was lost while querying result of an event query."); + } + else if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to get query data, result: 0x%X.", result); + } + + ASSERT(result == S_OK || result == S_FALSE); + *outFinished = ((result == S_OK) ? GL_TRUE : GL_FALSE); + return gl::Error(GL_NO_ERROR); +} + +gl::Error FenceNV9::finishFence(GLboolean *outFinished) +{ + ASSERT(outFinished); + + while (*outFinished != GL_TRUE) + { + gl::Error error = test(true, outFinished); + if (error.isError()) + { + return error; + } + + Sleep(0); + } + + return gl::Error(GL_NO_ERROR); +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Fence9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Fence9.h new file mode 100644 index 0000000000..4b86747396 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Fence9.h @@ -0,0 +1,36 @@ +// +// 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::FenceNV9 class which implements rx::FenceNVImpl. + +#ifndef LIBANGLE_RENDERER_D3D_D3D9_FENCE9_H_ +#define LIBANGLE_RENDERER_D3D_D3D9_FENCE9_H_ + +#include "libANGLE/renderer/FenceNVImpl.h" +#include "libANGLE/renderer/FenceSyncImpl.h" + +namespace rx +{ +class Renderer9; + +class FenceNV9 : public FenceNVImpl +{ + public: + explicit FenceNV9(Renderer9 *renderer); + virtual ~FenceNV9(); + + gl::Error set(); + gl::Error test(bool flushCommandBuffer, GLboolean *outFinished); + gl::Error finishFence(GLboolean *outFinished); + + private: + Renderer9 *mRenderer; + IDirect3DQuery9 *mQuery; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_D3D9_FENCE9_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp new file mode 100644 index 0000000000..dbdfc6d6de --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp @@ -0,0 +1,422 @@ +// +// Copyright 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Framebuffer9.cpp: Implements the Framebuffer9 class. + +#include "libANGLE/renderer/d3d/d3d9/Framebuffer9.h" +#include "libANGLE/renderer/d3d/d3d9/formatutils9.h" +#include "libANGLE/renderer/d3d/d3d9/TextureStorage9.h" +#include "libANGLE/renderer/d3d/d3d9/Renderer9.h" +#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h" +#include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h" +#include "libANGLE/renderer/d3d/TextureD3D.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/Framebuffer.h" +#include "libANGLE/FramebufferAttachment.h" +#include "libANGLE/Texture.h" + +namespace rx +{ + +Framebuffer9::Framebuffer9(const gl::Framebuffer::Data &data, Renderer9 *renderer) + : FramebufferD3D(data, renderer), + mRenderer(renderer) +{ + ASSERT(mRenderer != nullptr); +} + +Framebuffer9::~Framebuffer9() +{ +} + +gl::Error Framebuffer9::clear(const gl::State &state, const ClearParameters &clearParams) +{ + const gl::FramebufferAttachment *colorAttachment = mData.mColorAttachments[0]; + const gl::FramebufferAttachment *depthStencilAttachment = mData.getDepthOrStencilAttachment(); + + gl::Error error = mRenderer->applyRenderTarget(colorAttachment, depthStencilAttachment); + if (error.isError()) + { + return error; + } + + float nearZ, farZ; + state.getDepthRange(&nearZ, &farZ); + mRenderer->setViewport(state.getViewport(), nearZ, farZ, GL_TRIANGLES, state.getRasterizerState().frontFace, true); + + mRenderer->setScissorRectangle(state.getScissor(), state.isScissorTestEnabled()); + + return mRenderer->clear(clearParams, colorAttachment, depthStencilAttachment); +} + +gl::Error Framebuffer9::readPixels(const gl::Rectangle &area, GLenum format, GLenum type, size_t outputPitch, const gl::PixelPackState &pack, uint8_t *pixels) const +{ + ASSERT(pack.pixelBuffer.get() == NULL); + + const gl::FramebufferAttachment *colorbuffer = mData.mColorAttachments[0]; + ASSERT(colorbuffer); + + RenderTarget9 *renderTarget = NULL; + gl::Error error = d3d9::GetAttachmentRenderTarget(colorbuffer, &renderTarget); + if (error.isError()) + { + return error; + } + ASSERT(renderTarget); + + IDirect3DSurface9 *surface = renderTarget->getSurface(); + ASSERT(surface); + + D3DSURFACE_DESC desc; + surface->GetDesc(&desc); + + if (desc.MultiSampleType != D3DMULTISAMPLE_NONE) + { + UNIMPLEMENTED(); // FIXME: Requires resolve using StretchRect into non-multisampled render target + SafeRelease(surface); + return gl::Error(GL_OUT_OF_MEMORY, "ReadPixels is unimplemented for multisampled framebuffer attachments."); + } + + IDirect3DDevice9 *device = mRenderer->getDevice(); + ASSERT(device); + + HRESULT result; + IDirect3DSurface9 *systemSurface = NULL; + bool directToPixels = !pack.reverseRowOrder && pack.alignment <= 4 && mRenderer->getShareHandleSupport() && + area.x == 0 && area.y == 0 && + static_cast(area.width) == desc.Width && static_cast(area.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 = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, + D3DPOOL_SYSTEMMEM, &systemSurface, reinterpret_cast(&pixels)); + if (FAILED(result)) + { + // Try again without the shared handle + directToPixels = false; + } + } + + if (!directToPixels) + { + result = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, + D3DPOOL_SYSTEMMEM, &systemSurface, NULL); + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + SafeRelease(surface); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal texture for ReadPixels."); + } + } + + result = device->GetRenderTargetData(surface, systemSurface); + SafeRelease(surface); + + if (FAILED(result)) + { + SafeRelease(systemSurface); + + // It turns out that D3D will sometimes produce more error + // codes than those documented. + if (d3d9::isDeviceLostError(result)) + { + mRenderer->notifyDeviceLost(); + } + else + { + UNREACHABLE(); + } + + return gl::Error(GL_OUT_OF_MEMORY, "Failed to read internal render target data."); + } + + if (directToPixels) + { + SafeRelease(systemSurface); + return gl::Error(GL_NO_ERROR); + } + + RECT rect; + rect.left = gl::clamp(area.x, 0L, static_cast(desc.Width)); + rect.top = gl::clamp(area.y, 0L, static_cast(desc.Height)); + rect.right = gl::clamp(area.x + area.width, 0L, static_cast(desc.Width)); + rect.bottom = gl::clamp(area.y + area.height, 0L, static_cast(desc.Height)); + + D3DLOCKED_RECT lock; + result = systemSurface->LockRect(&lock, &rect, D3DLOCK_READONLY); + + if (FAILED(result)) + { + UNREACHABLE(); + SafeRelease(systemSurface); + + return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock internal render target."); + } + + uint8_t *source; + int inputPitch; + if (pack.reverseRowOrder) + { + source = reinterpret_cast(lock.pBits) + lock.Pitch * (rect.bottom - rect.top - 1); + inputPitch = -lock.Pitch; + } + else + { + source = reinterpret_cast(lock.pBits); + inputPitch = lock.Pitch; + } + + const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(desc.Format); + const gl::InternalFormat &sourceFormatInfo = gl::GetInternalFormatInfo(d3dFormatInfo.internalFormat); + if (sourceFormatInfo.format == format && sourceFormatInfo.type == type) + { + // Direct copy possible + for (int y = 0; y < rect.bottom - rect.top; y++) + { + memcpy(pixels + y * outputPitch, source + y * inputPitch, (rect.right - rect.left) * sourceFormatInfo.pixelBytes); + } + } + else + { + const d3d9::D3DFormat &sourceD3DFormatInfo = d3d9::GetD3DFormatInfo(desc.Format); + ColorCopyFunction fastCopyFunc = sourceD3DFormatInfo.getFastCopyFunction(format, type); + + GLenum sizedDestInternalFormat = gl::GetSizedInternalFormat(format, type); + const gl::InternalFormat &destFormatInfo = gl::GetInternalFormatInfo(sizedDestInternalFormat); + + if (fastCopyFunc) + { + // Fast copy is possible through some special function + for (int y = 0; y < rect.bottom - rect.top; y++) + { + for (int x = 0; x < rect.right - rect.left; x++) + { + uint8_t *dest = pixels + y * outputPitch + x * destFormatInfo.pixelBytes; + const uint8_t *src = source + y * inputPitch + x * sourceFormatInfo.pixelBytes; + + fastCopyFunc(src, dest); + } + } + } + else + { + ColorReadFunction colorReadFunction = sourceD3DFormatInfo.colorReadFunction; + ColorWriteFunction colorWriteFunction = GetColorWriteFunction(format, type); + + uint8_t temp[sizeof(gl::ColorF)]; + for (int y = 0; y < rect.bottom - rect.top; y++) + { + for (int x = 0; x < rect.right - rect.left; x++) + { + uint8_t *dest = pixels + y * outputPitch + x * destFormatInfo.pixelBytes; + const uint8_t *src = source + y * inputPitch + x * sourceFormatInfo.pixelBytes; + + // readFunc and writeFunc will be using the same type of color, CopyTexImage + // will not allow the copy otherwise. + colorReadFunction(src, temp); + colorWriteFunction(temp, dest); + } + } + } + } + + systemSurface->UnlockRect(); + SafeRelease(systemSurface); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Framebuffer9::blit(const gl::Rectangle &sourceArea, const gl::Rectangle &destArea, const gl::Rectangle *scissor, + bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter, + const gl::Framebuffer *sourceFramebuffer) +{ + ASSERT(filter == GL_NEAREST); + + IDirect3DDevice9 *device = mRenderer->getDevice(); + ASSERT(device); + + mRenderer->endScene(); + + if (blitRenderTarget) + { + const gl::FramebufferAttachment *readBuffer = sourceFramebuffer->getColorbuffer(0); + ASSERT(readBuffer); + + RenderTarget9 *readRenderTarget = NULL; + gl::Error error = d3d9::GetAttachmentRenderTarget(readBuffer, &readRenderTarget); + if (error.isError()) + { + return error; + } + ASSERT(readRenderTarget); + + const gl::FramebufferAttachment *drawBuffer = mData.mColorAttachments[0]; + ASSERT(drawBuffer); + + RenderTarget9 *drawRenderTarget = NULL; + error = d3d9::GetAttachmentRenderTarget(drawBuffer, &drawRenderTarget); + if (error.isError()) + { + return error; + } + ASSERT(drawRenderTarget); + + // The getSurface calls do an AddRef so save them until after no errors are possible + IDirect3DSurface9* readSurface = readRenderTarget->getSurface(); + ASSERT(readSurface); + + IDirect3DSurface9* drawSurface = drawRenderTarget->getSurface(); + ASSERT(drawSurface); + + gl::Extents srcSize(readRenderTarget->getWidth(), readRenderTarget->getHeight(), 1); + gl::Extents dstSize(drawRenderTarget->getWidth(), drawRenderTarget->getHeight(), 1); + + RECT srcRect; + srcRect.left = sourceArea.x; + srcRect.right = sourceArea.x + sourceArea.width; + srcRect.top = sourceArea.y; + srcRect.bottom = sourceArea.y + sourceArea.height; + + RECT dstRect; + dstRect.left = destArea.x; + dstRect.right = destArea.x + destArea.width; + dstRect.top = destArea.y; + dstRect.bottom = destArea.y + destArea.height; + + // Clip the rectangles to the scissor rectangle + if (scissor) + { + if (dstRect.left < scissor->x) + { + srcRect.left += (scissor->x - dstRect.left); + dstRect.left = scissor->x; + } + if (dstRect.top < scissor->y) + { + srcRect.top += (scissor->y - dstRect.top); + dstRect.top = scissor->y; + } + if (dstRect.right > scissor->x + scissor->width) + { + srcRect.right -= (dstRect.right - (scissor->x + scissor->width)); + dstRect.right = scissor->x + scissor->width; + } + if (dstRect.bottom > scissor->y + scissor->height) + { + srcRect.bottom -= (dstRect.bottom - (scissor->y + scissor->height)); + dstRect.bottom = scissor->y + scissor->height; + } + } + + // Clip the rectangles to the destination size + if (dstRect.left < 0) + { + srcRect.left += -dstRect.left; + dstRect.left = 0; + } + if (dstRect.right > dstSize.width) + { + srcRect.right -= (dstRect.right - dstSize.width); + dstRect.right = dstSize.width; + } + if (dstRect.top < 0) + { + srcRect.top += -dstRect.top; + dstRect.top = 0; + } + if (dstRect.bottom > dstSize.height) + { + srcRect.bottom -= (dstRect.bottom - dstSize.height); + dstRect.bottom = dstSize.height; + } + + // Clip the rectangles to the source size + if (srcRect.left < 0) + { + dstRect.left += -srcRect.left; + srcRect.left = 0; + } + if (srcRect.right > srcSize.width) + { + dstRect.right -= (srcRect.right - srcSize.width); + srcRect.right = srcSize.width; + } + if (srcRect.top < 0) + { + dstRect.top += -srcRect.top; + srcRect.top = 0; + } + if (srcRect.bottom > srcSize.height) + { + dstRect.bottom -= (srcRect.bottom - srcSize.height); + srcRect.bottom = srcSize.height; + } + + HRESULT result = device->StretchRect(readSurface, &srcRect, drawSurface, &dstRect, D3DTEXF_NONE); + + SafeRelease(readSurface); + SafeRelease(drawSurface); + + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Internal blit failed, StretchRect returned 0x%X.", result); + } + } + + if (blitDepth || blitStencil) + { + const gl::FramebufferAttachment *readBuffer = sourceFramebuffer->getDepthOrStencilbuffer(); + ASSERT(readBuffer); + + RenderTarget9 *readDepthStencil = NULL; + gl::Error error = d3d9::GetAttachmentRenderTarget(readBuffer, &readDepthStencil); + if (error.isError()) + { + return error; + } + ASSERT(readDepthStencil); + + const gl::FramebufferAttachment *drawBuffer = mData.getDepthOrStencilAttachment(); + ASSERT(drawBuffer); + + RenderTarget9 *drawDepthStencil = NULL; + error = d3d9::GetAttachmentRenderTarget(drawBuffer, &drawDepthStencil); + if (error.isError()) + { + return error; + } + ASSERT(drawDepthStencil); + + // The getSurface calls do an AddRef so save them until after no errors are possible + IDirect3DSurface9* readSurface = readDepthStencil->getSurface(); + ASSERT(readDepthStencil); + + IDirect3DSurface9* drawSurface = drawDepthStencil->getSurface(); + ASSERT(drawDepthStencil); + + HRESULT result = device->StretchRect(readSurface, NULL, drawSurface, NULL, D3DTEXF_NONE); + + SafeRelease(readSurface); + SafeRelease(drawSurface); + + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Internal blit failed, StretchRect returned 0x%X.", result); + } + } + + return gl::Error(GL_NO_ERROR); +} + +GLenum Framebuffer9::getRenderTargetImplementationFormat(RenderTargetD3D *renderTarget) const +{ + RenderTarget9 *renderTarget9 = RenderTarget9::makeRenderTarget9(renderTarget); + const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(renderTarget9->getD3DFormat()); + return d3dFormatInfo.internalFormat; +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.h new file mode 100644 index 0000000000..292118e6db --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.h @@ -0,0 +1,41 @@ +// +// Copyright 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Framebuffer9.h: Defines the Framebuffer9 class. + +#ifndef LIBANGLE_RENDERER_D3D_D3D9_FRAMBUFFER9_H_ +#define LIBANGLE_RENDERER_D3D_D3D9_FRAMBUFFER9_H_ + +#include "libANGLE/renderer/d3d/FramebufferD3D.h" + +namespace rx +{ +class Renderer9; + +class Framebuffer9 : public FramebufferD3D +{ + public: + Framebuffer9(const gl::Framebuffer::Data &data, Renderer9 *renderer); + virtual ~Framebuffer9(); + + private: + gl::Error clear(const gl::State &state, const ClearParameters &clearParams) override; + + gl::Error readPixels(const gl::Rectangle &area, GLenum format, GLenum type, size_t outputPitch, + const gl::PixelPackState &pack, uint8_t *pixels) const override; + + gl::Error blit(const gl::Rectangle &sourceArea, const gl::Rectangle &destArea, const gl::Rectangle *scissor, + bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter, + const gl::Framebuffer *sourceFramebuffer) override; + + GLenum getRenderTargetImplementationFormat(RenderTargetD3D *renderTarget) const override; + + Renderer9 *const mRenderer; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_D3D9_FRAMBUFFER9_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Image9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Image9.cpp new file mode 100644 index 0000000000..d149f7a806 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Image9.cpp @@ -0,0 +1,788 @@ +// +// 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 "libANGLE/renderer/d3d/d3d9/Image9.h" +#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h" +#include "libANGLE/renderer/d3d/d3d9/formatutils9.h" +#include "libANGLE/renderer/d3d/d3d9/Renderer9.h" +#include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h" +#include "libANGLE/renderer/d3d/d3d9/TextureStorage9.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/Framebuffer.h" +#include "libANGLE/FramebufferAttachment.h" +#include "libANGLE/Renderbuffer.h" +#include "common/utilities.h" + +namespace rx +{ + +Image9::Image9(Renderer9 *renderer) +{ + mSurface = NULL; + mRenderer = NULL; + + mD3DPool = D3DPOOL_SYSTEMMEM; + mD3DFormat = D3DFMT_UNKNOWN; + + mRenderer = renderer; +} + +Image9::~Image9() +{ + SafeRelease(mSurface); +} + +gl::Error Image9::generateMip(IDirect3DSurface9 *destSurface, IDirect3DSurface9 *sourceSurface) +{ + D3DSURFACE_DESC destDesc; + HRESULT result = destSurface->GetDesc(&destDesc); + ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to query the source surface description for mipmap generation, result: 0x%X.", result); + } + + D3DSURFACE_DESC sourceDesc; + result = sourceSurface->GetDesc(&sourceDesc); + ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to query the destination surface description for mipmap generation, result: 0x%X.", result); + } + + ASSERT(sourceDesc.Format == destDesc.Format); + ASSERT(sourceDesc.Width == 1 || sourceDesc.Width / 2 == destDesc.Width); + ASSERT(sourceDesc.Height == 1 || sourceDesc.Height / 2 == destDesc.Height); + + const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(sourceDesc.Format); + ASSERT(d3dFormatInfo.mipGenerationFunction != NULL); + + D3DLOCKED_RECT sourceLocked = {0}; + result = sourceSurface->LockRect(&sourceLocked, NULL, D3DLOCK_READONLY); + ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock the source surface for mipmap generation, result: 0x%X.", result); + } + + D3DLOCKED_RECT destLocked = {0}; + result = destSurface->LockRect(&destLocked, NULL, 0); + ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + sourceSurface->UnlockRect(); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock the destination surface for mipmap generation, result: 0x%X.", result); + } + + const uint8_t *sourceData = reinterpret_cast(sourceLocked.pBits); + uint8_t *destData = reinterpret_cast(destLocked.pBits); + + ASSERT(sourceData && destData); + + d3dFormatInfo.mipGenerationFunction(sourceDesc.Width, sourceDesc.Height, 1, sourceData, sourceLocked.Pitch, 0, + destData, destLocked.Pitch, 0); + + destSurface->UnlockRect(); + sourceSurface->UnlockRect(); + + return gl::Error(GL_NO_ERROR); +} + +Image9 *Image9::makeImage9(ImageD3D *img) +{ + ASSERT(HAS_DYNAMIC_TYPE(Image9*, img)); + return static_cast(img); +} + +gl::Error Image9::generateMipmap(Image9 *dest, Image9 *source) +{ + IDirect3DSurface9 *sourceSurface = NULL; + gl::Error error = source->getSurface(&sourceSurface); + if (error.isError()) + { + return error; + } + + IDirect3DSurface9 *destSurface = NULL; + error = dest->getSurface(&destSurface); + if (error.isError()) + { + return error; + } + + error = generateMip(destSurface, sourceSurface); + if (error.isError()) + { + return error; + } + + dest->markDirty(); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Image9::copyLockableSurfaces(IDirect3DSurface9 *dest, IDirect3DSurface9 *source) +{ + D3DLOCKED_RECT sourceLock = {0}; + D3DLOCKED_RECT destLock = {0}; + + HRESULT result; + + result = source->LockRect(&sourceLock, NULL, 0); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock source surface for copy, result: 0x%X.", result); + } + + result = dest->LockRect(&destLock, NULL, 0); + if (FAILED(result)) + { + source->UnlockRect(); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock source surface for copy, result: 0x%X.", result); + } + + ASSERT(sourceLock.pBits && destLock.pBits); + + D3DSURFACE_DESC desc; + source->GetDesc(&desc); + + const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(desc.Format); + unsigned int rows = desc.Height / d3dFormatInfo.blockHeight; + + unsigned int bytes = d3d9::ComputeBlockSize(desc.Format, desc.Width, d3dFormatInfo.blockHeight); + ASSERT(bytes <= static_cast(sourceLock.Pitch) && + bytes <= static_cast(destLock.Pitch)); + + for(unsigned int i = 0; i < rows; i++) + { + memcpy((char*)destLock.pBits + destLock.Pitch * i, (char*)sourceLock.pBits + sourceLock.Pitch * i, bytes); + } + + source->UnlockRect(); + dest->UnlockRect(); + + return gl::Error(GL_NO_ERROR); +} + +bool Image9::redefine(GLenum target, GLenum internalformat, const gl::Extents &size, bool forceRelease) +{ + // 3D textures are not supported by the D3D9 backend. + ASSERT(size.depth <= 1); + + // Only 2D and cube texture are supported by the D3D9 backend. + ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP); + + if (mWidth != size.width || + mHeight != size.height || + mDepth != size.depth || + mInternalFormat != internalformat || + forceRelease) + { + mWidth = size.width; + mHeight = size.height; + mDepth = size.depth; + mInternalFormat = internalformat; + + // compute the d3d format that will be used + const d3d9::TextureFormat &d3d9FormatInfo = d3d9::GetTextureFormatInfo(internalformat); + mD3DFormat = d3d9FormatInfo.texFormat; + mRenderable = (d3d9FormatInfo.renderFormat != D3DFMT_UNKNOWN); + + SafeRelease(mSurface); + mDirty = (d3d9FormatInfo.dataInitializerFunction != NULL); + + return true; + } + + return false; +} + +gl::Error Image9::createSurface() +{ + if (mSurface) + { + return gl::Error(GL_NO_ERROR); + } + + IDirect3DTexture9 *newTexture = NULL; + IDirect3DSurface9 *newSurface = NULL; + const D3DPOOL poolToUse = D3DPOOL_SYSTEMMEM; + const D3DFORMAT d3dFormat = getD3DFormat(); + + if (mWidth != 0 && mHeight != 0) + { + int levelToFetch = 0; + GLsizei requestWidth = mWidth; + GLsizei requestHeight = mHeight; + d3d9::MakeValidSize(true, d3dFormat, &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); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create image surface, result: 0x%X.", result); + } + + newTexture->GetSurfaceLevel(levelToFetch, &newSurface); + SafeRelease(newTexture); + + const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(mInternalFormat); + if (d3dFormatInfo.dataInitializerFunction != NULL) + { + RECT entireRect; + entireRect.left = 0; + entireRect.right = mWidth; + entireRect.top = 0; + entireRect.bottom = mHeight; + + D3DLOCKED_RECT lockedRect; + result = newSurface->LockRect(&lockedRect, &entireRect, 0); + ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock image surface, result: 0x%X.", result); + } + + d3dFormatInfo.dataInitializerFunction(mWidth, mHeight, 1, reinterpret_cast(lockedRect.pBits), + lockedRect.Pitch, 0); + + result = newSurface->UnlockRect(); + ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to unlock image surface, result: 0x%X.", result); + } + } + } + + mSurface = newSurface; + mDirty = false; + mD3DPool = poolToUse; + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Image9::lock(D3DLOCKED_RECT *lockedRect, const RECT &rect) +{ + gl::Error error = createSurface(); + if (error.isError()) + { + return error; + } + + if (mSurface) + { + HRESULT result = mSurface->LockRect(lockedRect, &rect, 0); + ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock image surface, result: 0x%X.", result); + } + + mDirty = true; + } + + return gl::Error(GL_NO_ERROR); +} + +void Image9::unlock() +{ + if (mSurface) + { + HRESULT result = mSurface->UnlockRect(); + UNUSED_ASSERTION_VARIABLE(result); + ASSERT(SUCCEEDED(result)); + } +} + +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; +} + +bool Image9::isDirty() const +{ + // Make sure to that this image is marked as dirty even if the staging texture hasn't been created yet + // if initialization is required before use. + return (mSurface || d3d9::GetTextureFormatInfo(mInternalFormat).dataInitializerFunction != NULL) && mDirty; +} + +gl::Error Image9::getSurface(IDirect3DSurface9 **outSurface) +{ + gl::Error error = createSurface(); + if (error.isError()) + { + return error; + } + + *outSurface = mSurface; + return gl::Error(GL_NO_ERROR); +} + +gl::Error Image9::setManagedSurface2D(TextureStorage *storage, int level) +{ + IDirect3DSurface9 *surface = NULL; + TextureStorage9_2D *storage9 = TextureStorage9_2D::makeTextureStorage9_2D(storage); + gl::Error error = storage9->getSurfaceLevel(level, false, &surface); + if (error.isError()) + { + return error; + } + return setManagedSurface(surface); +} + +gl::Error Image9::setManagedSurfaceCube(TextureStorage *storage, int face, int level) +{ + IDirect3DSurface9 *surface = NULL; + TextureStorage9_Cube *storage9 = TextureStorage9_Cube::makeTextureStorage9_Cube(storage); + gl::Error error = storage9->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, false, &surface); + if (error.isError()) + { + return error; + } + return setManagedSurface(surface); +} + +gl::Error 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) + { + gl::Error error = copyLockableSurfaces(surface, mSurface); + SafeRelease(mSurface); + if (error.isError()) + { + return error; + } + } + + mSurface = surface; + mD3DPool = desc.Pool; + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Image9::copyToStorage(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box ®ion) +{ + gl::Error error = createSurface(); + if (error.isError()) + { + return error; + } + + IDirect3DSurface9 *destSurface = NULL; + + if (index.type == GL_TEXTURE_2D) + { + TextureStorage9_2D *storage9 = TextureStorage9_2D::makeTextureStorage9_2D(storage); + error = storage9->getSurfaceLevel(index.mipIndex, true, &destSurface); + if (error.isError()) + { + return error; + } + } + else + { + ASSERT(gl::IsCubeMapTextureTarget(index.type)); + TextureStorage9_Cube *storage9 = TextureStorage9_Cube::makeTextureStorage9_Cube(storage); + error = storage9->getCubeMapSurface(index.type, index.mipIndex, true, &destSurface); + if (error.isError()) + { + return error; + } + } + + error = copyToSurface(destSurface, region); + SafeRelease(destSurface); + return error; +} + +gl::Error Image9::copyToSurface(IDirect3DSurface9 *destSurface, const gl::Box &area) +{ + ASSERT(area.width > 0 && area.height > 0 && area.depth == 1); + ASSERT(destSurface); + + IDirect3DSurface9 *sourceSurface = NULL; + gl::Error error = getSurface(&sourceSurface); + if (error.isError()) + { + return error; + } + + ASSERT(sourceSurface && sourceSurface != destSurface); + + RECT rect; + rect.left = area.x; + rect.top = area.y; + rect.right = area.x + area.width; + rect.bottom = area.y + area.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 (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Internal CreateOffscreenPlainSurface call failed, result: 0x%X.", result); + } + + copyLockableSurfaces(surf, sourceSurface); + result = device->UpdateSurface(surf, &rect, destSurface, &point); + SafeRelease(surf); + ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Internal UpdateSurface call failed, result: 0x%X.", result); + } + } + else + { + // UpdateSurface: source must be SYSTEMMEM, dest must be DEFAULT pools + HRESULT result = device->UpdateSurface(sourceSurface, &rect, destSurface, &point); + ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Internal UpdateSurface call failed, result: 0x%X.", result); + } + } + + return gl::Error(GL_NO_ERROR); +} + +// Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as format/type at input +// into the target pixel rectangle. +gl::Error Image9::loadData(const gl::Box &area, const gl::PixelUnpackState &unpack, GLenum type, const void *input) +{ + // 3D textures are not supported by the D3D9 backend. + ASSERT(area.z == 0 && area.depth == 1); + + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat); + GLsizei inputRowPitch = formatInfo.computeRowPitch(type, area.width, unpack.alignment, unpack.rowLength); + + const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(mInternalFormat); + ASSERT(d3dFormatInfo.loadFunction != NULL); + + RECT lockRect = + { + area.x, area.y, + area.x + area.width, area.y + area.height + }; + + D3DLOCKED_RECT locked; + gl::Error error = lock(&locked, lockRect); + if (error.isError()) + { + return error; + } + + d3dFormatInfo.loadFunction(area.width, area.height, area.depth, + reinterpret_cast(input), inputRowPitch, 0, + reinterpret_cast(locked.pBits), locked.Pitch, 0); + + unlock(); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Image9::loadCompressedData(const gl::Box &area, const void *input) +{ + // 3D textures are not supported by the D3D9 backend. + ASSERT(area.z == 0 && area.depth == 1); + + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat); + GLsizei inputRowPitch = formatInfo.computeRowPitch(GL_UNSIGNED_BYTE, area.width, 1, 0); + GLsizei inputDepthPitch = formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, area.width, area.height, 1, 0); + + const d3d9::TextureFormat &d3d9FormatInfo = d3d9::GetTextureFormatInfo(mInternalFormat); + + ASSERT(area.x % d3d9::GetD3DFormatInfo(d3d9FormatInfo.texFormat).blockWidth == 0); + ASSERT(area.y % d3d9::GetD3DFormatInfo(d3d9FormatInfo.texFormat).blockHeight == 0); + + ASSERT(d3d9FormatInfo.loadFunction != NULL); + + RECT lockRect = + { + area.x, area.y, + area.x + area.width, area.y + area.height + }; + + D3DLOCKED_RECT locked; + gl::Error error = lock(&locked, lockRect); + if (error.isError()) + { + return error; + } + + d3d9FormatInfo.loadFunction(area.width, area.height, area.depth, + reinterpret_cast(input), inputRowPitch, inputDepthPitch, + reinterpret_cast(locked.pBits), locked.Pitch, 0); + + unlock(); + + return gl::Error(GL_NO_ERROR); +} + +// This implements glCopyTex[Sub]Image2D for non-renderable internal texture formats and incomplete textures +gl::Error Image9::copy(const gl::Offset &destOffset, const gl::Rectangle &sourceArea, RenderTargetD3D *source) +{ + ASSERT(source); + + // ES3.0 only behaviour to copy into a 3d texture + ASSERT(destOffset.z == 0); + + RenderTarget9 *renderTarget = RenderTarget9::makeRenderTarget9(source); + + IDirect3DSurface9 *surface = renderTarget->getSurface(); + ASSERT(surface); + + 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)) + { + SafeRelease(surface); + return gl::Error(GL_OUT_OF_MEMORY, "Could not create matching destination surface, result: 0x%X.", result); + } + + result = device->GetRenderTargetData(surface, renderTargetData); + + if (FAILED(result)) + { + SafeRelease(renderTargetData); + SafeRelease(surface); + return gl::Error(GL_OUT_OF_MEMORY, "GetRenderTargetData unexpectedly failed, result: 0x%X.", result); + } + + int width = sourceArea.width; + int height = sourceArea.height; + + RECT sourceRect = { sourceArea.x, sourceArea.y, sourceArea.x + width, sourceArea.y + height }; + RECT destRect = { destOffset.x, destOffset.y, destOffset.x + width, destOffset.y + height }; + + D3DLOCKED_RECT sourceLock = {0}; + result = renderTargetData->LockRect(&sourceLock, &sourceRect, 0); + + if (FAILED(result)) + { + SafeRelease(renderTargetData); + SafeRelease(surface); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock the source surface (rectangle might be invalid), result: 0x%X.", result); + } + + D3DLOCKED_RECT destLock = {0}; + gl::Error error = lock(&destLock, destRect); + if (error.isError()) + { + renderTargetData->UnlockRect(); + SafeRelease(renderTargetData); + SafeRelease(surface); + return error; + } + + ASSERT(destLock.pBits && sourceLock.pBits); + + unsigned char *sourcePixels = (unsigned char*)sourceLock.pBits; + unsigned char *destPixels = (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(destPixels, sourcePixels, 4 * width); + sourcePixels += sourceLock.Pitch; + destPixels += destLock.Pitch; + } + break; + case D3DFMT_L8: + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++) + { + destPixels[x] = sourcePixels[x * 4 + 2]; + } + sourcePixels += sourceLock.Pitch; + destPixels += destLock.Pitch; + } + break; + case D3DFMT_A8L8: + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++) + { + destPixels[x * 2 + 0] = sourcePixels[x * 4 + 2]; + destPixels[x * 2 + 1] = sourcePixels[x * 4 + 3]; + } + sourcePixels += sourceLock.Pitch; + destPixels += 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*)sourcePixels)[x]; + unsigned char red = (rgb & 0xF800) >> 8; + unsigned char green = (rgb & 0x07E0) >> 3; + unsigned char blue = (rgb & 0x001F) << 3; + destPixels[x + 0] = blue | (blue >> 5); + destPixels[x + 1] = green | (green >> 6); + destPixels[x + 2] = red | (red >> 5); + destPixels[x + 3] = 0xFF; + } + sourcePixels += sourceLock.Pitch; + destPixels += destLock.Pitch; + } + break; + case D3DFMT_L8: + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++) + { + unsigned char red = sourcePixels[x * 2 + 1] & 0xF8; + destPixels[x] = red | (red >> 5); + } + sourcePixels += sourceLock.Pitch; + destPixels += 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*)sourcePixels)[x]; + unsigned char red = (argb & 0x7C00) >> 7; + unsigned char green = (argb & 0x03E0) >> 2; + unsigned char blue = (argb & 0x001F) << 3; + destPixels[x + 0] = blue | (blue >> 5); + destPixels[x + 1] = green | (green >> 5); + destPixels[x + 2] = red | (red >> 5); + destPixels[x + 3] = 0xFF; + } + sourcePixels += sourceLock.Pitch; + destPixels += 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*)sourcePixels)[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; + destPixels[x + 0] = blue | (blue >> 5); + destPixels[x + 1] = green | (green >> 5); + destPixels[x + 2] = red | (red >> 5); + destPixels[x + 3] = alpha; + } + sourcePixels += sourceLock.Pitch; + destPixels += destLock.Pitch; + } + break; + case D3DFMT_L8: + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++) + { + unsigned char red = sourcePixels[x * 2 + 1] & 0x7C; + destPixels[x] = (red << 1) | (red >> 4); + } + sourcePixels += sourceLock.Pitch; + destPixels += destLock.Pitch; + } + break; + case D3DFMT_A8L8: + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++) + { + unsigned char red = sourcePixels[x * 2 + 1] & 0x7C; + destPixels[x * 2 + 0] = (red << 1) | (red >> 4); + destPixels[x * 2 + 1] = (signed char)sourcePixels[x * 2 + 1] >> 7; + } + sourcePixels += sourceLock.Pitch; + destPixels += destLock.Pitch; + } + break; + default: + UNREACHABLE(); + } + break; + default: + UNREACHABLE(); + } + + unlock(); + renderTargetData->UnlockRect(); + + SafeRelease(renderTargetData); + SafeRelease(surface); + + mDirty = true; + return gl::Error(GL_NO_ERROR); +} + +gl::Error Image9::copy(const gl::Offset &destOffset, const gl::Box &area, const gl::ImageIndex &srcIndex, TextureStorage *srcStorage) +{ + // Currently unreachable, due to only being used in a D3D11-only workaround + UNIMPLEMENTED(); + return gl::Error(GL_INVALID_OPERATION); +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Image9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Image9.h new file mode 100644 index 0000000000..8cbfbbebf6 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Image9.h @@ -0,0 +1,73 @@ +// +// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Image9.h: Defines the rx::Image9 class, which acts as the interface to +// the actual underlying surfaces of a Texture. + +#ifndef LIBANGLE_RENDERER_D3D_D3D9_IMAGE9_H_ +#define LIBANGLE_RENDERER_D3D_D3D9_IMAGE9_H_ + +#include "libANGLE/renderer/d3d/ImageD3D.h" +#include "common/debug.h" + +namespace gl +{ +class Framebuffer; +} + +namespace rx +{ +class Renderer9; + +class Image9 : public ImageD3D +{ + public: + Image9(Renderer9 *renderer); + ~Image9(); + + static Image9 *makeImage9(ImageD3D *img); + + static gl::Error generateMipmap(Image9 *dest, Image9 *source); + static gl::Error generateMip(IDirect3DSurface9 *destSurface, IDirect3DSurface9 *sourceSurface); + static gl::Error copyLockableSurfaces(IDirect3DSurface9 *dest, IDirect3DSurface9 *source); + + bool redefine(GLenum target, GLenum internalformat, const gl::Extents &size, bool forceRelease) override; + + D3DFORMAT getD3DFormat() const; + + virtual bool isDirty() const; + + virtual gl::Error setManagedSurface2D(TextureStorage *storage, int level); + virtual gl::Error setManagedSurfaceCube(TextureStorage *storage, int face, int level); + virtual gl::Error copyToStorage(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box ®ion); + + virtual gl::Error loadData(const gl::Box &area, const gl::PixelUnpackState &unpack, GLenum type, const void *input); + virtual gl::Error loadCompressedData(const gl::Box &area, const void *input); + + virtual gl::Error copy(const gl::Offset &destOffset, const gl::Rectangle &sourceArea, RenderTargetD3D *source); + virtual gl::Error copy(const gl::Offset &destOffset, const gl::Box &sourceArea, + const gl::ImageIndex &sourceIndex, TextureStorage *source); + + private: + gl::Error getSurface(IDirect3DSurface9 **outSurface); + + gl::Error createSurface(); + gl::Error setManagedSurface(IDirect3DSurface9 *surface); + gl::Error copyToSurface(IDirect3DSurface9 *dest, const gl::Box &area); + + gl::Error 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 // LIBANGLE_RENDERER_D3D_D3D9_IMAGE9_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.cpp new file mode 100644 index 0000000000..c5d72e6a50 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.cpp @@ -0,0 +1,173 @@ +// +// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Indexffer9.cpp: Defines the D3D9 IndexBuffer implementation. + +#include "libANGLE/renderer/d3d/d3d9/IndexBuffer9.h" +#include "libANGLE/renderer/d3d/d3d9/Renderer9.h" + +namespace rx +{ + +IndexBuffer9::IndexBuffer9(Renderer9 *const renderer) : mRenderer(renderer) +{ + mIndexBuffer = NULL; + mBufferSize = 0; + mIndexType = 0; + mDynamic = false; +} + +IndexBuffer9::~IndexBuffer9() +{ + SafeRelease(mIndexBuffer); +} + +gl::Error IndexBuffer9::initialize(unsigned int bufferSize, GLenum indexType, bool dynamic) +{ + SafeRelease(mIndexBuffer); + + updateSerial(); + + if (bufferSize > 0) + { + D3DFORMAT format = D3DFMT_UNKNOWN; + if (indexType == GL_UNSIGNED_SHORT || indexType == GL_UNSIGNED_BYTE) + { + format = D3DFMT_INDEX16; + } + else if (indexType == GL_UNSIGNED_INT) + { + ASSERT(mRenderer->getRendererExtensions().elementIndexUint); + format = D3DFMT_INDEX32; + } + else UNREACHABLE(); + + DWORD usageFlags = D3DUSAGE_WRITEONLY; + if (dynamic) + { + usageFlags |= D3DUSAGE_DYNAMIC; + } + + HRESULT result = mRenderer->createIndexBuffer(bufferSize, usageFlags, format, &mIndexBuffer); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal index buffer of size, %lu.", bufferSize); + } + } + + mBufferSize = bufferSize; + mIndexType = indexType; + mDynamic = dynamic; + + return gl::Error(GL_NO_ERROR); +} + +IndexBuffer9 *IndexBuffer9::makeIndexBuffer9(IndexBuffer *indexBuffer) +{ + ASSERT(HAS_DYNAMIC_TYPE(IndexBuffer9*, indexBuffer)); + return static_cast(indexBuffer); +} + +gl::Error IndexBuffer9::mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory) +{ + if (!mIndexBuffer) + { + return gl::Error(GL_OUT_OF_MEMORY, "Internal index buffer is not initialized."); + } + + DWORD lockFlags = mDynamic ? D3DLOCK_NOOVERWRITE : 0; + + void *mapPtr = NULL; + HRESULT result = mIndexBuffer->Lock(offset, size, &mapPtr, lockFlags); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock internal index buffer, HRESULT: 0x%08x.", result); + } + + *outMappedMemory = mapPtr; + return gl::Error(GL_NO_ERROR); +} + +gl::Error IndexBuffer9::unmapBuffer() +{ + if (!mIndexBuffer) + { + return gl::Error(GL_OUT_OF_MEMORY, "Internal index buffer is not initialized."); + } + + HRESULT result = mIndexBuffer->Unlock(); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to unlock internal index buffer, HRESULT: 0x%08x.", result); + } + + return gl::Error(GL_NO_ERROR); +} + +GLenum IndexBuffer9::getIndexType() const +{ + return mIndexType; +} + +unsigned int IndexBuffer9::getBufferSize() const +{ + return mBufferSize; +} + +gl::Error IndexBuffer9::setSize(unsigned int bufferSize, GLenum indexType) +{ + if (bufferSize > mBufferSize || indexType != mIndexType) + { + return initialize(bufferSize, indexType, mDynamic); + } + else + { + return gl::Error(GL_NO_ERROR); + } +} + +gl::Error IndexBuffer9::discard() +{ + if (!mIndexBuffer) + { + return gl::Error(GL_OUT_OF_MEMORY, "Internal index buffer is not initialized."); + } + + void *dummy; + HRESULT result; + + result = mIndexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock internal index buffer, HRESULT: 0x%08x.", result); + } + + result = mIndexBuffer->Unlock(); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to unlock internal index buffer, HRESULT: 0x%08x.", result); + } + + return gl::Error(GL_NO_ERROR); +} + +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; +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.h new file mode 100644 index 0000000000..61f8b11566 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.h @@ -0,0 +1,51 @@ +// +// 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 LIBANGLE_RENDERER_D3D_D3D9_INDEXBUFFER9_H_ +#define LIBANGLE_RENDERER_D3D_D3D9_INDEXBUFFER9_H_ + +#include "libANGLE/renderer/d3d/IndexBuffer.h" + +namespace rx +{ +class Renderer9; + +class IndexBuffer9 : public IndexBuffer +{ + public: + explicit IndexBuffer9(Renderer9 *const renderer); + virtual ~IndexBuffer9(); + + virtual gl::Error initialize(unsigned int bufferSize, GLenum indexType, bool dynamic); + + static IndexBuffer9 *makeIndexBuffer9(IndexBuffer *indexBuffer); + + virtual gl::Error mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory); + virtual gl::Error unmapBuffer(); + + virtual GLenum getIndexType() const; + virtual unsigned int getBufferSize() const; + virtual gl::Error setSize(unsigned int bufferSize, GLenum indexType); + + virtual gl::Error discard(); + + D3DFORMAT getIndexFormat() const; + IDirect3DIndexBuffer9 *getBuffer() const; + + private: + Renderer9 *const mRenderer; + + IDirect3DIndexBuffer9 *mIndexBuffer; + unsigned int mBufferSize; + GLenum mIndexType; + bool mDynamic; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_D3D9_INDEXBUFFER9_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Query9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Query9.cpp new file mode 100644 index 0000000000..96f12d7868 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Query9.cpp @@ -0,0 +1,144 @@ +// +// 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 "libANGLE/renderer/d3d/d3d9/Query9.h" +#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h" +#include "libANGLE/renderer/d3d/d3d9/Renderer9.h" + +#include + +namespace rx +{ +Query9::Query9(Renderer9 *renderer, GLenum type) + : QueryImpl(type), + mResult(GL_FALSE), + mQueryFinished(false), + mRenderer(renderer), + mQuery(NULL) +{ +} + +Query9::~Query9() +{ + SafeRelease(mQuery); +} + +gl::Error Query9::begin() +{ + if (mQuery == NULL) + { + HRESULT result = mRenderer->getDevice()->CreateQuery(D3DQUERYTYPE_OCCLUSION, &mQuery); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Internal query creation failed, result: 0x%X.", result); + } + } + + HRESULT result = mQuery->Issue(D3DISSUE_BEGIN); + ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to begin internal query, result: 0x%X.", result); + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Query9::end() +{ + ASSERT(mQuery); + + HRESULT result = mQuery->Issue(D3DISSUE_END); + ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to end internal query, result: 0x%X.", result); + } + + mQueryFinished = false; + mResult = GL_FALSE; + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Query9::getResult(GLuint *params) +{ + while (!mQueryFinished) + { + gl::Error error = testQuery(); + if (error.isError()) + { + return error; + } + + if (!mQueryFinished) + { + Sleep(0); + } + } + + ASSERT(mQueryFinished); + *params = mResult; + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Query9::isResultAvailable(GLuint *available) +{ + gl::Error error = testQuery(); + if (error.isError()) + { + return error; + } + + *available = (mQueryFinished ? GL_TRUE : GL_FALSE); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Query9::testQuery() +{ + if (!mQueryFinished) + { + ASSERT(mQuery); + + DWORD numPixels = 0; + + HRESULT hres = mQuery->GetData(&numPixels, sizeof(DWORD), D3DGETDATA_FLUSH); + if (hres == S_OK) + { + mQueryFinished = 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(); + break; + } + } + else if (d3d9::isDeviceLostError(hres)) + { + mRenderer->notifyDeviceLost(); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to test get query result, device is lost."); + } + else if (mRenderer->testDeviceLost()) + { + mRenderer->notifyDeviceLost(); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to test get query result, device is lost."); + } + } + + return gl::Error(GL_NO_ERROR); +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Query9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Query9.h new file mode 100644 index 0000000000..399da2ed83 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Query9.h @@ -0,0 +1,41 @@ +// +// 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 LIBANGLE_RENDERER_D3D_D3D9_QUERY9_H_ +#define LIBANGLE_RENDERER_D3D_D3D9_QUERY9_H_ + +#include "libANGLE/renderer/QueryImpl.h" + +namespace rx +{ +class Renderer9; + +class Query9 : public QueryImpl +{ + public: + Query9(Renderer9 *renderer, GLenum type); + virtual ~Query9(); + + virtual gl::Error begin(); + virtual gl::Error end(); + virtual gl::Error getResult(GLuint *params); + virtual gl::Error isResultAvailable(GLuint *available); + + private: + gl::Error testQuery(); + + GLuint mResult; + bool mQueryFinished; + + Renderer9 *mRenderer; + IDirect3DQuery9 *mQuery; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_D3D9_QUERY9_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.cpp new file mode 100644 index 0000000000..412c0109f5 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.cpp @@ -0,0 +1,139 @@ +// +// Copyright (c) 2012-2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// RenderTarget9.cpp: Implements a D3D9-specific wrapper for IDirect3DSurface9 +// pointers retained by renderbuffers. + +#include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h" +#include "libANGLE/renderer/d3d/d3d9/Renderer9.h" +#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h" +#include "libANGLE/renderer/d3d/d3d9/SwapChain9.h" +#include "libANGLE/renderer/d3d/d3d9/formatutils9.h" + +namespace rx +{ + +RenderTarget9 *RenderTarget9::makeRenderTarget9(RenderTargetD3D *target) +{ + ASSERT(HAS_DYNAMIC_TYPE(RenderTarget9*, target)); + return static_cast(target); +} + +// TODO: AddRef the incoming surface to take ownership instead of expecting that its ref is being given. +TextureRenderTarget9::TextureRenderTarget9(IDirect3DSurface9 *surface, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, + GLsizei samples) + : mWidth(width), + mHeight(height), + mDepth(depth), + mInternalFormat(internalFormat), + mD3DFormat(D3DFMT_UNKNOWN), + mSamples(samples), + mRenderTarget(surface) +{ + ASSERT(mDepth == 1); + + if (mRenderTarget) + { + D3DSURFACE_DESC description; + mRenderTarget->GetDesc(&description); + mD3DFormat = description.Format; + } +} + +TextureRenderTarget9::~TextureRenderTarget9() +{ + SafeRelease(mRenderTarget); +} + +GLsizei TextureRenderTarget9::getWidth() const +{ + return mWidth; +} + +GLsizei TextureRenderTarget9::getHeight() const +{ + return mHeight; +} + +GLsizei TextureRenderTarget9::getDepth() const +{ + return mDepth; +} + +GLenum TextureRenderTarget9::getInternalFormat() const +{ + return mInternalFormat; +} + +GLsizei TextureRenderTarget9::getSamples() const +{ + return mSamples; +} + +IDirect3DSurface9 *TextureRenderTarget9::getSurface() +{ + // Caller is responsible for releasing the returned surface reference. + // TODO: remove the AddRef to match RenderTarget11 + if (mRenderTarget) + { + mRenderTarget->AddRef(); + } + + return mRenderTarget; +} + +D3DFORMAT TextureRenderTarget9::getD3DFormat() const +{ + return mD3DFormat; +} + +SurfaceRenderTarget9::SurfaceRenderTarget9(SwapChain9 *swapChain, bool depth) + : mSwapChain(swapChain), + mDepth(depth) +{ +} + +SurfaceRenderTarget9::~SurfaceRenderTarget9() +{ +} + +GLsizei SurfaceRenderTarget9::getWidth() const +{ + return mSwapChain->getWidth(); +} + +GLsizei SurfaceRenderTarget9::getHeight() const +{ + return mSwapChain->getHeight(); +} + +GLsizei SurfaceRenderTarget9::getDepth() const +{ + return 1; +} + +GLenum SurfaceRenderTarget9::getInternalFormat() const +{ + return (mDepth ? mSwapChain->GetDepthBufferInternalFormat() : mSwapChain->GetBackBufferInternalFormat()); +} + +GLsizei SurfaceRenderTarget9::getSamples() const +{ + // Our EGL surfaces do not support multisampling. + return 0; +} + +IDirect3DSurface9 *SurfaceRenderTarget9::getSurface() +{ + return (mDepth ? mSwapChain->getDepthStencil() : mSwapChain->getRenderTarget()); +} + +D3DFORMAT SurfaceRenderTarget9::getD3DFormat() const +{ + return d3d9::GetTextureFormatInfo(getInternalFormat()).texFormat; +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.h new file mode 100644 index 0000000000..32c7dfa09c --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.h @@ -0,0 +1,84 @@ +// +// 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 LIBANGLE_RENDERER_D3D_D3D9_RENDERTARGET9_H_ +#define LIBANGLE_RENDERER_D3D_D3D9_RENDERTARGET9_H_ + +#include "libANGLE/renderer/d3d/RenderTargetD3D.h" + +namespace rx +{ +class Renderer9; +class SwapChain9; + +class RenderTarget9 : public RenderTargetD3D +{ + public: + RenderTarget9() { } + virtual ~RenderTarget9() { } + + static RenderTarget9 *makeRenderTarget9(RenderTargetD3D *renderTarget); + + virtual IDirect3DSurface9 *getSurface() = 0; + + virtual D3DFORMAT getD3DFormat() const = 0; +}; + +class TextureRenderTarget9 : public RenderTarget9 +{ + public: + TextureRenderTarget9(IDirect3DSurface9 *surface, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, + GLsizei samples); + virtual ~TextureRenderTarget9(); + + GLsizei getWidth() const override; + GLsizei getHeight() const override; + GLsizei getDepth() const override; + GLenum getInternalFormat() const override; + GLsizei getSamples() const override; + + IDirect3DSurface9 *getSurface() override; + + D3DFORMAT getD3DFormat() const override; + + private: + GLsizei mWidth; + GLsizei mHeight; + GLsizei mDepth; + GLenum mInternalFormat; + D3DFORMAT mD3DFormat; + GLsizei mSamples; + + IDirect3DSurface9 *mRenderTarget; +}; + +class SurfaceRenderTarget9 : public RenderTarget9 +{ + public: + SurfaceRenderTarget9(SwapChain9 *swapChain, bool depth); + virtual ~SurfaceRenderTarget9(); + + GLsizei getWidth() const override; + GLsizei getHeight() const override; + GLsizei getDepth() const override; + GLenum getInternalFormat() const override; + GLsizei getSamples() const override; + + IDirect3DSurface9 *getSurface() override; + + D3DFORMAT getD3DFormat() const override; + + private: + SwapChain9 *mSwapChain; + bool mDepth; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_D3D9_RENDERTARGET9_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp new file mode 100644 index 0000000000..bf1c367693 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp @@ -0,0 +1,2933 @@ +// +// Copyright (c) 2012-2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Renderer9.cpp: Implements a back-end specific class for the D3D9 renderer. + +#include "libANGLE/renderer/d3d/d3d9/Renderer9.h" + +#include "common/utilities.h" +#include "libANGLE/Buffer.h" +#include "libANGLE/Display.h" +#include "libANGLE/Framebuffer.h" +#include "libANGLE/FramebufferAttachment.h" +#include "libANGLE/Program.h" +#include "libANGLE/Renderbuffer.h" +#include "libANGLE/State.h" +#include "libANGLE/Surface.h" +#include "libANGLE/Texture.h" +#include "libANGLE/angletypes.h" +#include "libANGLE/features.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/renderer/d3d/CompilerD3D.h" +#include "libANGLE/renderer/d3d/FramebufferD3D.h" +#include "libANGLE/renderer/d3d/IndexDataManager.h" +#include "libANGLE/renderer/d3d/ProgramD3D.h" +#include "libANGLE/renderer/d3d/RenderbufferD3D.h" +#include "libANGLE/renderer/d3d/ShaderD3D.h" +#include "libANGLE/renderer/d3d/SurfaceD3D.h" +#include "libANGLE/renderer/d3d/TextureD3D.h" +#include "libANGLE/renderer/d3d/TransformFeedbackD3D.h" +#include "libANGLE/renderer/d3d/d3d9/Blit9.h" +#include "libANGLE/renderer/d3d/d3d9/Buffer9.h" +#include "libANGLE/renderer/d3d/d3d9/Fence9.h" +#include "libANGLE/renderer/d3d/d3d9/Framebuffer9.h" +#include "libANGLE/renderer/d3d/d3d9/Image9.h" +#include "libANGLE/renderer/d3d/d3d9/IndexBuffer9.h" +#include "libANGLE/renderer/d3d/d3d9/Query9.h" +#include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h" +#include "libANGLE/renderer/d3d/d3d9/ShaderExecutable9.h" +#include "libANGLE/renderer/d3d/d3d9/SwapChain9.h" +#include "libANGLE/renderer/d3d/d3d9/TextureStorage9.h" +#include "libANGLE/renderer/d3d/d3d9/VertexArray9.h" +#include "libANGLE/renderer/d3d/d3d9/VertexBuffer9.h" +#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h" +#include "libANGLE/renderer/d3d/d3d9/formatutils9.h" + +#include "third_party/trace_event/trace_event.h" + +#include + +#include + +#if !defined(ANGLE_COMPILE_OPTIMIZATION_LEVEL) +#define ANGLE_COMPILE_OPTIMIZATION_LEVEL D3DCOMPILE_OPTIMIZATION_LEVEL3 +#endif + +// Enable ANGLE_SUPPORT_SHADER_MODEL_2 if you wish devices with only shader model 2. +// Such a device would not be conformant. +#ifndef ANGLE_SUPPORT_SHADER_MODEL_2 +#define ANGLE_SUPPORT_SHADER_MODEL_2 0 +#endif + +namespace rx +{ + +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) + : RendererD3D(display) +{ + // Initialize global annotator + gl::InitializeDebugAnnotations(&mAnnotator); + + mD3d9Module = NULL; + + mD3d9 = NULL; + mD3d9Ex = NULL; + mDevice = NULL; + mDeviceEx = NULL; + mDeviceWindow = NULL; + mBlit = NULL; + + mAdapter = D3DADAPTER_DEFAULT; + + const egl::AttributeMap &attributes = display->getAttributeMap(); + EGLint requestedDeviceType = attributes.get(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, + EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE); + switch (requestedDeviceType) + { + case EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE: + mDeviceType = D3DDEVTYPE_HAL; + break; + + case EGL_PLATFORM_ANGLE_DEVICE_TYPE_REFERENCE_ANGLE: + mDeviceType = D3DDEVTYPE_REF; + break; + + case EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE: + mDeviceType = D3DDEVTYPE_NULLREF; + break; + + default: + UNREACHABLE(); + } + + mMaskedClearSavedState = NULL; + + mVertexDataManager = NULL; + mIndexDataManager = NULL; + mLineLoopIB = NULL; + mCountingIB = 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; + } + + mAppliedVertexShader = NULL; + mAppliedPixelShader = NULL; + mAppliedProgramSerial = 0; +} + +Renderer9::~Renderer9() +{ + if (mDevice) + { + // If the device is lost, reset it first to prevent leaving the driver in an unstable state + if (testDeviceLost()) + { + resetDevice(); + } + } + + release(); + + gl::UninitializeDebugAnnotations(); +} + +void Renderer9::release() +{ + RendererD3D::cleanup(); + + releaseDeviceResources(); + + SafeRelease(mDevice); + SafeRelease(mDeviceEx); + SafeRelease(mD3d9); + SafeRelease(mD3d9Ex); + + mCompiler.release(); + + if (mDeviceWindow) + { + DestroyWindow(mDeviceWindow); + mDeviceWindow = NULL; + } + + mD3d9Module = NULL; +} + +Renderer9 *Renderer9::makeRenderer9(Renderer *renderer) +{ + ASSERT(HAS_DYNAMIC_TYPE(Renderer9*, renderer)); + return static_cast(renderer); +} + +egl::Error Renderer9::initialize() +{ + if (!mCompiler.initialize()) + { + return egl::Error(EGL_NOT_INITIALIZED, + D3D9_INIT_COMPILER_ERROR, + "Compiler failed to initialize."); + } + + TRACE_EVENT0("gpu", "GetModuleHandle_d3d9"); + mD3d9Module = GetModuleHandle(TEXT("d3d9.dll")); + + if (mD3d9Module == NULL) + { + return egl::Error(EGL_NOT_INITIALIZED, D3D9_INIT_MISSING_DEP, "No D3D9 module found."); + } + + 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_D3D9EX == ANGLE_ENABLED && Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &mD3d9Ex))) + { + TRACE_EVENT0("gpu", "D3d9Ex_QueryInterface"); + ASSERT(mD3d9Ex); + mD3d9Ex->QueryInterface(IID_IDirect3D9, reinterpret_cast(&mD3d9)); + ASSERT(mD3d9); + } + else + { + TRACE_EVENT0("gpu", "Direct3DCreate9"); + mD3d9 = Direct3DCreate9(D3D_SDK_VERSION); + } + + if (!mD3d9) + { + return egl::Error(EGL_NOT_INITIALIZED, D3D9_INIT_MISSING_DEP, "Could not create D3D9 device."); + } + + if (mDisplay->getNativeDisplayId() != nullptr) + { + // UNIMPLEMENTED(); // FIXME: Determine which adapter index the device context corresponds to + } + + HRESULT result; + + // Give up on getting device caps after about one second. + { + TRACE_EVENT0("gpu", "GetDeviceCaps"); + for (int i = 0; i < 10; ++i) + { + result = mD3d9->GetDeviceCaps(mAdapter, mDeviceType, &mDeviceCaps); + if (SUCCEEDED(result)) + { + break; + } + else if (result == D3DERR_NOTAVAILABLE) + { + Sleep(100); // Give the driver some time to initialize/recover + } + else if (FAILED(result)) // D3DERR_OUTOFVIDEOMEMORY, E_OUTOFMEMORY, D3DERR_INVALIDDEVICE, or another error we can't recover from + { + return egl::Error(EGL_NOT_INITIALIZED, + D3D9_INIT_OTHER_ERROR, + "Failed to get device caps: Error code 0x%x\n", result); + } + } + } + +#if ANGLE_SUPPORT_SHADER_MODEL_2 + size_t minShaderModel = 2; +#else + size_t minShaderModel = 3; +#endif + + if (mDeviceCaps.PixelShaderVersion < D3DPS_VERSION(minShaderModel, 0)) + { + return egl::Error(EGL_NOT_INITIALIZED, + D3D9_INIT_UNSUPPORTED_VERSION, + "Renderer does not support PS %u.%u.aborting!", minShaderModel, 0); + } + + // 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::ensureRenderTarget. + if ((mDeviceCaps.DevCaps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES) == 0) + { + return egl::Error(EGL_NOT_INITIALIZED, + D3D9_INIT_UNSUPPORTED_STRETCHRECT, + "Renderer does not support StretctRect from textures."); + } + + { + TRACE_EVENT0("gpu", "GetAdapterIdentifier"); + mD3d9->GetAdapterIdentifier(mAdapter, 0, &mAdapterIdentifier); + } + + static const TCHAR windowName[] = TEXT("AngleHiddenWindow"); + static const TCHAR className[] = TEXT("STATIC"); + + { + TRACE_EVENT0("gpu", "CreateWindowEx"); + mDeviceWindow = CreateWindowEx(WS_EX_NOACTIVATE, className, windowName, WS_DISABLED | WS_POPUP, 0, 0, 1, 1, HWND_MESSAGE, NULL, GetModuleHandle(NULL), NULL); + } + + D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters(); + DWORD behaviorFlags = D3DCREATE_FPU_PRESERVE | D3DCREATE_NOWINDOWCHANGES | D3DCREATE_MULTITHREADED; + + { + TRACE_EVENT0("gpu", "D3d9_CreateDevice"); + result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE, &presentParameters, &mDevice); + } + if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DEVICELOST) + { + return egl::Error(EGL_BAD_ALLOC, D3D9_INIT_OUT_OF_MEMORY, + "CreateDevice failed: device lost of out of memory"); + } + + if (FAILED(result)) + { + TRACE_EVENT0("gpu", "D3d9_CreateDevice2"); + result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_SOFTWARE_VERTEXPROCESSING, &presentParameters, &mDevice); + + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_NOTAVAILABLE || result == D3DERR_DEVICELOST); + return egl::Error(EGL_BAD_ALLOC, D3D9_INIT_OUT_OF_MEMORY, + "CreateDevice2 failed: device lost, not available, or of out of memory"); + } + } + + if (mD3d9Ex) + { + TRACE_EVENT0("gpu", "mDevice_QueryInterface"); + result = mDevice->QueryInterface(IID_IDirect3DDevice9Ex, (void**)&mDeviceEx); + ASSERT(SUCCEEDED(result)); + } + + { + TRACE_EVENT0("gpu", "ShaderCache initialize"); + mVertexShaderCache.initialize(mDevice); + mPixelShaderCache.initialize(mDevice); + } + + 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)); + + initializeDevice(); + + return egl::Error(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 + } + + const gl::Caps &rendererCaps = getRendererCaps(); + + mForceSetVertexSamplerStates.resize(rendererCaps.maxVertexTextureImageUnits); + mCurVertexSamplerStates.resize(rendererCaps.maxVertexTextureImageUnits); + + mForceSetPixelSamplerStates.resize(rendererCaps.maxTextureImageUnits); + mCurPixelSamplerStates.resize(rendererCaps.maxTextureImageUnits); + + mCurVertexTextureSerials.resize(rendererCaps.maxVertexTextureImageUnits); + mCurPixelTextureSerials.resize(rendererCaps.maxTextureImageUnits); + + markAllStateDirty(); + + mSceneStarted = false; + + ASSERT(!mBlit); + mBlit = new Blit9(this); + mBlit->initialize(); + + ASSERT(!mVertexDataManager && !mIndexDataManager); + mVertexDataManager = new VertexDataManager(this); + mIndexDataManager = new IndexDataManager(this, getRendererClass()); +} + +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; +} + +egl::ConfigSet Renderer9::generateConfigs() const +{ + static const GLenum colorBufferFormats[] = + { + GL_BGR5_A1_ANGLEX, + GL_BGRA8_EXT, + GL_RGB565, + + }; + + static const GLenum depthStencilBufferFormats[] = + { + GL_NONE, + GL_DEPTH_COMPONENT32_OES, + GL_DEPTH24_STENCIL8_OES, + GL_DEPTH_COMPONENT24_OES, + GL_DEPTH_COMPONENT16, + }; + + const gl::Caps &rendererCaps = getRendererCaps(); + const gl::TextureCapsMap &rendererTextureCaps = getRendererTextureCaps(); + + D3DDISPLAYMODE currentDisplayMode; + mD3d9->GetAdapterDisplayMode(mAdapter, ¤tDisplayMode); + + // Determine the min and max swap intervals + int minSwapInterval = 4; + int maxSwapInterval = 0; + + if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE) + { + minSwapInterval = std::min(minSwapInterval, 0); + maxSwapInterval = std::max(maxSwapInterval, 0); + } + if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_ONE) + { + minSwapInterval = std::min(minSwapInterval, 1); + maxSwapInterval = std::max(maxSwapInterval, 1); + } + if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_TWO) + { + minSwapInterval = std::min(minSwapInterval, 2); + maxSwapInterval = std::max(maxSwapInterval, 2); + } + if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_THREE) + { + minSwapInterval = std::min(minSwapInterval, 3); + maxSwapInterval = std::max(maxSwapInterval, 3); + } + if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_FOUR) + { + minSwapInterval = std::min(minSwapInterval, 4); + maxSwapInterval = std::max(maxSwapInterval, 4); + } + + egl::ConfigSet configs; + for (size_t formatIndex = 0; formatIndex < ArraySize(colorBufferFormats); formatIndex++) + { + GLenum colorBufferInternalFormat = colorBufferFormats[formatIndex]; + const gl::TextureCaps &colorBufferFormatCaps = rendererTextureCaps.get(colorBufferInternalFormat); + if (colorBufferFormatCaps.renderable) + { + for (size_t depthStencilIndex = 0; depthStencilIndex < ArraySize(depthStencilBufferFormats); depthStencilIndex++) + { + GLenum depthStencilBufferInternalFormat = depthStencilBufferFormats[depthStencilIndex]; + const gl::TextureCaps &depthStencilBufferFormatCaps = rendererTextureCaps.get(depthStencilBufferInternalFormat); + if (depthStencilBufferFormatCaps.renderable || depthStencilBufferInternalFormat == GL_NONE) + { + const gl::InternalFormat &colorBufferFormatInfo = gl::GetInternalFormatInfo(colorBufferInternalFormat); + const gl::InternalFormat &depthStencilBufferFormatInfo = gl::GetInternalFormatInfo(depthStencilBufferInternalFormat); + const d3d9::TextureFormat &d3d9ColorBufferFormatInfo = d3d9::GetTextureFormatInfo(colorBufferInternalFormat); + + egl::Config config; + config.renderTargetFormat = colorBufferInternalFormat; + config.depthStencilFormat = depthStencilBufferInternalFormat; + config.bufferSize = colorBufferFormatInfo.pixelBytes * 8; + config.redSize = colorBufferFormatInfo.redBits; + config.greenSize = colorBufferFormatInfo.greenBits; + config.blueSize = colorBufferFormatInfo.blueBits; + config.luminanceSize = colorBufferFormatInfo.luminanceBits; + config.alphaSize = colorBufferFormatInfo.alphaBits; + config.alphaMaskSize = 0; + config.bindToTextureRGB = (colorBufferFormatInfo.format == GL_RGB); + config.bindToTextureRGBA = (colorBufferFormatInfo.format == GL_RGBA || colorBufferFormatInfo.format == GL_BGRA_EXT); + config.colorBufferType = EGL_RGB_BUFFER; + // Mark as slow if blits to the back-buffer won't be straight forward + config.configCaveat = (currentDisplayMode.Format == d3d9ColorBufferFormatInfo.renderFormat) ? EGL_NONE : EGL_SLOW_CONFIG; + config.configID = static_cast(configs.size() + 1); + config.conformant = EGL_OPENGL_ES2_BIT; + config.depthSize = depthStencilBufferFormatInfo.depthBits; + config.level = 0; + config.matchNativePixmap = EGL_NONE; + config.maxPBufferWidth = rendererCaps.max2DTextureSize; + config.maxPBufferHeight = rendererCaps.max2DTextureSize; + config.maxPBufferPixels = rendererCaps.max2DTextureSize * rendererCaps.max2DTextureSize; + config.maxSwapInterval = maxSwapInterval; + config.minSwapInterval = minSwapInterval; + config.nativeRenderable = EGL_FALSE; + config.nativeVisualID = 0; + config.nativeVisualType = EGL_NONE; + config.renderableType = EGL_OPENGL_ES2_BIT; + config.sampleBuffers = 0; // FIXME: enumerate multi-sampling + config.samples = 0; + config.stencilSize = depthStencilBufferFormatInfo.stencilBits; + config.surfaceType = EGL_PBUFFER_BIT | EGL_WINDOW_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT; + config.transparentType = EGL_NONE; + config.transparentRedValue = 0; + config.transparentGreenValue = 0; + config.transparentBlueValue = 0; + + configs.add(config); + } + } + } + } + + ASSERT(configs.size() > 0); + return configs; +} + +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; + } +} + +gl::Error Renderer9::flush() +{ + IDirect3DQuery9* query = NULL; + gl::Error error = allocateEventQuery(&query); + if (error.isError()) + { + return error; + } + + HRESULT result = query->Issue(D3DISSUE_END); + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to issue event query, result: 0x%X.", result); + } + + // Grab the query data once + result = query->GetData(NULL, 0, D3DGETDATA_FLUSH); + freeEventQuery(query); + if (FAILED(result)) + { + if (d3d9::isDeviceLostError(result)) + { + notifyDeviceLost(); + } + + return gl::Error(GL_OUT_OF_MEMORY, "Failed to get event query data, result: 0x%X.", result); + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Renderer9::finish() +{ + IDirect3DQuery9* query = NULL; + gl::Error error = allocateEventQuery(&query); + if (error.isError()) + { + return error; + } + + HRESULT result = query->Issue(D3DISSUE_END); + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to issue event query, result: 0x%X.", result); + } + + // Grab the query data once + result = query->GetData(NULL, 0, D3DGETDATA_FLUSH); + if (FAILED(result)) + { + if (d3d9::isDeviceLostError(result)) + { + notifyDeviceLost(); + } + + freeEventQuery(query); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to get event query data, result: 0x%X.", result); + } + + // Loop until the query completes + while (result == S_FALSE) + { + // Keep polling, but allow other threads to do something useful first + Sleep(0); + + result = query->GetData(NULL, 0, D3DGETDATA_FLUSH); + + // 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 (result == S_FALSE && testDeviceLost()) + { + result = D3DERR_DEVICELOST; + } + + if (FAILED(result)) + { + if (d3d9::isDeviceLostError(result)) + { + notifyDeviceLost(); + } + + freeEventQuery(query); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to get event query data, result: 0x%X.", result); + } + + } + + freeEventQuery(query); + + return gl::Error(GL_NO_ERROR); +} + +SwapChainD3D *Renderer9::createSwapChain(NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) +{ + return new SwapChain9(this, nativeWindow, shareHandle, backBufferFormat, depthBufferFormat); +} + +gl::Error Renderer9::allocateEventQuery(IDirect3DQuery9 **outQuery) +{ + if (mEventQueryPool.empty()) + { + HRESULT result = mDevice->CreateQuery(D3DQUERYTYPE_EVENT, outQuery); + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate event query, result: 0x%X.", result); + } + } + else + { + *outQuery = mEventQueryPool.back(); + mEventQueryPool.pop_back(); + } + + return gl::Error(GL_NO_ERROR); +} + +void Renderer9::freeEventQuery(IDirect3DQuery9* query) +{ + if (mEventQueryPool.size() > 1000) + { + SafeRelease(query); + } + else + { + mEventQueryPool.push_back(query); + } +} + +gl::Error Renderer9::createVertexShader(const DWORD *function, size_t length, IDirect3DVertexShader9 **outShader) +{ + return mVertexShaderCache.create(function, length, outShader); +} + +gl::Error Renderer9::createPixelShader(const DWORD *function, size_t length, IDirect3DPixelShader9 **outShader) +{ + return mPixelShaderCache.create(function, length, outShader); +} + +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); +} + +BufferImpl *Renderer9::createBuffer() +{ + return new Buffer9(this); +} + +VertexArrayImpl *Renderer9::createVertexArray() +{ + return new VertexArray9(this); +} + +QueryImpl *Renderer9::createQuery(GLenum type) +{ + return new Query9(this, type); +} + +FenceNVImpl *Renderer9::createFenceNV() +{ + return new FenceNV9(this); +} + +FenceSyncImpl *Renderer9::createFenceSync() +{ + // Renderer9 doesn't support ES 3.0 and its sync objects. + UNREACHABLE(); + return NULL; +} + +TransformFeedbackImpl* Renderer9::createTransformFeedback() +{ + return new TransformFeedbackD3D(); +} + +bool Renderer9::supportsFastCopyBufferToTexture(GLenum internalFormat) const +{ + // Pixel buffer objects are not supported in D3D9, since D3D9 is ES2-only and PBOs are ES3. + return false; +} + +gl::Error Renderer9::fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTargetD3D *destRenderTarget, + GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea) +{ + // Pixel buffer objects are not supported in D3D9, since D3D9 is ES2-only and PBOs are ES3. + UNREACHABLE(); + return gl::Error(GL_INVALID_OPERATION); +} + +gl::Error Renderer9::generateSwizzle(gl::Texture *texture) +{ + // Swizzled textures are not available in ES2 or D3D9 + UNREACHABLE(); + return gl::Error(GL_INVALID_OPERATION); +} + +gl::Error Renderer9::setSamplerState(gl::SamplerType type, int index, gl::Texture *texture, const gl::SamplerState &samplerState) +{ + std::vector &forceSetSamplers = (type == gl::SAMPLER_PIXEL) ? mForceSetPixelSamplerStates : mForceSetVertexSamplerStates; + std::vector &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; + + // Make sure to add the level offset for our tiny compressed texture workaround + TextureD3D *textureD3D = GetImplAs(texture); + + TextureStorage *storage = nullptr; + gl::Error error = textureD3D->getNativeTexture(&storage); + if (error.isError()) + { + return error; + } + + // Storage should exist, texture should be complete + ASSERT(storage); + + DWORD baseLevel = samplerState.baseLevel + storage->getTopLevel(); + + 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, baseLevel); + if (getRendererExtensions().textureFilterAnisotropic) + { + mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAXANISOTROPY, (DWORD)samplerState.maxAnisotropy); + } + } + + forceSetSamplers[index] = false; + appliedSamplers[index] = samplerState; + + return gl::Error(GL_NO_ERROR); +} + +gl::Error 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; + + std::vector &appliedSerials = (type == gl::SAMPLER_PIXEL) ? mCurPixelTextureSerials : mCurVertexTextureSerials; + + if (texture) + { + TextureD3D *textureImpl = GetImplAs(texture); + + TextureStorage *texStorage = nullptr; + gl::Error error = textureImpl->getNativeTexture(&texStorage); + if (error.isError()) + { + return error; + } + + // Texture should be complete and have a storage + ASSERT(texStorage); + + TextureStorage9 *storage9 = TextureStorage9::makeTextureStorage9(texStorage); + error = storage9->getBaseTexture(&d3dTexture); + if (error.isError()) + { + return error; + } + + // 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 = textureImpl->hasDirtyImages(); + textureImpl->resetDirty(); + } + + if (forceSetTexture || appliedSerials[index] != serial) + { + mDevice->SetTexture(d3dSampler, d3dTexture); + } + + appliedSerials[index] = serial; + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Renderer9::setUniformBuffers(const gl::Data &/*data*/, + const GLint /*vertexUniformBuffers*/[], + const GLint /*fragmentUniformBuffers*/[]) +{ + // No effect in ES2/D3D9 + return gl::Error(GL_NO_ERROR); +} + +gl::Error 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; + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Renderer9::setBlendState(const gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::ColorF &blendColor, + unsigned int sampleMask) +{ + bool blendStateChanged = mForceSetBlendState || memcmp(&blendState, &mCurBlendState, sizeof(gl::BlendState)) != 0; + bool blendColorChanged = mForceSetBlendState || memcmp(&blendColor, &mCurBlendColor, sizeof(gl::ColorF)) != 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."); + } + + gl::FramebufferAttachment *attachment = framebuffer->getFirstColorbuffer(); + GLenum internalFormat = attachment ? attachment->getInternalFormat() : GL_NONE; + + // Set the color mask + bool zeroColorMaskAllowed = getVendorId() != 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 + + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat); + DWORD colorMask = gl_d3d9::ConvertColorMask(formatInfo.redBits > 0 && blendState.colorMaskRed, + formatInfo.greenBits > 0 && blendState.colorMaskGreen, + formatInfo.blueBits > 0 && blendState.colorMaskBlue, + formatInfo.alphaBits > 0 && 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; + + return gl::Error(GL_NO_ERROR); +} + +gl::Error 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; + + ASSERT(depthStencilState.stencilWritemask == depthStencilState.stencilBackWritemask); + ASSERT(stencilRef == stencilBackRef); + ASSERT(depthStencilState.stencilMask == depthStencilState.stencilBackMask); + + // 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; + + return gl::Error(GL_NO_ERROR); +} + +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; +} + +void 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; + + float depthFront = !gl::IsTriangleMode(drawMode) ? 0.0f : (frontFace == GL_CCW ? 1.0f : -1.0f); + + bool viewportChanged = mForceSetViewport || memcmp(&actualViewport, &mCurViewport, sizeof(gl::Rectangle)) != 0 || + actualZNear != mCurNear || actualZFar != mCurFar || mCurDepthFront != depthFront; + if (viewportChanged) + { + mDevice->SetViewport(&dxViewport); + + mCurViewport = actualViewport; + mCurNear = actualZNear; + mCurFar = actualZFar; + mCurDepthFront = depthFront; + + dx_VertexConstants vc = {0}; + dx_PixelConstants pc = {0}; + + vc.viewAdjust[0] = (float)((actualViewport.width - (int)dxViewport.Width) + 2 * (actualViewport.x - (int)dxViewport.X) - 1) / dxViewport.Width; + vc.viewAdjust[1] = (float)((actualViewport.height - (int)dxViewport.Height) + 2 * (actualViewport.y - (int)dxViewport.Y) - 1) / dxViewport.Height; + vc.viewAdjust[2] = (float)actualViewport.width / dxViewport.Width; + vc.viewAdjust[3] = (float)actualViewport.height / dxViewport.Height; + + pc.viewCoords[0] = actualViewport.width * 0.5f; + pc.viewCoords[1] = actualViewport.height * 0.5f; + pc.viewCoords[2] = actualViewport.x + (actualViewport.width * 0.5f); + pc.viewCoords[3] = actualViewport.y + (actualViewport.height * 0.5f); + + pc.depthFront[0] = (actualZFar - actualZNear) * 0.5f; + pc.depthFront[1] = (actualZNear + actualZFar) * 0.5f; + pc.depthFront[2] = depthFront; + + vc.depthRange[0] = actualZNear; + vc.depthRange[1] = actualZFar; + vc.depthRange[2] = actualZFar - actualZNear; + + pc.depthRange[0] = actualZNear; + pc.depthRange[1] = actualZFar; + pc.depthRange[2] = actualZFar - actualZNear; + + if (memcmp(&vc, &mVertexConstants, sizeof(dx_VertexConstants)) != 0) + { + mVertexConstants = vc; + mDxUniformsDirty = true; + } + + if (memcmp(&pc, &mPixelConstants, sizeof(dx_PixelConstants)) != 0) + { + mPixelConstants = pc; + mDxUniformsDirty = true; + } + } + + mForceSetViewport = false; +} + +bool Renderer9::applyPrimitiveType(GLenum mode, GLsizei count, bool usesPointSize) +{ + 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: + UNREACHABLE(); + return false; + } + + return mPrimitiveCount > 0; +} + + +gl::Error Renderer9::getNullColorbuffer(const gl::FramebufferAttachment *depthbuffer, const gl::FramebufferAttachment **outColorBuffer) +{ + ASSERT(depthbuffer); + + 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; + *outColorBuffer = mNullColorbufferCache[i].buffer; + return gl::Error(GL_NO_ERROR); + } + } + + gl::Renderbuffer *nullRenderbuffer = new gl::Renderbuffer(createRenderbuffer(), 0); + gl::Error error = nullRenderbuffer->setStorage(GL_NONE, width, height); + if (error.isError()) + { + SafeDelete(nullRenderbuffer); + return error; + } + + gl::RenderbufferAttachment *nullbuffer = new gl::RenderbufferAttachment(GL_NONE, nullRenderbuffer); + + // 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; + + *outColorBuffer = nullbuffer; + return gl::Error(GL_NO_ERROR); +} + +gl::Error Renderer9::applyRenderTarget(const gl::FramebufferAttachment *colorBuffer, const gl::FramebufferAttachment *depthStencilBuffer) +{ + // 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. + if (!colorBuffer) + { + gl::Error error = getNullColorbuffer(depthStencilBuffer, &colorBuffer); + if (error.isError()) + { + return error; + } + } + ASSERT(colorBuffer); + + size_t renderTargetWidth = 0; + size_t renderTargetHeight = 0; + D3DFORMAT renderTargetFormat = D3DFMT_UNKNOWN; + + bool renderTargetChanged = false; + unsigned int renderTargetSerial = GetAttachmentSerial(colorBuffer); + if (renderTargetSerial != mAppliedRenderTargetSerial) + { + // Apply the render target on the device + RenderTarget9 *renderTarget = NULL; + gl::Error error = d3d9::GetAttachmentRenderTarget(colorBuffer, &renderTarget); + if (error.isError()) + { + return error; + } + ASSERT(renderTarget); + + IDirect3DSurface9 *renderTargetSurface = renderTarget->getSurface(); + ASSERT(renderTargetSurface); + + mDevice->SetRenderTarget(0, renderTargetSurface); + SafeRelease(renderTargetSurface); + + renderTargetWidth = renderTarget->getWidth(); + renderTargetHeight = renderTarget->getHeight(); + renderTargetFormat = renderTarget->getD3DFormat(); + + mAppliedRenderTargetSerial = renderTargetSerial; + renderTargetChanged = true; + } + + unsigned int depthStencilSerial = (depthStencilBuffer != nullptr) ? GetAttachmentSerial(depthStencilBuffer) : 0; + if (depthStencilSerial != mAppliedDepthStencilSerial || !mDepthStencilInitialized) + { + unsigned int depthSize = 0; + unsigned int stencilSize = 0; + + // Apply the depth stencil on the device + if (depthStencilBuffer) + { + RenderTarget9 *depthStencilRenderTarget = NULL; + gl::Error error = d3d9::GetAttachmentRenderTarget(depthStencilBuffer, &depthStencilRenderTarget); + if (error.isError()) + { + return error; + } + ASSERT(depthStencilRenderTarget); + + IDirect3DSurface9 *depthStencilSurface = depthStencilRenderTarget->getSurface(); + ASSERT(depthStencilSurface); + + mDevice->SetDepthStencilSurface(depthStencilSurface); + SafeRelease(depthStencilSurface); + + depthSize = depthStencilBuffer->getDepthSize(); + stencilSize = depthStencilBuffer->getStencilSize(); + } + else + { + mDevice->SetDepthStencilSurface(NULL); + } + + if (!mDepthStencilInitialized || depthSize != mCurDepthSize) + { + mCurDepthSize = depthSize; + mForceSetRasterState = true; + } + + if (!mDepthStencilInitialized || stencilSize != mCurStencilSize) + { + mCurStencilSize = stencilSize; + mForceSetDepthStencilState = true; + } + + mAppliedDepthStencilSerial = depthStencilSerial; + mDepthStencilInitialized = true; + } + + if (renderTargetChanged || !mRenderTargetDescInitialized) + { + mForceSetScissor = true; + mForceSetViewport = true; + mForceSetBlendState = true; + + mRenderTargetDesc.width = renderTargetWidth; + mRenderTargetDesc.height = renderTargetHeight; + mRenderTargetDesc.format = renderTargetFormat; + mRenderTargetDescInitialized = true; + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Renderer9::applyRenderTarget(const gl::Framebuffer *framebuffer) +{ + return applyRenderTarget(framebuffer->getColorbuffer(0), framebuffer->getDepthOrStencilbuffer()); +} + +gl::Error Renderer9::applyVertexBuffer(const gl::State &state, GLenum mode, GLint first, GLsizei count, GLsizei instances) +{ + TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS]; + gl::Error error = mVertexDataManager->prepareVertexData(state, first, count, attributes, instances); + if (error.isError()) + { + return error; + } + + return mVertexDeclarationCache.applyDeclaration(mDevice, attributes, state.getProgram(), instances, &mRepeatDraw); +} + +// Applies the indices and element array bindings to the Direct3D 9 device +gl::Error Renderer9::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo) +{ + gl::Error error = mIndexDataManager->prepareIndexData(type, count, elementArrayBuffer, indices, indexInfo); + if (error.isError()) + { + return 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 gl::Error(GL_NO_ERROR); +} + +void Renderer9::applyTransformFeedbackBuffers(const gl::State& state) +{ + ASSERT(!state.isTransformFeedbackActiveUnpaused()); +} + +gl::Error Renderer9::drawArrays(const gl::Data &data, GLenum mode, GLsizei count, GLsizei instances, bool usesPointSize) +{ + ASSERT(!data.state->isTransformFeedbackActiveUnpaused()); + + startScene(); + + if (mode == GL_LINE_LOOP) + { + return drawLineLoop(count, GL_NONE, NULL, 0, NULL); + } + else if (instances > 0) + { + StaticIndexBufferInterface *countingIB = NULL; + gl::Error error = getCountingIB(count, &countingIB); + if (error.isError()) + { + return error; + } + + 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); + } + + return gl::Error(GL_NO_ERROR); + } + else // Regular case + { + mDevice->DrawPrimitive(mPrimitiveType, 0, mPrimitiveCount); + return gl::Error(GL_NO_ERROR); + } +} + +gl::Error Renderer9::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, + gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei /*instances*/) +{ + startScene(); + + int minIndex = static_cast(indexInfo.indexRange.start); + + if (mode == GL_POINTS) + { + return drawIndexedPoints(count, type, indices, minIndex, elementArrayBuffer); + } + else if (mode == GL_LINE_LOOP) + { + return drawLineLoop(count, type, indices, minIndex, elementArrayBuffer); + } + else + { + for (int i = 0; i < mRepeatDraw; i++) + { + GLsizei vertexCount = static_cast(indexInfo.indexRange.length()) + 1; + mDevice->DrawIndexedPrimitive(mPrimitiveType, -minIndex, minIndex, vertexCount, indexInfo.startIndex, mPrimitiveCount); + } + return gl::Error(GL_NO_ERROR); + } +} + +gl::Error 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) + { + BufferD3D *storage = GetImplAs(elementArrayBuffer); + intptr_t offset = reinterpret_cast(indices); + const uint8_t *bufferData = NULL; + gl::Error error = storage->getData(&bufferData); + if (error.isError()) + { + return error; + } + indices = bufferData + offset; + } + + unsigned int startIndex = 0; + + if (getRendererExtensions().elementIndexUint) + { + if (!mLineLoopIB) + { + mLineLoopIB = new StreamingIndexBufferInterface(this); + gl::Error error = mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT); + if (error.isError()) + { + SafeDelete(mLineLoopIB); + return error; + } + } + + // Checked by Renderer9::applyPrimitiveType + ASSERT(count >= 0); + + if (static_cast(count) + 1 > (std::numeric_limits::max() / sizeof(unsigned int))) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create a 32-bit looping index buffer for GL_LINE_LOOP, too many indices required."); + } + + const unsigned int spaceNeeded = (static_cast(count)+1) * sizeof(unsigned int); + gl::Error error = mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT); + if (error.isError()) + { + return error; + } + + void* mappedMemory = NULL; + unsigned int offset = 0; + error = mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset); + if (error.isError()) + { + return error; + } + + 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(); + } + + error = mLineLoopIB->unmapBuffer(); + if (error.isError()) + { + return error; + } + } + else + { + if (!mLineLoopIB) + { + mLineLoopIB = new StreamingIndexBufferInterface(this); + gl::Error error = mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_SHORT); + if (error.isError()) + { + SafeDelete(mLineLoopIB); + return error; + } + } + + // Checked by Renderer9::applyPrimitiveType + ASSERT(count >= 0); + + if (static_cast(count) + 1 > (std::numeric_limits::max() / sizeof(unsigned short))) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create a 16-bit looping index buffer for GL_LINE_LOOP, too many indices required."); + } + + const unsigned int spaceNeeded = (static_cast(count) + 1) * sizeof(unsigned short); + gl::Error error = mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_SHORT); + if (error.isError()) + { + return error; + } + + void* mappedMemory = NULL; + unsigned int offset; + error = mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset); + if (error.isError()) + { + return error; + } + + 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(); + } + + error = mLineLoopIB->unmapBuffer(); + if (error.isError()) + { + return error; + } + } + + 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); + + return gl::Error(GL_NO_ERROR); +} + +template +static gl::Error drawPoints(IDirect3DDevice9* device, GLsizei count, const GLvoid *indices, int minIndex) +{ + for (int i = 0; i < count; i++) + { + unsigned int indexValue = static_cast(static_cast(indices)[i]) - minIndex; + device->DrawPrimitive(D3DPT_POINTLIST, indexValue, 1); + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Renderer9::drawIndexedPoints(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer) +{ + // Drawing index point lists is unsupported in d3d9, fall back to a regular DrawPrimitive call + // for each individual point. This call is not expected to happen often. + + if (elementArrayBuffer) + { + BufferD3D *storage = GetImplAs(elementArrayBuffer); + intptr_t offset = reinterpret_cast(indices); + + const uint8_t *bufferData = NULL; + gl::Error error = storage->getData(&bufferData); + if (error.isError()) + { + return error; + } + + indices = bufferData + offset; + } + + switch (type) + { + case GL_UNSIGNED_BYTE: return drawPoints(mDevice, count, indices, minIndex); + case GL_UNSIGNED_SHORT: return drawPoints(mDevice, count, indices, minIndex); + case GL_UNSIGNED_INT: return drawPoints(mDevice, count, indices, minIndex); + default: UNREACHABLE(); return gl::Error(GL_INVALID_OPERATION); + } +} + +gl::Error Renderer9::getCountingIB(size_t count, StaticIndexBufferInterface **outIB) +{ + // Update the counting index buffer if it is not large enough or has not been created yet. + if (count <= 65536) // 16-bit indices + { + const unsigned int spaceNeeded = count * sizeof(unsigned short); + + if (!mCountingIB || mCountingIB->getBufferSize() < spaceNeeded) + { + SafeDelete(mCountingIB); + mCountingIB = new StaticIndexBufferInterface(this); + mCountingIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_SHORT); + + void *mappedMemory = NULL; + gl::Error error = mCountingIB->mapBuffer(spaceNeeded, &mappedMemory, NULL); + if (error.isError()) + { + return error; + } + + unsigned short *data = reinterpret_cast(mappedMemory); + for (size_t i = 0; i < count; i++) + { + data[i] = i; + } + + error = mCountingIB->unmapBuffer(); + if (error.isError()) + { + return error; + } + } + } + else if (getRendererExtensions().elementIndexUint) + { + const unsigned int spaceNeeded = count * sizeof(unsigned int); + + if (!mCountingIB || mCountingIB->getBufferSize() < spaceNeeded) + { + SafeDelete(mCountingIB); + mCountingIB = new StaticIndexBufferInterface(this); + mCountingIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT); + + void *mappedMemory = NULL; + gl::Error error = mCountingIB->mapBuffer(spaceNeeded, &mappedMemory, NULL); + if (error.isError()) + { + return error; + } + + unsigned int *data = reinterpret_cast(mappedMemory); + for (size_t i = 0; i < count; i++) + { + data[i] = i; + } + + error = mCountingIB->unmapBuffer(); + if (error.isError()) + { + return error; + } + } + } + else + { + return gl::Error(GL_OUT_OF_MEMORY, "Could not create a counting index buffer for glDrawArraysInstanced."); + } + + *outIB = mCountingIB; + return gl::Error(GL_NO_ERROR); +} + +gl::Error Renderer9::applyShaders(gl::Program *program, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer, + bool rasterizerDiscard, bool transformFeedbackActive) +{ + ASSERT(!transformFeedbackActive); + ASSERT(!rasterizerDiscard); + + ProgramD3D *programD3D = GetImplAs(program); + + ShaderExecutableD3D *vertexExe = NULL; + gl::Error error = programD3D->getVertexExecutableForInputLayout(inputLayout, &vertexExe, nullptr); + if (error.isError()) + { + return error; + } + + ShaderExecutableD3D *pixelExe = NULL; + error = programD3D->getPixelExecutableForFramebuffer(framebuffer, &pixelExe); + if (error.isError()) + { + return error; + } + + IDirect3DVertexShader9 *vertexShader = (vertexExe ? ShaderExecutable9::makeShaderExecutable9(vertexExe)->getVertexShader() : NULL); + IDirect3DPixelShader9 *pixelShader = (pixelExe ? ShaderExecutable9::makeShaderExecutable9(pixelExe)->getPixelShader() : NULL); + + if (vertexShader != mAppliedVertexShader) + { + mDevice->SetVertexShader(vertexShader); + mAppliedVertexShader = vertexShader; + } + + if (pixelShader != mAppliedPixelShader) + { + mDevice->SetPixelShader(pixelShader); + mAppliedPixelShader = pixelShader; + } + + // D3D9 has a quirk where creating multiple shaders with the same content + // can return the same shader pointer. Because GL programs store different data + // per-program, checking the program serial guarantees we upload fresh + // uniform data even if our shader pointers are the same. + // https://code.google.com/p/angleproject/issues/detail?id=661 + unsigned int programSerial = programD3D->getSerial(); + if (programSerial != mAppliedProgramSerial) + { + programD3D->dirtyAllUniforms(); + mDxUniformsDirty = true; + mAppliedProgramSerial = programSerial; + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Renderer9::applyUniforms(const ProgramImpl &program, const std::vector &uniformArray) +{ + for (size_t uniformIndex = 0; uniformIndex < uniformArray.size(); uniformIndex++) + { + gl::LinkedUniform *targetUniform = uniformArray[uniformIndex]; + + 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(); + } + } + } + + // 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; + } + + return gl::Error(GL_NO_ERROR); +} + +void Renderer9::applyUniformnfv(gl::LinkedUniform *targetUniform, const GLfloat *v) +{ + if (targetUniform->isReferencedByFragmentShader()) + { + mDevice->SetPixelShaderConstantF(targetUniform->psRegisterIndex, v, targetUniform->registerCount); + } + + if (targetUniform->isReferencedByVertexShader()) + { + mDevice->SetVertexShaderConstantF(targetUniform->vsRegisterIndex, v, targetUniform->registerCount); + } +} + +void Renderer9::applyUniformniv(gl::LinkedUniform *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::LinkedUniform *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); +} + +gl::Error Renderer9::clear(const ClearParameters &clearParams, + const gl::FramebufferAttachment *colorBuffer, + const gl::FramebufferAttachment *depthStencilBuffer) +{ + if (clearParams.colorClearType != GL_FLOAT) + { + // Clearing buffers with non-float values is not supported by Renderer9 and ES 2.0 + UNREACHABLE(); + return gl::Error(GL_INVALID_OPERATION); + } + + bool clearColor = clearParams.clearColor[0]; + for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++) + { + if (clearParams.clearColor[i] != clearColor) + { + // Clearing individual buffers other than buffer zero is not supported by Renderer9 and ES 2.0 + UNREACHABLE(); + return gl::Error(GL_INVALID_OPERATION); + } + } + + float depth = gl::clamp01(clearParams.depthClearValue); + DWORD stencil = clearParams.stencilClearValue & 0x000000FF; + + unsigned int stencilUnmasked = 0x0; + if (clearParams.clearStencil && depthStencilBuffer->getStencilSize() > 0) + { + RenderTargetD3D *stencilRenderTarget = NULL; + gl::Error error = GetAttachmentRenderTarget(depthStencilBuffer, &stencilRenderTarget); + if (error.isError()) + { + return error; + } + + RenderTarget9 *stencilRenderTarget9 = RenderTarget9::makeRenderTarget9(stencilRenderTarget); + ASSERT(stencilRenderTarget9); + + const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(stencilRenderTarget9->getD3DFormat()); + stencilUnmasked = (0x1 << d3dFormatInfo.stencilBits) - 1; + } + + const bool needMaskedStencilClear = clearParams.clearStencil && + (clearParams.stencilWriteMask & stencilUnmasked) != stencilUnmasked; + + bool needMaskedColorClear = false; + D3DCOLOR color = D3DCOLOR_ARGB(255, 0, 0, 0); + if (clearColor) + { + RenderTargetD3D *colorRenderTarget = NULL; + gl::Error error = GetAttachmentRenderTarget(colorBuffer, &colorRenderTarget); + if (error.isError()) + { + return error; + } + + RenderTarget9 *colorRenderTarget9 = RenderTarget9::makeRenderTarget9(colorRenderTarget); + ASSERT(colorRenderTarget9); + + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(colorBuffer->getInternalFormat()); + const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(colorRenderTarget9->getD3DFormat()); + + color = D3DCOLOR_ARGB(gl::unorm<8>((formatInfo.alphaBits == 0 && d3dFormatInfo.alphaBits > 0) ? 1.0f : clearParams.colorFClearValue.alpha), + gl::unorm<8>((formatInfo.redBits == 0 && d3dFormatInfo.redBits > 0) ? 0.0f : clearParams.colorFClearValue.red), + gl::unorm<8>((formatInfo.greenBits == 0 && d3dFormatInfo.greenBits > 0) ? 0.0f : clearParams.colorFClearValue.green), + gl::unorm<8>((formatInfo.blueBits == 0 && d3dFormatInfo.blueBits > 0) ? 0.0f : clearParams.colorFClearValue.blue)); + + if ((formatInfo.redBits > 0 && !clearParams.colorMaskRed) || + (formatInfo.greenBits > 0 && !clearParams.colorMaskGreen) || + (formatInfo.blueBits > 0 && !clearParams.colorMaskBlue) || + (formatInfo.alphaBits > 0 && !clearParams.colorMaskAlpha)) + { + needMaskedColorClear = true; + } + } + + 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 (clearColor) + { + 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.clearStencil) + { + 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.clearDepth) + { + 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 (clearColor || clearParams.clearDepth || clearParams.clearStencil) + { + DWORD dxClearFlags = 0; + if (clearColor) + { + dxClearFlags |= D3DCLEAR_TARGET; + } + if (clearParams.clearDepth) + { + dxClearFlags |= D3DCLEAR_ZBUFFER; + } + if (clearParams.clearStencil) + { + dxClearFlags |= D3DCLEAR_STENCIL; + } + + mDevice->Clear(0, NULL, dxClearFlags, color, depth, stencil); + } + + return gl::Error(GL_NO_ERROR); +} + +void Renderer9::markAllStateDirty() +{ + mAppliedRenderTargetSerial = 0; + mAppliedDepthStencilSerial = 0; + mDepthStencilInitialized = false; + mRenderTargetDescInitialized = false; + + mForceSetDepthStencilState = true; + mForceSetRasterState = true; + mForceSetScissor = true; + mForceSetViewport = true; + mForceSetBlendState = true; + + ASSERT(mForceSetVertexSamplerStates.size() == mCurVertexTextureSerials.size()); + for (unsigned int i = 0; i < mForceSetVertexSamplerStates.size(); i++) + { + mForceSetVertexSamplerStates[i] = true; + mCurVertexTextureSerials[i] = 0; + } + + ASSERT(mForceSetPixelSamplerStates.size() == mCurPixelTextureSerials.size()); + for (unsigned int i = 0; i < mForceSetPixelSamplerStates.size(); i++) + { + mForceSetPixelSamplerStates[i] = true; + mCurPixelTextureSerials[i] = 0; + } + + mAppliedIBSerial = 0; + mAppliedVertexShader = NULL; + mAppliedPixelShader = NULL; + mAppliedProgramSerial = 0; + mDxUniformsDirty = true; + + mVertexDeclarationCache.markStateDirty(); +} + +void Renderer9::releaseDeviceResources() +{ + for (size_t i = 0; i < mEventQueryPool.size(); i++) + { + SafeRelease(mEventQueryPool[i]); + } + mEventQueryPool.clear(); + + SafeRelease(mMaskedClearSavedState); + + mVertexShaderCache.clear(); + mPixelShaderCache.clear(); + + SafeDelete(mBlit); + SafeDelete(mVertexDataManager); + SafeDelete(mIndexDataManager); + SafeDelete(mLineLoopIB); + SafeDelete(mCountingIB); + + for (int i = 0; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++) + { + SafeDelete(mNullColorbufferCache[i].buffer); + } +} + +// set notify to true to broadcast a message to all contexts of the device loss +bool Renderer9::testDeviceLost() +{ + HRESULT status = getDeviceStatusCode(); + bool isLost = FAILED(status); + + if (isLost) + { + // ensure we note the device loss -- + // we'll probably get this done again by notifyDeviceLost + // but best to remember it! + // Note that we don't want to clear the device loss status here + // -- this needs to be done by resetDevice + mDeviceLost = true; + } + + return isLost; +} + +HRESULT Renderer9::getDeviceStatusCode() +{ + HRESULT status = D3D_OK; + + if (mDeviceEx) + { + status = mDeviceEx->CheckDeviceState(NULL); + } + else if (mDevice) + { + status = mDevice->TestCooperativeLevel(); + } + + return status; +} + +bool Renderer9::testDeviceResettable() +{ + // On D3D9Ex, DEVICELOST represents a hung device that needs to be restarted + // DEVICEREMOVED indicates the device has been stopped and must be recreated + switch (getDeviceStatusCode()) + { + case D3DERR_DEVICENOTRESET: + case D3DERR_DEVICEHUNG: + return true; + case D3DERR_DEVICELOST: + return (mDeviceEx != NULL); + case D3DERR_DEVICEREMOVED: + ASSERT(mDeviceEx != NULL); + return isRemovedDeviceResettable(); + default: + return false; + } +} + +bool Renderer9::resetDevice() +{ + releaseDeviceResources(); + + D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters(); + + HRESULT result = D3D_OK; + bool lost = testDeviceLost(); + bool removedDevice = (getDeviceStatusCode() == D3DERR_DEVICEREMOVED); + + // Device Removed is a feature which is only present with D3D9Ex + ASSERT(mDeviceEx != NULL || !removedDevice); + + for (int attempts = 3; lost && attempts > 0; attempts--) + { + if (removedDevice) + { + // Device removed, which may trigger on driver reinstallation, + // may cause a longer wait other reset attempts before the + // system is ready to handle creating a new device. + Sleep(800); + lost = !resetRemovedDevice(); + } + else if (mDeviceEx) + { + Sleep(500); // Give the graphics driver some CPU time + result = mDeviceEx->ResetEx(&presentParameters, NULL); + lost = testDeviceLost(); + } + 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(); + } + } + + if (FAILED(result)) + { + ERR("Reset/ResetEx failed multiple times: 0x%08X", result); + return false; + } + + if (removedDevice && lost) + { + ERR("Device lost reset failed multiple times"); + return false; + } + + // If the device was removed, we already finished re-initialization in resetRemovedDevice + if (!removedDevice) + { + // reset device defaults + initializeDevice(); + } + + mDeviceLost = false; + + return true; +} + +bool Renderer9::isRemovedDeviceResettable() const +{ + bool success = false; + +#if ANGLE_D3D9EX == ANGLE_ENABLED + IDirect3D9Ex *d3d9Ex = NULL; + typedef HRESULT (WINAPI *Direct3DCreate9ExFunc)(UINT, IDirect3D9Ex**); + Direct3DCreate9ExFunc Direct3DCreate9ExPtr = reinterpret_cast(GetProcAddress(mD3d9Module, "Direct3DCreate9Ex")); + + if (Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &d3d9Ex))) + { + D3DCAPS9 deviceCaps; + HRESULT result = d3d9Ex->GetDeviceCaps(mAdapter, mDeviceType, &deviceCaps); + success = SUCCEEDED(result); + } + + SafeRelease(d3d9Ex); +#else + ASSERT(UNREACHABLE()); +#endif + + return success; +} + +bool Renderer9::resetRemovedDevice() +{ + // From http://msdn.microsoft.com/en-us/library/windows/desktop/bb172554(v=vs.85).aspx: + // The hardware adapter has been removed. Application must destroy the device, do enumeration of + // adapters and create another Direct3D device. If application continues rendering without + // calling Reset, the rendering calls will succeed. Applies to Direct3D 9Ex only. + release(); + return !initialize().isError(); +} + +VendorID Renderer9::getVendorId() const +{ + return static_cast(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; +} + +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::getReservedVertexUniformBuffers() const +{ + return 0; +} + +unsigned int Renderer9::getReservedFragmentUniformBuffers() const +{ + return 0; +} + +bool Renderer9::getShareHandleSupport() const +{ + // PIX doesn't seem to support using share handles, so disable them. + return (mD3d9Ex != NULL) && !gl::DebugAnnotationsActive(); +} + +bool Renderer9::getPostSubBufferSupport() const +{ + return true; +} + +int Renderer9::getMajorShaderModel() const +{ + return D3DSHADER_VERSION_MAJOR(mDeviceCaps.PixelShaderVersion); +} + +int Renderer9::getMinorShaderModel() const +{ + return D3DSHADER_VERSION_MINOR(mDeviceCaps.PixelShaderVersion); +} + +std::string Renderer9::getShaderModelSuffix() const +{ + return ""; +} + +DWORD Renderer9::getCapsDeclTypes() const +{ + return mDeviceCaps.DeclTypes; +} + +D3DPOOL Renderer9::getBufferPool(DWORD usage) const +{ + if (mD3d9Ex != NULL) + { + return D3DPOOL_DEFAULT; + } + else + { + if (!(usage & D3DUSAGE_DYNAMIC)) + { + return D3DPOOL_MANAGED; + } + } + + return D3DPOOL_DEFAULT; +} + +gl::Error Renderer9::copyImage2D(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + const gl::Offset &destOffset, TextureStorage *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->copy2D(framebuffer, rect, destFormat, destOffset, storage, level); +} + +gl::Error Renderer9::copyImageCube(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + const gl::Offset &destOffset, TextureStorage *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->copyCube(framebuffer, rect, destFormat, destOffset, storage, target, level); +} + +gl::Error Renderer9::copyImage3D(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + const gl::Offset &destOffset, TextureStorage *storage, GLint level) +{ + // 3D textures are not available in the D3D9 backend. + UNREACHABLE(); + return gl::Error(GL_INVALID_OPERATION); +} + +gl::Error Renderer9::copyImage2DArray(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + const gl::Offset &destOffset, TextureStorage *storage, GLint level) +{ + // 2D array textures are not available in the D3D9 backend. + UNREACHABLE(); + return gl::Error(GL_INVALID_OPERATION); +} + +gl::Error Renderer9::createRenderTarget(int width, int height, GLenum format, GLsizei samples, RenderTargetD3D **outRT) +{ + const d3d9::TextureFormat &d3d9FormatInfo = d3d9::GetTextureFormatInfo(format); + + const gl::TextureCaps &textureCaps = getRendererTextureCaps().get(format); + GLuint supportedSamples = textureCaps.getNearestSamples(samples); + + IDirect3DSurface9 *renderTarget = NULL; + if (width > 0 && height > 0) + { + bool requiresInitialization = false; + HRESULT result = D3DERR_INVALIDCALL; + + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format); + if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0) + { + result = mDevice->CreateDepthStencilSurface(width, height, d3d9FormatInfo.renderFormat, + gl_d3d9::GetMultisampleType(supportedSamples), + 0, FALSE, &renderTarget, NULL); + } + else + { + requiresInitialization = (d3d9FormatInfo.dataInitializerFunction != NULL); + result = mDevice->CreateRenderTarget(width, height, d3d9FormatInfo.renderFormat, + gl_d3d9::GetMultisampleType(supportedSamples), + 0, FALSE, &renderTarget, NULL); + } + + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create render target, result: 0x%X.", result); + } + + if (requiresInitialization) + { + // This format requires that the data be initialized before the render target can be used + // Unfortunately this requires a Get call on the d3d device but it is far better than having + // to mark the render target as lockable and copy data to the gpu. + IDirect3DSurface9 *prevRenderTarget = NULL; + mDevice->GetRenderTarget(0, &prevRenderTarget); + mDevice->SetRenderTarget(0, renderTarget); + mDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_RGBA(0, 0, 0, 255), 0.0f, 0); + mDevice->SetRenderTarget(0, prevRenderTarget); + } + } + + *outRT = new TextureRenderTarget9(renderTarget, format, width, height, 1, supportedSamples); + return gl::Error(GL_NO_ERROR); +} + +FramebufferImpl *Renderer9::createDefaultFramebuffer(const gl::Framebuffer::Data &data) +{ + return createFramebuffer(data); +} + +FramebufferImpl *Renderer9::createFramebuffer(const gl::Framebuffer::Data &data) +{ + return new Framebuffer9(data, this); +} + +CompilerImpl *Renderer9::createCompiler(const gl::Data &data) +{ + return new CompilerD3D(data, SH_HLSL9_OUTPUT); +} + +ShaderImpl *Renderer9::createShader(GLenum type) +{ + return new ShaderD3D(type); +} + +ProgramImpl *Renderer9::createProgram() +{ + return new ProgramD3D(this); +} + +gl::Error Renderer9::loadExecutable(const void *function, size_t length, ShaderType type, + const std::vector &transformFeedbackVaryings, + bool separatedOutputBuffers, ShaderExecutableD3D **outExecutable) +{ + // Transform feedback is not supported in ES2 or D3D9 + ASSERT(transformFeedbackVaryings.size() == 0); + + switch (type) + { + case SHADER_VERTEX: + { + IDirect3DVertexShader9 *vshader = NULL; + gl::Error error = createVertexShader((DWORD*)function, length, &vshader); + if (error.isError()) + { + return error; + } + *outExecutable = new ShaderExecutable9(function, length, vshader); + } + break; + case SHADER_PIXEL: + { + IDirect3DPixelShader9 *pshader = NULL; + gl::Error error = createPixelShader((DWORD*)function, length, &pshader); + if (error.isError()) + { + return error; + } + *outExecutable = new ShaderExecutable9(function, length, pshader); + } + break; + default: + UNREACHABLE(); + return gl::Error(GL_INVALID_OPERATION); + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error Renderer9::compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, ShaderType type, + const std::vector &transformFeedbackVaryings, + bool separatedOutputBuffers, const D3DCompilerWorkarounds &workarounds, + ShaderExecutableD3D **outExectuable) +{ + // Transform feedback is not supported in ES2 or D3D9 + ASSERT(transformFeedbackVaryings.size() == 0); + + const char *profileType = NULL; + switch (type) + { + case SHADER_VERTEX: + profileType = "vs"; + break; + case SHADER_PIXEL: + profileType = "ps"; + break; + default: + UNREACHABLE(); + return gl::Error(GL_INVALID_OPERATION); + } + unsigned int profileMajorVersion = (getMajorShaderModel() >= 3) ? 3 : 2; + unsigned int profileMinorVersion = 0; + std::string profile = FormatString("%s_%u_%u", profileType, profileMajorVersion, profileMinorVersion); + + UINT flags = ANGLE_COMPILE_OPTIMIZATION_LEVEL; + + if (workarounds.skipOptimization) + { + flags = D3DCOMPILE_SKIP_OPTIMIZATION; + } + else if (workarounds.useMaxOptimization) + { + flags = D3DCOMPILE_OPTIMIZATION_LEVEL3; + } + + if (gl::DebugAnnotationsActive()) + { +#ifndef NDEBUG + flags = D3DCOMPILE_SKIP_OPTIMIZATION; +#endif + + flags |= D3DCOMPILE_DEBUG; + } + + // 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. + std::vector configs; + configs.push_back(CompileConfig(flags, "default" )); + configs.push_back(CompileConfig(flags | D3DCOMPILE_AVOID_FLOW_CONTROL, "avoid flow control" )); + configs.push_back(CompileConfig(flags | D3DCOMPILE_PREFER_FLOW_CONTROL, "prefer flow control")); + + ID3DBlob *binary = NULL; + std::string debugInfo; + gl::Error error = mCompiler.compileToBinary(infoLog, shaderHLSL, profile, configs, NULL, &binary, &debugInfo); + if (error.isError()) + { + return error; + } + + // It's possible that binary is NULL if the compiler failed in all configurations. Set the executable to NULL + // and return GL_NO_ERROR to signify that there was a link error but the internal state is still OK. + if (!binary) + { + *outExectuable = NULL; + return gl::Error(GL_NO_ERROR); + } + + error = loadExecutable(binary->GetBufferPointer(), binary->GetBufferSize(), type, + transformFeedbackVaryings, separatedOutputBuffers, outExectuable); + + SafeRelease(binary); + if (error.isError()) + { + return error; + } + + if (!debugInfo.empty()) + { + (*outExectuable)->appendDebugInfo(debugInfo); + } + + return gl::Error(GL_NO_ERROR); +} + +UniformStorageD3D *Renderer9::createUniformStorage(size_t storageSize) +{ + return new UniformStorageD3D(storageSize); +} + +gl::Error 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; +} + +gl::Error Renderer9::copyToRenderTarget(IDirect3DSurface9 *dest, IDirect3DSurface9 *source, bool fromManaged) +{ + ASSERT(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); + SafeRelease(surf); + } + } + else + { + endScene(); + result = mDevice->StretchRect(source, NULL, dest, NULL, D3DTEXF_NONE); + } + + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to blit internal texture, result: 0x%X.", result); + } + + return gl::Error(GL_NO_ERROR); +} + +ImageD3D *Renderer9::createImage() +{ + return new Image9(this); +} + +gl::Error Renderer9::generateMipmap(ImageD3D *dest, ImageD3D *src) +{ + Image9 *src9 = Image9::makeImage9(src); + Image9 *dst9 = Image9::makeImage9(dest); + return Image9::generateMipmap(dst9, src9); +} + +TextureStorage *Renderer9::createTextureStorage2D(SwapChainD3D *swapChain) +{ + SwapChain9 *swapChain9 = SwapChain9::makeSwapChain9(swapChain); + return new TextureStorage9_2D(this, swapChain9); +} + +TextureStorage *Renderer9::createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels, bool hintLevelZeroOnly) +{ + return new TextureStorage9_2D(this, internalformat, renderTarget, width, height, levels); +} + +TextureStorage *Renderer9::createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly) +{ + return new TextureStorage9_Cube(this, internalformat, renderTarget, size, levels, hintLevelZeroOnly); +} + +TextureStorage *Renderer9::createTextureStorage3D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) +{ + // 3D textures are not supported by the D3D9 backend. + UNREACHABLE(); + + return NULL; +} + +TextureStorage *Renderer9::createTextureStorage2DArray(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) +{ + // 2D array textures are not supported by the D3D9 backend. + UNREACHABLE(); + + return NULL; +} + +TextureImpl *Renderer9::createTexture(GLenum target) +{ + switch(target) + { + case GL_TEXTURE_2D: return new TextureD3D_2D(this); + case GL_TEXTURE_CUBE_MAP: return new TextureD3D_Cube(this); + default: UNREACHABLE(); + } + + return NULL; +} + +RenderbufferImpl *Renderer9::createRenderbuffer() +{ + RenderbufferD3D *renderbuffer = new RenderbufferD3D(this); + return renderbuffer; +} + +bool Renderer9::getLUID(LUID *adapterLuid) const +{ + adapterLuid->HighPart = 0; + adapterLuid->LowPart = 0; + + if (mD3d9Ex) + { + mD3d9Ex->GetAdapterLUID(mAdapter, adapterLuid); + return true; + } + + return false; +} + +VertexConversionType Renderer9::getVertexConversionType(const gl::VertexFormat &vertexFormat) const +{ + return d3d9::GetVertexFormatInfo(getCapsDeclTypes(), vertexFormat).conversionType; +} + +GLenum Renderer9::getVertexComponentType(const gl::VertexFormat &vertexFormat) const +{ + return d3d9::GetVertexFormatInfo(getCapsDeclTypes(), vertexFormat).componentType; +} + +void Renderer9::generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureCaps, gl::Extensions *outExtensions) const +{ + d3d9_gl::GenerateCaps(mD3d9, mDevice, mDeviceType, mAdapter, outCaps, outTextureCaps, outExtensions); +} + +Workarounds Renderer9::generateWorkarounds() const +{ + return d3d9::GenerateWorkarounds(); +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.h new file mode 100644 index 0000000000..19bea3eb35 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.h @@ -0,0 +1,377 @@ +// +// Copyright (c) 2012-2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Renderer9.h: Defines a back-end specific class for the D3D9 renderer. + +#ifndef LIBANGLE_RENDERER_D3D_D3D9_RENDERER9_H_ +#define LIBANGLE_RENDERER_D3D_D3D9_RENDERER9_H_ + +#include "common/angleutils.h" +#include "common/mathutil.h" +#include "libANGLE/renderer/d3d/HLSLCompiler.h" +#include "libANGLE/renderer/d3d/RendererD3D.h" +#include "libANGLE/renderer/d3d/RenderTargetD3D.h" +#include "libANGLE/renderer/d3d/d3d9/DebugAnnotator9.h" +#include "libANGLE/renderer/d3d/d3d9/ShaderCache.h" +#include "libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.h" + +namespace gl +{ +class FramebufferAttachment; +} + +namespace egl +{ +class AttributeMap; +} + +namespace rx +{ +class Blit9; +class IndexDataManager; +class StreamingIndexBufferInterface; +class StaticIndexBufferInterface; +class VertexDataManager; +struct ClearParameters; +struct TranslatedAttribute; + +enum D3D9InitError +{ + D3D9_INIT_SUCCESS = 0, + // Failed to load the D3D or ANGLE compiler + D3D9_INIT_COMPILER_ERROR, + // Failed to load a necessary DLL + D3D9_INIT_MISSING_DEP, + // Device creation error + D3D9_INIT_CREATE_DEVICE_ERROR, + // System does not meet minimum shader spec + D3D9_INIT_UNSUPPORTED_VERSION, + // System does not support stretchrect from textures + D3D9_INIT_UNSUPPORTED_STRETCHRECT, + // A call returned out of memory or device lost + D3D9_INIT_OUT_OF_MEMORY, + // Other unspecified error + D3D9_INIT_OTHER_ERROR, + NUM_D3D9_INIT_ERRORS +}; + +class Renderer9 : public RendererD3D +{ + public: + explicit Renderer9(egl::Display *display); + virtual ~Renderer9(); + + static Renderer9 *makeRenderer9(Renderer *renderer); + + egl::Error initialize() override; + virtual bool resetDevice(); + + egl::ConfigSet generateConfigs() const override; + + void startScene(); + void endScene(); + + gl::Error flush() override; + gl::Error finish() override; + + virtual SwapChainD3D *createSwapChain(NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat); + + gl::Error allocateEventQuery(IDirect3DQuery9 **outQuery); + void freeEventQuery(IDirect3DQuery9* query); + + // resource creation + gl::Error createVertexShader(const DWORD *function, size_t length, IDirect3DVertexShader9 **outShader); + gl::Error createPixelShader(const DWORD *function, size_t length, IDirect3DPixelShader9 **outShader); + HRESULT createVertexBuffer(UINT Length, DWORD Usage, IDirect3DVertexBuffer9 **ppVertexBuffer); + HRESULT createIndexBuffer(UINT Length, DWORD Usage, D3DFORMAT Format, IDirect3DIndexBuffer9 **ppIndexBuffer); + virtual gl::Error generateSwizzle(gl::Texture *texture); + virtual gl::Error setSamplerState(gl::SamplerType type, int index, gl::Texture *texture, const gl::SamplerState &sampler); + virtual gl::Error setTexture(gl::SamplerType type, int index, gl::Texture *texture); + + gl::Error setUniformBuffers(const gl::Data &data, + const GLint vertexUniformBuffers[], + const GLint fragmentUniformBuffers[]) override; + + virtual gl::Error setRasterizerState(const gl::RasterizerState &rasterState); + gl::Error setBlendState(const gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::ColorF &blendColor, + unsigned int sampleMask) override; + virtual gl::Error setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef, + int stencilBackRef, bool frontFaceCCW); + + virtual void setScissorRectangle(const gl::Rectangle &scissor, bool enabled); + virtual void setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace, + bool ignoreViewport); + + gl::Error applyRenderTarget(const gl::Framebuffer *frameBuffer) override; + gl::Error applyRenderTarget(const gl::FramebufferAttachment *colorBuffer, const gl::FramebufferAttachment *depthStencilBuffer); + virtual gl::Error applyShaders(gl::Program *program, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer, + bool rasterizerDiscard, bool transformFeedbackActive); + virtual gl::Error applyUniforms(const ProgramImpl &program, const std::vector &uniformArray); + virtual bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount, bool usesPointSize); + virtual gl::Error applyVertexBuffer(const gl::State &state, GLenum mode, GLint first, GLsizei count, GLsizei instances); + virtual gl::Error applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo); + + void applyTransformFeedbackBuffers(const gl::State &state) override; + + gl::Error drawArrays(const gl::Data &data, GLenum mode, GLsizei count, GLsizei instances, bool usesPointSize) override; + virtual gl::Error drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, + gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances); + + gl::Error clear(const ClearParameters &clearParams, + const gl::FramebufferAttachment *colorBuffer, + const gl::FramebufferAttachment *depthStencilBuffer); + + virtual void markAllStateDirty(); + + // lost device + bool testDeviceLost() override; + bool testDeviceResettable() override; + + VendorID getVendorId() const override; + std::string getRendererDescription() const override; + GUID getAdapterIdentifier() const override; + + IDirect3DDevice9 *getDevice() { return mDevice; } + + virtual unsigned int getReservedVertexUniformVectors() const; + virtual unsigned int getReservedFragmentUniformVectors() const; + virtual unsigned int getReservedVertexUniformBuffers() const; + virtual unsigned int getReservedFragmentUniformBuffers() const; + virtual bool getShareHandleSupport() const; + virtual bool getPostSubBufferSupport() const; + + virtual int getMajorShaderModel() const; + int getMinorShaderModel() const override; + std::string getShaderModelSuffix() const override; + + DWORD getCapsDeclTypes() const; + + // Pixel operations + virtual gl::Error copyImage2D(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + const gl::Offset &destOffset, TextureStorage *storage, GLint level); + virtual gl::Error copyImageCube(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + const gl::Offset &destOffset, TextureStorage *storage, GLenum target, GLint level); + virtual gl::Error copyImage3D(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + const gl::Offset &destOffset, TextureStorage *storage, GLint level); + virtual gl::Error copyImage2DArray(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + const gl::Offset &destOffset, TextureStorage *storage, GLint level); + + // RenderTarget creation + virtual gl::Error createRenderTarget(int width, int height, GLenum format, GLsizei samples, RenderTargetD3D **outRT); + + // Framebuffer creation + FramebufferImpl *createDefaultFramebuffer(const gl::Framebuffer::Data &data) override; + FramebufferImpl *createFramebuffer(const gl::Framebuffer::Data &data) override; + + // Shader creation + virtual CompilerImpl *createCompiler(const gl::Data &data); + virtual ShaderImpl *createShader(GLenum type); + virtual ProgramImpl *createProgram(); + + // Shader operations + virtual gl::Error loadExecutable(const void *function, size_t length, ShaderType type, + const std::vector &transformFeedbackVaryings, + bool separatedOutputBuffers, ShaderExecutableD3D **outExecutable); + virtual gl::Error compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, ShaderType type, + const std::vector &transformFeedbackVaryings, + bool separatedOutputBuffers, const D3DCompilerWorkarounds &workarounds, + ShaderExecutableD3D **outExectuable); + virtual UniformStorageD3D *createUniformStorage(size_t storageSize); + + // Image operations + virtual ImageD3D *createImage(); + gl::Error generateMipmap(ImageD3D *dest, ImageD3D *source) override; + virtual TextureStorage *createTextureStorage2D(SwapChainD3D *swapChain); + virtual TextureStorage *createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels, bool hintLevelZeroOnly); + virtual TextureStorage *createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly); + virtual TextureStorage *createTextureStorage3D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels); + virtual TextureStorage *createTextureStorage2DArray(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels); + + // Texture creation + virtual TextureImpl *createTexture(GLenum target); + + // Renderbuffer creation + virtual RenderbufferImpl *createRenderbuffer(); + + // Buffer creation + virtual BufferImpl *createBuffer(); + virtual VertexBuffer *createVertexBuffer(); + virtual IndexBuffer *createIndexBuffer(); + + // Vertex Array creation + virtual VertexArrayImpl *createVertexArray(); + + // Query and Fence creation + virtual QueryImpl *createQuery(GLenum type); + virtual FenceNVImpl *createFenceNV(); + virtual FenceSyncImpl *createFenceSync(); + + // Transform Feedback creation + virtual TransformFeedbackImpl* createTransformFeedback(); + + // Buffer-to-texture and Texture-to-buffer copies + virtual bool supportsFastCopyBufferToTexture(GLenum internalFormat) const; + virtual gl::Error fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTargetD3D *destRenderTarget, + GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea); + + // D3D9-renderer specific methods + gl::Error boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest); + + D3DPOOL getTexturePool(DWORD usage) const; + + bool getLUID(LUID *adapterLuid) const override; + virtual VertexConversionType getVertexConversionType(const gl::VertexFormat &vertexFormat) const; + virtual GLenum getVertexComponentType(const gl::VertexFormat &vertexFormat) const; + + gl::Error copyToRenderTarget(IDirect3DSurface9 *dest, IDirect3DSurface9 *source, bool fromManaged); + + RendererClass getRendererClass() const override { return RENDERER_D3D9; } + + D3DDEVTYPE getD3D9DeviceType() const { return mDeviceType; } + + private: + void generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureCaps, gl::Extensions *outExtensions) const override; + Workarounds generateWorkarounds() const override; + + void release(); + + void applyUniformnfv(gl::LinkedUniform *targetUniform, const GLfloat *v); + void applyUniformniv(gl::LinkedUniform *targetUniform, const GLint *v); + void applyUniformnbv(gl::LinkedUniform *targetUniform, const GLint *v); + + gl::Error drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer); + gl::Error drawIndexedPoints(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer); + + gl::Error getCountingIB(size_t count, StaticIndexBufferInterface **outIB); + + gl::Error getNullColorbuffer(const gl::FramebufferAttachment *depthbuffer, const gl::FramebufferAttachment **outColorBuffer); + + D3DPOOL getBufferPool(DWORD usage) const; + + HMODULE mD3d9Module; + + void initializeDevice(); + D3DPRESENT_PARAMETERS getDefaultPresentParameters(); + void releaseDeviceResources(); + + HRESULT getDeviceStatusCode(); + bool isRemovedDeviceResettable() const; + bool resetRemovedDevice(); + + 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. + + HLSLCompiler mCompiler; + + Blit9 *mBlit; + + HWND mDeviceWindow; + + D3DCAPS9 mDeviceCaps; + D3DADAPTER_IDENTIFIER9 mAdapterIdentifier; + + D3DPRIMITIVETYPE mPrimitiveType; + int mPrimitiveCount; + GLsizei mRepeatDraw; + + bool mSceneStarted; + + bool mVertexTextureSupport; + + // current render target states + unsigned int mAppliedRenderTargetSerial; + unsigned int mAppliedDepthStencilSerial; + bool mDepthStencilInitialized; + bool mRenderTargetDescInitialized; + unsigned int mCurStencilSize; + unsigned int mCurDepthSize; + + struct RenderTargetDesc + { + size_t width; + size_t height; + D3DFORMAT format; + }; + RenderTargetDesc mRenderTargetDesc; + + IDirect3DStateBlock9 *mMaskedClearSavedState; + + // previously set render states + bool mForceSetDepthStencilState; + gl::DepthStencilState mCurDepthStencilState; + int mCurStencilRef; + int mCurStencilBackRef; + bool mCurFrontFaceCCW; + + bool mForceSetRasterState; + gl::RasterizerState mCurRasterState; + + bool mForceSetScissor; + gl::Rectangle mCurScissor; + bool mScissorEnabled; + + bool mForceSetViewport; + gl::Rectangle mCurViewport; + float mCurNear; + float mCurFar; + float mCurDepthFront; + + bool mForceSetBlendState; + gl::BlendState mCurBlendState; + gl::ColorF mCurBlendColor; + GLuint mCurSampleMask; + + // Currently applied sampler states + std::vector mForceSetVertexSamplerStates; + std::vector mCurVertexSamplerStates; + + std::vector mForceSetPixelSamplerStates; + std::vector mCurPixelSamplerStates; + + // Currently applied textures + std::vector mCurVertexTextureSerials; + std::vector mCurPixelTextureSerials; + + unsigned int mAppliedIBSerial; + IDirect3DVertexShader9 *mAppliedVertexShader; + IDirect3DPixelShader9 *mAppliedPixelShader; + unsigned int mAppliedProgramSerial; + + dx_VertexConstants mVertexConstants; + 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; + StaticIndexBufferInterface *mCountingIB; + + enum { NUM_NULL_COLORBUFFER_CACHE_ENTRIES = 12 }; + struct NullColorbufferCacheEntry + { + UINT lruCount; + int width; + int height; + gl::FramebufferAttachment *buffer; + } mNullColorbufferCache[NUM_NULL_COLORBUFFER_CACHE_ENTRIES]; + UINT mMaxNullColorbufferLRU; + + DebugAnnotator9 mAnnotator; +}; + +} +#endif // LIBANGLE_RENDERER_D3D_D3D9_RENDERER9_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/ShaderCache.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/ShaderCache.h new file mode 100644 index 0000000000..cf831c62fa --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/ShaderCache.h @@ -0,0 +1,108 @@ +// +// 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 LIBANGLE_RENDERER_D3D_D3D9_SHADERCACHE_H_ +#define LIBANGLE_RENDERER_D3D_D3D9_SHADERCACHE_H_ + +#include "libANGLE/Error.h" + +#include "common/debug.h" + +#include +#include +#include + +namespace rx +{ +template +class ShaderCache : angle::NonCopyable +{ + public: + ShaderCache() : mDevice(NULL) + { + } + + ~ShaderCache() + { + // Call clear while the device is still valid. + ASSERT(mMap.empty()); + } + + void initialize(IDirect3DDevice9* device) + { + mDevice = device; + } + + gl::Error create(const DWORD *function, size_t length, ShaderObject **outShaderObject) + { + std::string key(reinterpret_cast(function), length); + typename Map::iterator it = mMap.find(key); + if (it != mMap.end()) + { + it->second->AddRef(); + *outShaderObject = it->second; + return gl::Error(GL_NO_ERROR); + } + + ShaderObject *shader; + HRESULT result = createShader(function, &shader); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create shader, result: 0x%X.", result); + } + + // Random eviction policy. + if (mMap.size() >= kMaxMapSize) + { + SafeRelease(mMap.begin()->second); + mMap.erase(mMap.begin()); + } + + shader->AddRef(); + mMap[key] = shader; + + *outShaderObject = shader; + return gl::Error(GL_NO_ERROR); + } + + void clear() + { + for (typename Map::iterator it = mMap.begin(); it != mMap.end(); ++it) + { + SafeRelease(it->second); + } + + mMap.clear(); + } + + private: + 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); + } + + typedef std::unordered_map Map; + Map mMap; + + IDirect3DDevice9 *mDevice; +}; + +typedef ShaderCache VertexShaderCache; +typedef ShaderCache PixelShaderCache; + +} + +#endif // LIBANGLE_RENDERER_D3D_D3D9_SHADERCACHE_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.cpp new file mode 100644 index 0000000000..280e80930b --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.cpp @@ -0,0 +1,53 @@ +// +// 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 "libANGLE/renderer/d3d/d3d9/ShaderExecutable9.h" + +#include "common/debug.h" + +namespace rx +{ + +ShaderExecutable9::ShaderExecutable9(const void *function, size_t length, IDirect3DPixelShader9 *executable) + : ShaderExecutableD3D(function, length) +{ + mPixelExecutable = executable; + mVertexExecutable = NULL; +} + +ShaderExecutable9::ShaderExecutable9(const void *function, size_t length, IDirect3DVertexShader9 *executable) + : ShaderExecutableD3D(function, length) +{ + mVertexExecutable = executable; + mPixelExecutable = NULL; +} + +ShaderExecutable9::~ShaderExecutable9() +{ + SafeRelease(mVertexExecutable); + SafeRelease(mPixelExecutable); +} + +ShaderExecutable9 *ShaderExecutable9::makeShaderExecutable9(ShaderExecutableD3D *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/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.h new file mode 100644 index 0000000000..561f7defc8 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.h @@ -0,0 +1,37 @@ +// +// 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 LIBANGLE_RENDERER_D3D_D3D9_SHADEREXECUTABLE9_H_ +#define LIBANGLE_RENDERER_D3D_D3D9_SHADEREXECUTABLE9_H_ + +#include "libANGLE/renderer/d3d/ShaderExecutableD3D.h" + +namespace rx +{ + +class ShaderExecutable9 : public ShaderExecutableD3D +{ + public: + ShaderExecutable9(const void *function, size_t length, IDirect3DPixelShader9 *executable); + ShaderExecutable9(const void *function, size_t length, IDirect3DVertexShader9 *executable); + virtual ~ShaderExecutable9(); + + static ShaderExecutable9 *makeShaderExecutable9(ShaderExecutableD3D *executable); + + IDirect3DPixelShader9 *getPixelShader() const; + IDirect3DVertexShader9 *getVertexShader() const; + + private: + IDirect3DPixelShader9 *mPixelExecutable; + IDirect3DVertexShader9 *mVertexExecutable; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_D3D9_SHADEREXECUTABLE9_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.cpp new file mode 100644 index 0000000000..1620668166 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.cpp @@ -0,0 +1,425 @@ +// +// Copyright (c) 2012-2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// SwapChain9.cpp: Implements a back-end specific class for the D3D9 swap chain. + +#include "libANGLE/renderer/d3d/d3d9/SwapChain9.h" +#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h" +#include "libANGLE/renderer/d3d/d3d9/formatutils9.h" +#include "libANGLE/renderer/d3d/d3d9/Renderer9.h" +#include "libANGLE/features.h" + +namespace rx +{ + +SwapChain9::SwapChain9(Renderer9 *renderer, NativeWindow nativeWindow, HANDLE shareHandle, + GLenum backBufferFormat, GLenum depthBufferFormat) + : mRenderer(renderer), + SwapChainD3D(nativeWindow, shareHandle, backBufferFormat, depthBufferFormat), + mColorRenderTarget(this, false), + mDepthStencilRenderTarget(this, true) +{ + mSwapChain = NULL; + mBackBuffer = NULL; + mDepthStencil = NULL; + mRenderTarget = NULL; + mOffscreenTexture = NULL; + mWidth = -1; + mHeight = -1; + mSwapInterval = -1; +} + +SwapChain9::~SwapChain9() +{ + release(); +} + +void SwapChain9::release() +{ + SafeRelease(mSwapChain); + SafeRelease(mBackBuffer); + SafeRelease(mDepthStencil); + SafeRelease(mRenderTarget); + SafeRelease(mOffscreenTexture); + + if (mNativeWindow.getNativeWindow()) + { + mShareHandle = NULL; + } +} + +static DWORD convertInterval(EGLint interval) +{ +#if ANGLE_VSYNC == ANGLE_DISABLED + return D3DPRESENT_INTERVAL_IMMEDIATE; +#else + switch(interval) + { + case 0: return D3DPRESENT_INTERVAL_IMMEDIATE; + case 1: return D3DPRESENT_INTERVAL_ONE; + case 2: return D3DPRESENT_INTERVAL_TWO; + case 3: return D3DPRESENT_INTERVAL_THREE; + case 4: return D3DPRESENT_INTERVAL_FOUR; + default: UNREACHABLE(); + } + + return D3DPRESENT_INTERVAL_DEFAULT; +#endif +} + +EGLint SwapChain9::resize(int backbufferWidth, int backbufferHeight) +{ + // D3D9 does not support resizing swap chains without recreating them + return reset(backbufferWidth, backbufferHeight, mSwapInterval); +} + +EGLint SwapChain9::reset(int backbufferWidth, int backbufferHeight, EGLint swapInterval) +{ + IDirect3DDevice9 *device = mRenderer->getDevice(); + + if (device == NULL) + { + return EGL_BAD_ACCESS; + } + + // Evict all non-render target textures to system memory and release all resources + // before reallocating them to free up as much video memory as possible. + device->EvictManagedResources(); + + HRESULT result; + + // Release specific resources to free up memory for the new render target, while the + // old render target still exists for the purpose of preserving its contents. + SafeRelease(mSwapChain); + SafeRelease(mBackBuffer); + SafeRelease(mOffscreenTexture); + SafeRelease(mDepthStencil); + + HANDLE *pShareHandle = NULL; + if (!mNativeWindow.getNativeWindow() && mRenderer->getShareHandleSupport()) + { + pShareHandle = &mShareHandle; + } + + const d3d9::TextureFormat &backBufferd3dFormatInfo = d3d9::GetTextureFormatInfo(mBackBufferFormat); + result = device->CreateTexture(backbufferWidth, backbufferHeight, 1, D3DUSAGE_RENDERTARGET, + backBufferd3dFormatInfo.texFormat, 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)); + + SafeRelease(oldRenderTarget); + } + + const d3d9::TextureFormat &depthBufferd3dFormatInfo = d3d9::GetTextureFormatInfo(mDepthBufferFormat); + + // Don't create a swapchain for NULLREF devices + D3DDEVTYPE deviceType = mRenderer->getD3D9DeviceType(); + EGLNativeWindowType window = mNativeWindow.getNativeWindow(); + if (window && deviceType != D3DDEVTYPE_NULLREF) + { + D3DPRESENT_PARAMETERS presentParameters = {0}; + presentParameters.AutoDepthStencilFormat = depthBufferd3dFormatInfo.renderFormat; + presentParameters.BackBufferCount = 1; + presentParameters.BackBufferFormat = backBufferd3dFormatInfo.renderFormat; + presentParameters.EnableAutoDepthStencil = FALSE; + presentParameters.Flags = 0; + presentParameters.hDeviceWindow = window; + 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->getVendorId() == 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(window, NULL, FALSE); + } + + if (mDepthBufferFormat != GL_NONE) + { + result = device->CreateDepthStencilSurface(backbufferWidth, backbufferHeight, + depthBufferd3dFormatInfo.renderFormat, + D3DMULTISAMPLE_NONE, 0, FALSE, &mDepthStencil, NULL); + + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_INVALIDCALL); + + ERR("Could not create depthstencil surface for new swap chain: 0x%08X", result); + release(); + + if (d3d9::isDeviceLostError(result)) + { + return EGL_CONTEXT_LOST; + } + else + { + return EGL_BAD_ALLOC; + } + } + } + + mWidth = backbufferWidth; + mHeight = backbufferHeight; + mSwapInterval = swapInterval; + + return EGL_SUCCESS; +} + +// parameters should be validated/clamped by caller +EGLint SwapChain9::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) +{ + if (!mSwapChain) + { + return EGL_SUCCESS; + } + + IDirect3DDevice9 *device = mRenderer->getDevice(); + + // Disable all pipeline operations + device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE); + device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); + device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); + device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); + device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); + device->SetRenderState(D3DRS_STENCILENABLE, FALSE); + device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0); + device->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA | D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_RED); + device->SetRenderState(D3DRS_SRGBWRITEENABLE, FALSE); + device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE); + device->SetPixelShader(NULL); + device->SetVertexShader(NULL); + + device->SetRenderTarget(0, mBackBuffer); + device->SetDepthStencilSurface(NULL); + + device->SetTexture(0, mOffscreenTexture); + device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); + device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); + device->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); + device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT); + device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT); + device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); + device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); + device->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1); + + for (UINT streamIndex = 0; streamIndex < gl::MAX_VERTEX_ATTRIBS; streamIndex++) + { + device->SetStreamSourceFreq(streamIndex, 1); + } + + D3DVIEWPORT9 viewport = {0, 0, mWidth, mHeight, 0.0f, 1.0f}; + device->SetViewport(&viewport); + + float x1 = x - 0.5f; + float y1 = (mHeight - y - height) - 0.5f; + float x2 = (x + width) - 0.5f; + float y2 = (mHeight - y) - 0.5f; + + float u1 = x / float(mWidth); + float v1 = y / float(mHeight); + float u2 = (x + width) / float(mWidth); + float v2 = (y + height) / float(mHeight); + + float quad[4][6] = {{x1, y1, 0.0f, 1.0f, u1, v2}, + {x2, y1, 0.0f, 1.0f, u2, v2}, + {x2, y2, 0.0f, 1.0f, u2, v1}, + {x1, y2, 0.0f, 1.0f, u1, v1}}; // x, y, z, rhw, u, v + + mRenderer->startScene(); + device->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, quad, 6 * sizeof(float)); + mRenderer->endScene(); + + device->SetTexture(0, NULL); + + RECT rect = + { + x, mHeight - y - height, + x + width, mHeight - y + }; + + HRESULT result = mSwapChain->Present(&rect, &rect, NULL, NULL, 0); + + mRenderer->markAllStateDirty(); + + if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DRIVERINTERNALERROR) + { + return EGL_BAD_ALLOC; + } + + // On Windows 8 systems, IDirect3DSwapChain9::Present sometimes returns 0x88760873 when the windows is + // in the process of entering/exiting fullscreen. This code doesn't seem to have any documentation. The + // device appears to be ok after emitting this error so simply return a failure to swap. + if (result == 0x88760873) + { + return EGL_BAD_MATCH; + } + + // http://crbug.com/313210 + // If our swap failed, trigger a device lost event. Resetting will work around an AMD-specific + // device removed bug with lost contexts when reinstalling drivers. + if (FAILED(result)) + { + mRenderer->notifyDeviceLost(); + return EGL_CONTEXT_LOST; + } + + return EGL_SUCCESS; +} + +// Increments refcount on surface. +// caller must Release() the returned surface +// TODO: remove the AddRef to match SwapChain11 +IDirect3DSurface9 *SwapChain9::getRenderTarget() +{ + if (mRenderTarget) + { + mRenderTarget->AddRef(); + } + + return mRenderTarget; +} + +// Increments refcount on surface. +// caller must Release() the returned surface +// TODO: remove the AddRef to match SwapChain11 +IDirect3DSurface9 *SwapChain9::getDepthStencil() +{ + if (mDepthStencil) + { + mDepthStencil->AddRef(); + } + + return mDepthStencil; +} + +// Increments refcount on texture. +// caller must Release() the returned texture +// TODO: remove the AddRef to match SwapChain11 +IDirect3DTexture9 *SwapChain9::getOffscreenTexture() +{ + if (mOffscreenTexture) + { + mOffscreenTexture->AddRef(); + } + + return mOffscreenTexture; +} + +SwapChain9 *SwapChain9::makeSwapChain9(SwapChainD3D *swapChain) +{ + ASSERT(HAS_DYNAMIC_TYPE(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; + } + + SafeRelease(mSwapChain); + mSwapChain = newSwapChain; + + SafeRelease(mBackBuffer); + result = mSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &mBackBuffer); + ASSERT(SUCCEEDED(result)); +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.h new file mode 100644 index 0000000000..81ac08ca7b --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.h @@ -0,0 +1,63 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// SwapChain9.h: Defines a back-end specific class for the D3D9 swap chain. + +#ifndef LIBANGLE_RENDERER_D3D_D3D9_SWAPCHAIN9_H_ +#define LIBANGLE_RENDERER_D3D_D3D9_SWAPCHAIN9_H_ + +#include "common/angleutils.h" +#include "libANGLE/renderer/d3d/SwapChainD3D.h" +#include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h" + +namespace rx +{ +class Renderer9; + +class SwapChain9 : public SwapChainD3D +{ + public: + SwapChain9(Renderer9 *renderer, NativeWindow nativeWindow, 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(); + + RenderTargetD3D *getColorRenderTarget() override { return &mColorRenderTarget; } + RenderTargetD3D *getDepthStencilRenderTarget() override { return &mDepthStencilRenderTarget; } + + virtual IDirect3DSurface9 *getRenderTarget(); + virtual IDirect3DSurface9 *getDepthStencil(); + virtual IDirect3DTexture9 *getOffscreenTexture(); + + EGLint getWidth() const { return mWidth; } + EGLint getHeight() const { return mHeight; } + + static SwapChain9 *makeSwapChain9(SwapChainD3D *swapChain); + + private: + void release(); + + Renderer9 *mRenderer; + EGLint mHeight; + EGLint mWidth; + EGLint mSwapInterval; + + IDirect3DSwapChain9 *mSwapChain; + IDirect3DSurface9 *mBackBuffer; + IDirect3DSurface9 *mRenderTarget; + IDirect3DSurface9 *mDepthStencil; + IDirect3DTexture9* mOffscreenTexture; + + SurfaceRenderTarget9 mColorRenderTarget; + SurfaceRenderTarget9 mDepthStencilRenderTarget; +}; + +} +#endif // LIBANGLE_RENDERER_D3D_D3D9_SWAPCHAIN9_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.cpp new file mode 100644 index 0000000000..139cb3eb08 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.cpp @@ -0,0 +1,472 @@ +// +// Copyright (c) 2012-2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// 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 "libANGLE/renderer/d3d/d3d9/TextureStorage9.h" +#include "libANGLE/renderer/d3d/d3d9/Renderer9.h" +#include "libANGLE/renderer/d3d/d3d9/SwapChain9.h" +#include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h" +#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h" +#include "libANGLE/renderer/d3d/d3d9/formatutils9.h" +#include "libANGLE/renderer/d3d/TextureD3D.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/Texture.h" + +namespace rx +{ +TextureStorage9::TextureStorage9(Renderer9 *renderer, DWORD usage) + : mTopLevel(0), + mMipLevels(0), + mTextureWidth(0), + mTextureHeight(0), + mInternalFormat(GL_NONE), + mTextureFormat(D3DFMT_UNKNOWN), + 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(GLenum internalformat, bool renderTarget) +{ + DWORD d3dusage = 0; + + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat); + const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(internalformat); + if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0) + { + d3dusage |= D3DUSAGE_DEPTHSTENCIL; + } + else if (renderTarget && (d3dFormatInfo.renderFormat != D3DFMT_UNKNOWN)) + { + d3dusage |= D3DUSAGE_RENDERTARGET; + } + + return d3dusage; +} + + +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::getTopLevel() const +{ + return mTopLevel; +} + +int TextureStorage9::getLevelCount() const +{ + return mMipLevels - mTopLevel; +} + +gl::Error TextureStorage9::setData(const gl::ImageIndex &index, ImageD3D *image, const gl::Box *destBox, GLenum type, + const gl::PixelUnpackState &unpack, const uint8_t *pixelData) +{ + UNREACHABLE(); + return gl::Error(GL_INVALID_OPERATION); +} + +TextureStorage9_2D::TextureStorage9_2D(Renderer9 *renderer, SwapChain9 *swapchain) + : TextureStorage9(renderer, D3DUSAGE_RENDERTARGET) +{ + IDirect3DTexture9 *surfaceTexture = swapchain->getOffscreenTexture(); + mTexture = surfaceTexture; + mMipLevels = surfaceTexture->GetLevelCount(); + + mInternalFormat = swapchain->GetBackBufferInternalFormat(); + + D3DSURFACE_DESC surfaceDesc; + surfaceTexture->GetLevelDesc(0, &surfaceDesc); + mTextureWidth = surfaceDesc.Width; + mTextureHeight = surfaceDesc.Height; + mTextureFormat = surfaceDesc.Format; + + mRenderTarget = NULL; + + initializeSerials(1, 1); +} + +TextureStorage9_2D::TextureStorage9_2D(Renderer9 *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels) + : TextureStorage9(renderer, GetTextureUsage(internalformat, renderTarget)) +{ + mTexture = NULL; + mRenderTarget = NULL; + + mInternalFormat = internalformat; + + const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(internalformat); + mTextureFormat = d3dFormatInfo.texFormat; + + d3d9::MakeValidSize(false, d3dFormatInfo.texFormat, &width, &height, &mTopLevel); + mTextureWidth = width; + mTextureHeight = height; + mMipLevels = mTopLevel + levels; + + initializeSerials(getLevelCount(), 1); +} + +TextureStorage9_2D::~TextureStorage9_2D() +{ + SafeRelease(mTexture); + SafeDelete(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 +gl::Error TextureStorage9_2D::getSurfaceLevel(int level, bool dirty, IDirect3DSurface9 **outSurface) +{ + IDirect3DBaseTexture9 *baseTexture = NULL; + gl::Error error = getBaseTexture(&baseTexture); + if (error.isError()) + { + return error; + } + + IDirect3DTexture9 *texture = static_cast(baseTexture); + + HRESULT result = texture->GetSurfaceLevel(level + mTopLevel, outSurface); + + ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to get the surface from a texture, result: 0x%X.", result); + } + + // With managed textures the driver needs to be informed of updates to the lower mipmap levels + if (level + mTopLevel != 0 && isManaged() && dirty) + { + texture->AddDirtyRect(NULL); + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage9_2D::getRenderTarget(const gl::ImageIndex &/*index*/, RenderTargetD3D **outRT) +{ + if (!mRenderTarget && isRenderTarget()) + { + IDirect3DSurface9 *surface = NULL; + gl::Error error = getSurfaceLevel(0, false, &surface); + if (error.isError()) + { + return error; + } + + mRenderTarget = new TextureRenderTarget9(surface, mInternalFormat, mTextureWidth, mTextureHeight, 1, 0); + } + + ASSERT(outRT); + *outRT = mRenderTarget; + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage9_2D::generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex) +{ + IDirect3DSurface9 *upper = NULL; + gl::Error error = getSurfaceLevel(sourceIndex.mipIndex, false, &upper); + if (error.isError()) + { + return error; + } + + IDirect3DSurface9 *lower = NULL; + error = getSurfaceLevel(destIndex.mipIndex, true, &lower); + if (error.isError()) + { + SafeRelease(upper); + return error; + } + + ASSERT(upper && lower); + error = mRenderer->boxFilter(upper, lower); + + SafeRelease(upper); + SafeRelease(lower); + + return error; +} + +gl::Error TextureStorage9_2D::getBaseTexture(IDirect3DBaseTexture9 **outTexture) +{ + // 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 (mTexture == NULL && mTextureWidth > 0 && mTextureHeight > 0) + { + ASSERT(mMipLevels > 0); + + IDirect3DDevice9 *device = mRenderer->getDevice(); + HRESULT result = device->CreateTexture(mTextureWidth, mTextureHeight, mMipLevels, getUsage(), mTextureFormat, + getPool(), &mTexture, NULL); + + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create 2D storage texture, result: 0x%X.", result); + } + } + + *outTexture = mTexture; + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage9_2D::copyToStorage(TextureStorage *destStorage) +{ + ASSERT(destStorage); + + TextureStorage9_2D *dest9 = TextureStorage9_2D::makeTextureStorage9_2D(destStorage); + + int levels = getLevelCount(); + for (int i = 0; i < levels; ++i) + { + IDirect3DSurface9 *srcSurf = NULL; + gl::Error error = getSurfaceLevel(i, false, &srcSurf); + if (error.isError()) + { + return error; + } + + IDirect3DSurface9 *dstSurf = NULL; + error = dest9->getSurfaceLevel(i, true, &dstSurf); + if (error.isError()) + { + SafeRelease(srcSurf); + return error; + } + + error = mRenderer->copyToRenderTarget(dstSurf, srcSurf, isManaged()); + + SafeRelease(srcSurf); + SafeRelease(dstSurf); + + if (error.isError()) + { + return error; + } + } + + return gl::Error(GL_NO_ERROR); +} + +TextureStorage9_Cube::TextureStorage9_Cube(Renderer9 *renderer, GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly) + : TextureStorage9(renderer, GetTextureUsage(internalformat, renderTarget)) +{ + mTexture = NULL; + for (int i = 0; i < CUBE_FACE_COUNT; ++i) + { + mRenderTarget[i] = NULL; + } + + mInternalFormat = internalformat; + + const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(internalformat); + mTextureFormat = d3dFormatInfo.texFormat; + + int height = size; + d3d9::MakeValidSize(false, d3dFormatInfo.texFormat, &size, &height, &mTopLevel); + mTextureWidth = size; + mTextureHeight = size; + mMipLevels = mTopLevel + levels; + + initializeSerials(getLevelCount() * CUBE_FACE_COUNT, CUBE_FACE_COUNT); +} + +TextureStorage9_Cube::~TextureStorage9_Cube() +{ + SafeRelease(mTexture); + + for (int i = 0; i < CUBE_FACE_COUNT; ++i) + { + SafeDelete(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 +gl::Error TextureStorage9_Cube::getCubeMapSurface(GLenum faceTarget, int level, bool dirty, IDirect3DSurface9 **outSurface) +{ + IDirect3DBaseTexture9 *baseTexture = NULL; + gl::Error error = getBaseTexture(&baseTexture); + if (error.isError()) + { + return error; + } + + IDirect3DCubeTexture9 *texture = static_cast(baseTexture); + + D3DCUBEMAP_FACES face = gl_d3d9::ConvertCubeFace(faceTarget); + HRESULT result = texture->GetCubeMapSurface(face, level + mTopLevel, outSurface); + + ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to get the surface from a texture, result: 0x%X.", result); + } + + // With managed textures the driver needs to be informed of updates to the lower mipmap levels + if (level != 0 && isManaged() && dirty) + { + texture->AddDirtyRect(face, NULL); + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage9_Cube::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) +{ + ASSERT(outRT); + ASSERT(index.mipIndex == 0); + ASSERT(index.layerIndex >= 0 && index.layerIndex < CUBE_FACE_COUNT); + + if (mRenderTarget[index.layerIndex] == NULL && isRenderTarget()) + { + IDirect3DSurface9 *surface = NULL; + gl::Error error = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + index.layerIndex, 0, false, &surface); + if (error.isError()) + { + return error; + } + + mRenderTarget[index.layerIndex] = new TextureRenderTarget9(surface, mInternalFormat, mTextureWidth, mTextureHeight, 1, 0); + } + + *outRT = mRenderTarget[index.layerIndex]; + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage9_Cube::generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex) +{ + IDirect3DSurface9 *upper = NULL; + gl::Error error = getCubeMapSurface(sourceIndex.type, sourceIndex.mipIndex, false, &upper); + if (error.isError()) + { + return error; + } + + IDirect3DSurface9 *lower = NULL; + error = getCubeMapSurface(destIndex.type, destIndex.mipIndex, true, &lower); + if (error.isError()) + { + SafeRelease(upper); + return error; + } + + ASSERT(upper && lower); + error = mRenderer->boxFilter(upper, lower); + + SafeRelease(upper); + SafeRelease(lower); + + return error; +} + +gl::Error TextureStorage9_Cube::getBaseTexture(IDirect3DBaseTexture9 **outTexture) +{ + // 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 (mTexture == NULL && mTextureWidth > 0 && mTextureHeight > 0) + { + ASSERT(mMipLevels > 0); + ASSERT(mTextureWidth == mTextureHeight); + + IDirect3DDevice9 *device = mRenderer->getDevice(); + HRESULT result = device->CreateCubeTexture(mTextureWidth, mMipLevels, getUsage(), mTextureFormat, getPool(), + &mTexture, NULL); + + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create cube storage texture, result: 0x%X.", result); + } + } + + *outTexture = mTexture; + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage9_Cube::copyToStorage(TextureStorage *destStorage) +{ + ASSERT(destStorage); + + TextureStorage9_Cube *dest9 = TextureStorage9_Cube::makeTextureStorage9_Cube(destStorage); + + int levels = getLevelCount(); + for (int f = 0; f < CUBE_FACE_COUNT; f++) + { + for (int i = 0; i < levels; i++) + { + IDirect3DSurface9 *srcSurf = NULL; + gl::Error error = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, false, &srcSurf); + if (error.isError()) + { + return error; + } + + IDirect3DSurface9 *dstSurf = NULL; + error = dest9->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, true, &dstSurf); + if (error.isError()) + { + SafeRelease(srcSurf); + return error; + } + + error = mRenderer->copyToRenderTarget(dstSurf, srcSurf, isManaged()); + + SafeRelease(srcSurf); + SafeRelease(dstSurf); + + if (error.isError()) + { + return error; + } + } + } + + return gl::Error(GL_NO_ERROR); +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.h new file mode 100644 index 0000000000..5cc06f07b1 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.h @@ -0,0 +1,108 @@ +// +// 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. +// + +// 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 LIBANGLE_RENDERER_D3D_D3D9_TEXTURESTORAGE9_H_ +#define LIBANGLE_RENDERER_D3D_D3D9_TEXTURESTORAGE9_H_ + +#include "libANGLE/renderer/d3d/TextureStorage.h" +#include "common/debug.h" + +namespace rx +{ +class Renderer9; +class SwapChain9; +class RenderTargetD3D; +class RenderTarget9; + +class TextureStorage9 : public TextureStorage +{ + public: + virtual ~TextureStorage9(); + + static TextureStorage9 *makeTextureStorage9(TextureStorage *storage); + + static DWORD GetTextureUsage(GLenum internalformat, bool renderTarget); + + D3DPOOL getPool() const; + DWORD getUsage() const; + + virtual gl::Error getBaseTexture(IDirect3DBaseTexture9 **outTexture) = 0; + virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) = 0; + + virtual int getTopLevel() const; + virtual bool isRenderTarget() const; + virtual bool isManaged() const; + virtual int getLevelCount() const; + + virtual gl::Error setData(const gl::ImageIndex &index, ImageD3D *image, const gl::Box *destBox, GLenum type, + const gl::PixelUnpackState &unpack, const uint8_t *pixelData); + + protected: + int mTopLevel; + size_t mMipLevels; + size_t mTextureWidth; + size_t mTextureHeight; + GLenum mInternalFormat; + D3DFORMAT mTextureFormat; + + Renderer9 *mRenderer; + + TextureStorage9(Renderer9 *renderer, DWORD usage); + + private: + const DWORD mD3DUsage; + const D3DPOOL mD3DPool; +}; + +class TextureStorage9_2D : public TextureStorage9 +{ + public: + TextureStorage9_2D(Renderer9 *renderer, SwapChain9 *swapchain); + TextureStorage9_2D(Renderer9 *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels); + virtual ~TextureStorage9_2D(); + + static TextureStorage9_2D *makeTextureStorage9_2D(TextureStorage *storage); + + gl::Error getSurfaceLevel(int level, bool dirty, IDirect3DSurface9 **outSurface); + virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT); + virtual gl::Error getBaseTexture(IDirect3DBaseTexture9 **outTexture); + virtual gl::Error generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex); + virtual gl::Error copyToStorage(TextureStorage *destStorage); + + private: + IDirect3DTexture9 *mTexture; + RenderTarget9 *mRenderTarget; +}; + +class TextureStorage9_Cube : public TextureStorage9 +{ + public: + TextureStorage9_Cube(Renderer9 *renderer, GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly); + virtual ~TextureStorage9_Cube(); + + static TextureStorage9_Cube *makeTextureStorage9_Cube(TextureStorage *storage); + + gl::Error getCubeMapSurface(GLenum faceTarget, int level, bool dirty, IDirect3DSurface9 **outSurface); + virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT); + virtual gl::Error getBaseTexture(IDirect3DBaseTexture9 **outTexture); + virtual gl::Error generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex); + virtual gl::Error copyToStorage(TextureStorage *destStorage); + + private: + static const size_t CUBE_FACE_COUNT = 6; + + IDirect3DCubeTexture9 *mTexture; + RenderTarget9 *mRenderTarget[CUBE_FACE_COUNT]; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_D3D9_TEXTURESTORAGE9_H_ + diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexArray9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexArray9.h new file mode 100644 index 0000000000..fb626bc0cf --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexArray9.h @@ -0,0 +1,41 @@ +// +// Copyright 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// VertexArray9.h: Defines the rx::VertexArray9 class which implements rx::VertexArrayImpl. + +#ifndef LIBANGLE_RENDERER_D3D_D3D9_VERTEXARRAY9_H_ +#define LIBANGLE_RENDERER_D3D_D3D9_VERTEXARRAY9_H_ + +#include "libANGLE/renderer/VertexArrayImpl.h" +#include "libANGLE/renderer/d3d/d3d9/Renderer9.h" + +namespace rx +{ +class Renderer9; + +class VertexArray9 : public VertexArrayImpl +{ + public: + VertexArray9(Renderer9 *renderer) + : VertexArrayImpl(), + mRenderer(renderer) + { + } + + virtual ~VertexArray9() { } + + virtual void setElementArrayBuffer(const gl::Buffer *buffer) { } + virtual void setAttribute(size_t idx, const gl::VertexAttribute &attr) { } + virtual void setAttributeDivisor(size_t idx, GLuint divisor) { } + virtual void enableAttribute(size_t idx, bool enabledState) { } + + private: + Renderer9 *mRenderer; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_D3D9_VERTEXARRAY9_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.cpp new file mode 100644 index 0000000000..cb5003997f --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.cpp @@ -0,0 +1,239 @@ +// +// 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 "libANGLE/renderer/d3d/d3d9/VertexBuffer9.h" +#include "libANGLE/renderer/d3d/d3d9/Renderer9.h" +#include "libANGLE/renderer/d3d/d3d9/formatutils9.h" +#include "libANGLE/renderer/d3d/d3d9/vertexconversion.h" +#include "libANGLE/renderer/d3d/BufferD3D.h" +#include "libANGLE/VertexAttribute.h" +#include "libANGLE/Buffer.h" + +namespace rx +{ + +VertexBuffer9::VertexBuffer9(Renderer9 *renderer) : mRenderer(renderer) +{ + mVertexBuffer = NULL; + mBufferSize = 0; + mDynamicUsage = false; +} + +VertexBuffer9::~VertexBuffer9() +{ + SafeRelease(mVertexBuffer); +} + +gl::Error VertexBuffer9::initialize(unsigned int size, bool dynamicUsage) +{ + SafeRelease(mVertexBuffer); + + updateSerial(); + + if (size > 0) + { + DWORD flags = D3DUSAGE_WRITEONLY; + if (dynamicUsage) + { + flags |= D3DUSAGE_DYNAMIC; + } + + HRESULT result = mRenderer->createVertexBuffer(size, flags, &mVertexBuffer); + + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal vertex buffer of size, %lu.", size); + } + } + + mBufferSize = size; + mDynamicUsage = dynamicUsage; + return gl::Error(GL_NO_ERROR); +} + +VertexBuffer9 *VertexBuffer9::makeVertexBuffer9(VertexBuffer *vertexBuffer) +{ + ASSERT(HAS_DYNAMIC_TYPE(VertexBuffer9*, vertexBuffer)); + return static_cast(vertexBuffer); +} + +gl::Error VertexBuffer9::storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData ¤tValue, + GLint start, GLsizei count, GLsizei instances, unsigned int offset) +{ + if (!mVertexBuffer) + { + return gl::Error(GL_OUT_OF_MEMORY, "Internal vertex buffer is not initialized."); + } + + gl::Buffer *buffer = attrib.buffer.get(); + + int inputStride = gl::ComputeVertexAttributeStride(attrib); + int elementSize = gl::ComputeVertexAttributeTypeSize(attrib); + + DWORD lockFlags = mDynamicUsage ? D3DLOCK_NOOVERWRITE : 0; + + uint8_t *mapPtr = NULL; + + unsigned int mapSize; + gl::Error error = spaceRequired(attrib, count, instances, &mapSize); + if (error.isError()) + { + return error; + } + + HRESULT result = mVertexBuffer->Lock(offset, mapSize, reinterpret_cast(&mapPtr), lockFlags); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock internal vertex buffer, HRESULT: 0x%08x.", result); + } + + const uint8_t *input = NULL; + if (attrib.enabled) + { + if (buffer) + { + BufferD3D *storage = GetImplAs(buffer); + ASSERT(storage); + error = storage->getData(&input); + if (error.isError()) + { + return error; + } + input += static_cast(attrib.offset); + } + else + { + input = static_cast(attrib.pointer); + } + } + else + { + input = reinterpret_cast(currentValue.FloatValues); + } + + if (instances == 0 || attrib.divisor == 0) + { + input += inputStride * start; + } + + gl::VertexFormat vertexFormat(attrib, currentValue.Type); + const d3d9::VertexFormat &d3dVertexInfo = d3d9::GetVertexFormatInfo(mRenderer->getCapsDeclTypes(), vertexFormat); + bool needsConversion = (d3dVertexInfo.conversionType & VERTEX_CONVERT_CPU) > 0; + + if (!needsConversion && inputStride == elementSize) + { + size_t copySize = static_cast(count) * static_cast(inputStride); + memcpy(mapPtr, input, copySize); + } + else + { + d3dVertexInfo.copyFunction(input, inputStride, count, mapPtr); + } + + mVertexBuffer->Unlock(); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error VertexBuffer9::getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances, + unsigned int *outSpaceRequired) const +{ + return spaceRequired(attrib, count, instances, outSpaceRequired); +} + +unsigned int VertexBuffer9::getBufferSize() const +{ + return mBufferSize; +} + +gl::Error VertexBuffer9::setBufferSize(unsigned int size) +{ + if (size > mBufferSize) + { + return initialize(size, mDynamicUsage); + } + else + { + return gl::Error(GL_NO_ERROR); + } +} + +gl::Error VertexBuffer9::discard() +{ + if (!mVertexBuffer) + { + return gl::Error(GL_OUT_OF_MEMORY, "Internal vertex buffer is not initialized."); + } + + void *dummy; + HRESULT result; + + result = mVertexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock internal buffer for discarding, HRESULT: 0x%08x", result); + } + + result = mVertexBuffer->Unlock(); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to unlock internal buffer for discarding, HRESULT: 0x%08x", result); + } + + return gl::Error(GL_NO_ERROR); +} + +IDirect3DVertexBuffer9 * VertexBuffer9::getBuffer() const +{ + return mVertexBuffer; +} + +gl::Error VertexBuffer9::spaceRequired(const gl::VertexAttribute &attrib, std::size_t count, GLsizei instances, + unsigned int *outSpaceRequired) const +{ + gl::VertexFormat vertexFormat(attrib, GL_FLOAT); + const d3d9::VertexFormat &d3d9VertexInfo = d3d9::GetVertexFormatInfo(mRenderer->getCapsDeclTypes(), vertexFormat); + + if (attrib.enabled) + { + unsigned int elementCount = 0; + if (instances == 0 || attrib.divisor == 0) + { + elementCount = count; + } + else + { + // Round up to divisor, if possible + elementCount = UnsignedCeilDivide(static_cast(instances), attrib.divisor); + } + + if (d3d9VertexInfo.outputElementSize <= std::numeric_limits::max() / elementCount) + { + if (outSpaceRequired) + { + *outSpaceRequired = d3d9VertexInfo.outputElementSize * elementCount; + } + return gl::Error(GL_NO_ERROR); + } + else + { + return gl::Error(GL_OUT_OF_MEMORY, "New vertex buffer size would result in an overflow."); + } + } + else + { + const unsigned int elementSize = 4; + if (outSpaceRequired) + { + *outSpaceRequired = elementSize * 4; + } + return gl::Error(GL_NO_ERROR); + } +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.h new file mode 100644 index 0000000000..f5b110b22b --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.h @@ -0,0 +1,52 @@ +// +// 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 LIBANGLE_RENDERER_D3D_D3D9_VERTEXBUFFER9_H_ +#define LIBANGLE_RENDERER_D3D_D3D9_VERTEXBUFFER9_H_ + +#include "libANGLE/renderer/d3d/VertexBuffer.h" + +namespace rx +{ +class Renderer9; + +class VertexBuffer9 : public VertexBuffer +{ + public: + explicit VertexBuffer9(Renderer9 *renderer); + virtual ~VertexBuffer9(); + + virtual gl::Error initialize(unsigned int size, bool dynamicUsage); + + static VertexBuffer9 *makeVertexBuffer9(VertexBuffer *vertexBuffer); + + virtual gl::Error storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData ¤tValue, + GLint start, GLsizei count, GLsizei instances, unsigned int offset); + + virtual gl::Error getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances, unsigned int *outSpaceRequired) const; + + virtual unsigned int getBufferSize() const; + virtual gl::Error setBufferSize(unsigned int size); + virtual gl::Error discard(); + + IDirect3DVertexBuffer9 *getBuffer() const; + + private: + Renderer9 *mRenderer; + + IDirect3DVertexBuffer9 *mVertexBuffer; + unsigned int mBufferSize; + bool mDynamicUsage; + + gl::Error spaceRequired(const gl::VertexAttribute &attrib, std::size_t count, GLsizei instances, + unsigned int *outSpaceRequired) const; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_D3D9_VERTEXBUFFER9_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.cpp new file mode 100644 index 0000000000..f9eded9b50 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.cpp @@ -0,0 +1,237 @@ +// +// 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 "libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.h" +#include "libANGLE/renderer/d3d/d3d9/VertexBuffer9.h" +#include "libANGLE/renderer/d3d/d3d9/formatutils9.h" +#include "libANGLE/Program.h" +#include "libANGLE/VertexAttribute.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++) + { + SafeRelease(mVertexDeclCache[i].vertexDeclaration); + } +} + +gl::Error VertexDeclarationCache::applyDeclaration(IDirect3DDevice9 *device, TranslatedAttribute attributes[], gl::Program *program, GLsizei instances, GLsizei *repeatDraw) +{ + *repeatDraw = 1; + + int indexedAttribute = gl::MAX_VERTEX_ATTRIBS; + int instancedAttribute = gl::MAX_VERTEX_ATTRIBS; + + if (instances == 0) + { + for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; ++i) + { + if (attributes[i].divisor != 0) + { + // If a divisor is set, it still applies even if an instanced draw was not used, so treat + // as a single-instance draw. + instances = 1; + break; + } + } + } + + 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 + } + } + + // The validation layer checks that there is at least one active attribute with a zero divisor as per + // the GL_ANGLE_instanced_arrays spec. + ASSERT(indexedAttribute != gl::MAX_VERTEX_ATTRIBS); + } + + D3DCAPS9 caps; + device->GetDeviceCaps(&caps); + + 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; + } + + gl::VertexFormat vertexFormat(*attributes[i].attribute, GL_FLOAT); + const d3d9::VertexFormat &d3d9VertexInfo = d3d9::GetVertexFormatInfo(caps.DeclTypes, vertexFormat); + + element->Stream = stream; + element->Offset = 0; + element->Type = d3d9VertexInfo.nativeFormat; + element->Method = D3DDECLMETHOD_DEFAULT; + element->Usage = D3DDECLUSAGE_TEXCOORD; + element->UsageIndex = program->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::Error(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) + { + SafeRelease(lastCache->vertexDeclaration); + // mLastSetVDecl is set to the replacement, so we don't have to worry + // about it. + } + + memcpy(lastCache->cachedElements, elements, (element - elements) * sizeof(D3DVERTEXELEMENT9)); + HRESULT result = device->CreateVertexDeclaration(elements, &lastCache->vertexDeclaration); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal vertex declaration, result: 0x%X.", result); + } + + device->SetVertexDeclaration(lastCache->vertexDeclaration); + mLastSetVDecl = lastCache->vertexDeclaration; + lastCache->lruCount = ++mMaxLru; + + return gl::Error(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/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.h new file mode 100644 index 0000000000..fbd673097f --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.h @@ -0,0 +1,60 @@ +// +// 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 LIBANGLE_RENDERER_D3D_D3D9_VERTEXDECLARATIONCACHE_H_ +#define LIBANGLE_RENDERER_D3D_D3D9_VERTEXDECLARATIONCACHE_H_ + +#include "libANGLE/Error.h" +#include "libANGLE/renderer/d3d/VertexDataManager.h" + +namespace gl +{ +class VertexDataManager; +class Program; +} + +namespace rx +{ + +class VertexDeclarationCache +{ + public: + VertexDeclarationCache(); + ~VertexDeclarationCache(); + + gl::Error applyDeclaration(IDirect3DDevice9 *device, TranslatedAttribute attributes[], gl::Program *program, 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 // LIBANGLE_RENDERER_D3D_D3D9_VERTEXDECLARATIONCACHE_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/formatutils9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/formatutils9.cpp new file mode 100644 index 0000000000..9bad5503d9 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/formatutils9.cpp @@ -0,0 +1,602 @@ +// +// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// formatutils9.cpp: Queries for GL image formats and their translations to D3D9 +// formats. + +#include "libANGLE/renderer/d3d/copyimage.h" +#include "libANGLE/renderer/d3d/d3d9/formatutils9.h" +#include "libANGLE/renderer/d3d/d3d9/Renderer9.h" +#include "libANGLE/renderer/d3d/d3d9/vertexconversion.h" +#include "libANGLE/renderer/d3d/generatemip.h" +#include "libANGLE/renderer/d3d/loadimage.h" + +namespace rx +{ + +namespace d3d9 +{ + +const D3DFORMAT D3DFMT_INTZ = ((D3DFORMAT)(MAKEFOURCC('I', 'N', 'T', 'Z'))); +const D3DFORMAT D3DFMT_NULL = ((D3DFORMAT)(MAKEFOURCC('N', 'U', 'L', 'L'))); + +struct D3D9FastCopyFormat +{ + GLenum destFormat; + GLenum destType; + ColorCopyFunction copyFunction; + + D3D9FastCopyFormat(GLenum destFormat, GLenum destType, ColorCopyFunction copyFunction) + : destFormat(destFormat), destType(destType), copyFunction(copyFunction) + { } + + bool operator<(const D3D9FastCopyFormat& other) const + { + return memcmp(this, &other, sizeof(D3D9FastCopyFormat)) < 0; + } +}; + +typedef std::multimap D3D9FastCopyMap; + +static D3D9FastCopyMap BuildFastCopyMap() +{ + D3D9FastCopyMap map; + + map.insert(std::make_pair(D3DFMT_A8R8G8B8, D3D9FastCopyFormat(GL_RGBA, GL_UNSIGNED_BYTE, CopyBGRA8ToRGBA8))); + + return map; +} + +// A map to determine the pixel size and mip generation function of a given D3D format +typedef std::map D3D9FormatInfoMap; + +D3DFormat::D3DFormat() + : pixelBytes(0), + blockWidth(0), + blockHeight(0), + redBits(0), + greenBits(0), + blueBits(0), + alphaBits(0), + luminanceBits(0), + depthBits(0), + stencilBits(0), + internalFormat(GL_NONE), + mipGenerationFunction(NULL), + colorReadFunction(NULL), + fastCopyFunctions() +{ +} + +ColorCopyFunction D3DFormat::getFastCopyFunction(GLenum format, GLenum type) const +{ + FastCopyFunctionMap::const_iterator iter = fastCopyFunctions.find(std::make_pair(format, type)); + return (iter != fastCopyFunctions.end()) ? iter->second : NULL; +} + +static inline void InsertD3DFormatInfo(D3D9FormatInfoMap *map, D3DFORMAT format, GLuint bits, GLuint blockWidth, + GLuint blockHeight, GLuint redBits, GLuint greenBits, GLuint blueBits, + GLuint alphaBits, GLuint lumBits, GLuint depthBits, GLuint stencilBits, + GLenum internalFormat, MipGenerationFunction mipFunc, + ColorReadFunction colorReadFunc) +{ + D3DFormat info; + info.pixelBytes = bits / 8; + info.blockWidth = blockWidth; + info.blockHeight = blockHeight; + info.redBits = redBits; + info.greenBits = greenBits; + info.blueBits = blueBits; + info.alphaBits = alphaBits; + info.luminanceBits = lumBits; + info.depthBits = depthBits; + info.stencilBits = stencilBits; + info.internalFormat = internalFormat; + info.mipGenerationFunction = mipFunc; + info.colorReadFunction = colorReadFunc; + + static const D3D9FastCopyMap fastCopyMap = BuildFastCopyMap(); + std::pair fastCopyIter = fastCopyMap.equal_range(format); + for (D3D9FastCopyMap::const_iterator i = fastCopyIter.first; i != fastCopyIter.second; i++) + { + info.fastCopyFunctions.insert(std::make_pair(std::make_pair(i->second.destFormat, i->second.destType), i->second.copyFunction)); + } + + map->insert(std::make_pair(format, info)); +} + +static D3D9FormatInfoMap BuildD3D9FormatInfoMap() +{ + D3D9FormatInfoMap map; + + // | D3DFORMAT | S |W |H | R | G | B | A | L | D | S | Internal format | Mip generation function | Color read function | + InsertD3DFormatInfo(&map, D3DFMT_NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, GL_NONE, NULL, NULL ); + InsertD3DFormatInfo(&map, D3DFMT_UNKNOWN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, GL_NONE, NULL, NULL ); + + InsertD3DFormatInfo(&map, D3DFMT_L8, 8, 1, 1, 0, 0, 0, 0, 8, 0, 0, GL_LUMINANCE8_EXT, GenerateMip, ReadColor ); + InsertD3DFormatInfo(&map, D3DFMT_A8, 8, 1, 1, 0, 0, 0, 8, 0, 0, 0, GL_ALPHA8_EXT, GenerateMip, ReadColor ); + InsertD3DFormatInfo(&map, D3DFMT_A8L8, 16, 1, 1, 0, 0, 0, 8, 8, 0, 0, GL_LUMINANCE8_ALPHA8_EXT, GenerateMip, ReadColor ); + InsertD3DFormatInfo(&map, D3DFMT_A4R4G4B4, 16, 1, 1, 4, 4, 4, 4, 0, 0, 0, GL_BGRA4_ANGLEX, GenerateMip, ReadColor ); + InsertD3DFormatInfo(&map, D3DFMT_A1R5G5B5, 16, 1, 1, 5, 5, 5, 1, 0, 0, 0, GL_BGR5_A1_ANGLEX, GenerateMip, ReadColor ); + InsertD3DFormatInfo(&map, D3DFMT_R5G6B5, 16, 1, 1, 5, 6, 5, 0, 0, 0, 0, GL_RGB565, GenerateMip, ReadColor ); + InsertD3DFormatInfo(&map, D3DFMT_X8R8G8B8, 32, 1, 1, 8, 8, 8, 0, 0, 0, 0, GL_BGRA8_EXT, GenerateMip, ReadColor ); + InsertD3DFormatInfo(&map, D3DFMT_A8R8G8B8, 32, 1, 1, 8, 8, 8, 8, 0, 0, 0, GL_BGRA8_EXT, GenerateMip, ReadColor ); + InsertD3DFormatInfo(&map, D3DFMT_R16F, 16, 1, 1, 16, 0, 0, 0, 0, 0, 0, GL_R16F_EXT, GenerateMip, ReadColor ); + InsertD3DFormatInfo(&map, D3DFMT_G16R16F, 32, 1, 1, 16, 16, 0, 0, 0, 0, 0, GL_RG16F_EXT, GenerateMip, ReadColor ); + InsertD3DFormatInfo(&map, D3DFMT_A16B16G16R16F, 64, 1, 1, 16, 16, 16, 16, 0, 0, 0, GL_RGBA16F_EXT, GenerateMip, ReadColor); + InsertD3DFormatInfo(&map, D3DFMT_R32F, 32, 1, 1, 32, 0, 0, 0, 0, 0, 0, GL_R32F_EXT, GenerateMip, ReadColor ); + InsertD3DFormatInfo(&map, D3DFMT_G32R32F, 64, 1, 1, 32, 32, 0, 0, 0, 0, 0, GL_RG32F_EXT, GenerateMip, ReadColor ); + InsertD3DFormatInfo(&map, D3DFMT_A32B32G32R32F, 128, 1, 1, 32, 32, 32, 32, 0, 0, 0, GL_RGBA32F_EXT, GenerateMip, ReadColor); + + InsertD3DFormatInfo(&map, D3DFMT_D16, 16, 1, 1, 0, 0, 0, 0, 0, 16, 0, GL_DEPTH_COMPONENT16, NULL, NULL ); + InsertD3DFormatInfo(&map, D3DFMT_D24S8, 32, 1, 1, 0, 0, 0, 0, 0, 24, 8, GL_DEPTH24_STENCIL8_OES, NULL, NULL ); + InsertD3DFormatInfo(&map, D3DFMT_D24X8, 32, 1, 1, 0, 0, 0, 0, 0, 24, 0, GL_DEPTH_COMPONENT16, NULL, NULL ); + InsertD3DFormatInfo(&map, D3DFMT_D32, 32, 1, 1, 0, 0, 0, 0, 0, 32, 0, GL_DEPTH_COMPONENT32_OES, NULL, NULL ); + + InsertD3DFormatInfo(&map, D3DFMT_INTZ, 32, 1, 1, 0, 0, 0, 0, 0, 24, 8, GL_DEPTH24_STENCIL8_OES, NULL, NULL ); + + InsertD3DFormatInfo(&map, D3DFMT_DXT1, 64, 4, 4, 0, 0, 0, 0, 0, 0, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, NULL, NULL ); + InsertD3DFormatInfo(&map, D3DFMT_DXT3, 128, 4, 4, 0, 0, 0, 0, 0, 0, 0, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, NULL, NULL ); + InsertD3DFormatInfo(&map, D3DFMT_DXT5, 128, 4, 4, 0, 0, 0, 0, 0, 0, 0, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, NULL, NULL ); + + return map; +} + +const D3DFormat &GetD3DFormatInfo(D3DFORMAT format) +{ + static const D3D9FormatInfoMap infoMap = BuildD3D9FormatInfoMap(); + D3D9FormatInfoMap::const_iterator iter = infoMap.find(format); + if (iter != infoMap.end()) + { + return iter->second; + } + else + { + static const D3DFormat defaultInfo; + return defaultInfo; + } +} + + + +typedef std::pair InternalFormatInitialzerPair; +typedef std::map InternalFormatInitialzerMap; + +static InternalFormatInitialzerMap BuildInternalFormatInitialzerMap() +{ + InternalFormatInitialzerMap map; + + map.insert(InternalFormatInitialzerPair(GL_RGB16F, Initialize4ComponentData)); + map.insert(InternalFormatInitialzerPair(GL_RGB32F, Initialize4ComponentData)); + + return map; +} + +// Each GL internal format corresponds to one D3D format and data loading function. +// Due to not all formats being available all the time, some of the function/format types are wrapped +// in templates that perform format support queries on a Renderer9 object which is supplied +// when requesting the function or format. + +typedef bool(*FallbackPredicateFunction)(); + +template +static void FallbackLoad(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + if (pred()) + { + prefered(width, height, depth, input, inputRowPitch, inputDepthPitch, output, outputRowPitch, outputDepthPitch); + } + else + { + fallback(width, height, depth, input, inputRowPitch, inputDepthPitch, output, outputRowPitch, outputDepthPitch); + } +} + +static void UnreachableLoad(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + UNREACHABLE(); +} + +typedef std::pair D3D9FormatPair; +typedef std::map D3D9FormatMap; + +TextureFormat::TextureFormat() + : texFormat(D3DFMT_UNKNOWN), + renderFormat(D3DFMT_UNKNOWN), + dataInitializerFunction(NULL), + loadFunction(UnreachableLoad) +{ +} + +static inline void InsertD3D9FormatInfo(D3D9FormatMap *map, GLenum internalFormat, D3DFORMAT texFormat, + D3DFORMAT renderFormat, LoadImageFunction loadFunction) +{ + TextureFormat info; + info.texFormat = texFormat; + info.renderFormat = renderFormat; + + static const InternalFormatInitialzerMap dataInitializationMap = BuildInternalFormatInitialzerMap(); + InternalFormatInitialzerMap::const_iterator dataInitIter = dataInitializationMap.find(internalFormat); + info.dataInitializerFunction = (dataInitIter != dataInitializationMap.end()) ? dataInitIter->second : NULL; + + info.loadFunction = loadFunction; + + map->insert(std::make_pair(internalFormat, info)); +} + +static D3D9FormatMap BuildD3D9FormatMap() +{ + D3D9FormatMap map; + + // | Internal format | Texture format | Render format | Load function | + InsertD3D9FormatInfo(&map, GL_NONE, D3DFMT_NULL, D3DFMT_NULL, UnreachableLoad ); + + // We choose to downsample the GL_DEPTH_COMPONENT32_OES format to a 24-bit format because D3DFMT_D32 is not widely + // supported. We're allowed to do this because: + // - The ES spec 2.0.25 sec 3.7.1 states that we're allowed to store texture formats with internal format + // resolutions of our own choosing. + // - OES_depth_texture states that downsampling of the depth formats is allowed. + // - ANGLE_depth_texture does not state minimum required resolutions of the depth texture formats it + // introduces. + // In ES3 however, there are minimum resolutions for the texture formats and this would not be allowed. + + InsertD3D9FormatInfo(&map, GL_DEPTH_COMPONENT16, D3DFMT_INTZ, D3DFMT_D24S8, UnreachableLoad ); + InsertD3D9FormatInfo(&map, GL_DEPTH_COMPONENT32_OES, D3DFMT_INTZ, D3DFMT_D24X8, UnreachableLoad ); + InsertD3D9FormatInfo(&map, GL_DEPTH24_STENCIL8_OES, D3DFMT_INTZ, D3DFMT_D24S8, UnreachableLoad ); + InsertD3D9FormatInfo(&map, GL_STENCIL_INDEX8, D3DFMT_UNKNOWN, D3DFMT_D24S8, UnreachableLoad ); // TODO: What's the texture format? + + InsertD3D9FormatInfo(&map, GL_RGBA32F_EXT, D3DFMT_A32B32G32R32F, D3DFMT_A32B32G32R32F, LoadToNative ); + InsertD3D9FormatInfo(&map, GL_RGB32F_EXT, D3DFMT_A32B32G32R32F, D3DFMT_A32B32G32R32F, LoadToNative3To4); + InsertD3D9FormatInfo(&map, GL_RG32F_EXT, D3DFMT_G32R32F, D3DFMT_G32R32F, LoadToNative ); + InsertD3D9FormatInfo(&map, GL_R32F_EXT, D3DFMT_R32F, D3DFMT_R32F, LoadToNative ); + InsertD3D9FormatInfo(&map, GL_ALPHA32F_EXT, D3DFMT_A32B32G32R32F, D3DFMT_UNKNOWN, LoadA32FToRGBA32F ); + InsertD3D9FormatInfo(&map, GL_LUMINANCE32F_EXT, D3DFMT_A32B32G32R32F, D3DFMT_UNKNOWN, LoadL32FToRGBA32F ); + InsertD3D9FormatInfo(&map, GL_LUMINANCE_ALPHA32F_EXT, D3DFMT_A32B32G32R32F, D3DFMT_UNKNOWN, LoadLA32FToRGBA32F ); + + InsertD3D9FormatInfo(&map, GL_RGBA16F_EXT, D3DFMT_A16B16G16R16F, D3DFMT_A16B16G16R16F, LoadToNative ); + InsertD3D9FormatInfo(&map, GL_RGB16F_EXT, D3DFMT_A16B16G16R16F, D3DFMT_A16B16G16R16F, LoadToNative3To4 ); + InsertD3D9FormatInfo(&map, GL_RG16F_EXT, D3DFMT_G16R16F, D3DFMT_G16R16F, LoadToNative ); + InsertD3D9FormatInfo(&map, GL_R16F_EXT, D3DFMT_R16F, D3DFMT_R16F, LoadToNative ); + InsertD3D9FormatInfo(&map, GL_ALPHA16F_EXT, D3DFMT_A16B16G16R16F, D3DFMT_UNKNOWN, LoadA16FToRGBA16F ); + InsertD3D9FormatInfo(&map, GL_LUMINANCE16F_EXT, D3DFMT_A16B16G16R16F, D3DFMT_UNKNOWN, LoadL16FToRGBA16F ); + InsertD3D9FormatInfo(&map, GL_LUMINANCE_ALPHA16F_EXT, D3DFMT_A16B16G16R16F, D3DFMT_UNKNOWN, LoadLA16FToRGBA16F ); + + InsertD3D9FormatInfo(&map, GL_ALPHA8_EXT, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, FallbackLoad); + + InsertD3D9FormatInfo(&map, GL_RGB8_OES, D3DFMT_X8R8G8B8, D3DFMT_X8R8G8B8, LoadRGB8ToBGRX8 ); + InsertD3D9FormatInfo(&map, GL_RGB565, D3DFMT_X8R8G8B8, D3DFMT_X8R8G8B8, LoadR5G6B5ToBGRA8 ); + InsertD3D9FormatInfo(&map, GL_RGBA8_OES, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, FallbackLoad); + InsertD3D9FormatInfo(&map, GL_RGBA4, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, LoadRGBA4ToBGRA8 ); + InsertD3D9FormatInfo(&map, GL_RGB5_A1, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, LoadRGB5A1ToBGRA8 ); + InsertD3D9FormatInfo(&map, GL_R8_EXT, D3DFMT_X8R8G8B8, D3DFMT_X8R8G8B8, LoadR8ToBGRX8 ); + InsertD3D9FormatInfo(&map, GL_RG8_EXT, D3DFMT_X8R8G8B8, D3DFMT_X8R8G8B8, LoadRG8ToBGRX8 ); + + InsertD3D9FormatInfo(&map, GL_BGRA8_EXT, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, LoadToNative ); + InsertD3D9FormatInfo(&map, GL_BGRA4_ANGLEX, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, LoadBGRA4ToBGRA8 ); + InsertD3D9FormatInfo(&map, GL_BGR5_A1_ANGLEX, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, LoadBGR5A1ToBGRA8 ); + + InsertD3D9FormatInfo(&map, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, D3DFMT_DXT1, D3DFMT_UNKNOWN, LoadCompressedToNative<4, 4, 8> ); + InsertD3D9FormatInfo(&map, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, D3DFMT_DXT1, D3DFMT_UNKNOWN, LoadCompressedToNative<4, 4, 8> ); + InsertD3D9FormatInfo(&map, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, D3DFMT_DXT3, D3DFMT_UNKNOWN, LoadCompressedToNative<4, 4, 16> ); + InsertD3D9FormatInfo(&map, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, D3DFMT_DXT5, D3DFMT_UNKNOWN, LoadCompressedToNative<4, 4, 16> ); + + // These formats require checking if the renderer supports D3DFMT_L8 or D3DFMT_A8L8 and + // then changing the format and loading function appropriately. + InsertD3D9FormatInfo(&map, GL_LUMINANCE8_EXT, D3DFMT_L8, D3DFMT_UNKNOWN, LoadToNative ); + InsertD3D9FormatInfo(&map, GL_LUMINANCE8_ALPHA8_EXT, D3DFMT_A8L8, D3DFMT_UNKNOWN, LoadToNative ); + + return map; +} + +const TextureFormat &GetTextureFormatInfo(GLenum internalFormat) +{ + static const D3D9FormatMap formatMap = BuildD3D9FormatMap(); + D3D9FormatMap::const_iterator iter = formatMap.find(internalFormat); + if (iter != formatMap.end()) + { + return iter->second; + } + else + { + static const TextureFormat defaultInfo; + return defaultInfo; + } +} + +static GLenum GetDeclTypeComponentType(D3DDECLTYPE declType) +{ + switch (declType) + { + case D3DDECLTYPE_FLOAT1: return GL_FLOAT; + case D3DDECLTYPE_FLOAT2: return GL_FLOAT; + case D3DDECLTYPE_FLOAT3: return GL_FLOAT; + case D3DDECLTYPE_FLOAT4: return GL_FLOAT; + case D3DDECLTYPE_UBYTE4: return GL_UNSIGNED_INT; + case D3DDECLTYPE_SHORT2: return GL_INT; + case D3DDECLTYPE_SHORT4: return GL_INT; + case D3DDECLTYPE_UBYTE4N: return GL_UNSIGNED_NORMALIZED; + case D3DDECLTYPE_SHORT4N: return GL_SIGNED_NORMALIZED; + case D3DDECLTYPE_USHORT4N: return GL_UNSIGNED_NORMALIZED; + case D3DDECLTYPE_SHORT2N: return GL_SIGNED_NORMALIZED; + case D3DDECLTYPE_USHORT2N: return GL_UNSIGNED_NORMALIZED; + default: UNREACHABLE(); return GL_NONE; + } +} + +// Attribute format conversion +enum { NUM_GL_VERTEX_ATTRIB_TYPES = 6 }; + +struct TranslationDescription +{ + DWORD capsFlag; + VertexFormat preferredConversion; + VertexFormat fallbackConversion; +}; + +// 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 }; +}; + +VertexFormat::VertexFormat() + : conversionType(VERTEX_CONVERT_NONE), + outputElementSize(0), + copyFunction(NULL), + nativeFormat(D3DDECLTYPE_UNUSED), + componentType(GL_NONE) +{ +} + +// Initialize a TranslationInfo +VertexFormat CreateVertexFormatInfo(bool identity, size_t elementSize, VertexCopyFunction copyFunc, D3DDECLTYPE nativeFormat) +{ + VertexFormat formatInfo; + formatInfo.conversionType = identity ? VERTEX_CONVERT_NONE : VERTEX_CONVERT_CPU; + formatInfo.outputElementSize = elementSize; + formatInfo.copyFunction = copyFunc; + formatInfo.nativeFormat = nativeFormat; + formatInfo.componentType = GetDeclTypeComponentType(nativeFormat); + return formatInfo; +} + +#define TRANSLATION(type, norm, size, preferred) \ + CreateVertexFormatInfo \ + ( \ + 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) }, \ + } + +static inline unsigned int ComputeTypeIndex(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 VertexFormat &GetVertexFormatInfo(DWORD supportedDeclTypes, const gl::VertexFormat &vertexFormat) +{ + static bool initialized = false; + static DWORD intializedDeclTypes = 0; + static VertexFormat formatConverters[NUM_GL_VERTEX_ATTRIB_TYPES][2][4]; + if (intializedDeclTypes != supportedDeclTypes) + { + const TranslationDescription translations[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) + }; + 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 (translations[i][j][k].capsFlag == 0 || (supportedDeclTypes & translations[i][j][k].capsFlag) != 0) + { + formatConverters[i][j][k] = translations[i][j][k].preferredConversion; + } + else + { + formatConverters[i][j][k] = translations[i][j][k].fallbackConversion; + } + } + } + } + initialized = true; + intializedDeclTypes = supportedDeclTypes; + } + + // Pure integer attributes only supported in ES3.0 + ASSERT(!vertexFormat.mPureInteger); + return formatConverters[ComputeTypeIndex(vertexFormat.mType)][vertexFormat.mNormalized][vertexFormat.mComponents - 1]; +} + +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/formatutils9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/formatutils9.h new file mode 100644 index 0000000000..15e26599c8 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/formatutils9.h @@ -0,0 +1,86 @@ +// +// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// formatutils9.h: Queries for GL image formats and their translations to D3D9 +// formats. + +#ifndef LIBANGLE_RENDERER_D3D_D3D9_FORMATUTILS9_H_ +#define LIBANGLE_RENDERER_D3D_D3D9_FORMATUTILS9_H_ + +#include "libANGLE/renderer/d3d/formatutilsD3D.h" +#include "libANGLE/angletypes.h" + +#include "common/platform.h" + +#include + +namespace rx +{ + +class Renderer9; + +namespace d3d9 +{ + +typedef std::map, ColorCopyFunction> FastCopyFunctionMap; + +struct D3DFormat +{ + D3DFormat(); + + GLuint pixelBytes; + GLuint blockWidth; + GLuint blockHeight; + + GLuint redBits; + GLuint greenBits; + GLuint blueBits; + GLuint alphaBits; + GLuint luminanceBits; + + GLuint depthBits; + GLuint stencilBits; + + GLenum internalFormat; + + MipGenerationFunction mipGenerationFunction; + ColorReadFunction colorReadFunction; + + FastCopyFunctionMap fastCopyFunctions; + ColorCopyFunction getFastCopyFunction(GLenum format, GLenum type) const; +}; +const D3DFormat &GetD3DFormatInfo(D3DFORMAT format); + +struct VertexFormat +{ + VertexFormat(); + + VertexConversionType conversionType; + size_t outputElementSize; + VertexCopyFunction copyFunction; + D3DDECLTYPE nativeFormat; + GLenum componentType; +}; +const VertexFormat &GetVertexFormatInfo(DWORD supportedDeclTypes, const gl::VertexFormat &vertexFormat); + +struct TextureFormat +{ + TextureFormat(); + + D3DFORMAT texFormat; + D3DFORMAT renderFormat; + + InitializeTextureDataFunction dataInitializerFunction; + + LoadImageFunction loadFunction; +}; +const TextureFormat &GetTextureFormatInfo(GLenum internalFormat); + +} + +} + +#endif // LIBANGLE_RENDERER_D3D_D3D9_FORMATUTILS9_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.cpp new file mode 100644 index 0000000000..c9711ac052 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.cpp @@ -0,0 +1,597 @@ +// +// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// renderer9_utils.cpp: Conversion functions and other utility routines +// specific to the D3D9 renderer. + +#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h" +#include "libANGLE/renderer/d3d/d3d9/formatutils9.h" +#include "libANGLE/renderer/d3d/FramebufferD3D.h" +#include "libANGLE/renderer/Workarounds.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/Framebuffer.h" +#include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h" + +#include "common/mathutil.h" +#include "common/debug.h" + +#include "third_party/systeminfo/SystemInfo.h" + +namespace rx +{ + +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::ColorF 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; + case GL_MIN_EXT: d3dBlendOp = D3DBLENDOP_MIN; break; + case GL_MAX_EXT: d3dBlendOp = D3DBLENDOP_MAX; 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; + } +} + +D3DMULTISAMPLE_TYPE GetMultisampleType(GLuint samples) +{ + return (samples > 1) ? static_cast(samples) : D3DMULTISAMPLE_NONE; +} + +} + +namespace d3d9_gl +{ + +GLsizei GetSamplesCount(D3DMULTISAMPLE_TYPE type) +{ + return (type != D3DMULTISAMPLE_NONMASKABLE) ? type : 0; +} + +bool IsFormatChannelEquivalent(D3DFORMAT d3dformat, GLenum format) +{ + GLenum internalFormat = d3d9::GetD3DFormatInfo(d3dformat).internalFormat; + GLenum convertedFormat = gl::GetInternalFormatInfo(internalFormat).format; + return convertedFormat == format; +} + +static gl::TextureCaps GenerateTextureFormatCaps(GLenum internalFormat, IDirect3D9 *d3d9, D3DDEVTYPE deviceType, + UINT adapter, D3DFORMAT adapterFormat) +{ + gl::TextureCaps textureCaps; + + const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(internalFormat); + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat); + + if (d3dFormatInfo.texFormat != D3DFMT_UNKNOWN) + { + if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0) + { + textureCaps.texturable = SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, 0, D3DRTYPE_TEXTURE, d3dFormatInfo.texFormat)); + } + else + { + textureCaps.texturable = SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, 0, D3DRTYPE_TEXTURE, d3dFormatInfo.texFormat)) && + SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, 0, D3DRTYPE_CUBETEXTURE, d3dFormatInfo.texFormat)); + } + + textureCaps.filterable = SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, D3DUSAGE_QUERY_FILTER, D3DRTYPE_TEXTURE, d3dFormatInfo.texFormat)); + } + + if (d3dFormatInfo.renderFormat != D3DFMT_UNKNOWN) + { + textureCaps.renderable = SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, d3dFormatInfo.renderFormat)); + + if ((formatInfo.depthBits > 0 || formatInfo.stencilBits > 0) && !textureCaps.renderable) + { + textureCaps.renderable = SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_TEXTURE, d3dFormatInfo.renderFormat)); + } + + textureCaps.sampleCounts.insert(1); + for (size_t i = D3DMULTISAMPLE_2_SAMPLES; i <= D3DMULTISAMPLE_16_SAMPLES; i++) + { + D3DMULTISAMPLE_TYPE multisampleType = D3DMULTISAMPLE_TYPE(i); + + HRESULT result = d3d9->CheckDeviceMultiSampleType(adapter, deviceType, d3dFormatInfo.renderFormat, TRUE, multisampleType, NULL); + if (SUCCEEDED(result)) + { + textureCaps.sampleCounts.insert(i); + } + } + } + + return textureCaps; +} + +void GenerateCaps(IDirect3D9 *d3d9, IDirect3DDevice9 *device, D3DDEVTYPE deviceType, UINT adapter, gl::Caps *caps, + gl::TextureCapsMap *textureCapsMap, gl::Extensions *extensions) +{ + D3DCAPS9 deviceCaps; + if (FAILED(d3d9->GetDeviceCaps(adapter, deviceType, &deviceCaps))) + { + // Can't continue with out device caps + return; + } + + D3DDISPLAYMODE currentDisplayMode; + d3d9->GetAdapterDisplayMode(adapter, ¤tDisplayMode); + + GLuint maxSamples = 0; + const gl::FormatSet &allFormats = gl::GetAllSizedInternalFormats(); + for (gl::FormatSet::const_iterator internalFormat = allFormats.begin(); internalFormat != allFormats.end(); ++internalFormat) + { + gl::TextureCaps textureCaps = GenerateTextureFormatCaps(*internalFormat, d3d9, deviceType, adapter, + currentDisplayMode.Format); + textureCapsMap->insert(*internalFormat, textureCaps); + + maxSamples = std::max(maxSamples, textureCaps.getMaxSamples()); + + if (gl::GetInternalFormatInfo(*internalFormat).compressed) + { + caps->compressedTextureFormats.push_back(*internalFormat); + } + } + + // GL core feature limits + caps->maxElementIndex = static_cast(std::numeric_limits::max()); + + // 3D textures are unimplemented in D3D9 + caps->max3DTextureSize = 1; + + // Only one limit in GL, use the minimum dimension + caps->max2DTextureSize = std::min(deviceCaps.MaxTextureWidth, deviceCaps.MaxTextureHeight); + + // D3D treats cube maps as a special case of 2D textures + caps->maxCubeMapTextureSize = caps->max2DTextureSize; + + // Array textures are not available in D3D9 + caps->maxArrayTextureLayers = 1; + + // ES3-only feature + caps->maxLODBias = 0.0f; + + // No specific limits on render target size, maximum 2D texture size is equivalent + caps->maxRenderbufferSize = caps->max2DTextureSize; + + // Draw buffers are not supported in D3D9 + caps->maxDrawBuffers = 1; + caps->maxColorAttachments = 1; + + // No specific limits on viewport size, maximum 2D texture size is equivalent + caps->maxViewportWidth = caps->max2DTextureSize; + caps->maxViewportHeight = caps->maxViewportWidth; + + // Point size is clamped to 1.0f when the shader model is less than 3 + caps->minAliasedPointSize = 1.0f; + caps->maxAliasedPointSize = ((D3DSHADER_VERSION_MAJOR(deviceCaps.PixelShaderVersion) >= 3) ? deviceCaps.MaxPointSize : 1.0f); + + // Wide lines not supported + caps->minAliasedLineWidth = 1.0f; + caps->maxAliasedLineWidth = 1.0f; + + // Primitive count limits (unused in ES2) + caps->maxElementsIndices = 0; + caps->maxElementsVertices = 0; + + // Program and shader binary formats (no supported shader binary formats) + caps->programBinaryFormats.push_back(GL_PROGRAM_BINARY_ANGLE); + + caps->vertexHighpFloat.setIEEEFloat(); + caps->vertexMediumpFloat.setIEEEFloat(); + caps->vertexLowpFloat.setIEEEFloat(); + caps->fragmentHighpFloat.setIEEEFloat(); + caps->fragmentMediumpFloat.setIEEEFloat(); + caps->fragmentLowpFloat.setIEEEFloat(); + + // Some (most) hardware only supports single-precision floating-point numbers, + // which can accurately represent integers up to +/-16777216 + caps->vertexHighpInt.setSimulatedInt(24); + caps->vertexMediumpInt.setSimulatedInt(24); + caps->vertexLowpInt.setSimulatedInt(24); + caps->fragmentHighpInt.setSimulatedInt(24); + caps->fragmentMediumpInt.setSimulatedInt(24); + caps->fragmentLowpInt.setSimulatedInt(24); + + // WaitSync is ES3-only, set to zero + caps->maxServerWaitTimeout = 0; + + // Vertex shader limits + caps->maxVertexAttributes = 16; + + const size_t reservedVertexUniformVectors = 2; // dx_ViewAdjust and dx_DepthRange. + const size_t MAX_VERTEX_CONSTANT_VECTORS_D3D9 = 256; + caps->maxVertexUniformVectors = MAX_VERTEX_CONSTANT_VECTORS_D3D9 - reservedVertexUniformVectors; + caps->maxVertexUniformComponents = caps->maxVertexUniformVectors * 4; + + caps->maxVertexUniformBlocks = 0; + + // SM3 only supports 11 output variables, with a special 12th register for PSIZE. + const size_t MAX_VERTEX_OUTPUT_VECTORS_SM3 = 9; + const size_t MAX_VERTEX_OUTPUT_VECTORS_SM2 = 7; + caps->maxVertexOutputComponents = ((deviceCaps.VertexShaderVersion >= D3DVS_VERSION(3, 0)) ? MAX_VERTEX_OUTPUT_VECTORS_SM3 + : MAX_VERTEX_OUTPUT_VECTORS_SM2) * 4; + + // Only Direct3D 10 ready devices support all the necessary vertex texture formats. + // We test this using D3D9 by checking support for the R16F format. + if (deviceCaps.VertexShaderVersion >= D3DVS_VERSION(3, 0) && + SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, currentDisplayMode.Format, + D3DUSAGE_QUERY_VERTEXTEXTURE, D3DRTYPE_TEXTURE, D3DFMT_R16F))) + { + const size_t MAX_TEXTURE_IMAGE_UNITS_VTF_SM3 = 4; + caps->maxVertexTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS_VTF_SM3; + } + else + { + caps->maxVertexTextureImageUnits = 0; + } + + // Fragment shader limits + const size_t reservedPixelUniformVectors = 3; // dx_ViewCoords, dx_DepthFront and dx_DepthRange. + + const size_t MAX_PIXEL_CONSTANT_VECTORS_SM3 = 224; + const size_t MAX_PIXEL_CONSTANT_VECTORS_SM2 = 32; + caps->maxFragmentUniformVectors = ((deviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0)) ? MAX_PIXEL_CONSTANT_VECTORS_SM3 + : MAX_PIXEL_CONSTANT_VECTORS_SM2) - reservedPixelUniformVectors; + caps->maxFragmentUniformComponents = caps->maxFragmentUniformVectors * 4; + caps->maxFragmentUniformBlocks = 0; + caps->maxFragmentInputComponents = caps->maxVertexOutputComponents; + caps->maxTextureImageUnits = 16; + caps->minProgramTexelOffset = 0; + caps->maxProgramTexelOffset = 0; + + // Aggregate shader limits (unused in ES2) + caps->maxUniformBufferBindings = 0; + caps->maxUniformBlockSize = 0; + caps->uniformBufferOffsetAlignment = 0; + caps->maxCombinedUniformBlocks = 0; + caps->maxCombinedVertexUniformComponents = 0; + caps->maxCombinedFragmentUniformComponents = 0; + caps->maxVaryingComponents = 0; + + // Aggregate shader limits + caps->maxVaryingVectors = caps->maxVertexOutputComponents / 4; + caps->maxCombinedTextureImageUnits = caps->maxVertexTextureImageUnits + caps->maxTextureImageUnits; + + // Transform feedback limits + caps->maxTransformFeedbackInterleavedComponents = 0; + caps->maxTransformFeedbackSeparateAttributes = 0; + caps->maxTransformFeedbackSeparateComponents = 0; + + // GL extension support + extensions->setTextureExtensionSupport(*textureCapsMap); + extensions->elementIndexUint = deviceCaps.MaxVertexIndex >= (1 << 16); + extensions->packedDepthStencil = true; + extensions->getProgramBinary = true; + extensions->rgb8rgba8 = true; + extensions->readFormatBGRA = true; + extensions->pixelBufferObject = false; + extensions->mapBuffer = false; + extensions->mapBufferRange = false; + + // textureRG is emulated and not performant. + extensions->textureRG = false; + + D3DADAPTER_IDENTIFIER9 adapterId = { 0 }; + if (SUCCEEDED(d3d9->GetAdapterIdentifier(adapter, 0, &adapterId))) + { + // ATI cards on XP have problems with non-power-of-two textures. + extensions->textureNPOT = !(deviceCaps.TextureCaps & D3DPTEXTURECAPS_POW2) && + !(deviceCaps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2) && + !(deviceCaps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL) && + !(!isWindowsVistaOrGreater() && adapterId.VendorId == VENDOR_ID_AMD); + + // Disable depth texture support on AMD cards (See ANGLE issue 839) + if (adapterId.VendorId == VENDOR_ID_AMD) + { + extensions->depthTextures = false; + } + } + else + { + extensions->textureNPOT = false; + } + + extensions->drawBuffers = false; + extensions->textureStorage = true; + + // Must support a minimum of 2:1 anisotropy for max anisotropy to be considered supported, per the spec + extensions->textureFilterAnisotropic = (deviceCaps.RasterCaps & D3DPRASTERCAPS_ANISOTROPY) != 0 && deviceCaps.MaxAnisotropy >= 2; + extensions->maxTextureAnisotropy = static_cast(deviceCaps.MaxAnisotropy); + + // Check occlusion query support by trying to create one + IDirect3DQuery9 *occlusionQuery = NULL; + extensions->occlusionQueryBoolean = SUCCEEDED(device->CreateQuery(D3DQUERYTYPE_OCCLUSION, &occlusionQuery)) && occlusionQuery; + SafeRelease(occlusionQuery); + + // Check event query support by trying to create one + IDirect3DQuery9 *eventQuery = NULL; + extensions->fence = SUCCEEDED(device->CreateQuery(D3DQUERYTYPE_EVENT, &eventQuery)) && eventQuery; + SafeRelease(eventQuery); + + extensions->timerQuery = false; // Unimplemented + extensions->robustness = true; + extensions->blendMinMax = true; + extensions->framebufferBlit = true; + extensions->framebufferMultisample = true; + extensions->maxSamples = maxSamples; + extensions->instancedArrays = deviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0); + extensions->packReverseRowOrder = true; + extensions->standardDerivatives = (deviceCaps.PS20Caps.Caps & D3DPS20CAPS_GRADIENTINSTRUCTIONS) != 0; + extensions->shaderTextureLOD = true; + extensions->fragDepth = true; + extensions->textureUsage = true; + extensions->translatedShaderSource = true; + extensions->colorBufferFloat = false; +} + +} + +namespace d3d9 +{ + +GLuint ComputeBlockSize(D3DFORMAT format, GLuint width, GLuint height) +{ + const D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(format); + GLuint numBlocksWide = (width + d3dFormatInfo.blockWidth - 1) / d3dFormatInfo.blockWidth; + GLuint numBlocksHight = (height + d3dFormatInfo.blockHeight - 1) / d3dFormatInfo.blockHeight; + return (d3dFormatInfo.pixelBytes * numBlocksWide * numBlocksHight); +} + +void MakeValidSize(bool isImage, D3DFORMAT format, GLsizei *requestWidth, GLsizei *requestHeight, int *levelOffset) +{ + const D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(format); + + int upsampleCount = 0; + // Don't expand the size of full textures that are at least (blockWidth x blockHeight) already. + if (isImage || *requestWidth < static_cast(d3dFormatInfo.blockWidth) || + *requestHeight < static_cast(d3dFormatInfo.blockHeight)) + { + while (*requestWidth % d3dFormatInfo.blockWidth != 0 || *requestHeight % d3dFormatInfo.blockHeight != 0) + { + *requestWidth <<= 1; + *requestHeight <<= 1; + upsampleCount++; + } + } + *levelOffset = upsampleCount; +} + +gl::Error GetAttachmentRenderTarget(const gl::FramebufferAttachment *attachment, RenderTarget9 **outRT) +{ + RenderTargetD3D *renderTarget = NULL; + gl::Error error = rx::GetAttachmentRenderTarget(attachment, &renderTarget); + if (error.isError()) + { + return error; + } + *outRT = RenderTarget9::makeRenderTarget9(renderTarget); + return gl::Error(GL_NO_ERROR); +} + +Workarounds GenerateWorkarounds() +{ + Workarounds workarounds; + workarounds.mrtPerfWorkaround = true; + workarounds.setDataFasterThanImageUpload = false; + workarounds.useInstancedPointSpriteEmulation = false; + return workarounds; +} + +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.h new file mode 100644 index 0000000000..3c6a57aee3 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.h @@ -0,0 +1,86 @@ +// +// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// renderer9_utils.h: Conversion functions and other utility routines +// specific to the D3D9 renderer + +#ifndef LIBANGLE_RENDERER_D3D_D3D9_RENDERER9UTILS_H_ +#define LIBANGLE_RENDERER_D3D_D3D9_RENDERER9UTILS_H_ + +#include "libANGLE/angletypes.h" +#include "libANGLE/Caps.h" +#include "libANGLE/Error.h" + +namespace gl +{ +class FramebufferAttachment; +} + +namespace rx +{ +class RenderTarget9; +struct Workarounds; + +namespace gl_d3d9 +{ + +D3DCMPFUNC ConvertComparison(GLenum comparison); +D3DCOLOR ConvertColor(gl::ColorF 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); + +D3DMULTISAMPLE_TYPE GetMultisampleType(GLuint samples); + +} + +namespace d3d9_gl +{ + +GLsizei GetSamplesCount(D3DMULTISAMPLE_TYPE type); + +bool IsFormatChannelEquivalent(D3DFORMAT d3dformat, GLenum format); + +void GenerateCaps(IDirect3D9 *d3d9, IDirect3DDevice9 *device, D3DDEVTYPE deviceType, UINT adapter, gl::Caps *caps, + gl::TextureCapsMap *textureCapsMap, gl::Extensions *extensions); + +} + +namespace d3d9 +{ + +GLuint ComputeBlockSize(D3DFORMAT format, GLuint width, GLuint height); + +void MakeValidSize(bool isImage, D3DFORMAT format, GLsizei *requestWidth, GLsizei *requestHeight, int *levelOffset); + +inline bool isDeviceLostError(HRESULT errorCode) +{ + switch (errorCode) + { + case D3DERR_DRIVERINTERNALERROR: + case D3DERR_DEVICELOST: + case D3DERR_DEVICEHUNG: + case D3DERR_DEVICEREMOVED: + return true; + default: + return false; + } +} + +gl::Error GetAttachmentRenderTarget(const gl::FramebufferAttachment *attachment, RenderTarget9 **outRT); +Workarounds GenerateWorkarounds(); + +} + +} + +#endif // LIBANGLE_RENDERER_D3D_D3D9_RENDERER9UTILS_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/shaders/Blit.ps b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/shaders/Blit.ps new file mode 100644 index 0000000000..dc357d0fa6 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/shaders/Blit.ps @@ -0,0 +1,33 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +sampler2D tex : s0; + +uniform float4 mult : c0; +uniform float4 add : c1; + +// 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 +// Performs a mad operation using the LA data from the texture with mult.xw and add.xw. +// Returns data in the form of llla +float4 luminanceps(float4 texcoord : TEXCOORD0) : COLOR +{ + return (tex2D(tex, texcoord.xy).xw * mult.xw + add.xw).xxxy; +}; + +// RGB/A Component Mask Pixel Shader +// Performs a mad operation using the texture's RGBA data with mult.xyzw and add.xyzw. +// Returns data in the form of rgba +float4 componentmaskps(float4 texcoord : TEXCOORD0) : COLOR +{ + return tex2D(tex, texcoord.xy) * mult + add; +}; diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/shaders/Blit.vs b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/shaders/Blit.vs new file mode 100644 index 0000000000..3a36980b93 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/shaders/Blit.vs @@ -0,0 +1,43 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +struct VS_OUTPUT +{ + float4 position : POSITION; + float4 texcoord : TEXCOORD0; +}; + +uniform float4 halfPixelSize : c0; + +// Standard Vertex Shader +// Input 0 is the homogenous position. +// Outputs the homogenous position as-is. +// Outputs a tex coord with (0,0) in the upper-left corner of the screen and (1,1) in the bottom right. +// C0.X must be negative half-pixel width, C0.Y must be half-pixel height. C0.ZW must be 0. +VS_OUTPUT standardvs(in float4 position : POSITION) +{ + VS_OUTPUT Out; + + Out.position = position + halfPixelSize; + Out.texcoord = position * float4(0.5, -0.5, 1.0, 1.0) + float4(0.5, 0.5, 0, 0); + + return Out; +}; + +// Flip Y Vertex Shader +// Input 0 is the homogenous position. +// Outputs the homogenous position as-is. +// Outputs a tex coord with (0,1) in the upper-left corner of the screen and (1,0) in the bottom right. +// C0.XY must be the half-pixel width and height. C0.ZW must be 0. +VS_OUTPUT flipyvs(in float4 position : POSITION) +{ + VS_OUTPUT Out; + + Out.position = position + halfPixelSize; + Out.texcoord = position * float4(0.5, 0.5, 1.0, 1.0) + float4(0.5, 0.5, 0, 0); + + return Out; +}; diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/vertexconversion.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/vertexconversion.h new file mode 100644 index 0000000000..32eb376a78 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/vertexconversion.h @@ -0,0 +1,197 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project 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 LIBANGLE_RENDERER_D3D_D3D9_VERTEXCONVERSION_H_ +#define LIBANGLE_RENDERER_D3D_D3D9_VERTEXCONVERSION_H_ + +#include +#include +#include + +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 uint8_t *input, size_t stride, size_t n, uint8_t *output) + { + OutputType *out = reinterpret_cast(output); + + for (std::size_t i = 0; i < n; i++) + { + const InputType *ein = reinterpret_cast(input + 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; + } + } + + private: + 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 // LIBANGLE_RENDERER_D3D_D3D9_VERTEXCONVERSION_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/formatutilsD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/formatutilsD3D.cpp new file mode 100644 index 0000000000..8a4d41cbd9 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/formatutilsD3D.cpp @@ -0,0 +1,147 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// formatutils9.cpp: Queries for GL image formats and their translations to D3D +// formats. + +#include "libANGLE/renderer/d3d/formatutilsD3D.h" + +#include + +#include "common/debug.h" +#include "libANGLE/renderer/d3d/imageformats.h" +#include "libANGLE/renderer/d3d/copyimage.h" + +namespace rx +{ + +typedef std::pair FormatTypePair; +typedef std::pair FormatWriteFunctionPair; +typedef std::map FormatWriteFunctionMap; + +static inline void InsertFormatWriteFunctionMapping(FormatWriteFunctionMap *map, GLenum format, GLenum type, + ColorWriteFunction writeFunc) +{ + map->insert(FormatWriteFunctionPair(FormatTypePair(format, type), writeFunc)); +} + +static FormatWriteFunctionMap BuildFormatWriteFunctionMap() +{ + FormatWriteFunctionMap map; + + // | Format | Type | Color write function | + InsertFormatWriteFunctionMapping(&map, GL_RGBA, GL_UNSIGNED_BYTE, WriteColor ); + InsertFormatWriteFunctionMapping(&map, GL_RGBA, GL_BYTE, WriteColor ); + InsertFormatWriteFunctionMapping(&map, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, WriteColor ); + InsertFormatWriteFunctionMapping(&map, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, WriteColor ); + InsertFormatWriteFunctionMapping(&map, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, WriteColor ); + InsertFormatWriteFunctionMapping(&map, GL_RGBA, GL_FLOAT, WriteColor); + InsertFormatWriteFunctionMapping(&map, GL_RGBA, GL_HALF_FLOAT, WriteColor); + InsertFormatWriteFunctionMapping(&map, GL_RGBA, GL_HALF_FLOAT_OES, WriteColor); + + InsertFormatWriteFunctionMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, WriteColor ); + InsertFormatWriteFunctionMapping(&map, GL_RGBA_INTEGER, GL_BYTE, WriteColor ); + InsertFormatWriteFunctionMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT, WriteColor ); + InsertFormatWriteFunctionMapping(&map, GL_RGBA_INTEGER, GL_SHORT, WriteColor ); + InsertFormatWriteFunctionMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_INT, WriteColor ); + InsertFormatWriteFunctionMapping(&map, GL_RGBA_INTEGER, GL_INT, WriteColor ); + InsertFormatWriteFunctionMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV, WriteColor ); + + InsertFormatWriteFunctionMapping(&map, GL_RGB, GL_UNSIGNED_BYTE, WriteColor ); + InsertFormatWriteFunctionMapping(&map, GL_RGB, GL_BYTE, WriteColor ); + InsertFormatWriteFunctionMapping(&map, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, WriteColor ); + InsertFormatWriteFunctionMapping(&map, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV, WriteColor ); + InsertFormatWriteFunctionMapping(&map, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV, WriteColor ); + InsertFormatWriteFunctionMapping(&map, GL_RGB, GL_FLOAT, WriteColor ); + InsertFormatWriteFunctionMapping(&map, GL_RGB, GL_HALF_FLOAT, WriteColor ); + InsertFormatWriteFunctionMapping(&map, GL_RGB, GL_HALF_FLOAT_OES, WriteColor ); + + InsertFormatWriteFunctionMapping(&map, GL_RGB_INTEGER, GL_UNSIGNED_BYTE, WriteColor ); + InsertFormatWriteFunctionMapping(&map, GL_RGB_INTEGER, GL_BYTE, WriteColor ); + InsertFormatWriteFunctionMapping(&map, GL_RGB_INTEGER, GL_UNSIGNED_SHORT, WriteColor ); + InsertFormatWriteFunctionMapping(&map, GL_RGB_INTEGER, GL_SHORT, WriteColor ); + InsertFormatWriteFunctionMapping(&map, GL_RGB_INTEGER, GL_UNSIGNED_INT, WriteColor ); + InsertFormatWriteFunctionMapping(&map, GL_RGB_INTEGER, GL_INT, WriteColor ); + + InsertFormatWriteFunctionMapping(&map, GL_RG, GL_UNSIGNED_BYTE, WriteColor ); + InsertFormatWriteFunctionMapping(&map, GL_RG, GL_BYTE, WriteColor ); + InsertFormatWriteFunctionMapping(&map, GL_RG, GL_FLOAT, WriteColor ); + InsertFormatWriteFunctionMapping(&map, GL_RG, GL_HALF_FLOAT, WriteColor ); + InsertFormatWriteFunctionMapping(&map, GL_RG, GL_HALF_FLOAT_OES, WriteColor ); + + InsertFormatWriteFunctionMapping(&map, GL_RG_INTEGER, GL_UNSIGNED_BYTE, WriteColor ); + InsertFormatWriteFunctionMapping(&map, GL_RG_INTEGER, GL_BYTE, WriteColor ); + InsertFormatWriteFunctionMapping(&map, GL_RG_INTEGER, GL_UNSIGNED_SHORT, WriteColor ); + InsertFormatWriteFunctionMapping(&map, GL_RG_INTEGER, GL_SHORT, WriteColor ); + InsertFormatWriteFunctionMapping(&map, GL_RG_INTEGER, GL_UNSIGNED_INT, WriteColor ); + InsertFormatWriteFunctionMapping(&map, GL_RG_INTEGER, GL_INT, WriteColor ); + + InsertFormatWriteFunctionMapping(&map, GL_RED, GL_UNSIGNED_BYTE, WriteColor ); + InsertFormatWriteFunctionMapping(&map, GL_RED, GL_BYTE, WriteColor ); + InsertFormatWriteFunctionMapping(&map, GL_RED, GL_FLOAT, WriteColor ); + InsertFormatWriteFunctionMapping(&map, GL_RED, GL_HALF_FLOAT, WriteColor ); + InsertFormatWriteFunctionMapping(&map, GL_RED, GL_HALF_FLOAT_OES, WriteColor ); + + InsertFormatWriteFunctionMapping(&map, GL_RED_INTEGER, GL_UNSIGNED_BYTE, WriteColor ); + InsertFormatWriteFunctionMapping(&map, GL_RED_INTEGER, GL_BYTE, WriteColor ); + InsertFormatWriteFunctionMapping(&map, GL_RED_INTEGER, GL_UNSIGNED_SHORT, WriteColor ); + InsertFormatWriteFunctionMapping(&map, GL_RED_INTEGER, GL_SHORT, WriteColor ); + InsertFormatWriteFunctionMapping(&map, GL_RED_INTEGER, GL_UNSIGNED_INT, WriteColor ); + InsertFormatWriteFunctionMapping(&map, GL_RED_INTEGER, GL_INT, WriteColor ); + + InsertFormatWriteFunctionMapping(&map, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, WriteColor ); + InsertFormatWriteFunctionMapping(&map, GL_LUMINANCE, GL_UNSIGNED_BYTE, WriteColor ); + InsertFormatWriteFunctionMapping(&map, GL_ALPHA, GL_UNSIGNED_BYTE, WriteColor ); + InsertFormatWriteFunctionMapping(&map, GL_LUMINANCE_ALPHA, GL_FLOAT, WriteColor ); + InsertFormatWriteFunctionMapping(&map, GL_LUMINANCE, GL_FLOAT, WriteColor ); + InsertFormatWriteFunctionMapping(&map, GL_ALPHA, GL_FLOAT, WriteColor ); + InsertFormatWriteFunctionMapping(&map, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT, WriteColor ); + InsertFormatWriteFunctionMapping(&map, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES, WriteColor ); + InsertFormatWriteFunctionMapping(&map, GL_LUMINANCE, GL_HALF_FLOAT, WriteColor ); + InsertFormatWriteFunctionMapping(&map, GL_LUMINANCE, GL_HALF_FLOAT_OES, WriteColor ); + InsertFormatWriteFunctionMapping(&map, GL_ALPHA, GL_HALF_FLOAT, WriteColor ); + InsertFormatWriteFunctionMapping(&map, GL_ALPHA, GL_HALF_FLOAT_OES, WriteColor ); + + InsertFormatWriteFunctionMapping(&map, GL_BGRA_EXT, GL_UNSIGNED_BYTE, WriteColor ); + InsertFormatWriteFunctionMapping(&map, GL_BGRA_EXT, GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT, WriteColor ); + InsertFormatWriteFunctionMapping(&map, GL_BGRA_EXT, GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT, WriteColor ); + + InsertFormatWriteFunctionMapping(&map, GL_SRGB_EXT, GL_UNSIGNED_BYTE, WriteColor ); + InsertFormatWriteFunctionMapping(&map, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE, WriteColor ); + + InsertFormatWriteFunctionMapping(&map, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, NULL ); + InsertFormatWriteFunctionMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, NULL ); + InsertFormatWriteFunctionMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, GL_UNSIGNED_BYTE, NULL ); + InsertFormatWriteFunctionMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, GL_UNSIGNED_BYTE, NULL ); + + InsertFormatWriteFunctionMapping(&map, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, NULL ); + InsertFormatWriteFunctionMapping(&map, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL ); + InsertFormatWriteFunctionMapping(&map, GL_DEPTH_COMPONENT, GL_FLOAT, NULL ); + + InsertFormatWriteFunctionMapping(&map, GL_STENCIL, GL_UNSIGNED_BYTE, NULL ); + + InsertFormatWriteFunctionMapping(&map, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, NULL ); + InsertFormatWriteFunctionMapping(&map, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, NULL ); + + return map; +} + +ColorWriteFunction GetColorWriteFunction(GLenum format, GLenum type) +{ + static const FormatWriteFunctionMap formatTypeMap = BuildFormatWriteFunctionMap(); + FormatWriteFunctionMap::const_iterator iter = formatTypeMap.find(FormatTypePair(format, type)); + ASSERT(iter != formatTypeMap.end()); + if (iter != formatTypeMap.end()) + { + return iter->second; + } + else + { + return NULL; + } +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/formatutilsD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/formatutilsD3D.h new file mode 100644 index 0000000000..6dd59ca94b --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/formatutilsD3D.h @@ -0,0 +1,50 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// formatutils9.h: Queries for GL image formats and their translations to D3D +// formats. + +#ifndef LIBANGLE_RENDERER_D3D_FORMATUTILSD3D_H_ +#define LIBANGLE_RENDERER_D3D_FORMATUTILSD3D_H_ + +#include "angle_gl.h" + +#include +#include + +namespace rx +{ + +typedef void (*MipGenerationFunction)(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth, + const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch, + uint8_t *destData, size_t destRowPitch, size_t destDepthPitch); + +typedef void (*LoadImageFunction)(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +typedef void (*InitializeTextureDataFunction)(size_t width, size_t height, size_t depth, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +typedef void (*ColorReadFunction)(const uint8_t *source, uint8_t *dest); +typedef void (*ColorWriteFunction)(const uint8_t *source, uint8_t *dest); +typedef void (*ColorCopyFunction)(const uint8_t *source, uint8_t *dest); + +typedef void (*VertexCopyFunction)(const uint8_t *input, size_t stride, size_t count, uint8_t *output); + +enum VertexConversionType +{ + VERTEX_CONVERT_NONE = 0, + VERTEX_CONVERT_CPU = 1, + VERTEX_CONVERT_GPU = 2, + VERTEX_CONVERT_BOTH = 3 +}; + +ColorWriteFunction GetColorWriteFunction(GLenum format, GLenum type); + +} + +#endif // LIBANGLE_RENDERER_D3D_FORMATUTILSD3D_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/generatemip.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/generatemip.h new file mode 100644 index 0000000000..398ef26b30 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/generatemip.h @@ -0,0 +1,28 @@ +// +// Copyright (c) 2002-2015 The ANGLE Project 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 LIBANGLE_RENDERER_D3D_GENERATEMIP_H_ +#define LIBANGLE_RENDERER_D3D_GENERATEMIP_H_ + +#include "libANGLE/renderer/d3d/imageformats.h" +#include "libANGLE/angletypes.h" + +namespace rx +{ + +template +inline void GenerateMip(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth, + const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch, + uint8_t *destData, size_t destRowPitch, size_t destDepthPitch); + +} + +#include "generatemip.inl" + +#endif // LIBANGLE_RENDERER_D3D_GENERATEMIP_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/generatemip.inl b/src/3rdparty/angle/src/libANGLE/renderer/d3d/generatemip.inl new file mode 100644 index 0000000000..265783641e --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/generatemip.inl @@ -0,0 +1,266 @@ +// +// Copyright (c) 2015 The ANGLE Project 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.inl: Defines the GenerateMip function, templated on the format +// type of the image for which mip levels are being generated. + +#include "common/mathutil.h" + +namespace rx +{ + +namespace priv +{ + +template +static inline T *GetPixel(uint8_t *data, size_t x, size_t y, size_t z, size_t rowPitch, size_t depthPitch) +{ + return reinterpret_cast(data + (x * sizeof(T)) + (y * rowPitch) + (z * depthPitch)); +} + +template +static inline const T *GetPixel(const uint8_t *data, size_t x, size_t y, size_t z, size_t rowPitch, size_t depthPitch) +{ + return reinterpret_cast(data + (x * sizeof(T)) + (y * rowPitch) + (z * depthPitch)); +} + +template +static void GenerateMip_Y(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth, + const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch, + size_t destWidth, size_t destHeight, size_t destDepth, + uint8_t *destData, size_t destRowPitch, size_t destDepthPitch) +{ + ASSERT(sourceWidth == 1); + ASSERT(sourceHeight > 1); + ASSERT(sourceDepth == 1); + + for (size_t y = 0; y < destHeight; y++) + { + const T *src0 = GetPixel(sourceData, 0, y * 2, 0, sourceRowPitch, sourceDepthPitch); + const T *src1 = GetPixel(sourceData, 0, y * 2 + 1, 0, sourceRowPitch, sourceDepthPitch); + T *dst = GetPixel(destData, 0, y, 0, destRowPitch, destDepthPitch); + + T::average(dst, src0, src1); + } +} + +template +static void GenerateMip_X(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth, + const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch, + size_t destWidth, size_t destHeight, size_t destDepth, + uint8_t *destData, size_t destRowPitch, size_t destDepthPitch) +{ + ASSERT(sourceWidth > 1); + ASSERT(sourceHeight == 1); + ASSERT(sourceDepth == 1); + + for (size_t x = 0; x < destWidth; x++) + { + const T *src0 = GetPixel(sourceData, x * 2, 0, 0, sourceRowPitch, sourceDepthPitch); + const T *src1 = GetPixel(sourceData, x * 2 + 1, 0, 0, sourceRowPitch, sourceDepthPitch); + T *dst = GetPixel(destData, x, 0, 0, destRowPitch, destDepthPitch); + + T::average(dst, src0, src1); + } +} + +template +static void GenerateMip_Z(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth, + const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch, + size_t destWidth, size_t destHeight, size_t destDepth, + uint8_t *destData, size_t destRowPitch, size_t destDepthPitch) +{ + ASSERT(sourceWidth == 1); + ASSERT(sourceHeight == 1); + ASSERT(sourceDepth > 1); + + for (size_t z = 0; z < destDepth; z++) + { + const T *src0 = GetPixel(sourceData, 0, 0, z * 2, sourceRowPitch, sourceDepthPitch); + const T *src1 = GetPixel(sourceData, 0, 0, z * 2 + 1, sourceRowPitch, sourceDepthPitch); + T *dst = GetPixel(destData, 0, 0, z, destRowPitch, destDepthPitch); + + T::average(dst, src0, src1); + } +} + +template +static void GenerateMip_XY(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth, + const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch, + size_t destWidth, size_t destHeight, size_t destDepth, + uint8_t *destData, size_t destRowPitch, size_t destDepthPitch) +{ + ASSERT(sourceWidth > 1); + ASSERT(sourceHeight > 1); + ASSERT(sourceDepth == 1); + + for (size_t y = 0; y < destHeight; y++) + { + for (size_t x = 0; x < destWidth; x++) + { + const T *src0 = GetPixel(sourceData, x * 2, y * 2, 0, sourceRowPitch, sourceDepthPitch); + const T *src1 = GetPixel(sourceData, x * 2, y * 2 + 1, 0, sourceRowPitch, sourceDepthPitch); + const T *src2 = GetPixel(sourceData, x * 2 + 1, y * 2, 0, sourceRowPitch, sourceDepthPitch); + const T *src3 = GetPixel(sourceData, x * 2 + 1, y * 2 + 1, 0, sourceRowPitch, sourceDepthPitch); + T *dst = GetPixel(destData, x, y, 0, destRowPitch, destDepthPitch); + + T tmp0, tmp1; + + T::average(&tmp0, src0, src1); + T::average(&tmp1, src2, src3); + T::average(dst, &tmp0, &tmp1); + } + } +} + +template +static void GenerateMip_YZ(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth, + const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch, + size_t destWidth, size_t destHeight, size_t destDepth, + uint8_t *destData, size_t destRowPitch, size_t destDepthPitch) +{ + ASSERT(sourceWidth == 1); + ASSERT(sourceHeight > 1); + ASSERT(sourceDepth > 1); + + for (size_t z = 0; z < destDepth; z++) + { + for (size_t y = 0; y < destHeight; y++) + { + const T *src0 = GetPixel(sourceData, 0, y * 2, z * 2, sourceRowPitch, sourceDepthPitch); + const T *src1 = GetPixel(sourceData, 0, y * 2, z * 2 + 1, sourceRowPitch, sourceDepthPitch); + const T *src2 = GetPixel(sourceData, 0, y * 2 + 1, z * 2, sourceRowPitch, sourceDepthPitch); + const T *src3 = GetPixel(sourceData, 0, y * 2 + 1, z * 2 + 1, sourceRowPitch, sourceDepthPitch); + T *dst = GetPixel(destData, 0, y, z, destRowPitch, destDepthPitch); + + T tmp0, tmp1; + + T::average(&tmp0, src0, src1); + T::average(&tmp1, src2, src3); + T::average(dst, &tmp0, &tmp1); + } + } +} + +template +static void GenerateMip_XZ(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth, + const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch, + size_t destWidth, size_t destHeight, size_t destDepth, + uint8_t *destData, size_t destRowPitch, size_t destDepthPitch) +{ + ASSERT(sourceWidth > 1); + ASSERT(sourceHeight == 1); + ASSERT(sourceDepth > 1); + + for (size_t z = 0; z < destDepth; z++) + { + for (size_t x = 0; x < destWidth; x++) + { + const T *src0 = GetPixel(sourceData, x * 2, 0, z * 2, sourceRowPitch, sourceDepthPitch); + const T *src1 = GetPixel(sourceData, x * 2, 0, z * 2 + 1, sourceRowPitch, sourceDepthPitch); + const T *src2 = GetPixel(sourceData, x * 2 + 1, 0, z * 2, sourceRowPitch, sourceDepthPitch); + const T *src3 = GetPixel(sourceData, x * 2 + 1, 0, z * 2 + 1, sourceRowPitch, sourceDepthPitch); + T *dst = GetPixel(destData, x, 0, z, destRowPitch, destDepthPitch); + + T tmp0, tmp1; + + T::average(&tmp0, src0, src1); + T::average(&tmp1, src2, src3); + T::average(dst, &tmp0, &tmp1); + } + } +} + +template +static void GenerateMip_XYZ(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth, + const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch, + size_t destWidth, size_t destHeight, size_t destDepth, + uint8_t *destData, size_t destRowPitch, size_t destDepthPitch) +{ + ASSERT(sourceWidth > 1); + ASSERT(sourceHeight > 1); + ASSERT(sourceDepth > 1); + + for (size_t z = 0; z < destDepth; z++) + { + for (size_t y = 0; y < destHeight; y++) + { + for (size_t x = 0; x < destWidth; x++) + { + const T *src0 = GetPixel(sourceData, x * 2, y * 2, z * 2, sourceRowPitch, sourceDepthPitch); + const T *src1 = GetPixel(sourceData, x * 2, y * 2, z * 2 + 1, sourceRowPitch, sourceDepthPitch); + const T *src2 = GetPixel(sourceData, x * 2, y * 2 + 1, z * 2, sourceRowPitch, sourceDepthPitch); + const T *src3 = GetPixel(sourceData, x * 2, y * 2 + 1, z * 2 + 1, sourceRowPitch, sourceDepthPitch); + const T *src4 = GetPixel(sourceData, x * 2 + 1, y * 2, z * 2, sourceRowPitch, sourceDepthPitch); + const T *src5 = GetPixel(sourceData, x * 2 + 1, y * 2, z * 2 + 1, sourceRowPitch, sourceDepthPitch); + const T *src6 = GetPixel(sourceData, x * 2 + 1, y * 2 + 1, z * 2, sourceRowPitch, sourceDepthPitch); + const T *src7 = GetPixel(sourceData, x * 2 + 1, y * 2 + 1, z * 2 + 1, sourceRowPitch, sourceDepthPitch); + T *dst = GetPixel(destData, x, y, z, destRowPitch, destDepthPitch); + + T tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; + + T::average(&tmp0, src0, src1); + T::average(&tmp1, src2, src3); + T::average(&tmp2, src4, src5); + T::average(&tmp3, src6, src7); + + T::average(&tmp4, &tmp0, &tmp1); + T::average(&tmp5, &tmp2, &tmp3); + + T::average(dst, &tmp4, &tmp5); + } + } + } +} + + +typedef void (*MipGenerationFunction)(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth, + const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch, + size_t destWidth, size_t destHeight, size_t destDepth, + uint8_t *destData, size_t destRowPitch, size_t destDepthPitch); + +template +static MipGenerationFunction GetMipGenerationFunction(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth) +{ + uint8_t index = ((sourceWidth > 1) ? 1 : 0) | + ((sourceHeight > 1) ? 2 : 0) | + ((sourceDepth > 1) ? 4 : 0); + + switch (index) + { + case 0: return NULL; + case 1: return GenerateMip_X; // W x 1 x 1 + case 2: return GenerateMip_Y; // 1 x H x 1 + case 3: return GenerateMip_XY; // W x H x 1 + case 4: return GenerateMip_Z; // 1 x 1 x D + case 5: return GenerateMip_XZ; // W x 1 x D + case 6: return GenerateMip_YZ; // 1 x H x D + case 7: return GenerateMip_XYZ; // W x H x D + } + + UNREACHABLE(); + return NULL; +} + +} + +template +inline void GenerateMip(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth, + const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch, + uint8_t *destData, size_t destRowPitch, size_t destDepthPitch) +{ + size_t mipWidth = std::max(1, sourceWidth >> 1); + size_t mipHeight = std::max(1, sourceHeight >> 1); + size_t mipDepth = std::max(1, sourceDepth >> 1); + + priv::MipGenerationFunction generationFunction = priv::GetMipGenerationFunction(sourceWidth, sourceHeight, sourceDepth); + ASSERT(generationFunction != NULL); + + generationFunction(sourceWidth, sourceHeight, sourceDepth, sourceData, sourceRowPitch, sourceDepthPitch, + mipWidth, mipHeight, mipDepth, destData, destRowPitch, destDepthPitch); +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/imageformats.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/imageformats.h new file mode 100644 index 0000000000..e0f9a16c1a --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/imageformats.h @@ -0,0 +1,2031 @@ +// +// Copyright (c) 2013-2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// imageformats.h: Defines image format types with functions for mip generation +// and copying. + +#ifndef LIBANGLE_RENDERER_D3D_IMAGEFORMATS_H_ +#define LIBANGLE_RENDERER_D3D_IMAGEFORMATS_H_ + +#include "libANGLE/angletypes.h" + +#include "common/mathutil.h" + +namespace rx +{ + +// Several structures share functionality for reading, writing or mipmapping but the layout +// must match the texture format which the structure represents. If collapsing or typedefing +// structs in this header, make sure the functionality and memory layout is exactly the same. + +struct L8 +{ + unsigned char L; + + static void readColor(gl::ColorF *dst, const L8 *src) + { + const float lum = gl::normalizedToFloat(src->L); + dst->red = lum; + dst->green = lum; + dst->blue = lum; + dst->alpha = 1.0f; + } + + static void writeColor(L8 *dst, const gl::ColorF *src) + { + dst->L = gl::floatToNormalized((src->red + src->green + src->blue) / 3.0f); + } + + static void average(L8 *dst, const L8 *src1, const L8 *src2) + { + dst->L = gl::average(src1->L, src2->L); + } +}; + +struct R8 +{ + unsigned char R; + + static void readColor(gl::ColorF *dst, const R8 *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = 0.0f; + dst->blue = 0.0f; + dst->alpha = 1.0f; + } + + static void readColor(gl::ColorUI *dst, const R8 *src) + { + dst->red = src->R; + dst->green = 0; + dst->blue = 0; + dst->alpha = 1; + } + + static void writeColor(R8 *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized(src->red); + } + + static void writeColor(R8 *dst, const gl::ColorUI *src) + { + dst->R = static_cast(src->red); + } + + static void average(R8 *dst, const R8 *src1, const R8 *src2) + { + dst->R = gl::average(src1->R, src2->R); + } +}; + +struct A8 +{ + unsigned char A; + + static void readColor(gl::ColorF *dst, const A8 *src) + { + dst->red = 0.0f; + dst->green = 0.0f; + dst->blue = 0.0f; + dst->alpha = gl::normalizedToFloat(src->A); + } + + static void writeColor(A8 *dst, const gl::ColorF *src) + { + dst->A = gl::floatToNormalized(src->alpha); + } + + static void average(A8 *dst, const A8 *src1, const A8 *src2) + { + dst->A = gl::average(src1->A, src2->A); + } +}; + +struct L8A8 +{ + unsigned char L; + unsigned char A; + + static void readColor(gl::ColorF *dst, const L8A8 *src) + { + const float lum = gl::normalizedToFloat(src->L); + dst->red = lum; + dst->green = lum; + dst->blue = lum; + dst->alpha = gl::normalizedToFloat(src->A); + } + + static void writeColor(L8A8 *dst, const gl::ColorF *src) + { + dst->L = gl::floatToNormalized((src->red + src->green + src->blue) / 3.0f); + dst->A = gl::floatToNormalized(src->alpha); + } + + static void average(L8A8 *dst, const L8A8 *src1, const L8A8 *src2) + { + *(unsigned short*)dst = (((*(unsigned short*)src1 ^ *(unsigned short*)src2) & 0xFEFE) >> 1) + (*(unsigned short*)src1 & *(unsigned short*)src2); + } +}; + +struct A8L8 +{ + unsigned char A; + unsigned char L; + + static void readColor(gl::ColorF *dst, const A8L8 *src) + { + const float lum = gl::normalizedToFloat(src->L); + dst->red = lum; + dst->green = lum; + dst->blue = lum; + dst->alpha = gl::normalizedToFloat(src->A); + } + + static void writeColor(A8L8 *dst, const gl::ColorF *src) + { + dst->L = gl::floatToNormalized((src->red + src->green + src->blue) / 3.0f); + dst->A = gl::floatToNormalized(src->alpha); + } + + 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 R8G8 +{ + unsigned char R; + unsigned char G; + + static void readColor(gl::ColorF *dst, const R8G8 *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = gl::normalizedToFloat(src->G); + dst->blue = 0.0f; + dst->alpha = 1.0f; + } + + static void readColor(gl::ColorUI *dst, const R8G8 *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = 0; + dst->alpha = 1; + } + + static void writeColor(R8G8 *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized(src->red); + dst->G = gl::floatToNormalized(src->green); + } + + static void writeColor(R8G8 *dst, const gl::ColorUI *src) + { + dst->R = static_cast(src->red); + dst->G = static_cast(src->green); + } + + static void average(R8G8 *dst, const R8G8 *src1, const R8G8 *src2) + { + *(unsigned short*)dst = (((*(unsigned short*)src1 ^ *(unsigned short*)src2) & 0xFEFE) >> 1) + (*(unsigned short*)src1 & *(unsigned short*)src2); + } +}; + +struct R8G8B8 +{ + unsigned char R; + unsigned char G; + unsigned char B; + + static void readColor(gl::ColorF *dst, const R8G8B8 *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = gl::normalizedToFloat(src->G); + dst->blue = gl::normalizedToFloat(src->B); + dst->alpha = 1.0f; + } + + static void readColor(gl::ColorUI *dst, const R8G8B8 *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = src->G; + dst->alpha = 1; + } + + static void writeColor(R8G8B8 *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized(src->red); + dst->G = gl::floatToNormalized(src->green); + dst->B = gl::floatToNormalized(src->blue); + } + + static void writeColor(R8G8B8 *dst, const gl::ColorUI *src) + { + dst->R = static_cast(src->red); + dst->G = static_cast(src->green); + dst->B = static_cast(src->blue); + } + + static void average(R8G8B8 *dst, const R8G8B8 *src1, const R8G8B8 *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + dst->B = gl::average(src1->B, src2->B); + } +}; + +struct B8G8R8 +{ + unsigned char B; + unsigned char G; + unsigned char R; + + static void readColor(gl::ColorF *dst, const B8G8R8 *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = gl::normalizedToFloat(src->G); + dst->blue = gl::normalizedToFloat(src->B); + dst->alpha = 1.0f; + } + + static void readColor(gl::ColorUI *dst, const B8G8R8 *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = src->G; + dst->alpha = 1; + } + + static void writeColor(B8G8R8 *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized(src->red); + dst->G = gl::floatToNormalized(src->green); + dst->B = gl::floatToNormalized(src->blue); + } + + static void writeColor(B8G8R8 *dst, const gl::ColorUI *src) + { + dst->R = static_cast(src->red); + dst->G = static_cast(src->green); + dst->B = static_cast(src->blue); + } + + static void average(B8G8R8 *dst, const B8G8R8 *src1, const B8G8R8 *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + dst->B = gl::average(src1->B, src2->B); + } +}; + +struct R5G6B5 +{ + unsigned short RGB; + + static void readColor(gl::ColorF *dst, const R5G6B5 *src) + { + dst->red = gl::normalizedToFloat<5>(gl::getShiftedData<5, 11>(src->RGB)); + dst->green = gl::normalizedToFloat<6>(gl::getShiftedData<6, 5>(src->RGB)); + dst->blue = gl::normalizedToFloat<5>(gl::getShiftedData<5, 0>(src->RGB)); + dst->alpha = 1.0f; + } + + static void writeColor(R5G6B5 *dst, const gl::ColorF *src) + { + dst->RGB = gl::shiftData<5, 11>(gl::floatToNormalized<5, unsigned short>(src->red)) | + gl::shiftData<6, 5>(gl::floatToNormalized<6, unsigned short>(src->green)) | + gl::shiftData<5, 0>(gl::floatToNormalized<5, unsigned short>(src->blue)); + } + + static void average(R5G6B5 *dst, const R5G6B5 *src1, const R5G6B5 *src2) + { + dst->RGB = gl::shiftData<5, 11>(gl::average(gl::getShiftedData<5, 11>(src1->RGB), gl::getShiftedData<5, 11>(src2->RGB))) | + gl::shiftData<6, 5>(gl::average(gl::getShiftedData<6, 5>(src1->RGB), gl::getShiftedData<6, 5>(src2->RGB))) | + gl::shiftData<5, 0>(gl::average(gl::getShiftedData<5, 0>(src1->RGB), gl::getShiftedData<5, 0>(src2->RGB))); + } +}; + +struct A8R8G8B8 +{ + unsigned char A; + unsigned char R; + unsigned char G; + unsigned char B; + + static void readColor(gl::ColorF *dst, const A8R8G8B8 *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = gl::normalizedToFloat(src->G); + dst->blue = gl::normalizedToFloat(src->B); + dst->alpha = gl::normalizedToFloat(src->A); + } + + static void readColor(gl::ColorUI *dst, const A8R8G8B8 *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = src->B; + dst->alpha = src->A; + } + + static void writeColor(A8R8G8B8 *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized(src->red); + dst->G = gl::floatToNormalized(src->green); + dst->B = gl::floatToNormalized(src->blue); + dst->A = gl::floatToNormalized(src->alpha); + } + + static void writeColor(A8R8G8B8 *dst, const gl::ColorUI *src) + { + dst->R = static_cast(src->red); + dst->G = static_cast(src->green); + dst->B = static_cast(src->blue); + dst->A = static_cast(src->alpha); + } + + 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 R8G8B8A8 +{ + unsigned char R; + unsigned char G; + unsigned char B; + unsigned char A; + + static void readColor(gl::ColorF *dst, const R8G8B8A8 *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = gl::normalizedToFloat(src->G); + dst->blue = gl::normalizedToFloat(src->B); + dst->alpha = gl::normalizedToFloat(src->A); + } + + static void readColor(gl::ColorUI *dst, const R8G8B8A8 *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = src->B; + dst->alpha = src->A; + } + + static void writeColor(R8G8B8A8 *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized(src->red); + dst->G = gl::floatToNormalized(src->green); + dst->B = gl::floatToNormalized(src->blue); + dst->A = gl::floatToNormalized(src->alpha); + } + + static void writeColor(R8G8B8A8 *dst, const gl::ColorUI *src) + { + dst->R = static_cast(src->red); + dst->G = static_cast(src->green); + dst->B = static_cast(src->blue); + dst->A = static_cast(src->alpha); + } + + static void average(R8G8B8A8 *dst, const R8G8B8A8 *src1, const R8G8B8A8 *src2) + { + *(unsigned int*)dst = (((*(unsigned int*)src1 ^ *(unsigned int*)src2) & 0xFEFEFEFE) >> 1) + (*(unsigned int*)src1 & *(unsigned int*)src2); + } +}; + +struct B8G8R8A8 +{ + unsigned char B; + unsigned char G; + unsigned char R; + unsigned char A; + + static void readColor(gl::ColorF *dst, const B8G8R8A8 *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = gl::normalizedToFloat(src->G); + dst->blue = gl::normalizedToFloat(src->B); + dst->alpha = gl::normalizedToFloat(src->A); + } + + static void readColor(gl::ColorUI *dst, const B8G8R8A8 *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = src->B; + dst->alpha = src->A; + } + + static void writeColor(B8G8R8A8 *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized(src->red); + dst->G = gl::floatToNormalized(src->green); + dst->B = gl::floatToNormalized(src->blue); + dst->A = gl::floatToNormalized(src->alpha); + } + + static void writeColor(B8G8R8A8 *dst, const gl::ColorUI *src) + { + dst->R = static_cast(src->red); + dst->G = static_cast(src->green); + dst->B = static_cast(src->blue); + dst->A = static_cast(src->alpha); + } + + static void average(B8G8R8A8 *dst, const B8G8R8A8 *src1, const B8G8R8A8 *src2) + { + *(unsigned int*)dst = (((*(unsigned int*)src1 ^ *(unsigned int*)src2) & 0xFEFEFEFE) >> 1) + (*(unsigned int*)src1 & *(unsigned int*)src2); + } +}; + +struct B8G8R8X8 +{ + unsigned char B; + unsigned char G; + unsigned char R; + unsigned char X; + + static void readColor(gl::ColorF *dst, const B8G8R8X8 *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = gl::normalizedToFloat(src->G); + dst->blue = gl::normalizedToFloat(src->B); + dst->alpha = 1.0f; + } + + static void readColor(gl::ColorUI *dst, const B8G8R8X8 *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = src->B; + dst->alpha = 1; + } + + static void writeColor(B8G8R8X8 *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized(src->red); + dst->G = gl::floatToNormalized(src->green); + dst->B = gl::floatToNormalized(src->blue); + dst->X = 255; + } + + static void writeColor(B8G8R8X8 *dst, const gl::ColorUI *src) + { + dst->R = static_cast(src->red); + dst->G = static_cast(src->green); + dst->B = static_cast(src->blue); + dst->X = 255; + } + + static void average(B8G8R8X8 *dst, const B8G8R8X8 *src1, const B8G8R8X8 *src2) + { + *(unsigned int*)dst = (((*(unsigned int*)src1 ^ *(unsigned int*)src2) & 0xFEFEFEFE) >> 1) + (*(unsigned int*)src1 & *(unsigned int*)src2); + dst->X = 255; + } +}; + +struct B5G5R5A1 +{ + unsigned short BGRA; + + static void readColor(gl::ColorF *dst, const B5G5R5A1 *src) + { + dst->alpha = gl::normalizedToFloat<1>(gl::getShiftedData<1, 15>(src->BGRA)); + dst->red = gl::normalizedToFloat<5>(gl::getShiftedData<5, 10>(src->BGRA)); + dst->green = gl::normalizedToFloat<5>(gl::getShiftedData<5, 5>(src->BGRA)); + dst->blue = gl::normalizedToFloat<5>(gl::getShiftedData<5, 0>(src->BGRA)); + } + + static void writeColor(B5G5R5A1 *dst, const gl::ColorF *src) + { + dst->BGRA = gl::shiftData<1, 15>(gl::floatToNormalized<1, unsigned short>(src->alpha)) | + gl::shiftData<5, 10>(gl::floatToNormalized<5, unsigned short>(src->red)) | + gl::shiftData<5, 5>(gl::floatToNormalized<5, unsigned short>(src->green)) | + gl::shiftData<5, 0>(gl::floatToNormalized<5, unsigned short>(src->blue)); + } + + static void average(B5G5R5A1 *dst, const B5G5R5A1 *src1, const B5G5R5A1 *src2) + { + dst->BGRA = gl::shiftData<1, 15>(gl::average(gl::getShiftedData<1, 15>(src1->BGRA), gl::getShiftedData<1, 15>(src2->BGRA))) | + gl::shiftData<5, 10>(gl::average(gl::getShiftedData<5, 10>(src1->BGRA), gl::getShiftedData<5, 10>(src2->BGRA))) | + gl::shiftData<5, 5>(gl::average(gl::getShiftedData<5, 5>(src1->BGRA), gl::getShiftedData<5, 5>(src2->BGRA))) | + gl::shiftData<5, 0>(gl::average(gl::getShiftedData<5, 0>(src1->BGRA), gl::getShiftedData<5, 0>(src2->BGRA))); + } +}; + +struct R5G5B5A1 +{ + unsigned short RGBA; + + static void readColor(gl::ColorF *dst, const R5G5B5A1 *src) + { + dst->alpha = gl::normalizedToFloat<1>(gl::getShiftedData<1, 15>(src->RGBA)); + dst->blue = gl::normalizedToFloat<5>(gl::getShiftedData<5, 10>(src->RGBA)); + dst->green = gl::normalizedToFloat<5>(gl::getShiftedData<5, 5>(src->RGBA)); + dst->red = gl::normalizedToFloat<5>(gl::getShiftedData<5, 0>(src->RGBA)); + } + + static void writeColor(R5G5B5A1 *dst, const gl::ColorF *src) + { + dst->RGBA = gl::shiftData<1, 15>(gl::floatToNormalized<1, unsigned short>(src->alpha)) | + gl::shiftData<5, 10>(gl::floatToNormalized<5, unsigned short>(src->blue)) | + gl::shiftData<5, 5>(gl::floatToNormalized<5, unsigned short>(src->green)) | + gl::shiftData<5, 0>(gl::floatToNormalized<5, unsigned short>(src->red)); + } + + static void average(R5G5B5A1 *dst, const R5G5B5A1 *src1, const R5G5B5A1 *src2) + { + dst->RGBA = gl::shiftData<1, 15>(gl::average(gl::getShiftedData<1, 15>(src1->RGBA), gl::getShiftedData<1, 15>(src2->RGBA))) | + gl::shiftData<5, 10>(gl::average(gl::getShiftedData<5, 10>(src1->RGBA), gl::getShiftedData<5, 10>(src2->RGBA))) | + gl::shiftData<5, 5>(gl::average(gl::getShiftedData<5, 5>(src1->RGBA), gl::getShiftedData<5, 5>(src2->RGBA))) | + gl::shiftData<5, 0>(gl::average(gl::getShiftedData<5, 0>(src1->RGBA), gl::getShiftedData<5, 0>(src2->RGBA))); + } +}; + +struct R4G4B4A4 +{ + unsigned char R : 4; + unsigned char G : 4; + unsigned char B : 4; + unsigned char A : 4; + + static void readColor(gl::ColorF *dst, const R4G4B4A4 *src) + { + dst->red = gl::normalizedToFloat<4>(src->R); + dst->green = gl::normalizedToFloat<4>(src->G); + dst->blue = gl::normalizedToFloat<4>(src->B); + dst->alpha = gl::normalizedToFloat<4>(src->A); + } + + static void writeColor(R4G4B4A4 *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized<4, unsigned char>(src->red); + dst->G = gl::floatToNormalized<4, unsigned char>(src->green); + dst->B = gl::floatToNormalized<4, unsigned char>(src->blue); + dst->A = gl::floatToNormalized<4, unsigned char>(src->alpha); + } + + static void average(R4G4B4A4 *dst, const R4G4B4A4 *src1, const R4G4B4A4 *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + dst->B = gl::average(src1->B, src2->B); + dst->A = gl::average(src1->A, src2->A); + } +}; + +struct A4R4G4B4 +{ + unsigned char A : 4; + unsigned char R : 4; + unsigned char G : 4; + unsigned char B : 4; + + static void readColor(gl::ColorF *dst, const A4R4G4B4 *src) + { + dst->red = gl::normalizedToFloat<4>(src->R); + dst->green = gl::normalizedToFloat<4>(src->G); + dst->blue = gl::normalizedToFloat<4>(src->B); + dst->alpha = gl::normalizedToFloat<4>(src->A); + } + + static void writeColor(A4R4G4B4 *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized<4, unsigned char>(src->red); + dst->G = gl::floatToNormalized<4, unsigned char>(src->green); + dst->B = gl::floatToNormalized<4, unsigned char>(src->blue); + dst->A = gl::floatToNormalized<4, unsigned char>(src->alpha); + } + + static void average(A4R4G4B4 *dst, const A4R4G4B4 *src1, const A4R4G4B4 *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + dst->B = gl::average(src1->B, src2->B); + dst->A = gl::average(src1->A, src2->A); + } +}; + +struct B4G4R4A4 +{ + unsigned char B : 4; + unsigned char G : 4; + unsigned char R : 4; + unsigned char A : 4; + + static void readColor(gl::ColorF *dst, const B4G4R4A4 *src) + { + dst->red = gl::normalizedToFloat<4>(src->R); + dst->green = gl::normalizedToFloat<4>(src->G); + dst->blue = gl::normalizedToFloat<4>(src->B); + dst->alpha = gl::normalizedToFloat<4>(src->A); + } + + static void writeColor(B4G4R4A4 *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized<4, unsigned char>(src->red); + dst->G = gl::floatToNormalized<4, unsigned char>(src->green); + dst->B = gl::floatToNormalized<4, unsigned char>(src->blue); + dst->A = gl::floatToNormalized<4, unsigned char>(src->alpha); + } + + static void average(B4G4R4A4 *dst, const B4G4R4A4 *src1, const B4G4R4A4 *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + dst->B = gl::average(src1->B, src2->B); + dst->A = gl::average(src1->A, src2->A); + } +}; + +struct R16 +{ + unsigned short R; + + static void readColor(gl::ColorF *dst, const R16 *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = 0.0f; + dst->blue = 0.0f; + dst->alpha = 1.0f; + } + + static void readColor(gl::ColorUI *dst, const R16 *src) + { + dst->red = src->R; + dst->green = 0; + dst->blue = 0; + dst->alpha = 1; + } + + static void writeColor(R16 *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized(src->red); + } + + static void writeColor(R16 *dst, const gl::ColorUI *src) + { + dst->R = static_cast(src->red); + } + + static void average(R16 *dst, const R16 *src1, const R16 *src2) + { + dst->R = gl::average(src1->R, src2->R); + } +}; + +struct R16G16 +{ + unsigned short R; + unsigned short G; + + static void readColor(gl::ColorF *dst, const R16G16 *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = gl::normalizedToFloat(src->G); + dst->blue = 0.0f; + dst->alpha = 1.0f; + } + + static void readColor(gl::ColorUI *dst, const R16G16 *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = 0; + dst->alpha = 1; + } + + static void writeColor(R16G16 *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized(src->red); + dst->G = gl::floatToNormalized(src->green); + } + + static void writeColor(R16G16 *dst, const gl::ColorUI *src) + { + dst->R = static_cast(src->red); + dst->G = static_cast(src->green); + } + + static void average(R16G16 *dst, const R16G16 *src1, const R16G16 *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + } +}; + +struct R16G16B16 +{ + unsigned short R; + unsigned short G; + unsigned short B; + + static void readColor(gl::ColorF *dst, const R16G16B16 *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = gl::normalizedToFloat(src->G); + dst->blue = gl::normalizedToFloat(src->B); + dst->alpha = 1.0f; + } + + static void readColor(gl::ColorUI *dst, const R16G16B16 *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = src->B; + dst->alpha = 1; + } + + static void writeColor(R16G16B16 *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized(src->red); + dst->G = gl::floatToNormalized(src->green); + dst->B = gl::floatToNormalized(src->blue); + } + + static void writeColor(R16G16B16 *dst, const gl::ColorUI *src) + { + dst->R = static_cast(src->red); + dst->G = static_cast(src->green); + dst->B = static_cast(src->blue); + } + + static void average(R16G16B16 *dst, const R16G16B16 *src1, const R16G16B16 *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + dst->B = gl::average(src1->B, src2->B); + } +}; + +struct R16G16B16A16 +{ + unsigned short R; + unsigned short G; + unsigned short B; + unsigned short A; + + static void readColor(gl::ColorF *dst, const R16G16B16A16 *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = gl::normalizedToFloat(src->G); + dst->blue = gl::normalizedToFloat(src->B); + dst->alpha = gl::normalizedToFloat(src->A); + } + + static void readColor(gl::ColorUI *dst, const R16G16B16A16 *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = src->B; + dst->alpha = src->A; + } + + static void writeColor(R16G16B16A16 *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized(src->red); + dst->G = gl::floatToNormalized(src->green); + dst->B = gl::floatToNormalized(src->blue); + dst->A = gl::floatToNormalized(src->alpha); + } + + static void writeColor(R16G16B16A16 *dst, const gl::ColorUI *src) + { + dst->R = static_cast(src->red); + dst->G = static_cast(src->green); + dst->B = static_cast(src->blue); + dst->A = static_cast(src->alpha); + } + + static void average(R16G16B16A16 *dst, const R16G16B16A16 *src1, const R16G16B16A16 *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + dst->B = gl::average(src1->B, src2->B); + dst->A = gl::average(src1->A, src2->A); + } +}; + +struct R32 +{ + unsigned int R; + + static void readColor(gl::ColorF *dst, const R32 *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = 0.0f; + dst->blue = 0.0f; + dst->alpha = 1.0f; + } + + static void readColor(gl::ColorUI *dst, const R32 *src) + { + dst->red = src->R; + dst->green = 0; + dst->blue = 0; + dst->alpha = 1; + } + + static void writeColor(R32 *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized(src->red); + } + + static void writeColor(R32 *dst, const gl::ColorUI *src) + { + dst->R = static_cast(src->red); + } + + static void average(R32 *dst, const R32 *src1, const R32 *src2) + { + dst->R = gl::average(src1->R, src2->R); + } +}; + +struct R32G32 +{ + unsigned int R; + unsigned int G; + + static void readColor(gl::ColorF *dst, const R32G32 *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = gl::normalizedToFloat(src->G); + dst->blue = 0.0f; + dst->alpha = 1.0f; + } + + static void readColor(gl::ColorUI *dst, const R32G32 *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = 0; + dst->alpha = 1; + } + + static void writeColor(R32G32 *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized(src->red); + dst->G = gl::floatToNormalized(src->green); + } + + static void writeColor(R32G32 *dst, const gl::ColorUI *src) + { + dst->R = static_cast(src->red); + dst->G = static_cast(src->green); + } + + static void average(R32G32 *dst, const R32G32 *src1, const R32G32 *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + } +}; + +struct R32G32B32 +{ + unsigned int R; + unsigned int G; + unsigned int B; + + static void readColor(gl::ColorF *dst, const R32G32B32 *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = gl::normalizedToFloat(src->G); + dst->blue = gl::normalizedToFloat(src->B); + dst->alpha = 1.0f; + } + + static void readColor(gl::ColorUI *dst, const R32G32B32 *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = src->B; + dst->alpha = 1; + } + + static void writeColor(R32G32B32 *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized(src->red); + dst->G = gl::floatToNormalized(src->green); + dst->B = gl::floatToNormalized(src->blue); + } + + static void writeColor(R32G32B32 *dst, const gl::ColorUI *src) + { + dst->R = static_cast(src->red); + dst->G = static_cast(src->green); + dst->B = static_cast(src->blue); + } + + static void average(R32G32B32 *dst, const R32G32B32 *src1, const R32G32B32 *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + dst->B = gl::average(src1->B, src2->B); + } +}; + +struct R32G32B32A32 +{ + unsigned int R; + unsigned int G; + unsigned int B; + unsigned int A; + + static void readColor(gl::ColorF *dst, const R32G32B32A32 *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = gl::normalizedToFloat(src->G); + dst->blue = gl::normalizedToFloat(src->B); + dst->alpha = gl::normalizedToFloat(src->A); + } + + static void readColor(gl::ColorUI *dst, const R32G32B32A32 *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = src->B; + dst->alpha = src->A; + } + + static void writeColor(R32G32B32A32 *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized(src->red); + dst->G = gl::floatToNormalized(src->green); + dst->B = gl::floatToNormalized(src->blue); + dst->A = gl::floatToNormalized(src->alpha); + } + + static void writeColor(R32G32B32A32 *dst, const gl::ColorUI *src) + { + dst->R = static_cast(src->red); + dst->G = static_cast(src->green); + dst->B = static_cast(src->blue); + dst->A = static_cast(src->alpha); + } + + static void average(R32G32B32A32 *dst, const R32G32B32A32 *src1, const R32G32B32A32 *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + dst->B = gl::average(src1->B, src2->B); + dst->A = gl::average(src1->A, src2->A); + } +}; + +struct R8S +{ + char R; + + static void readColor(gl::ColorF *dst, const R8S *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = 0.0f; + dst->blue = 0.0f; + dst->alpha = 1.0f; + } + + static void readColor(gl::ColorI *dst, const R8S *src) + { + dst->red = src->R; + dst->green = 0; + dst->blue = 0; + dst->alpha = 1; + } + + static void writeColor(R8S *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized(src->red); + } + + static void writeColor(R8S *dst, const gl::ColorI *src) + { + dst->R = static_cast(src->red); + } + + static void average(R8S *dst, const R8S *src1, const R8S *src2) + { + dst->R = gl::average(src1->R, src2->R); + } +}; + +struct R8G8S +{ + char R; + char G; + + static void readColor(gl::ColorF *dst, const R8G8S *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = gl::normalizedToFloat(src->G); + dst->blue = 0.0f; + dst->alpha = 1.0f; + } + + static void readColor(gl::ColorI *dst, const R8G8S *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = 0; + dst->alpha = 1; + } + + static void writeColor(R8G8S *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized(src->red); + dst->G = gl::floatToNormalized(src->green); + } + + static void writeColor(R8G8S *dst, const gl::ColorI *src) + { + dst->R = static_cast(src->red); + dst->G = static_cast(src->green); + } + + static void average(R8G8S *dst, const R8G8S *src1, const R8G8S *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + } +}; + +struct R8G8B8S +{ + char R; + char G; + char B; + + static void readColor(gl::ColorF *dst, const R8G8B8S *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = gl::normalizedToFloat(src->G); + dst->blue = gl::normalizedToFloat(src->B); + dst->alpha = 1.0f; + } + + static void readColor(gl::ColorI *dst, const R8G8B8S *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = src->B; + dst->alpha = 1; + } + + static void writeColor(R8G8B8S *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized(src->red); + dst->G = gl::floatToNormalized(src->green); + dst->B = gl::floatToNormalized(src->blue); + } + + static void writeColor(R8G8B8S *dst, const gl::ColorI *src) + { + dst->R = static_cast(src->red); + dst->G = static_cast(src->green); + dst->B = static_cast(src->blue); + } + + static void average(R8G8B8S *dst, const R8G8B8S *src1, const R8G8B8S *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + dst->B = gl::average(src1->B, src2->B); + } +}; + +struct R8G8B8A8S +{ + char R; + char G; + char B; + char A; + + static void readColor(gl::ColorF *dst, const R8G8B8A8S *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = gl::normalizedToFloat(src->G); + dst->blue = gl::normalizedToFloat(src->B); + dst->alpha = gl::normalizedToFloat(src->A); + } + + static void readColor(gl::ColorI *dst, const R8G8B8A8S *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = src->B; + dst->alpha = src->A; + } + + static void writeColor(R8G8B8A8S *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized(src->red); + dst->G = gl::floatToNormalized(src->green); + dst->B = gl::floatToNormalized(src->blue); + dst->A = gl::floatToNormalized(src->alpha); + } + + static void writeColor(R8G8B8A8S *dst, const gl::ColorI *src) + { + dst->R = static_cast(src->red); + dst->G = static_cast(src->green); + dst->B = static_cast(src->blue); + dst->A = static_cast(src->alpha); + } + + static void average(R8G8B8A8S *dst, const R8G8B8A8S *src1, const R8G8B8A8S *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + dst->B = gl::average(src1->B, src2->B); + dst->A = gl::average(src1->A, src2->A); + } +}; + +struct R16S +{ + short R; + + static void readColor(gl::ColorF *dst, const R16S *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = 0.0f; + dst->blue = 0.0f; + dst->alpha = 1.0f; + } + + static void readColor(gl::ColorI *dst, const R16S *src) + { + dst->red = src->R; + dst->green = 0; + dst->blue = 0; + dst->alpha = 1; + } + + static void writeColor(R16S *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized(src->red); + } + + static void writeColor(R16S *dst, const gl::ColorI *src) + { + dst->R = static_cast(src->red); + } + + static void average(R16S *dst, const R16S *src1, const R16S *src2) + { + dst->R = gl::average(src1->R, src2->R); + } +}; + +struct R16G16S +{ + short R; + short G; + + static void readColor(gl::ColorF *dst, const R16G16S *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = gl::normalizedToFloat(src->G); + dst->blue = 0.0f; + dst->alpha = 1.0f; + } + + static void readColor(gl::ColorI *dst, const R16G16S *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = 0; + dst->alpha = 1; + } + + static void writeColor(R16G16S *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized(src->red); + dst->G = gl::floatToNormalized(src->green); + } + + static void writeColor(R16G16S *dst, const gl::ColorI *src) + { + dst->R = static_cast(src->red); + dst->G = static_cast(src->green); + } + + static void average(R16G16S *dst, const R16G16S *src1, const R16G16S *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + } +}; + +struct R16G16B16S +{ + short R; + short G; + short B; + + static void readColor(gl::ColorF *dst, const R16G16B16S *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = gl::normalizedToFloat(src->G); + dst->blue = gl::normalizedToFloat(src->B); + dst->alpha = 1.0f; + } + + static void readColor(gl::ColorI *dst, const R16G16B16S *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = src->B; + dst->alpha = 1; + } + + static void writeColor(R16G16B16S *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized(src->red); + dst->G = gl::floatToNormalized(src->green); + dst->B = gl::floatToNormalized(src->blue); + } + + static void writeColor(R16G16B16S *dst, const gl::ColorI *src) + { + dst->R = static_cast(src->red); + dst->G = static_cast(src->green); + dst->B = static_cast(src->blue); + } + + static void average(R16G16B16S *dst, const R16G16B16S *src1, const R16G16B16S *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + dst->B = gl::average(src1->B, src2->B); + } +}; + +struct R16G16B16A16S +{ + short R; + short G; + short B; + short A; + + static void readColor(gl::ColorF *dst, const R16G16B16A16S *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = gl::normalizedToFloat(src->G); + dst->blue = gl::normalizedToFloat(src->B); + dst->alpha = gl::normalizedToFloat(src->A); + } + + static void readColor(gl::ColorI *dst, const R16G16B16A16S *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = src->B; + dst->alpha = src->A; + } + + static void writeColor(R16G16B16A16S *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized(src->red); + dst->G = gl::floatToNormalized(src->green); + dst->B = gl::floatToNormalized(src->blue); + dst->A = gl::floatToNormalized(src->alpha); + } + + static void writeColor(R16G16B16A16S *dst, const gl::ColorI *src) + { + dst->R = static_cast(src->red); + dst->G = static_cast(src->green); + dst->B = static_cast(src->blue); + dst->A = static_cast(src->alpha); + } + + static void average(R16G16B16A16S *dst, const R16G16B16A16S *src1, const R16G16B16A16S *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + dst->B = gl::average(src1->B, src2->B); + dst->A = gl::average(src1->A, src2->A); + } +}; + +struct R32S +{ + int R; + + static void readColor(gl::ColorF *dst, const R32S *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = 0.0f; + dst->blue = 0.0f; + dst->alpha = 1.0f; + } + + static void readColor(gl::ColorI *dst, const R32S *src) + { + dst->red = src->R; + dst->green = 0; + dst->blue = 0; + dst->alpha = 1; + } + + static void writeColor(R32S *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized(src->red); + } + + static void writeColor(R32S *dst, const gl::ColorI *src) + { + dst->R = static_cast(src->red); + } + + static void average(R32S *dst, const R32S *src1, const R32S *src2) + { + dst->R = gl::average(src1->R, src2->R); + } +}; + +struct R32G32S +{ + int R; + int G; + + static void readColor(gl::ColorF *dst, const R32G32S *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = gl::normalizedToFloat(src->G); + dst->blue = 0.0f; + dst->alpha = 1.0f; + } + + static void readColor(gl::ColorI *dst, const R32G32S *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = 0; + dst->alpha = 1; + } + + static void writeColor(R32G32S *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized(src->red); + dst->G = gl::floatToNormalized(src->green); + } + + static void writeColor(R32G32S *dst, const gl::ColorI *src) + { + dst->R = static_cast(src->red); + dst->G = static_cast(src->green); + } + + static void average(R32G32S *dst, const R32G32S *src1, const R32G32S *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + } +}; + +struct R32G32B32S +{ + int R; + int G; + int B; + + static void readColor(gl::ColorF *dst, const R32G32B32S *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = gl::normalizedToFloat(src->G); + dst->blue = gl::normalizedToFloat(src->B); + dst->alpha = 1.0f; + } + + static void readColor(gl::ColorI *dst, const R32G32B32S *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = src->B; + dst->alpha = 1; + } + + static void writeColor(R32G32B32S *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized(src->red); + dst->G = gl::floatToNormalized(src->green); + dst->B = gl::floatToNormalized(src->blue); + } + + static void writeColor(R32G32B32S *dst, const gl::ColorI *src) + { + dst->R = static_cast(src->red); + dst->G = static_cast(src->green); + dst->B = static_cast(src->blue); + } + + static void average(R32G32B32S *dst, const R32G32B32S *src1, const R32G32B32S *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + dst->B = gl::average(src1->B, src2->B); + } +}; + +struct R32G32B32A32S +{ + int R; + int G; + int B; + int A; + + static void readColor(gl::ColorF *dst, const R32G32B32A32S *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = gl::normalizedToFloat(src->G); + dst->blue = gl::normalizedToFloat(src->B); + dst->alpha = gl::normalizedToFloat(src->A); + } + + static void readColor(gl::ColorI *dst, const R32G32B32A32S *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = src->B; + dst->alpha = src->A; + } + + static void writeColor(R32G32B32A32S *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized(src->red); + dst->G = gl::floatToNormalized(src->green); + dst->B = gl::floatToNormalized(src->blue); + dst->A = gl::floatToNormalized(src->alpha); + } + + static void writeColor(R32G32B32A32S *dst, const gl::ColorI *src) + { + dst->R = static_cast(src->red); + dst->G = static_cast(src->green); + dst->B = static_cast(src->blue); + dst->A = static_cast(src->alpha); + } + + static void average(R32G32B32A32S *dst, const R32G32B32A32S *src1, const R32G32B32A32S *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + dst->B = gl::average(src1->B, src2->B); + dst->A = gl::average(src1->A, src2->A); + } +}; + +struct A16B16G16R16F +{ + unsigned short A; + unsigned short R; + unsigned short G; + unsigned short B; + + static void readColor(gl::ColorF *dst, const A16B16G16R16F *src) + { + dst->red = gl::float16ToFloat32(src->R); + dst->green = gl::float16ToFloat32(src->G); + dst->blue = gl::float16ToFloat32(src->B); + dst->alpha = gl::float16ToFloat32(src->A); + } + + static void writeColor(A16B16G16R16F *dst, const gl::ColorF *src) + { + dst->R = gl::float32ToFloat16(src->red); + dst->G = gl::float32ToFloat16(src->green); + dst->B = gl::float32ToFloat16(src->blue); + dst->A = gl::float32ToFloat16(src->alpha); + } + + static void average(A16B16G16R16F *dst, const A16B16G16R16F *src1, const A16B16G16R16F *src2) + { + dst->R = gl::averageHalfFloat(src1->R, src2->R); + dst->G = gl::averageHalfFloat(src1->G, src2->G); + dst->B = gl::averageHalfFloat(src1->B, src2->B); + dst->A = gl::averageHalfFloat(src1->A, src2->A); + } +}; + +struct R16G16B16A16F +{ + unsigned short R; + unsigned short G; + unsigned short B; + unsigned short A; + + static void readColor(gl::ColorF *dst, const R16G16B16A16F *src) + { + dst->red = gl::float16ToFloat32(src->R); + dst->green = gl::float16ToFloat32(src->G); + dst->blue = gl::float16ToFloat32(src->B); + dst->alpha = gl::float16ToFloat32(src->A); + } + + static void writeColor(R16G16B16A16F *dst, const gl::ColorF *src) + { + dst->R = gl::float32ToFloat16(src->red); + dst->G = gl::float32ToFloat16(src->green); + dst->B = gl::float32ToFloat16(src->blue); + dst->A = gl::float32ToFloat16(src->alpha); + } + + static void average(R16G16B16A16F *dst, const R16G16B16A16F *src1, const R16G16B16A16F *src2) + { + dst->R = gl::averageHalfFloat(src1->R, src2->R); + dst->G = gl::averageHalfFloat(src1->G, src2->G); + dst->B = gl::averageHalfFloat(src1->B, src2->B); + dst->A = gl::averageHalfFloat(src1->A, src2->A); + } +}; + +struct R16F +{ + unsigned short R; + + static void readColor(gl::ColorF *dst, const R16F *src) + { + dst->red = gl::float16ToFloat32(src->R); + dst->green = 0.0f; + dst->blue = 0.0f; + dst->alpha = 1.0f; + } + + static void writeColor(R16F *dst, const gl::ColorF *src) + { + dst->R = gl::float32ToFloat16(src->red); + } + + static void average(R16F *dst, const R16F *src1, const R16F *src2) + { + dst->R = gl::averageHalfFloat(src1->R, src2->R); + } +}; + +struct A16F +{ + unsigned short A; + + static void readColor(gl::ColorF *dst, const A16F *src) + { + dst->red = 0.0f; + dst->green = 0.0f; + dst->blue = 0.0f; + dst->alpha = gl::float16ToFloat32(src->A); + } + + static void writeColor(A16F *dst, const gl::ColorF *src) + { + dst->A = gl::float32ToFloat16(src->alpha); + } + + static void average(A16F *dst, const A16F *src1, const A16F *src2) + { + dst->A = gl::averageHalfFloat(src1->A, src2->A); + } +}; + +struct L16F +{ + unsigned short L; + + static void readColor(gl::ColorF *dst, const L16F *src) + { + float lum = gl::float16ToFloat32(src->L); + dst->red = lum; + dst->green = lum; + dst->blue = lum; + dst->alpha = 1.0f; + } + + static void writeColor(L16F *dst, const gl::ColorF *src) + { + dst->L = gl::float32ToFloat16((src->red + src->green + src->blue) / 3.0f); + } + + static void average(L16F *dst, const L16F *src1, const L16F *src2) + { + dst->L = gl::averageHalfFloat(src1->L, src2->L); + } +}; + +struct L16A16F +{ + unsigned short L; + unsigned short A; + + static void readColor(gl::ColorF *dst, const L16A16F *src) + { + float lum = gl::float16ToFloat32(src->L); + dst->red = lum; + dst->green = lum; + dst->blue = lum; + dst->alpha = gl::float16ToFloat32(src->A); + } + + static void writeColor(L16A16F *dst, const gl::ColorF *src) + { + dst->L = gl::float32ToFloat16((src->red + src->green + src->blue) / 3.0f); + dst->A = gl::float32ToFloat16(src->alpha); + } + + static void average(L16A16F *dst, const L16A16F *src1, const L16A16F *src2) + { + dst->L = gl::averageHalfFloat(src1->L, src2->L); + dst->A = gl::averageHalfFloat(src1->A, src2->A); + } +}; + +struct R16G16F +{ + unsigned short R; + unsigned short G; + + static void readColor(gl::ColorF *dst, const R16G16F *src) + { + dst->red = gl::float16ToFloat32(src->R); + dst->green = gl::float16ToFloat32(src->G); + dst->blue = 0.0f; + dst->alpha = 1.0f; + } + + static void writeColor(R16G16F *dst, const gl::ColorF *src) + { + dst->R = gl::float32ToFloat16(src->red); + dst->G = gl::float32ToFloat16(src->green); + } + + static void average(R16G16F *dst, const R16G16F *src1, const R16G16F *src2) + { + dst->R = gl::averageHalfFloat(src1->R, src2->R); + dst->G = gl::averageHalfFloat(src1->G, src2->G); + } +}; + +struct R16G16B16F +{ + unsigned short R; + unsigned short G; + unsigned short B; + + static void readColor(gl::ColorF *dst, const R16G16B16F *src) + { + dst->red = gl::float16ToFloat32(src->R); + dst->green = gl::float16ToFloat32(src->G); + dst->blue = gl::float16ToFloat32(src->B); + dst->alpha = 1.0f; + } + + static void writeColor(R16G16B16F *dst, const gl::ColorF *src) + { + dst->R = gl::float32ToFloat16(src->red); + dst->G = gl::float32ToFloat16(src->green); + dst->B = gl::float32ToFloat16(src->blue); + } + + static void average(R16G16B16F *dst, const R16G16B16F *src1, const R16G16B16F *src2) + { + dst->R = gl::averageHalfFloat(src1->R, src2->R); + dst->G = gl::averageHalfFloat(src1->G, src2->G); + dst->B = gl::averageHalfFloat(src1->B, src2->B); + } +}; + +struct A32B32G32R32F +{ + float A; + float R; + float G; + float B; + + static void readColor(gl::ColorF *dst, const A32B32G32R32F *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = src->B; + dst->alpha = src->A; + } + + static void writeColor(A32B32G32R32F *dst, const gl::ColorF *src) + { + dst->R = src->red; + dst->G = src->green; + dst->B = src->blue; + dst->A = src->alpha; + } + + static void average(A32B32G32R32F *dst, const A32B32G32R32F *src1, const A32B32G32R32F *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + dst->B = gl::average(src1->B, src2->B); + dst->A = gl::average(src1->A, src2->A); + } +}; + +struct R32G32B32A32F +{ + float R; + float G; + float B; + float A; + + static void readColor(gl::ColorF *dst, const R32G32B32A32F *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = src->B; + dst->alpha = src->A; + } + + static void writeColor(R32G32B32A32F *dst, const gl::ColorF *src) + { + dst->R = src->red; + dst->G = src->green; + dst->B = src->blue; + dst->A = src->alpha; + } + + static void average(R32G32B32A32F *dst, const R32G32B32A32F *src1, const R32G32B32A32F *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + dst->B = gl::average(src1->B, src2->B); + dst->A = gl::average(src1->A, src2->A); + } +}; + +struct R32F +{ + float R; + + static void readColor(gl::ColorF *dst, const R32F *src) + { + dst->red = src->R; + dst->green = 0.0f; + dst->blue = 0.0f; + dst->alpha = 1.0f; + } + + static void writeColor(R32F *dst, const gl::ColorF *src) + { + dst->R = src->red; + } + + static void average(R32F *dst, const R32F *src1, const R32F *src2) + { + dst->R = gl::average(src1->R, src2->R); + } +}; + +struct A32F +{ + float A; + + static void readColor(gl::ColorF *dst, const A32F *src) + { + dst->red = 0.0f; + dst->green = 0.0f; + dst->blue = 0.0f; + dst->alpha = src->A; + } + + static void writeColor(A32F *dst, const gl::ColorF *src) + { + dst->A = src->alpha; + } + + static void average(A32F *dst, const A32F *src1, const A32F *src2) + { + dst->A = gl::average(src1->A, src2->A); + } +}; + +struct L32F +{ + float L; + + static void readColor(gl::ColorF *dst, const L32F *src) + { + dst->red = src->L; + dst->green = src->L; + dst->blue = src->L; + dst->alpha = 1.0f; + } + + static void writeColor(L32F *dst, const gl::ColorF *src) + { + dst->L = (src->red + src->green + src->blue) / 3.0f; + } + + static void average(L32F *dst, const L32F *src1, const L32F *src2) + { + dst->L = gl::average(src1->L, src2->L); + } +}; + +struct L32A32F +{ + float L; + float A; + + static void readColor(gl::ColorF *dst, const L32A32F *src) + { + dst->red = src->L; + dst->green = src->L; + dst->blue = src->L; + dst->alpha = src->A; + } + + static void writeColor(L32A32F *dst, const gl::ColorF *src) + { + dst->L = (src->red + src->green + src->blue) / 3.0f; + dst->A = src->alpha; + } + + static void average(L32A32F *dst, const L32A32F *src1, const L32A32F *src2) + { + dst->L = gl::average(src1->L, src2->L); + dst->A = gl::average(src1->A, src2->A); + } +}; + +struct R32G32F +{ + float R; + float G; + + static void readColor(gl::ColorF *dst, const R32G32F *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = 0.0f; + dst->alpha = 1.0f; + } + + static void writeColor(R32G32F *dst, const gl::ColorF *src) + { + dst->R = src->red; + dst->G = src->green; + } + + static void average(R32G32F *dst, const R32G32F *src1, const R32G32F *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + } +}; + +struct R32G32B32F +{ + float R; + float G; + float B; + + static void readColor(gl::ColorF *dst, const R32G32B32F *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = src->B; + dst->alpha = 1.0f; + } + + static void writeColor(R32G32B32F *dst, const gl::ColorF *src) + { + dst->R = src->red; + dst->G = src->green; + dst->B = src->blue; + } + + static void average(R32G32B32F *dst, const R32G32B32F *src1, const R32G32B32F *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + dst->B = gl::average(src1->B, src2->B); + } +}; + +struct R10G10B10A2 +{ + unsigned int R : 10; + unsigned int G : 10; + unsigned int B : 10; + unsigned int A : 2; + + static void readColor(gl::ColorF *dst, const R10G10B10A2 *src) + { + dst->red = gl::normalizedToFloat<10>(src->R); + dst->green = gl::normalizedToFloat<10>(src->G); + dst->blue = gl::normalizedToFloat<10>(src->B); + dst->alpha = gl::normalizedToFloat< 2>(src->A); + } + + static void readColor(gl::ColorUI *dst, const R10G10B10A2 *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = src->B; + dst->alpha = src->A; + } + + static void writeColor(R10G10B10A2 *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized<10, unsigned int>(src->red); + dst->G = gl::floatToNormalized<10, unsigned int>(src->green); + dst->B = gl::floatToNormalized<10, unsigned int>(src->blue); + dst->A = gl::floatToNormalized< 2, unsigned int>(src->alpha); + } + + static void writeColor(R10G10B10A2 *dst, const gl::ColorUI *src) + { + dst->R = static_cast(src->red); + dst->G = static_cast(src->green); + dst->B = static_cast(src->blue); + dst->A = static_cast(src->alpha); + } + + static void average(R10G10B10A2 *dst, const R10G10B10A2 *src1, const R10G10B10A2 *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + dst->B = gl::average(src1->B, src2->B); + dst->A = gl::average(src1->A, src2->A); + } +}; + +struct R9G9B9E5 +{ + unsigned int R : 9; + unsigned int G : 9; + unsigned int B : 9; + unsigned int E : 5; + + static void readColor(gl::ColorF *dst, const R9G9B9E5 *src) + { + gl::convert999E5toRGBFloats(gl::bitCast(*src), &dst->red, &dst->green, &dst->blue); + dst->alpha = 1.0f; + } + + static void writeColor(R9G9B9E5 *dst, const gl::ColorF *src) + { + *reinterpret_cast(dst) = gl::convertRGBFloatsTo999E5(src->red, + src->green, + src->blue); + } + + static void average(R9G9B9E5 *dst, const R9G9B9E5 *src1, const R9G9B9E5 *src2) + { + float r1, g1, b1; + gl::convert999E5toRGBFloats(*reinterpret_cast(src1), &r1, &g1, &b1); + + float r2, g2, b2; + gl::convert999E5toRGBFloats(*reinterpret_cast(src2), &r2, &g2, &b2); + + *reinterpret_cast(dst) = gl::convertRGBFloatsTo999E5(gl::average(r1, r2), + gl::average(g1, g2), + gl::average(b1, b2)); + } +}; + +struct R11G11B10F +{ + unsigned int R : 11; + unsigned int G : 11; + unsigned int B : 10; + + static void readColor(gl::ColorF *dst, const R11G11B10F *src) + { + dst->red = gl::float11ToFloat32(src->R); + dst->green = gl::float11ToFloat32(src->G); + dst->blue = gl::float10ToFloat32(src->B); + dst->alpha = 1.0f; + } + + static void writeColor(R11G11B10F *dst, const gl::ColorF *src) + { + dst->R = gl::float32ToFloat11(src->red); + dst->G = gl::float32ToFloat11(src->green); + dst->B = gl::float32ToFloat10(src->blue); + } + + static void average(R11G11B10F *dst, const R11G11B10F *src1, const R11G11B10F *src2) + { + dst->R = gl::averageFloat11(src1->R, src2->R); + dst->G = gl::averageFloat11(src1->G, src2->G); + dst->B = gl::averageFloat10(src1->B, src2->B); + } +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_IMAGEFORMATS_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage.cpp new file mode 100644 index 0000000000..172832b3e7 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage.cpp @@ -0,0 +1,662 @@ +// +// Copyright (c) 2013-2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// loadimage.cpp: Defines image loading functions. + +#include "libANGLE/renderer/d3d/loadimage.h" + +namespace rx +{ + +void LoadA8ToRGBA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint8_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint32_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + dest[x] = static_cast(source[x]) << 24; + } + } + } +} + +void LoadA8ToBGRA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + // Same as loading to RGBA + LoadA8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output, outputRowPitch, outputDepthPitch); +} + +void LoadA32FToRGBA32F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const float *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + float *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + dest[4 * x + 0] = 0.0f; + dest[4 * x + 1] = 0.0f; + dest[4 * x + 2] = 0.0f; + dest[4 * x + 3] = source[x]; + } + } + } +} + +void LoadA16FToRGBA16F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint16_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint16_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t 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 LoadL8ToRGBA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint8_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint8_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + uint8_t sourceVal = source[x]; + dest[4 * x + 0] = sourceVal; + dest[4 * x + 1] = sourceVal; + dest[4 * x + 2] = sourceVal; + dest[4 * x + 3] = 0xFF; + } + } + } +} + +void LoadL8ToBGRA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + // Same as loading to RGBA + LoadL8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output, outputRowPitch, outputDepthPitch); +} + +void LoadL32FToRGBA32F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const float *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + float *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t 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 LoadL16FToRGBA16F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint16_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint16_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t 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] = gl::Float16One; + } + } + } +} + +void LoadLA8ToRGBA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint8_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint8_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t 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 LoadLA8ToBGRA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + // Same as loading to RGBA + LoadLA8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output, outputRowPitch, outputDepthPitch); +} + +void LoadLA32FToRGBA32F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const float *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + float *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t 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 LoadLA16FToRGBA16F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint16_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint16_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t 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 LoadRGB8ToBGRX8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint8_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint8_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t 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 LoadRG8ToBGRX8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint8_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint8_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + dest[4 * x + 0] = 0x00; + dest[4 * x + 1] = source[x * 2 + 1]; + dest[4 * x + 2] = source[x * 2 + 0]; + dest[4 * x + 3] = 0xFF; + } + } + } +} + +void LoadR8ToBGRX8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint8_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint8_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + dest[4 * x + 0] = 0x00; + dest[4 * x + 1] = 0x00; + dest[4 * x + 2] = source[x]; + dest[4 * x + 3] = 0xFF; + } + } + } +} + +void LoadR5G6B5ToBGRA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint16_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint8_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + uint16_t rgb = source[x]; + dest[4 * x + 0] = ((rgb & 0x001F) << 3) | ((rgb & 0x001F) >> 2); + dest[4 * x + 1] = ((rgb & 0x07E0) >> 3) | ((rgb & 0x07E0) >> 9); + dest[4 * x + 2] = ((rgb & 0xF800) >> 8) | ((rgb & 0xF800) >> 13); + dest[4 * x + 3] = 0xFF; + } + } + } +} + +void LoadR5G6B5ToRGBA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint16_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint8_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + uint16_t rgb = source[x]; + dest[4 * x + 0] = ((rgb & 0xF800) >> 8) | ((rgb & 0xF800) >> 13); + dest[4 * x + 1] = ((rgb & 0x07E0) >> 3) | ((rgb & 0x07E0) >> 9); + dest[4 * x + 2] = ((rgb & 0x001F) << 3) | ((rgb & 0x001F) >> 2); + dest[4 * x + 3] = 0xFF; + } + } + } +} + +void LoadRGBA8ToBGRA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint32_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint32_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + uint32_t rgba = source[x]; + dest[x] = (ANGLE_ROTL(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00); + } + } + } +} + +void LoadRGBA4ToBGRA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint16_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint8_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + uint16_t 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 LoadRGBA4ToRGBA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint16_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint8_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + uint16_t 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 LoadBGRA4ToBGRA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint16_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint8_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + uint16_t bgra = source[x]; + dest[4 * x + 0] = ((bgra & 0xF000) >> 8) | ((bgra & 0xF000) >> 12); + dest[4 * x + 1] = ((bgra & 0x0F00) >> 4) | ((bgra & 0x0F00) >> 8); + dest[4 * x + 2] = ((bgra & 0x00F0) << 0) | ((bgra & 0x00F0) >> 4); + dest[4 * x + 3] = ((bgra & 0x000F) << 4) | ((bgra & 0x000F) >> 0); + } + } + } +} + +void LoadRGB5A1ToBGRA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint16_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint8_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + uint16_t 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 LoadRGB5A1ToRGBA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint16_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint8_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + uint16_t 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 LoadBGR5A1ToBGRA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint16_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint8_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + uint16_t bgra = source[x]; + dest[4 * x + 0] = ((bgra & 0xF800) >> 8) | ((bgra & 0xF800) >> 13); + dest[4 * x + 1] = ((bgra & 0x07C0) >> 3) | ((bgra & 0x07C0) >> 8); + dest[4 * x + 2] = ((bgra & 0x003E) << 2) | ((bgra & 0x003E) >> 3); + dest[4 * x + 3] = (bgra & 0x0001) ? 0xFF : 0; + } + } + } +} + +void LoadRGB10A2ToRGBA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint32_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint8_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + uint32_t rgba = source[x]; + dest[4 * x + 0] = (rgba & 0x000003FF) >> 2; + dest[4 * x + 1] = (rgba & 0x000FFC00) >> 12; + dest[4 * x + 2] = (rgba & 0x3FF00000) >> 22; + dest[4 * x + 3] = ((rgba & 0xC0000000) >> 30) * 0x55; + } + } + } +} + +void LoadRGB16FToRGB9E5(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint16_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint32_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + dest[x] = gl::convertRGBFloatsTo999E5(gl::float16ToFloat32(source[x * 3 + 0]), + gl::float16ToFloat32(source[x * 3 + 1]), + gl::float16ToFloat32(source[x * 3 + 2])); + } + } + } +} + +void LoadRGB32FToRGB9E5(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const float *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint32_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + dest[x] = gl::convertRGBFloatsTo999E5(source[x * 3 + 0], source[x * 3 + 1], source[x * 3 + 2]); + } + } + } +} + +void LoadRGB16FToRG11B10F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint16_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint32_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + dest[x] = (gl::float32ToFloat11(gl::float16ToFloat32(source[x * 3 + 0])) << 0) | + (gl::float32ToFloat11(gl::float16ToFloat32(source[x * 3 + 1])) << 11) | + (gl::float32ToFloat10(gl::float16ToFloat32(source[x * 3 + 2])) << 22); + } + } + } +} + +void LoadRGB32FToRG11B10F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const float *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint32_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + dest[x] = (gl::float32ToFloat11(source[x * 3 + 0]) << 0) | + (gl::float32ToFloat11(source[x * 3 + 1]) << 11) | + (gl::float32ToFloat10(source[x * 3 + 2]) << 22); + } + } + } +} + +void LoadG8R24ToR24G8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint32_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint32_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + uint32_t d = source[x] >> 8; + uint8_t s = source[x] & 0xFF; + dest[x] = d | (s << 24); + } + } + } +} + +void LoadRGB32FToRGBA16F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const float *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint16_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + dest[x * 4 + 0] = gl::float32ToFloat16(source[x * 3 + 0]); + dest[x * 4 + 1] = gl::float32ToFloat16(source[x * 3 + 1]); + dest[x * 4 + 2] = gl::float32ToFloat16(source[x * 3 + 2]); + dest[x * 4 + 3] = gl::Float16One; + } + } + } +} + +void LoadR32ToR16(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint32_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint16_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + dest[x] = source[x] >> 16; + } + } + } +} + +void LoadR32ToR24G8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint32_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint32_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + + for (size_t x = 0; x < width; x++) + { + dest[x] = source[x] >> 8; + } + } + } +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage.h new file mode 100644 index 0000000000..6967dc868e --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage.h @@ -0,0 +1,193 @@ +// +// Copyright (c) 2013-2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// loadimage.h: Defines image loading functions + +#ifndef LIBANGLE_RENDERER_D3D_LOADIMAGE_H_ +#define LIBANGLE_RENDERER_D3D_LOADIMAGE_H_ + +#include "libANGLE/angletypes.h" + +#include + +namespace rx +{ + +void LoadA8ToRGBA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadA8ToBGRA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadA8ToBGRA8_SSE2(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadA32FToRGBA32F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadA16FToRGBA16F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadL8ToRGBA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadL8ToBGRA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadL32FToRGBA32F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadL16FToRGBA16F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadLA8ToRGBA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadLA8ToBGRA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadLA32FToRGBA32F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadLA16FToRGBA16F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadRGB8ToBGRX8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadRG8ToBGRX8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadR8ToBGRX8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadR5G6B5ToBGRA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadR5G6B5ToRGBA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadRGBA8ToBGRA8_SSE2(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadRGBA8ToBGRA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadRGBA4ToBGRA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadRGBA4ToRGBA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadBGRA4ToBGRA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadRGB5A1ToBGRA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadRGB5A1ToRGBA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadBGR5A1ToBGRA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadRGB10A2ToRGBA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadRGB16FToRGB9E5(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadRGB32FToRGB9E5(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadRGB16FToRG11B10F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadRGB32FToRG11B10F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadG8R24ToR24G8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +template +inline void LoadToNative(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +template +inline void LoadToNative3To4(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +template +inline void Load32FTo16F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadRGB32FToRGBA16F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +template +inline void LoadCompressedToNative(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadR32ToR16(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +template +inline void Initialize4ComponentData(size_t width, size_t height, size_t depth, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadR32ToR24G8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +template +inline T *OffsetDataPointer(uint8_t *data, size_t y, size_t z, size_t rowPitch, size_t depthPitch); + +template +inline const T *OffsetDataPointer(const uint8_t *data, size_t y, size_t z, size_t rowPitch, size_t depthPitch); + +} + +#include "loadimage.inl" + +#endif // LIBANGLE_RENDERER_D3D_LOADIMAGE_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage.inl b/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage.inl new file mode 100644 index 0000000000..920e667db1 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage.inl @@ -0,0 +1,156 @@ +// +// Copyright (c) 2014-2015 The ANGLE Project 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 "common/mathutil.h" + +namespace rx +{ + +template +inline T *OffsetDataPointer(uint8_t *data, size_t y, size_t z, size_t rowPitch, size_t depthPitch) +{ + return reinterpret_cast(data + (y * rowPitch) + (z * depthPitch)); +} + +template +inline const T *OffsetDataPointer(const uint8_t *data, size_t y, size_t z, size_t rowPitch, size_t depthPitch) +{ + return reinterpret_cast(data + (y * rowPitch) + (z * depthPitch)); +} + +template +inline void LoadToNative(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + const size_t rowSize = width * sizeof(type) * componentCount; + const size_t layerSize = rowSize * height; + const size_t imageSize = layerSize * depth; + + if (layerSize == inputDepthPitch && layerSize == outputDepthPitch) + { + ASSERT(rowSize == inputRowPitch && rowSize == outputRowPitch); + memcpy(output, input, imageSize); + } + else if (rowSize == inputRowPitch && rowSize == outputRowPitch) + { + for (size_t z = 0; z < depth; z++) + { + const type *source = OffsetDataPointer(input, 0, z, inputRowPitch, inputDepthPitch); + type *dest = OffsetDataPointer(output, 0, z, outputRowPitch, outputDepthPitch); + + memcpy(dest, source, layerSize); + } + } + else + { + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const type *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + type *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + memcpy(dest, source, width * sizeof(type) * componentCount); + } + } + } +} + +template +inline void LoadToNative3To4(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + const type fourthValue = gl::bitCast(fourthComponentBits); + + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const type *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + type *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + dest[x * 4 + 0] = source[x * 3 + 0]; + dest[x * 4 + 1] = source[x * 3 + 1]; + dest[x * 4 + 2] = source[x * 3 + 2]; + dest[x * 4 + 3] = fourthValue; + } + } + } +} + +template +inline void Load32FTo16F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + const size_t elementWidth = componentCount * width; + + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const float *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint16_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + + for (size_t x = 0; x < elementWidth; x++) + { + dest[x] = gl::float32ToFloat16(source[x]); + } + } + } +} + +template +inline void LoadCompressedToNative(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + const size_t columns = (width + (blockWidth - 1)) / blockWidth; + const size_t rows = (height + (blockHeight - 1)) / blockHeight; + + for (size_t z = 0; z < depth; ++z) + { + for (size_t y = 0; y < rows; ++y) + { + const uint8_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint8_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + memcpy(dest, source, columns * blockSize); + } + } +} + +template +inline void Initialize4ComponentData(size_t width, size_t height, size_t depth, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + type writeValues[4] = + { + gl::bitCast(firstBits), + gl::bitCast(secondBits), + gl::bitCast(thirdBits), + gl::bitCast(fourthBits), + }; + + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + type *destRow = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + type* destPixel = destRow + x * 4; + + // This could potentially be optimized by generating an entire row of initialization + // data and copying row by row instead of pixel by pixel. + memcpy(destPixel, writeValues, sizeof(type) * 4); + } + } + } +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimageSSE2.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimageSSE2.cpp new file mode 100644 index 0000000000..c87d35c82b --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimageSSE2.cpp @@ -0,0 +1,125 @@ +// +// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// loadimageSSE2.cpp: Defines image loading functions. 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 "libANGLE/renderer/d3d/loadimage.h" + +#include "common/platform.h" + +#ifdef ANGLE_USE_SSE +#include +#endif + +namespace rx +{ + +void LoadA8ToBGRA8_SSE2(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ +#if defined(ANGLE_USE_SSE) + __m128i zeroWide = _mm_setzero_si128(); + + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint8_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint32_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + + size_t x = 0; + + // Make output writes aligned + for (; ((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; + } + } + } +#else + // Ensure that this function is reported as not implemented for ARM builds because + // the instructions below are not present for that architecture. + UNIMPLEMENTED(); + return; +#endif +} + +void LoadRGBA8ToBGRA8_SSE2(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ +#if defined(ANGLE_USE_SSE) + __m128i brMask = _mm_set1_epi32(0x00ff00ff); + + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint32_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint32_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + + size_t x = 0; + + // Make output writes aligned + for (; ((reinterpret_cast(&dest[x]) & 15) != 0) && x < width; x++) + { + uint32_t rgba = source[x]; + dest[x] = (ANGLE_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++) + { + uint32_t rgba = source[x]; + dest[x] = (ANGLE_ROTL(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00); + } + } + } +#else + // Ensure that this function is reported as not implemented for ARM builds because + // the instructions below are not present for that architecture. + UNIMPLEMENTED(); + return; +#endif +} + +} + diff --git a/src/3rdparty/angle/src/libANGLE/validationEGL.cpp b/src/3rdparty/angle/src/libANGLE/validationEGL.cpp new file mode 100644 index 0000000000..12ee6a2b93 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/validationEGL.cpp @@ -0,0 +1,503 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// validationEGL.cpp: Validation functions for generic EGL entry point parameters + +#include "libANGLE/validationEGL.h" + +#include "libANGLE/Config.h" +#include "libANGLE/Context.h" +#include "libANGLE/Display.h" +#include "libANGLE/Surface.h" + +#include + +namespace egl +{ + +Error ValidateDisplay(const Display *display) +{ + if (display == EGL_NO_DISPLAY) + { + return Error(EGL_BAD_DISPLAY); + } + + if (!display->isInitialized()) + { + return Error(EGL_NOT_INITIALIZED); + } + + return Error(EGL_SUCCESS); +} + +Error ValidateSurface(const Display *display, Surface *surface) +{ + Error error = ValidateDisplay(display); + if (error.isError()) + { + return error; + } + + if (!display->isValidSurface(surface)) + { + return Error(EGL_BAD_SURFACE); + } + + return Error(EGL_SUCCESS); +} + +Error ValidateConfig(const Display *display, const Config *config) +{ + Error error = ValidateDisplay(display); + if (error.isError()) + { + return error; + } + + if (!display->isValidConfig(config)) + { + return Error(EGL_BAD_CONFIG); + } + + return Error(EGL_SUCCESS); +} + +Error ValidateContext(const Display *display, gl::Context *context) +{ + Error error = ValidateDisplay(display); + if (error.isError()) + { + return error; + } + + if (!display->isValidContext(context)) + { + return Error(EGL_BAD_CONTEXT); + } + + return Error(EGL_SUCCESS); +} + +Error ValidateCreateContext(Display *display, Config *configuration, gl::Context *shareContext, + const AttributeMap& attributes) +{ + Error error = ValidateConfig(display, configuration); + if (error.isError()) + { + return error; + } + + // Get the requested client version (default is 1) and check it is 2 or 3. + EGLint clientMajorVersion = 1; + EGLint clientMinorVersion = 0; + EGLint contextFlags = 0; + bool resetNotification = false; + bool robustAccess = false; + for (AttributeMap::const_iterator attributeIter = attributes.begin(); attributeIter != attributes.end(); attributeIter++) + { + EGLint attribute = attributeIter->first; + EGLint value = attributeIter->second; + + switch (attribute) + { + case EGL_CONTEXT_CLIENT_VERSION: + clientMajorVersion = value; + break; + + case EGL_CONTEXT_MINOR_VERSION: + clientMinorVersion = value; + break; + + case EGL_CONTEXT_FLAGS_KHR: + contextFlags = value; + break; + + case EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR: + // Only valid for OpenGL (non-ES) contexts + return Error(EGL_BAD_ATTRIBUTE); + + case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT: + if (!display->getExtensions().createContextRobustness) + { + return Error(EGL_BAD_ATTRIBUTE); + } + if (value != EGL_TRUE && value != EGL_FALSE) + { + return Error(EGL_BAD_ATTRIBUTE); + } + robustAccess = (value == EGL_TRUE); + break; + + case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR: + static_assert(EGL_LOSE_CONTEXT_ON_RESET_EXT == EGL_LOSE_CONTEXT_ON_RESET_KHR, "EGL extension enums not equal."); + static_assert(EGL_NO_RESET_NOTIFICATION_EXT == EGL_NO_RESET_NOTIFICATION_KHR, "EGL extension enums not equal."); + // same as EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT, fall through + case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT: + if (!display->getExtensions().createContextRobustness) + { + return Error(EGL_BAD_ATTRIBUTE); + } + if (value == EGL_LOSE_CONTEXT_ON_RESET_EXT) + { + resetNotification = true; + } + else if (value != EGL_NO_RESET_NOTIFICATION_EXT) + { + return Error(EGL_BAD_ATTRIBUTE); + } + break; + + default: + return Error(EGL_BAD_ATTRIBUTE); + } + } + + if ((clientMajorVersion != 2 && clientMajorVersion != 3) || clientMinorVersion != 0) + { + return Error(EGL_BAD_CONFIG); + } + + if (clientMajorVersion == 3 && !(configuration->conformant & EGL_OPENGL_ES3_BIT_KHR) && !(configuration->configCaveat & EGL_NON_CONFORMANT_CONFIG)) + { + return Error(EGL_BAD_CONFIG); + } + + // Note: EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR does not apply to ES + const EGLint validContextFlags = (EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR | + EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR); + if ((contextFlags & ~validContextFlags) != 0) + { + return Error(EGL_BAD_ATTRIBUTE); + } + + if ((contextFlags & EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR) > 0) + { + robustAccess = true; + } + + if (robustAccess) + { + // Unimplemented + return Error(EGL_BAD_CONFIG); + } + + if (shareContext) + { + // Shared context is invalid or is owned by another display + if (!display->isValidContext(shareContext)) + { + return Error(EGL_BAD_MATCH); + } + + if (shareContext->isResetNotificationEnabled() != resetNotification) + { + return Error(EGL_BAD_MATCH); + } + + if (shareContext->getClientVersion() != clientMajorVersion) + { + return Error(EGL_BAD_CONTEXT); + } + } + + return Error(EGL_SUCCESS); +} + +Error ValidateCreateWindowSurface(Display *display, Config *config, EGLNativeWindowType window, + const AttributeMap& attributes) +{ + Error error = ValidateConfig(display, config); + if (error.isError()) + { + return error; + } + + if (!display->isValidNativeWindow(window)) + { + return Error(EGL_BAD_NATIVE_WINDOW); + } + + const DisplayExtensions &displayExtensions = display->getExtensions(); + + for (AttributeMap::const_iterator attributeIter = attributes.begin(); attributeIter != attributes.end(); attributeIter++) + { + EGLint attribute = attributeIter->first; + EGLint value = attributeIter->second; + + switch (attribute) + { + case EGL_RENDER_BUFFER: + switch (value) + { + case EGL_BACK_BUFFER: + break; + case EGL_SINGLE_BUFFER: + return Error(EGL_BAD_MATCH); // Rendering directly to front buffer not supported + default: + return Error(EGL_BAD_ATTRIBUTE); + } + break; + + case EGL_POST_SUB_BUFFER_SUPPORTED_NV: + if (!displayExtensions.postSubBuffer) + { + return Error(EGL_BAD_ATTRIBUTE); + } + break; + + case EGL_WIDTH: + case EGL_HEIGHT: + if (!displayExtensions.windowFixedSize) + { + return Error(EGL_BAD_ATTRIBUTE); + } + if (value < 0) + { + return Error(EGL_BAD_PARAMETER); + } + break; + + case EGL_FIXED_SIZE_ANGLE: + if (!displayExtensions.windowFixedSize) + { + return Error(EGL_BAD_ATTRIBUTE); + } + break; + + case EGL_VG_COLORSPACE: + return Error(EGL_BAD_MATCH); + + case EGL_VG_ALPHA_FORMAT: + return Error(EGL_BAD_MATCH); + + default: + return Error(EGL_BAD_ATTRIBUTE); + } + } + + if (Display::hasExistingWindowSurface(window)) + { + return Error(EGL_BAD_ALLOC); + } + + return Error(EGL_SUCCESS); +} + +Error ValidateCreatePbufferSurface(Display *display, Config *config, const AttributeMap& attributes) +{ + Error error = ValidateConfig(display, config); + if (error.isError()) + { + return error; + } + + for (AttributeMap::const_iterator attributeIter = attributes.begin(); attributeIter != attributes.end(); attributeIter++) + { + EGLint attribute = attributeIter->first; + EGLint value = attributeIter->second; + + switch (attribute) + { + case EGL_WIDTH: + case EGL_HEIGHT: + if (value < 0) + { + return Error(EGL_BAD_PARAMETER); + } + break; + + case EGL_LARGEST_PBUFFER: + break; + + case EGL_TEXTURE_FORMAT: + switch (value) + { + case EGL_NO_TEXTURE: + case EGL_TEXTURE_RGB: + case EGL_TEXTURE_RGBA: + break; + default: + return Error(EGL_BAD_ATTRIBUTE); + } + break; + + case EGL_TEXTURE_TARGET: + switch (value) + { + case EGL_NO_TEXTURE: + case EGL_TEXTURE_2D: + break; + default: + return Error(EGL_BAD_ATTRIBUTE); + } + break; + + case EGL_MIPMAP_TEXTURE: + break; + + case EGL_VG_COLORSPACE: + break; + + case EGL_VG_ALPHA_FORMAT: + break; + + default: + return Error(EGL_BAD_ATTRIBUTE); + } + } + + if (!(config->surfaceType & EGL_PBUFFER_BIT)) + { + return Error(EGL_BAD_MATCH); + } + + const Caps &caps = display->getCaps(); + + EGLenum textureFormat = attributes.get(EGL_TEXTURE_FORMAT, EGL_NO_TEXTURE); + EGLenum textureTarget = attributes.get(EGL_TEXTURE_TARGET, EGL_NO_TEXTURE); + + if ((textureFormat != EGL_NO_TEXTURE && textureTarget == EGL_NO_TEXTURE) || + (textureFormat == EGL_NO_TEXTURE && textureTarget != EGL_NO_TEXTURE)) + { + return Error(EGL_BAD_MATCH); + } + + if ((textureFormat == EGL_TEXTURE_RGB && config->bindToTextureRGB != EGL_TRUE) || + (textureFormat == EGL_TEXTURE_RGBA && config->bindToTextureRGBA != EGL_TRUE)) + { + return Error(EGL_BAD_ATTRIBUTE); + } + + EGLint width = attributes.get(EGL_WIDTH, 0); + EGLint height = attributes.get(EGL_HEIGHT, 0); + if (textureFormat != EGL_NO_TEXTURE && !caps.textureNPOT && (!gl::isPow2(width) || !gl::isPow2(height))) + { + return Error(EGL_BAD_MATCH); + } + + return Error(EGL_SUCCESS); +} + +Error ValidateCreatePbufferFromClientBuffer(Display *display, EGLenum buftype, EGLClientBuffer buffer, + Config *config, const AttributeMap& attributes) +{ + Error error = ValidateConfig(display, config); + if (error.isError()) + { + return error; + } + + const DisplayExtensions &displayExtensions = display->getExtensions(); + + switch (buftype) + { + case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE: + if (!displayExtensions.d3dShareHandleClientBuffer) + { + return Error(EGL_BAD_PARAMETER); + } + if (buffer == nullptr) + { + return Error(EGL_BAD_PARAMETER); + } + break; + + default: + return Error(EGL_BAD_PARAMETER); + } + + for (AttributeMap::const_iterator attributeIter = attributes.begin(); attributeIter != attributes.end(); attributeIter++) + { + EGLint attribute = attributeIter->first; + EGLint value = attributeIter->second; + + switch (attribute) + { + case EGL_WIDTH: + case EGL_HEIGHT: + if (!displayExtensions.d3dShareHandleClientBuffer) + { + return Error(EGL_BAD_PARAMETER); + } + if (value < 0) + { + return Error(EGL_BAD_PARAMETER); + } + break; + + case EGL_TEXTURE_FORMAT: + switch (value) + { + case EGL_NO_TEXTURE: + case EGL_TEXTURE_RGB: + case EGL_TEXTURE_RGBA: + break; + default: + return Error(EGL_BAD_ATTRIBUTE); + } + break; + + case EGL_TEXTURE_TARGET: + switch (value) + { + case EGL_NO_TEXTURE: + case EGL_TEXTURE_2D: + break; + default: + return Error(EGL_BAD_ATTRIBUTE); + } + break; + + case EGL_MIPMAP_TEXTURE: + break; + + default: + return Error(EGL_BAD_ATTRIBUTE); + } + } + + if (!(config->surfaceType & EGL_PBUFFER_BIT)) + { + return Error(EGL_BAD_MATCH); + } + + EGLenum textureFormat = attributes.get(EGL_TEXTURE_FORMAT, EGL_NO_TEXTURE); + EGLenum textureTarget = attributes.get(EGL_TEXTURE_TARGET, EGL_NO_TEXTURE); + if ((textureFormat != EGL_NO_TEXTURE && textureTarget == EGL_NO_TEXTURE) || + (textureFormat == EGL_NO_TEXTURE && textureTarget != EGL_NO_TEXTURE)) + { + return Error(EGL_BAD_MATCH); + } + + if ((textureFormat == EGL_TEXTURE_RGB && config->bindToTextureRGB != EGL_TRUE) || + (textureFormat == EGL_TEXTURE_RGBA && config->bindToTextureRGBA != EGL_TRUE)) + { + return Error(EGL_BAD_ATTRIBUTE); + } + + if (buftype == EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE) + { + EGLint width = attributes.get(EGL_WIDTH, 0); + EGLint height = attributes.get(EGL_HEIGHT, 0); + + if (width == 0 || height == 0) + { + return Error(EGL_BAD_ATTRIBUTE); + } + +#if !defined(ANGLE_ENABLE_WINDOWS_STORE) // On Windows Store, we know the originating texture came from D3D11, so bypass this check + const Caps &caps = display->getCaps(); + if (textureFormat != EGL_NO_TEXTURE && !caps.textureNPOT && (!gl::isPow2(width) || !gl::isPow2(height))) + { + return Error(EGL_BAD_MATCH); + } +#endif + } + + return Error(EGL_SUCCESS); +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/validationEGL.h b/src/3rdparty/angle/src/libANGLE/validationEGL.h new file mode 100644 index 0000000000..4daff791fd --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/validationEGL.h @@ -0,0 +1,49 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// validationEGL.h: Validation functions for generic EGL entry point parameters + +#ifndef LIBANGLE_VALIDATIONEGL_H_ +#define LIBANGLE_VALIDATIONEGL_H_ + +#include "libANGLE/Error.h" + +#include + +namespace gl +{ +class Context; +} + +namespace egl +{ + +class AttributeMap; +struct Config; +class Display; +class Surface; + +// Object validation +Error ValidateDisplay(const Display *display); +Error ValidateSurface(const Display *display, Surface *surface); +Error ValidateConfig(const Display *display, const Config *config); +Error ValidateContext(const Display *display, gl::Context *context); + +// Entry point validation +Error ValidateCreateContext(Display *display, Config *configuration, gl::Context *shareContext, + const AttributeMap& attributes); + +Error ValidateCreateWindowSurface(Display *display, Config *config, EGLNativeWindowType window, + const AttributeMap& attributes); + +Error ValidateCreatePbufferSurface(Display *display, Config *config, const AttributeMap& attributes); +Error ValidateCreatePbufferFromClientBuffer(Display *display, EGLenum buftype, EGLClientBuffer buffer, + Config *config, const AttributeMap& attributes); + + +} + +#endif // LIBANGLE_VALIDATIONEGL_H_ diff --git a/src/3rdparty/angle/src/libANGLE/validationES.cpp b/src/3rdparty/angle/src/libANGLE/validationES.cpp new file mode 100644 index 0000000000..d267cbf2e6 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/validationES.cpp @@ -0,0 +1,1882 @@ +// +// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// validationES.h: Validation functions for generic OpenGL ES entry point parameters + +#include "libANGLE/validationES.h" +#include "libANGLE/validationES2.h" +#include "libANGLE/validationES3.h" +#include "libANGLE/Context.h" +#include "libANGLE/Texture.h" +#include "libANGLE/Framebuffer.h" +#include "libANGLE/FramebufferAttachment.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/Query.h" +#include "libANGLE/Program.h" +#include "libANGLE/Uniform.h" +#include "libANGLE/TransformFeedback.h" +#include "libANGLE/VertexArray.h" +#include "libANGLE/renderer/BufferImpl.h" + +#include "common/mathutil.h" +#include "common/utilities.h" + +namespace gl +{ + +bool ValidCap(const Context *context, GLenum cap) +{ + switch (cap) + { + case GL_CULL_FACE: + case GL_POLYGON_OFFSET_FILL: + case GL_SAMPLE_ALPHA_TO_COVERAGE: + case GL_SAMPLE_COVERAGE: + case GL_SCISSOR_TEST: + case GL_STENCIL_TEST: + case GL_DEPTH_TEST: + case GL_BLEND: + case GL_DITHER: + return true; + case GL_PRIMITIVE_RESTART_FIXED_INDEX: + case GL_RASTERIZER_DISCARD: + return (context->getClientVersion() >= 3); + default: + return false; + } +} + +bool ValidTextureTarget(const Context *context, GLenum target) +{ + switch (target) + { + case GL_TEXTURE_2D: + case GL_TEXTURE_CUBE_MAP: + return true; + + case GL_TEXTURE_3D: + case GL_TEXTURE_2D_ARRAY: + return (context->getClientVersion() >= 3); + + default: + return false; + } +} + +// This function differs from ValidTextureTarget in that the target must be +// usable as the destination of a 2D operation-- so a cube face is valid, but +// GL_TEXTURE_CUBE_MAP is not. +// Note: duplicate of IsInternalTextureTarget +bool ValidTexture2DDestinationTarget(const Context *context, GLenum target) +{ + switch (target) + { + case GL_TEXTURE_2D: + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: + return true; + case GL_TEXTURE_2D_ARRAY: + case GL_TEXTURE_3D: + return (context->getClientVersion() >= 3); + default: + return false; + } +} + +bool ValidFramebufferTarget(GLenum target) +{ + static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER && GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER, + "ANGLE framebuffer enums must equal the ES3 framebuffer enums."); + + switch (target) + { + case GL_FRAMEBUFFER: return true; + case GL_READ_FRAMEBUFFER: return true; + case GL_DRAW_FRAMEBUFFER: return true; + default: return false; + } +} + +bool ValidBufferTarget(const Context *context, GLenum target) +{ + switch (target) + { + case GL_ARRAY_BUFFER: + case GL_ELEMENT_ARRAY_BUFFER: + return true; + + case GL_PIXEL_PACK_BUFFER: + case GL_PIXEL_UNPACK_BUFFER: + return context->getExtensions().pixelBufferObject; + + case GL_COPY_READ_BUFFER: + case GL_COPY_WRITE_BUFFER: + case GL_TRANSFORM_FEEDBACK_BUFFER: + case GL_UNIFORM_BUFFER: + return (context->getClientVersion() >= 3); + + default: + return false; + } +} + +bool ValidBufferParameter(const Context *context, GLenum pname) +{ + switch (pname) + { + case GL_BUFFER_USAGE: + case GL_BUFFER_SIZE: + return true; + + // GL_BUFFER_MAP_POINTER is a special case, and may only be + // queried with GetBufferPointerv + case GL_BUFFER_ACCESS_FLAGS: + case GL_BUFFER_MAPPED: + case GL_BUFFER_MAP_OFFSET: + case GL_BUFFER_MAP_LENGTH: + return (context->getClientVersion() >= 3); + + default: + return false; + } +} + +bool ValidMipLevel(const Context *context, GLenum target, GLint level) +{ + size_t maxDimension = 0; + switch (target) + { + case GL_TEXTURE_2D: maxDimension = context->getCaps().max2DTextureSize; break; + case GL_TEXTURE_CUBE_MAP: + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: maxDimension = context->getCaps().maxCubeMapTextureSize; break; + case GL_TEXTURE_3D: maxDimension = context->getCaps().max3DTextureSize; break; + case GL_TEXTURE_2D_ARRAY: maxDimension = context->getCaps().max2DTextureSize; break; + default: UNREACHABLE(); + } + + return level <= gl::log2(maxDimension); +} + +bool ValidImageSize(const Context *context, GLenum target, GLint level, + GLsizei width, GLsizei height, GLsizei depth) +{ + if (level < 0 || width < 0 || height < 0 || depth < 0) + { + return false; + } + + if (!context->getExtensions().textureNPOT && + (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth)))) + { + return false; + } + + if (!ValidMipLevel(context, target, level)) + { + return false; + } + + return true; +} + +bool ValidCompressedImageSize(const Context *context, GLenum internalFormat, GLsizei width, GLsizei height) +{ + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat); + if (!formatInfo.compressed) + { + return false; + } + + if (width < 0 || (static_cast(width) > formatInfo.compressedBlockWidth && width % formatInfo.compressedBlockWidth != 0) || + height < 0 || (static_cast(height) > formatInfo.compressedBlockHeight && height % formatInfo.compressedBlockHeight != 0)) + { + return false; + } + + return true; +} + +bool ValidQueryType(const Context *context, GLenum queryType) +{ + static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT, "GL extension enums not equal."); + static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, "GL extension enums not equal."); + + switch (queryType) + { + case GL_ANY_SAMPLES_PASSED: + case GL_ANY_SAMPLES_PASSED_CONSERVATIVE: + return true; + case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: + return (context->getClientVersion() >= 3); + default: + return false; + } +} + +bool ValidProgram(Context *context, GLuint id) +{ + // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will generate the + // error INVALID_VALUE if the provided name is not the name of either a shader or program object and + // INVALID_OPERATION if the provided name identifies an object that is not the expected type." + + if (context->getProgram(id) != NULL) + { + return true; + } + else if (context->getShader(id) != NULL) + { + // ID is the wrong type + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + else + { + // No shader/program object has this ID + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } +} + +bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment) +{ + if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT) + { + const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT); + + if (colorAttachment >= context->getCaps().maxColorAttachments) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + } + else + { + switch (attachment) + { + case GL_DEPTH_ATTACHMENT: + case GL_STENCIL_ATTACHMENT: + break; + + case GL_DEPTH_STENCIL_ATTACHMENT: + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + } + + return true; +} + +bool ValidateRenderbufferStorageParametersBase(gl::Context *context, GLenum target, GLsizei samples, + GLenum internalformat, GLsizei width, GLsizei height) +{ + switch (target) + { + case GL_RENDERBUFFER: + break; + default: + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + + if (width < 0 || height < 0 || samples < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + + const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat); + if (!formatCaps.renderable) + { + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + + // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be + // sized but it does state that the format must be in the ES2.0 spec table 4.5 which contains + // only sized internal formats. + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat); + if (formatInfo.pixelBytes == 0) + { + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + + if (static_cast(std::max(width, height)) > context->getCaps().maxRenderbufferSize) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + + GLuint handle = context->getState().getRenderbufferId(); + if (handle == 0) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + return true; +} + +bool ValidateRenderbufferStorageParametersANGLE(gl::Context *context, GLenum target, GLsizei samples, + GLenum internalformat, GLsizei width, GLsizei height) +{ + ASSERT(samples == 0 || context->getExtensions().framebufferMultisample); + + // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal + // to MAX_SAMPLES_ANGLE (Context::getExtensions().maxSamples) otherwise GL_INVALID_VALUE is + // generated. + if (static_cast(samples) > context->getExtensions().maxSamples) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + + // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create + // the specified storage. This is different than ES 3.0 in which a sample number higher + // than the maximum sample number supported by this format generates a GL_INVALID_VALUE. + const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat); + if (static_cast(samples) > formatCaps.getMaxSamples()) + { + context->recordError(Error(GL_OUT_OF_MEMORY)); + return false; + } + + return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width, height); +} + +bool ValidateFramebufferRenderbufferParameters(gl::Context *context, GLenum target, GLenum attachment, + GLenum renderbuffertarget, GLuint renderbuffer) +{ + if (!ValidFramebufferTarget(target)) + { + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + + gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target); + GLuint framebufferHandle = context->getState().getTargetFramebuffer(target)->id(); + + if (!framebuffer || (framebufferHandle == 0 && renderbuffer != 0)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + if (!ValidateAttachmentTarget(context, attachment)) + { + return false; + } + + // [OpenGL ES 2.0.25] Section 4.4.3 page 112 + // [OpenGL ES 3.0.2] Section 4.4.2 page 201 + // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of + // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated. + if (renderbuffer != 0) + { + if (!context->getRenderbuffer(renderbuffer)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + } + + return true; +} + +static bool IsPartialBlit(gl::Context *context, gl::FramebufferAttachment *readBuffer, gl::FramebufferAttachment *writeBuffer, + GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, + GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1) +{ + if (srcX0 != 0 || srcY0 != 0 || dstX0 != 0 || dstY0 != 0 || + dstX1 != writeBuffer->getWidth() || dstY1 != writeBuffer->getHeight() || + srcX1 != readBuffer->getWidth() || srcY1 != readBuffer->getHeight()) + { + return true; + } + else if (context->getState().isScissorTestEnabled()) + { + const Rectangle &scissor = context->getState().getScissor(); + + return scissor.x > 0 || scissor.y > 0 || + scissor.width < writeBuffer->getWidth() || + scissor.height < writeBuffer->getHeight(); + } + else + { + return false; + } +} + +bool ValidateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, + GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, + GLenum filter, bool fromAngleExtension) +{ + switch (filter) + { + case GL_NEAREST: + break; + case GL_LINEAR: + if (fromAngleExtension) + { + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + break; + default: + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + + if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + + if (mask == 0) + { + // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no + // buffers are copied. + return false; + } + + if (fromAngleExtension && (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)) + { + ERR("Scaling and flipping in BlitFramebufferANGLE not supported by this implementation."); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the + // color buffer, leaving only nearest being unfiltered from above + if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + if (context->getState().getReadFramebuffer()->id() == context->getState().getDrawFramebuffer()->id()) + { + if (fromAngleExtension) + { + ERR("Blits with the same source and destination framebuffer are not supported by this " + "implementation."); + } + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + gl::Framebuffer *readFramebuffer = context->getState().getReadFramebuffer(); + gl::Framebuffer *drawFramebuffer = context->getState().getDrawFramebuffer(); + + if (!readFramebuffer || !drawFramebuffer) + { + context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION)); + return false; + } + + if (!readFramebuffer->checkStatus(context->getData())) + { + context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION)); + return false; + } + + if (!drawFramebuffer->checkStatus(context->getData())) + { + context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION)); + return false; + } + + if (drawFramebuffer->getSamples(context->getData()) != 0) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1; + + if (mask & GL_COLOR_BUFFER_BIT) + { + gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer(); + gl::FramebufferAttachment *drawColorBuffer = drawFramebuffer->getFirstColorbuffer(); + + if (readColorBuffer && drawColorBuffer) + { + GLenum readInternalFormat = readColorBuffer->getInternalFormat(); + const InternalFormat &readFormatInfo = GetInternalFormatInfo(readInternalFormat); + + for (GLuint i = 0; i < context->getCaps().maxColorAttachments; i++) + { + if (drawFramebuffer->isEnabledColorAttachment(i)) + { + GLenum drawInternalFormat = drawFramebuffer->getColorbuffer(i)->getInternalFormat(); + const InternalFormat &drawFormatInfo = GetInternalFormatInfo(drawInternalFormat); + + // The GL ES 3.0.2 spec (pg 193) states that: + // 1) If the read buffer is fixed point format, the draw buffer must be as well + // 2) If the read buffer is an unsigned integer format, the draw buffer must be as well + // 3) If the read buffer is a signed integer format, the draw buffer must be as well + if ( (readFormatInfo.componentType == GL_UNSIGNED_NORMALIZED || readFormatInfo.componentType == GL_SIGNED_NORMALIZED) && + !(drawFormatInfo.componentType == GL_UNSIGNED_NORMALIZED || drawFormatInfo.componentType == GL_SIGNED_NORMALIZED)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + if (readFormatInfo.componentType == GL_UNSIGNED_INT && drawFormatInfo.componentType != GL_UNSIGNED_INT) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + if (readFormatInfo.componentType == GL_INT && drawFormatInfo.componentType != GL_INT) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + if (readColorBuffer->getSamples() > 0 && (readInternalFormat != drawInternalFormat || !sameBounds)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + } + } + + if ((readFormatInfo.componentType == GL_INT || readFormatInfo.componentType == GL_UNSIGNED_INT) && filter == GL_LINEAR) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + if (fromAngleExtension) + { + FramebufferAttachment *readColorAttachment = readFramebuffer->getReadColorbuffer(); + if (!readColorAttachment || + (!(readColorAttachment->type() == GL_TEXTURE && readColorAttachment->getTextureImageIndex()->type == GL_TEXTURE_2D) && + readColorAttachment->type() != GL_RENDERBUFFER && + readColorAttachment->type() != GL_FRAMEBUFFER_DEFAULT)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + for (GLuint colorAttachment = 0; colorAttachment < context->getCaps().maxColorAttachments; ++colorAttachment) + { + if (drawFramebuffer->isEnabledColorAttachment(colorAttachment)) + { + FramebufferAttachment *attachment = drawFramebuffer->getColorbuffer(colorAttachment); + ASSERT(attachment); + + if (!(attachment->type() == GL_TEXTURE && attachment->getTextureImageIndex()->type == GL_TEXTURE_2D) && + attachment->type() != GL_RENDERBUFFER && + attachment->type() != GL_FRAMEBUFFER_DEFAULT) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + // Return an error if the destination formats do not match + if (attachment->getInternalFormat() != readColorBuffer->getInternalFormat()) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + } + } + + int readSamples = readFramebuffer->getSamples(context->getData()); + + if (readSamples != 0 && IsPartialBlit(context, readColorBuffer, drawColorBuffer, + srcX0, srcY0, srcX1, srcY1, + dstX0, dstY0, dstX1, dstY1)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + } + } + } + + GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT}; + GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT}; + for (size_t i = 0; i < 2; i++) + { + if (mask & masks[i]) + { + gl::FramebufferAttachment *readBuffer = readFramebuffer->getAttachment(attachments[i]); + gl::FramebufferAttachment *drawBuffer = drawFramebuffer->getAttachment(attachments[i]); + + if (readBuffer && drawBuffer) + { + if (readBuffer->getInternalFormat() != drawBuffer->getInternalFormat()) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + if (readBuffer->getSamples() > 0 && !sameBounds) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + if (fromAngleExtension) + { + if (IsPartialBlit(context, readBuffer, drawBuffer, + srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1)) + { + ERR("Only whole-buffer depth and stencil blits are supported by this implementation."); + context->recordError(Error(GL_INVALID_OPERATION)); // only whole-buffer copies are permitted + return false; + } + + if (readBuffer->getSamples() != 0 || drawBuffer->getSamples() != 0) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + } + } + } + } + + return true; +} + +bool ValidateGetVertexAttribParameters(Context *context, GLenum pname) +{ + switch (pname) + { + case GL_VERTEX_ATTRIB_ARRAY_ENABLED: + case GL_VERTEX_ATTRIB_ARRAY_SIZE: + case GL_VERTEX_ATTRIB_ARRAY_STRIDE: + case GL_VERTEX_ATTRIB_ARRAY_TYPE: + case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED: + case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: + case GL_CURRENT_VERTEX_ATTRIB: + return true; + + case GL_VERTEX_ATTRIB_ARRAY_DIVISOR: + // Don't verify ES3 context because GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE uses + // the same constant. + static_assert(GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE, + "ANGLE extension enums not equal to GL enums."); + return true; + + case GL_VERTEX_ATTRIB_ARRAY_INTEGER: + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + return true; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } +} + +bool ValidateTexParamParameters(gl::Context *context, GLenum pname, GLint param) +{ + switch (pname) + { + case GL_TEXTURE_WRAP_R: + case GL_TEXTURE_SWIZZLE_R: + case GL_TEXTURE_SWIZZLE_G: + case GL_TEXTURE_SWIZZLE_B: + case GL_TEXTURE_SWIZZLE_A: + case GL_TEXTURE_BASE_LEVEL: + case GL_TEXTURE_MAX_LEVEL: + case GL_TEXTURE_COMPARE_MODE: + case GL_TEXTURE_COMPARE_FUNC: + case GL_TEXTURE_MIN_LOD: + case GL_TEXTURE_MAX_LOD: + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + break; + + default: break; + } + + switch (pname) + { + case GL_TEXTURE_WRAP_S: + case GL_TEXTURE_WRAP_T: + case GL_TEXTURE_WRAP_R: + switch (param) + { + case GL_REPEAT: + case GL_CLAMP_TO_EDGE: + case GL_MIRRORED_REPEAT: + return true; + default: + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + + case GL_TEXTURE_MIN_FILTER: + switch (param) + { + case GL_NEAREST: + case GL_LINEAR: + case GL_NEAREST_MIPMAP_NEAREST: + case GL_LINEAR_MIPMAP_NEAREST: + case GL_NEAREST_MIPMAP_LINEAR: + case GL_LINEAR_MIPMAP_LINEAR: + return true; + default: + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + break; + + case GL_TEXTURE_MAG_FILTER: + switch (param) + { + case GL_NEAREST: + case GL_LINEAR: + return true; + default: + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + break; + + case GL_TEXTURE_USAGE_ANGLE: + switch (param) + { + case GL_NONE: + case GL_FRAMEBUFFER_ATTACHMENT_ANGLE: + return true; + default: + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + break; + + case GL_TEXTURE_MAX_ANISOTROPY_EXT: + if (!context->getExtensions().textureFilterAnisotropic) + { + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + + // we assume the parameter passed to this validation method is truncated, not rounded + if (param < 1) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + return true; + + case GL_TEXTURE_MIN_LOD: + case GL_TEXTURE_MAX_LOD: + // any value is permissible + return true; + + case GL_TEXTURE_COMPARE_MODE: + // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17 + switch (param) + { + case GL_NONE: + case GL_COMPARE_REF_TO_TEXTURE: + return true; + default: + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + break; + + case GL_TEXTURE_COMPARE_FUNC: + // Acceptable function parameters from GLES 3.0.2 spec, table 3.17 + switch (param) + { + case GL_LEQUAL: + case GL_GEQUAL: + case GL_LESS: + case GL_GREATER: + case GL_EQUAL: + case GL_NOTEQUAL: + case GL_ALWAYS: + case GL_NEVER: + return true; + default: + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + break; + + case GL_TEXTURE_SWIZZLE_R: + case GL_TEXTURE_SWIZZLE_G: + case GL_TEXTURE_SWIZZLE_B: + case GL_TEXTURE_SWIZZLE_A: + switch (param) + { + case GL_RED: + case GL_GREEN: + case GL_BLUE: + case GL_ALPHA: + case GL_ZERO: + case GL_ONE: + return true; + default: + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + break; + + case GL_TEXTURE_BASE_LEVEL: + case GL_TEXTURE_MAX_LEVEL: + if (param < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + return true; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } +} + +bool ValidateSamplerObjectParameter(gl::Context *context, GLenum pname) +{ + switch (pname) + { + case GL_TEXTURE_MIN_FILTER: + case GL_TEXTURE_MAG_FILTER: + case GL_TEXTURE_WRAP_S: + case GL_TEXTURE_WRAP_T: + case GL_TEXTURE_WRAP_R: + case GL_TEXTURE_MIN_LOD: + case GL_TEXTURE_MAX_LOD: + case GL_TEXTURE_COMPARE_MODE: + case GL_TEXTURE_COMPARE_FUNC: + return true; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } +} + +bool ValidateReadPixelsParameters(gl::Context *context, GLint x, GLint y, GLsizei width, GLsizei height, + GLenum format, GLenum type, GLsizei *bufSize, GLvoid *pixels) +{ + gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer(); + ASSERT(framebuffer); + + if (framebuffer->checkStatus(context->getData()) != GL_FRAMEBUFFER_COMPLETE) + { + context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION)); + return false; + } + + if (context->getState().getReadFramebuffer()->id() != 0 && + framebuffer->getSamples(context->getData()) != 0) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer(); + if (!readBuffer) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + GLenum currentFormat = framebuffer->getImplementationColorReadFormat(); + GLenum currentType = framebuffer->getImplementationColorReadType(); + GLenum currentInternalFormat = readBuffer->getInternalFormat(); + GLuint clientVersion = context->getClientVersion(); + + bool validReadFormat = (clientVersion < 3) ? ValidES2ReadFormatType(context, format, type) : + ValidES3ReadFormatType(context, currentInternalFormat, format, type); + + if (!(currentFormat == format && currentType == type) && !validReadFormat) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + GLenum sizedInternalFormat = GetSizedInternalFormat(format, type); + const InternalFormat &sizedFormatInfo = GetInternalFormatInfo(sizedInternalFormat); + + GLsizei outputPitch = sizedFormatInfo.computeRowPitch(type, width, context->getState().getPackAlignment(), 0); + // sized query sanity check + if (bufSize) + { + int requiredSize = outputPitch * height; + if (requiredSize > *bufSize) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + } + + return true; +} + +bool ValidateBeginQuery(gl::Context *context, GLenum target, GLuint id) +{ + if (!ValidQueryType(context, target)) + { + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + + if (id == 0) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an + // of zero, if the active query object name for is non-zero (for the + // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if + // the active query for either target is non-zero), if is the name of an + // existing query object whose type does not match , or if is the + // active query object name for any query type, the error INVALID_OPERATION is + // generated. + + // Ensure no other queries are active + // NOTE: If other queries than occlusion are supported, we will need to check + // separately that: + // a) The query ID passed is not the current active query for any target/type + // b) There are no active queries for the requested target (and in the case + // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, + // no query may be active for either if glBeginQuery targets either. + if (context->getState().isQueryActive()) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + Query *queryObject = context->getQuery(id, true, target); + + // check that name was obtained with glGenQueries + if (!queryObject) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + // check for type mismatch + if (queryObject->getType() != target) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + return true; +} + +bool ValidateEndQuery(gl::Context *context, GLenum target) +{ + if (!ValidQueryType(context, target)) + { + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + + const Query *queryObject = context->getState().getActiveQuery(target); + + if (queryObject == NULL) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + return true; +} + +static bool ValidateUniformCommonBase(gl::Context *context, GLenum targetUniformType, + GLint location, GLsizei count, LinkedUniform **uniformOut) +{ + if (count < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + + gl::Program *program = context->getState().getProgram(); + if (!program) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + if (location == -1) + { + // Silently ignore the uniform command + return false; + } + + if (!program->isValidUniformLocation(location)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + LinkedUniform *uniform = program->getUniformByLocation(location); + + // attempting to write an array to a non-array uniform is an INVALID_OPERATION + if (uniform->elementCount() == 1 && count > 1) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + *uniformOut = uniform; + return true; +} + +bool ValidateUniform(gl::Context *context, GLenum uniformType, GLint location, GLsizei count) +{ + // Check for ES3 uniform entry points + if (VariableComponentType(uniformType) == GL_UNSIGNED_INT && context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + LinkedUniform *uniform = NULL; + if (!ValidateUniformCommonBase(context, uniformType, location, count, &uniform)) + { + return false; + } + + GLenum targetBoolType = VariableBoolVectorType(uniformType); + bool samplerUniformCheck = (IsSamplerType(uniform->type) && uniformType == GL_INT); + if (!samplerUniformCheck && uniformType != uniform->type && targetBoolType != uniform->type) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + return true; +} + +bool ValidateUniformMatrix(gl::Context *context, GLenum matrixType, GLint location, GLsizei count, + GLboolean transpose) +{ + // Check for ES3 uniform entry points + int rows = VariableRowCount(matrixType); + int cols = VariableColumnCount(matrixType); + if (rows != cols && context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + if (transpose != GL_FALSE && context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + + LinkedUniform *uniform = NULL; + if (!ValidateUniformCommonBase(context, matrixType, location, count, &uniform)) + { + return false; + } + + if (uniform->type != matrixType) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + return true; +} + +bool ValidateStateQuery(gl::Context *context, GLenum pname, GLenum *nativeType, unsigned int *numParams) +{ + if (!context->getQueryParameterInfo(pname, nativeType, numParams)) + { + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + + const Caps &caps = context->getCaps(); + + if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15) + { + unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0); + + if (colorAttachment >= caps.maxDrawBuffers) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + } + + switch (pname) + { + case GL_TEXTURE_BINDING_2D: + case GL_TEXTURE_BINDING_CUBE_MAP: + case GL_TEXTURE_BINDING_3D: + case GL_TEXTURE_BINDING_2D_ARRAY: + if (context->getState().getActiveSampler() >= caps.maxCombinedTextureImageUnits) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + break; + + case GL_IMPLEMENTATION_COLOR_READ_TYPE: + case GL_IMPLEMENTATION_COLOR_READ_FORMAT: + { + Framebuffer *framebuffer = context->getState().getReadFramebuffer(); + ASSERT(framebuffer); + if (framebuffer->checkStatus(context->getData()) != GL_FRAMEBUFFER_COMPLETE) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + FramebufferAttachment *attachment = framebuffer->getReadColorbuffer(); + if (!attachment) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + } + break; + + default: + break; + } + + // pname is valid, but there are no parameters to return + if (numParams == 0) + { + return false; + } + + return true; +} + +bool ValidateCopyTexImageParametersBase(gl::Context* context, GLenum target, GLint level, GLenum internalformat, bool isSubImage, + GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, + GLint border, GLenum *textureFormatOut) +{ + + if (!ValidTexture2DDestinationTarget(context, target)) + { + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + + if (level < 0 || xoffset < 0 || yoffset < 0 || zoffset < 0 || width < 0 || height < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + + if (std::numeric_limits::max() - xoffset < width || std::numeric_limits::max() - yoffset < height) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + + if (border != 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + + if (!ValidMipLevel(context, target, level)) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + + gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer(); + if (framebuffer->checkStatus(context->getData()) != GL_FRAMEBUFFER_COMPLETE) + { + context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION)); + return false; + } + + if (context->getState().getReadFramebuffer()->id() != 0 && framebuffer->getSamples(context->getData()) != 0) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + const gl::Caps &caps = context->getCaps(); + + GLuint maxDimension = 0; + switch (target) + { + case GL_TEXTURE_2D: + maxDimension = caps.max2DTextureSize; + break; + + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: + maxDimension = caps.maxCubeMapTextureSize; + break; + + case GL_TEXTURE_2D_ARRAY: + maxDimension = caps.max2DTextureSize; + break; + + case GL_TEXTURE_3D: + maxDimension = caps.max3DTextureSize; + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + + gl::Texture *texture = context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target); + if (!texture) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + if (texture->isImmutable() && !isSubImage) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat); + + if (formatInfo.depthBits > 0) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + if (formatInfo.compressed && !ValidCompressedImageSize(context, internalformat, width, height)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + if (isSubImage) + { + if (static_cast(xoffset + width) > texture->getWidth(target, level) || + static_cast(yoffset + height) > texture->getHeight(target, level) || + static_cast(zoffset) >= texture->getDepth(target, level)) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + } + else + { + if (IsCubeMapTextureTarget(target) && width != height) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + + if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions())) + { + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + + int maxLevelDimension = (maxDimension >> level); + if (static_cast(width) > maxLevelDimension || static_cast(height) > maxLevelDimension) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + } + + *textureFormatOut = texture->getInternalFormat(target, level); + return true; +} + +static bool ValidateDrawBase(Context *context, GLenum mode, GLsizei count, GLsizei maxVertex, GLsizei primcount) +{ + switch (mode) + { + case GL_POINTS: + case GL_LINES: + case GL_LINE_LOOP: + case GL_LINE_STRIP: + case GL_TRIANGLES: + case GL_TRIANGLE_STRIP: + case GL_TRIANGLE_FAN: + break; + default: + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + + if (count < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + + const State &state = context->getState(); + + // Check for mapped buffers + if (state.hasMappedBuffer(GL_ARRAY_BUFFER)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + const gl::DepthStencilState &depthStencilState = state.getDepthStencilState(); + if (depthStencilState.stencilWritemask != depthStencilState.stencilBackWritemask || + state.getStencilRef() != state.getStencilBackRef() || + depthStencilState.stencilMask != depthStencilState.stencilBackMask) + { + // Note: these separate values are not supported in WebGL, due to D3D's limitations. + // See Section 6.10 of the WebGL 1.0 spec + ERR("This ANGLE implementation does not support separate front/back stencil " + "writemasks, reference values, or stencil mask values."); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + const gl::Framebuffer *fbo = state.getDrawFramebuffer(); + if (!fbo || fbo->checkStatus(context->getData()) != GL_FRAMEBUFFER_COMPLETE) + { + context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION)); + return false; + } + + gl::Program *program = state.getProgram(); + if (!program) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + if (!program->validateSamplers(NULL, context->getCaps())) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + // Buffer validations + const VertexArray *vao = state.getVertexArray(); + for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++) + { + const VertexAttribute &attrib = vao->getVertexAttribute(attributeIndex); + bool attribActive = (program->getSemanticIndex(attributeIndex) != -1); + if (attribActive && attrib.enabled) + { + gl::Buffer *buffer = attrib.buffer.get(); + + if (buffer) + { + GLint64 attribStride = static_cast(ComputeVertexAttributeStride(attrib)); + GLint64 maxVertexElement = 0; + + if (attrib.divisor > 0) + { + maxVertexElement = static_cast(primcount) / static_cast(attrib.divisor); + } + else + { + maxVertexElement = static_cast(maxVertex); + } + + GLint64 attribDataSize = maxVertexElement * attribStride; + + // [OpenGL ES 3.0.2] section 2.9.4 page 40: + // We can return INVALID_OPERATION if our vertex attribute does not have + // enough backing data. + if (attribDataSize > buffer->getSize()) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + } + else if (attrib.pointer == NULL) + { + // This is an application error that would normally result in a crash, + // but we catch it and return an error + context->recordError(Error(GL_INVALID_OPERATION, "An enabled vertex array has no buffer and no pointer.")); + return false; + } + } + } + + // Uniform buffer validation + for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++) + { + const gl::UniformBlock *uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex); + GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex); + const gl::Buffer *uniformBuffer = state.getIndexedUniformBuffer(blockBinding); + + if (!uniformBuffer) + { + // undefined behaviour + context->recordError(Error(GL_INVALID_OPERATION, "It is undefined behaviour to have a used but unbound uniform buffer.")); + return false; + } + + size_t uniformBufferSize = state.getIndexedUniformBufferSize(blockBinding); + + if (uniformBufferSize == 0) + { + // Bind the whole buffer. + uniformBufferSize = uniformBuffer->getSize(); + } + + if (uniformBufferSize < uniformBlock->dataSize) + { + // undefined behaviour + context->recordError(Error(GL_INVALID_OPERATION, "It is undefined behaviour to use a uniform buffer that is too small.")); + return false; + } + } + + // No-op if zero count + return (count > 0); +} + +bool ValidateDrawArrays(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount) +{ + if (first < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + + const State &state = context->getState(); + gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback(); + if (curTransformFeedback && curTransformFeedback->isStarted() && !curTransformFeedback->isPaused() && + curTransformFeedback->getDrawMode() != mode) + { + // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode + // that does not match the current transform feedback object's draw mode (if transform feedback + // is active), (3.0.2, section 2.14, pg 86) + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + if (!ValidateDrawBase(context, mode, count, count, primcount)) + { + return false; + } + + return true; +} + +bool ValidateDrawArraysInstanced(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount) +{ + if (primcount < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + + if (!ValidateDrawArrays(context, mode, first, count, primcount)) + { + return false; + } + + // No-op if zero primitive count + return (primcount > 0); +} + +static bool ValidateDrawInstancedANGLE(Context *context) +{ + // Verify there is at least one active attribute with a divisor of zero + const gl::State& state = context->getState(); + + gl::Program *program = state.getProgram(); + + const VertexArray *vao = state.getVertexArray(); + for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++) + { + const VertexAttribute &attrib = vao->getVertexAttribute(attributeIndex); + bool active = (program->getSemanticIndex(attributeIndex) != -1); + if (active && attrib.divisor == 0) + { + return true; + } + } + + context->recordError(Error(GL_INVALID_OPERATION, "ANGLE_instanced_arrays requires that at least one active attribute" + "has a divisor of zero.")); + return false; +} + +bool ValidateDrawArraysInstancedANGLE(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount) +{ + if (!ValidateDrawInstancedANGLE(context)) + { + return false; + } + + return ValidateDrawArraysInstanced(context, mode, first, count, primcount); +} + +bool ValidateDrawElements(Context *context, GLenum mode, GLsizei count, GLenum type, + const GLvoid* indices, GLsizei primcount, rx::RangeUI *indexRangeOut) +{ + switch (type) + { + case GL_UNSIGNED_BYTE: + case GL_UNSIGNED_SHORT: + break; + case GL_UNSIGNED_INT: + if (!context->getExtensions().elementIndexUint) + { + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + break; + default: + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + + const State &state = context->getState(); + + gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback(); + if (curTransformFeedback && curTransformFeedback->isStarted() && !curTransformFeedback->isPaused()) + { + // It is an invalid operation to call DrawElements, DrawRangeElements or DrawElementsInstanced + // while transform feedback is active, (3.0.2, section 2.14, pg 86) + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + // Check for mapped buffers + if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + const gl::VertexArray *vao = state.getVertexArray(); + gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer(); + if (!indices && !elementArrayBuffer) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + if (elementArrayBuffer) + { + const gl::Type &typeInfo = gl::GetTypeInfo(type); + + GLint64 offset = reinterpret_cast(indices); + GLint64 byteCount = static_cast(typeInfo.bytes) * static_cast(count)+offset; + + // check for integer overflows + if (static_cast(count) > (std::numeric_limits::max() / typeInfo.bytes) || + byteCount > static_cast(std::numeric_limits::max())) + { + context->recordError(Error(GL_OUT_OF_MEMORY)); + return false; + } + + // Check for reading past the end of the bound buffer object + if (byteCount > elementArrayBuffer->getSize()) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + } + else if (!indices) + { + // Catch this programming error here + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + // Use max index to validate if our vertex buffers are large enough for the pull. + // TODO: offer fast path, with disabled index validation. + // TODO: also disable index checking on back-ends that are robust to out-of-range accesses. + if (elementArrayBuffer) + { + uintptr_t offset = reinterpret_cast(indices); + if (!elementArrayBuffer->getIndexRangeCache()->findRange(type, offset, count, indexRangeOut)) + { + rx::BufferImpl *bufferImpl = elementArrayBuffer->getImplementation(); + const uint8_t *dataPointer = NULL; + Error error = bufferImpl->getData(&dataPointer); + if (error.isError()) + { + context->recordError(error); + return false; + } + + const uint8_t *offsetPointer = dataPointer + offset; + *indexRangeOut = rx::IndexRangeCache::ComputeRange(type, offsetPointer, count); + elementArrayBuffer->getIndexRangeCache()->addRange(type, offset, count, *indexRangeOut); + } + } + else + { + *indexRangeOut = rx::IndexRangeCache::ComputeRange(type, indices, count); + } + + if (!ValidateDrawBase(context, mode, count, static_cast(indexRangeOut->end), primcount)) + { + return false; + } + + return true; +} + +bool ValidateDrawElementsInstanced(Context *context, + GLenum mode, GLsizei count, GLenum type, + const GLvoid *indices, GLsizei primcount, + rx::RangeUI *indexRangeOut) +{ + if (primcount < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + + if (!ValidateDrawElements(context, mode, count, type, indices, primcount, indexRangeOut)) + { + return false; + } + + // No-op zero primitive count + return (primcount > 0); +} + +bool ValidateDrawElementsInstancedANGLE(Context *context, GLenum mode, GLsizei count, GLenum type, + const GLvoid *indices, GLsizei primcount, rx::RangeUI *indexRangeOut) +{ + if (!ValidateDrawInstancedANGLE(context)) + { + return false; + } + + return ValidateDrawElementsInstanced(context, mode, count, type, indices, primcount, indexRangeOut); +} + +bool ValidateFramebufferTextureBase(Context *context, GLenum target, GLenum attachment, + GLuint texture, GLint level) +{ + if (!ValidFramebufferTarget(target)) + { + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + + if (!ValidateAttachmentTarget(context, attachment)) + { + return false; + } + + if (texture != 0) + { + gl::Texture *tex = context->getTexture(texture); + + if (tex == NULL) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + if (level < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + } + + const gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target); + GLuint framebufferHandle = context->getState().getTargetFramebuffer(target)->id(); + + if (framebufferHandle == 0 || !framebuffer) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + return true; +} + +bool ValidateFramebufferTexture2D(Context *context, GLenum target, GLenum attachment, + GLenum textarget, GLuint texture, GLint level) +{ + // Attachments are required to be bound to level 0 in ES2 + if (context->getClientVersion() < 3 && level != 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + + if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level)) + { + return false; + } + + if (texture != 0) + { + gl::Texture *tex = context->getTexture(texture); + ASSERT(tex); + + const gl::Caps &caps = context->getCaps(); + + switch (textarget) + { + case GL_TEXTURE_2D: + { + if (level > gl::log2(caps.max2DTextureSize)) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + if (tex->getTarget() != GL_TEXTURE_2D) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + } + break; + + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: + { + if (level > gl::log2(caps.maxCubeMapTextureSize)) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + if (tex->getTarget() != GL_TEXTURE_CUBE_MAP) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + } + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + + const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(tex->getInternalFormat(textarget, level)); + if (internalFormatInfo.compressed) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + } + + return true; +} + +bool ValidateGetUniformBase(Context *context, GLuint program, GLint location) +{ + if (program == 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + + if (!ValidProgram(context, program)) + { + return false; + } + + gl::Program *programObject = context->getProgram(program); + + if (!programObject || !programObject->isLinked()) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + if (!programObject->isValidUniformLocation(location)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + return true; +} + +bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat* params) +{ + return ValidateGetUniformBase(context, program, location); +} + +bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint* params) +{ + return ValidateGetUniformBase(context, program, location); +} + +static bool ValidateSizedGetUniform(Context *context, GLuint program, GLint location, GLsizei bufSize) +{ + if (!ValidateGetUniformBase(context, program, location)) + { + return false; + } + + gl::Program *programObject = context->getProgram(program); + ASSERT(programObject); + + // sized queries -- ensure the provided buffer is large enough + LinkedUniform *uniform = programObject->getUniformByLocation(location); + size_t requiredBytes = VariableExternalSize(uniform->type); + if (static_cast(bufSize) < requiredBytes) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + return true; +} + +bool ValidateGetnUniformfvEXT(Context *context, GLuint program, GLint location, GLsizei bufSize, GLfloat* params) +{ + return ValidateSizedGetUniform(context, program, location, bufSize); +} + +bool ValidateGetnUniformivEXT(Context *context, GLuint program, GLint location, GLsizei bufSize, GLint* params) +{ + return ValidateSizedGetUniform(context, program, location, bufSize); +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/validationES.h b/src/3rdparty/angle/src/libANGLE/validationES.h new file mode 100644 index 0000000000..b0ccd8eecc --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/validationES.h @@ -0,0 +1,94 @@ +// +// 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. +// + +// validationES.h: Validation functions for generic OpenGL ES entry point parameters + +#ifndef LIBANGLE_VALIDATION_ES_H_ +#define LIBANGLE_VALIDATION_ES_H_ + +#include "common/mathutil.h" + +#include +#include + +namespace gl +{ + +class Context; + +bool ValidCap(const Context *context, GLenum cap); +bool ValidTextureTarget(const Context *context, GLenum target); +bool ValidTexture2DDestinationTarget(const Context *context, GLenum target); +bool ValidFramebufferTarget(GLenum target); +bool ValidBufferTarget(const Context *context, GLenum target); +bool ValidBufferParameter(const Context *context, GLenum pname); +bool ValidMipLevel(const Context *context, GLenum target, GLint level); +bool ValidImageSize(const Context *context, GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth); +bool ValidCompressedImageSize(const Context *context, GLenum internalFormat, GLsizei width, GLsizei height); +bool ValidQueryType(const Context *context, GLenum queryType); +bool ValidProgram(Context *context, GLuint id); + +bool ValidateAttachmentTarget(Context *context, GLenum attachment); +bool ValidateRenderbufferStorageParametersBase(Context *context, GLenum target, GLsizei samples, + GLenum internalformat, GLsizei width, GLsizei height); +bool ValidateRenderbufferStorageParametersANGLE(Context *context, GLenum target, GLsizei samples, + GLenum internalformat, GLsizei width, GLsizei height); + +bool ValidateFramebufferRenderbufferParameters(Context *context, GLenum target, GLenum attachment, + GLenum renderbuffertarget, GLuint renderbuffer); + +bool ValidateBlitFramebufferParameters(Context *context, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, + GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, + GLenum filter, bool fromAngleExtension); + +bool ValidateGetVertexAttribParameters(Context *context, GLenum pname); + +bool ValidateTexParamParameters(Context *context, GLenum pname, GLint param); + +bool ValidateSamplerObjectParameter(Context *context, GLenum pname); + +bool ValidateReadPixelsParameters(Context *context, GLint x, GLint y, GLsizei width, GLsizei height, + GLenum format, GLenum type, GLsizei *bufSize, GLvoid *pixels); + +bool ValidateBeginQuery(Context *context, GLenum target, GLuint id); +bool ValidateEndQuery(Context *context, GLenum target); + +bool ValidateUniform(Context *context, GLenum uniformType, GLint location, GLsizei count); +bool ValidateUniformMatrix(Context *context, GLenum matrixType, GLint location, GLsizei count, + GLboolean transpose); + +bool ValidateStateQuery(Context *context, GLenum pname, GLenum *nativeType, unsigned int *numParams); + +bool ValidateCopyTexImageParametersBase(Context* context, GLenum target, GLint level, GLenum internalformat, bool isSubImage, + GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, + GLint border, GLenum *textureInternalFormatOut); + +bool ValidateDrawArrays(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount); +bool ValidateDrawArraysInstanced(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount); +bool ValidateDrawArraysInstancedANGLE(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount); + +bool ValidateDrawElements(Context *context, GLenum mode, GLsizei count, GLenum type, + const GLvoid* indices, GLsizei primcount, rx::RangeUI *indexRangeOut); + +bool ValidateDrawElementsInstanced(Context *context, GLenum mode, GLsizei count, GLenum type, + const GLvoid *indices, GLsizei primcount, rx::RangeUI *indexRangeOut); +bool ValidateDrawElementsInstancedANGLE(Context *context, GLenum mode, GLsizei count, GLenum type, + const GLvoid *indices, GLsizei primcount, rx::RangeUI *indexRangeOut); + +bool ValidateFramebufferTextureBase(Context *context, GLenum target, GLenum attachment, + GLuint texture, GLint level); +bool ValidateFramebufferTexture2D(Context *context, GLenum target, GLenum attachment, + GLenum textarget, GLuint texture, GLint level); + +bool ValidateGetUniformBase(Context *context, GLuint program, GLint location); +bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat* params); +bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint* params); +bool ValidateGetnUniformfvEXT(Context *context, GLuint program, GLint location, GLsizei bufSize, GLfloat* params); +bool ValidateGetnUniformivEXT(Context *context, GLuint program, GLint location, GLsizei bufSize, GLint* params); + +} + +#endif // LIBANGLE_VALIDATION_ES_H_ diff --git a/src/3rdparty/angle/src/libANGLE/validationES2.cpp b/src/3rdparty/angle/src/libANGLE/validationES2.cpp new file mode 100644 index 0000000000..9eece1b54a --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/validationES2.cpp @@ -0,0 +1,882 @@ +// +// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// validationES2.cpp: Validation functions for OpenGL ES 2.0 entry point parameters + +#include "libANGLE/validationES2.h" +#include "libANGLE/validationES.h" +#include "libANGLE/Context.h" +#include "libANGLE/Texture.h" +#include "libANGLE/Framebuffer.h" +#include "libANGLE/Renderbuffer.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/FramebufferAttachment.h" + +#include "common/mathutil.h" +#include "common/utilities.h" + +namespace gl +{ + +bool ValidateES2TexImageParameters(Context *context, GLenum target, GLint level, GLenum internalformat, bool isCompressed, bool isSubImage, + GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + GLint border, GLenum format, GLenum type, const GLvoid *pixels) +{ + if (!ValidTexture2DDestinationTarget(context, target)) + { + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + + if (!ValidImageSize(context, target, level, width, height, 1)) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + + if (level < 0 || xoffset < 0 || + std::numeric_limits::max() - xoffset < width || + std::numeric_limits::max() - yoffset < height) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + + if (!isSubImage && !isCompressed && internalformat != format) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + const gl::Caps &caps = context->getCaps(); + + if (target == GL_TEXTURE_2D) + { + if (static_cast(width) > (caps.max2DTextureSize >> level) || + static_cast(height) > (caps.max2DTextureSize >> level)) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + } + else if (IsCubeMapTextureTarget(target)) + { + if (!isSubImage && width != height) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + + if (static_cast(width) > (caps.maxCubeMapTextureSize >> level) || + static_cast(height) > (caps.maxCubeMapTextureSize >> level)) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + } + else + { + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + + gl::Texture *texture = context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target); + if (!texture) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + if (isSubImage) + { + if (format != GL_NONE) + { + if (gl::GetSizedInternalFormat(format, type) != texture->getInternalFormat(target, level)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + } + + if (static_cast(xoffset + width) > texture->getWidth(target, level) || + static_cast(yoffset + height) > texture->getHeight(target, level)) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + } + else + { + if (texture->isImmutable()) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + } + + // Verify zero border + if (border != 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + + GLenum actualInternalFormat = isSubImage ? texture->getInternalFormat(target, level) : internalformat; + const InternalFormat &actualFormatInfo = GetInternalFormatInfo(actualInternalFormat); + + if (isCompressed != actualFormatInfo.compressed) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + if (isCompressed) + { + if (!ValidCompressedImageSize(context, actualInternalFormat, width, height)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + switch (actualInternalFormat) + { + case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + if (!context->getExtensions().textureCompressionDXT1) + { + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + break; + case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: + if (!context->getExtensions().textureCompressionDXT1) + { + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + break; + case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: + if (!context->getExtensions().textureCompressionDXT5) + { + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + break; + default: + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + } + else + { + // validate by itself (used as secondary key below) + switch (type) + { + case GL_UNSIGNED_BYTE: + case GL_UNSIGNED_SHORT_5_6_5: + case GL_UNSIGNED_SHORT_4_4_4_4: + case GL_UNSIGNED_SHORT_5_5_5_1: + case GL_UNSIGNED_SHORT: + case GL_UNSIGNED_INT: + case GL_UNSIGNED_INT_24_8_OES: + case GL_HALF_FLOAT_OES: + case GL_FLOAT: + break; + default: + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + + // validate + combinations + // - invalid -> sets INVALID_ENUM + // - invalid + combination -> sets INVALID_OPERATION + switch (format) + { + case GL_ALPHA: + case GL_LUMINANCE: + case GL_LUMINANCE_ALPHA: + switch (type) + { + case GL_UNSIGNED_BYTE: + case GL_FLOAT: + case GL_HALF_FLOAT_OES: + break; + default: + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + break; + case GL_RED: + case GL_RG: + if (!context->getExtensions().textureRG) + { + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + switch (type) + { + case GL_UNSIGNED_BYTE: + case GL_FLOAT: + case GL_HALF_FLOAT_OES: + break; + default: + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + break; + case GL_RGB: + switch (type) + { + case GL_UNSIGNED_BYTE: + case GL_UNSIGNED_SHORT_5_6_5: + case GL_FLOAT: + case GL_HALF_FLOAT_OES: + break; + default: + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + break; + case GL_RGBA: + switch (type) + { + case GL_UNSIGNED_BYTE: + case GL_UNSIGNED_SHORT_4_4_4_4: + case GL_UNSIGNED_SHORT_5_5_5_1: + case GL_FLOAT: + case GL_HALF_FLOAT_OES: + break; + default: + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + break; + case GL_BGRA_EXT: + switch (type) + { + case GL_UNSIGNED_BYTE: + break; + default: + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + break; + case GL_SRGB_EXT: + case GL_SRGB_ALPHA_EXT: + if (!context->getExtensions().sRGB) + { + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + switch (type) + { + case GL_UNSIGNED_BYTE: + break; + default: + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + break; + case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: // error cases for compressed textures are handled below + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: + case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: + break; + case GL_DEPTH_COMPONENT: + switch (type) + { + case GL_UNSIGNED_SHORT: + case GL_UNSIGNED_INT: + break; + default: + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + break; + case GL_DEPTH_STENCIL_OES: + switch (type) + { + case GL_UNSIGNED_INT_24_8_OES: + break; + default: + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + break; + default: + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + + switch (format) + { + case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + if (context->getExtensions().textureCompressionDXT1) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + else + { + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + break; + case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: + if (context->getExtensions().textureCompressionDXT3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + else + { + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + break; + case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: + if (context->getExtensions().textureCompressionDXT5) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + else + { + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + break; + case GL_DEPTH_COMPONENT: + case GL_DEPTH_STENCIL_OES: + if (!context->getExtensions().depthTextures) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + if (target != GL_TEXTURE_2D) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + // OES_depth_texture supports loading depth data and multiple levels, + // but ANGLE_depth_texture does not + if (pixels != NULL || level != 0) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + break; + default: + break; + } + + if (type == GL_FLOAT) + { + if (!context->getExtensions().textureFloat) + { + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + } + else if (type == GL_HALF_FLOAT_OES) + { + if (!context->getExtensions().textureHalfFloat) + { + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + } + } + + return true; +} + + + +bool ValidateES2CopyTexImageParameters(Context* context, GLenum target, GLint level, GLenum internalformat, bool isSubImage, + GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, + GLint border) +{ + GLenum textureInternalFormat = GL_NONE; + + if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage, + xoffset, yoffset, 0, x, y, width, height, border, &textureInternalFormat)) + { + return false; + } + + gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer(); + GLenum colorbufferFormat = framebuffer->getReadColorbuffer()->getInternalFormat(); + const auto &internalFormatInfo = gl::GetInternalFormatInfo(textureInternalFormat); + GLenum textureFormat = internalFormatInfo.format; + + // [OpenGL ES 2.0.24] table 3.9 + if (isSubImage) + { + switch (textureFormat) + { + case GL_ALPHA: + if (colorbufferFormat != GL_ALPHA8_EXT && + colorbufferFormat != GL_RGBA4 && + colorbufferFormat != GL_RGB5_A1 && + colorbufferFormat != GL_RGBA8_OES) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + break; + case GL_LUMINANCE: + if (colorbufferFormat != GL_R8_EXT && + colorbufferFormat != GL_RG8_EXT && + colorbufferFormat != GL_RGB565 && + colorbufferFormat != GL_RGB8_OES && + colorbufferFormat != GL_RGBA4 && + colorbufferFormat != GL_RGB5_A1 && + colorbufferFormat != GL_RGBA8_OES) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + break; + case GL_RED_EXT: + if (colorbufferFormat != GL_R8_EXT && + colorbufferFormat != GL_RG8_EXT && + colorbufferFormat != GL_RGB565 && + colorbufferFormat != GL_RGB8_OES && + colorbufferFormat != GL_RGBA4 && + colorbufferFormat != GL_RGB5_A1 && + colorbufferFormat != GL_RGBA8_OES && + colorbufferFormat != GL_R32F && + colorbufferFormat != GL_RG32F && + colorbufferFormat != GL_RGB32F && + colorbufferFormat != GL_RGBA32F) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + break; + case GL_RG_EXT: + if (colorbufferFormat != GL_RG8_EXT && + colorbufferFormat != GL_RGB565 && + colorbufferFormat != GL_RGB8_OES && + colorbufferFormat != GL_RGBA4 && + colorbufferFormat != GL_RGB5_A1 && + colorbufferFormat != GL_RGBA8_OES && + colorbufferFormat != GL_RG32F && + colorbufferFormat != GL_RGB32F && + colorbufferFormat != GL_RGBA32F) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + break; + case GL_RGB: + if (colorbufferFormat != GL_RGB565 && + colorbufferFormat != GL_RGB8_OES && + colorbufferFormat != GL_RGBA4 && + colorbufferFormat != GL_RGB5_A1 && + colorbufferFormat != GL_RGBA8_OES && + colorbufferFormat != GL_RGB32F && + colorbufferFormat != GL_RGBA32F) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + break; + case GL_LUMINANCE_ALPHA: + case GL_RGBA: + if (colorbufferFormat != GL_RGBA4 && + colorbufferFormat != GL_RGB5_A1 && + colorbufferFormat != GL_RGBA8_OES && + colorbufferFormat != GL_RGBA32F) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + 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: + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + case GL_DEPTH_COMPONENT: + case GL_DEPTH_STENCIL_OES: + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + default: + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + if (internalFormatInfo.type == GL_FLOAT && + !context->getExtensions().textureFloat) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + } + else + { + switch (internalformat) + { + case GL_ALPHA: + if (colorbufferFormat != GL_ALPHA8_EXT && + colorbufferFormat != GL_RGBA4 && + colorbufferFormat != GL_RGB5_A1 && + colorbufferFormat != GL_BGRA8_EXT && + colorbufferFormat != GL_RGBA8_OES && + colorbufferFormat != GL_BGR5_A1_ANGLEX) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + break; + case GL_LUMINANCE: + if (colorbufferFormat != GL_R8_EXT && + colorbufferFormat != GL_RG8_EXT && + colorbufferFormat != GL_RGB565 && + colorbufferFormat != GL_RGB8_OES && + colorbufferFormat != GL_RGBA4 && + colorbufferFormat != GL_RGB5_A1 && + colorbufferFormat != GL_BGRA8_EXT && + colorbufferFormat != GL_RGBA8_OES && + colorbufferFormat != GL_BGR5_A1_ANGLEX) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + break; + case GL_RED_EXT: + if (colorbufferFormat != GL_R8_EXT && + colorbufferFormat != GL_RG8_EXT && + colorbufferFormat != GL_RGB565 && + colorbufferFormat != GL_RGB8_OES && + colorbufferFormat != GL_RGBA4 && + colorbufferFormat != GL_RGB5_A1 && + colorbufferFormat != GL_BGRA8_EXT && + colorbufferFormat != GL_RGBA8_OES && + colorbufferFormat != GL_BGR5_A1_ANGLEX) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + break; + case GL_RG_EXT: + if (colorbufferFormat != GL_RG8_EXT && + colorbufferFormat != GL_RGB565 && + colorbufferFormat != GL_RGB8_OES && + colorbufferFormat != GL_RGBA4 && + colorbufferFormat != GL_RGB5_A1 && + colorbufferFormat != GL_BGRA8_EXT && + colorbufferFormat != GL_RGBA8_OES && + colorbufferFormat != GL_BGR5_A1_ANGLEX) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + break; + case GL_RGB: + if (colorbufferFormat != GL_RGB565 && + colorbufferFormat != GL_RGB8_OES && + colorbufferFormat != GL_RGBA4 && + colorbufferFormat != GL_RGB5_A1 && + colorbufferFormat != GL_BGRA8_EXT && + colorbufferFormat != GL_RGBA8_OES && + colorbufferFormat != GL_BGR5_A1_ANGLEX) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + break; + case GL_LUMINANCE_ALPHA: + case GL_RGBA: + if (colorbufferFormat != GL_RGBA4 && + colorbufferFormat != GL_RGB5_A1 && + colorbufferFormat != GL_BGRA8_EXT && + colorbufferFormat != GL_RGBA8_OES && + colorbufferFormat != GL_BGR5_A1_ANGLEX) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + break; + case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + if (context->getExtensions().textureCompressionDXT1) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + else + { + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + break; + case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: + if (context->getExtensions().textureCompressionDXT3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + else + { + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + break; + case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: + if (context->getExtensions().textureCompressionDXT5) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + else + { + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + break; + case GL_DEPTH_COMPONENT: + case GL_DEPTH_COMPONENT16: + case GL_DEPTH_COMPONENT32_OES: + case GL_DEPTH_STENCIL_OES: + case GL_DEPTH24_STENCIL8_OES: + if (context->getExtensions().depthTextures) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + else + { + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + default: + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + } + + // If width or height is zero, it is a no-op. Return false without setting an error. + return (width > 0 && height > 0); +} + +bool ValidateES2TexStorageParameters(Context *context, GLenum target, GLsizei levels, GLenum internalformat, + GLsizei width, GLsizei height) +{ + if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP) + { + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + + if (width < 1 || height < 1 || levels < 1) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + + if (target == GL_TEXTURE_CUBE_MAP && width != height) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + + if (levels != 1 && levels != gl::log2(std::max(width, height)) + 1) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat); + if (formatInfo.format == GL_NONE || formatInfo.type == GL_NONE) + { + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + + const gl::Caps &caps = context->getCaps(); + + switch (target) + { + case GL_TEXTURE_2D: + if (static_cast(width) > caps.max2DTextureSize || + static_cast(height) > caps.max2DTextureSize) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + break; + case GL_TEXTURE_CUBE_MAP: + if (static_cast(width) > caps.maxCubeMapTextureSize || + static_cast(height) > caps.maxCubeMapTextureSize) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + break; + default: + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + + if (levels != 1 && !context->getExtensions().textureNPOT) + { + if (!gl::isPow2(width) || !gl::isPow2(height)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + } + + switch (internalformat) + { + case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + if (!context->getExtensions().textureCompressionDXT1) + { + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + break; + case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: + if (!context->getExtensions().textureCompressionDXT3) + { + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + break; + case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: + if (!context->getExtensions().textureCompressionDXT5) + { + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + break; + case GL_RGBA32F_EXT: + case GL_RGB32F_EXT: + case GL_ALPHA32F_EXT: + case GL_LUMINANCE32F_EXT: + case GL_LUMINANCE_ALPHA32F_EXT: + if (!context->getExtensions().textureFloat) + { + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + break; + case GL_RGBA16F_EXT: + case GL_RGB16F_EXT: + case GL_ALPHA16F_EXT: + case GL_LUMINANCE16F_EXT: + case GL_LUMINANCE_ALPHA16F_EXT: + if (!context->getExtensions().textureHalfFloat) + { + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + break; + case GL_R8_EXT: + case GL_RG8_EXT: + case GL_R16F_EXT: + case GL_RG16F_EXT: + case GL_R32F_EXT: + case GL_RG32F_EXT: + if (!context->getExtensions().textureRG) + { + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + break; + case GL_DEPTH_COMPONENT16: + case GL_DEPTH_COMPONENT32_OES: + case GL_DEPTH24_STENCIL8_OES: + if (!context->getExtensions().depthTextures) + { + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + if (target != GL_TEXTURE_2D) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + // ANGLE_depth_texture only supports 1-level textures + if (levels != 1) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + break; + default: + break; + } + + gl::Texture *texture = context->getTargetTexture(target); + if (!texture || texture->id() == 0) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + if (texture->isImmutable()) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + return true; +} + +// check for combinations of format and type that are valid for ReadPixels +bool ValidES2ReadFormatType(Context *context, GLenum format, GLenum type) +{ + switch (format) + { + case GL_RGBA: + switch (type) + { + case GL_UNSIGNED_BYTE: + break; + default: + return false; + } + break; + case GL_BGRA_EXT: + switch (type) + { + case GL_UNSIGNED_BYTE: + case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT: + case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT: + break; + default: + return false; + } + break; + case GL_RG_EXT: + case GL_RED_EXT: + if (!context->getExtensions().textureRG) + { + return false; + } + switch (type) + { + case GL_UNSIGNED_BYTE: + break; + default: + return false; + } + break; + + default: + return false; + } + return true; +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/validationES2.h b/src/3rdparty/angle/src/libANGLE/validationES2.h new file mode 100644 index 0000000000..b9c1fd3bc4 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/validationES2.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. +// + +// validationES2.h: Validation functions for OpenGL ES 2.0 entry point parameters + +#ifndef LIBANGLE_VALIDATION_ES2_H_ +#define LIBANGLE_VALIDATION_ES2_H_ + +#include + +namespace gl +{ + +class Context; + +bool ValidateES2TexImageParameters(Context *context, GLenum target, GLint level, GLenum internalformat, bool isCompressed, bool isSubImage, + GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + GLint border, GLenum format, GLenum type, const GLvoid *pixels); + +bool ValidateES2CopyTexImageParameters(Context* context, GLenum target, GLint level, GLenum internalformat, bool isSubImage, + GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, + GLint border); + +bool ValidateES2TexStorageParameters(Context *context, GLenum target, GLsizei levels, GLenum internalformat, + GLsizei width, GLsizei height); + +bool ValidES2ReadFormatType(Context *context, GLenum format, GLenum type); + +} + +#endif // LIBANGLE_VALIDATION_ES2_H_ diff --git a/src/3rdparty/angle/src/libANGLE/validationES3.cpp b/src/3rdparty/angle/src/libANGLE/validationES3.cpp new file mode 100644 index 0000000000..e141bb6ece --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/validationES3.cpp @@ -0,0 +1,1282 @@ +// +// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// validationES3.cpp: Validation functions for OpenGL ES 3.0 entry point parameters + +#include "libANGLE/validationES3.h" +#include "libANGLE/validationES.h" +#include "libANGLE/Context.h" +#include "libANGLE/Texture.h" +#include "libANGLE/Framebuffer.h" +#include "libANGLE/Renderbuffer.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/FramebufferAttachment.h" + +#include "common/mathutil.h" +#include "common/utilities.h" + +namespace gl +{ + +struct ES3FormatCombination +{ + GLenum internalFormat; + GLenum format; + GLenum type; +}; + +bool operator<(const ES3FormatCombination& a, const ES3FormatCombination& b) +{ + return memcmp(&a, &b, sizeof(ES3FormatCombination)) < 0; +} + +typedef std::set ES3FormatCombinationSet; + +static inline void InsertES3FormatCombo(ES3FormatCombinationSet *set, GLenum internalFormat, GLenum format, GLenum type) +{ + ES3FormatCombination info; + info.internalFormat = internalFormat; + info.format = format; + info.type = type; + set->insert(info); +} + +ES3FormatCombinationSet BuildES3FormatSet() +{ + ES3FormatCombinationSet set; + + // Format combinations from ES 3.0.1 spec, table 3.2 + + // | Internal format | Format | Type | + // | | | | + InsertES3FormatCombo(&set, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE ); + InsertES3FormatCombo(&set, GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_BYTE ); + InsertES3FormatCombo(&set, GL_RGBA4, GL_RGBA, GL_UNSIGNED_BYTE ); + InsertES3FormatCombo(&set, GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE ); + InsertES3FormatCombo(&set, GL_RGBA8_SNORM, GL_RGBA, GL_BYTE ); + InsertES3FormatCombo(&set, GL_RGBA4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4 ); + InsertES3FormatCombo(&set, GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV ); + InsertES3FormatCombo(&set, GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV ); + InsertES3FormatCombo(&set, GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1 ); + InsertES3FormatCombo(&set, GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT ); + InsertES3FormatCombo(&set, GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT_OES ); + InsertES3FormatCombo(&set, GL_RGBA32F, GL_RGBA, GL_FLOAT ); + InsertES3FormatCombo(&set, GL_RGBA16F, GL_RGBA, GL_FLOAT ); + InsertES3FormatCombo(&set, GL_RGBA8UI, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE ); + InsertES3FormatCombo(&set, GL_RGBA8I, GL_RGBA_INTEGER, GL_BYTE ); + InsertES3FormatCombo(&set, GL_RGBA16UI, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT ); + InsertES3FormatCombo(&set, GL_RGBA16I, GL_RGBA_INTEGER, GL_SHORT ); + InsertES3FormatCombo(&set, GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT ); + InsertES3FormatCombo(&set, GL_RGBA32I, GL_RGBA_INTEGER, GL_INT ); + InsertES3FormatCombo(&set, GL_RGB10_A2UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV ); + InsertES3FormatCombo(&set, GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE ); + InsertES3FormatCombo(&set, GL_RGB565, GL_RGB, GL_UNSIGNED_BYTE ); + InsertES3FormatCombo(&set, GL_SRGB8, GL_RGB, GL_UNSIGNED_BYTE ); + InsertES3FormatCombo(&set, GL_RGB8_SNORM, GL_RGB, GL_BYTE ); + InsertES3FormatCombo(&set, GL_RGB565, GL_RGB, GL_UNSIGNED_SHORT_5_6_5 ); + InsertES3FormatCombo(&set, GL_R11F_G11F_B10F, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV ); + InsertES3FormatCombo(&set, GL_RGB9_E5, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV ); + InsertES3FormatCombo(&set, GL_RGB16F, GL_RGB, GL_HALF_FLOAT ); + InsertES3FormatCombo(&set, GL_RGB16F, GL_RGB, GL_HALF_FLOAT_OES ); + InsertES3FormatCombo(&set, GL_R11F_G11F_B10F, GL_RGB, GL_HALF_FLOAT ); + InsertES3FormatCombo(&set, GL_R11F_G11F_B10F, GL_RGB, GL_HALF_FLOAT_OES ); + InsertES3FormatCombo(&set, GL_RGB9_E5, GL_RGB, GL_HALF_FLOAT ); + InsertES3FormatCombo(&set, GL_RGB9_E5, GL_RGB, GL_HALF_FLOAT_OES ); + InsertES3FormatCombo(&set, GL_RGB32F, GL_RGB, GL_FLOAT ); + InsertES3FormatCombo(&set, GL_RGB16F, GL_RGB, GL_FLOAT ); + InsertES3FormatCombo(&set, GL_R11F_G11F_B10F, GL_RGB, GL_FLOAT ); + InsertES3FormatCombo(&set, GL_RGB9_E5, GL_RGB, GL_FLOAT ); + InsertES3FormatCombo(&set, GL_RGB8UI, GL_RGB_INTEGER, GL_UNSIGNED_BYTE ); + InsertES3FormatCombo(&set, GL_RGB8I, GL_RGB_INTEGER, GL_BYTE ); + InsertES3FormatCombo(&set, GL_RGB16UI, GL_RGB_INTEGER, GL_UNSIGNED_SHORT ); + InsertES3FormatCombo(&set, GL_RGB16I, GL_RGB_INTEGER, GL_SHORT ); + InsertES3FormatCombo(&set, GL_RGB32UI, GL_RGB_INTEGER, GL_UNSIGNED_INT ); + InsertES3FormatCombo(&set, GL_RGB32I, GL_RGB_INTEGER, GL_INT ); + InsertES3FormatCombo(&set, GL_RG8, GL_RG, GL_UNSIGNED_BYTE ); + InsertES3FormatCombo(&set, GL_RG8_SNORM, GL_RG, GL_BYTE ); + InsertES3FormatCombo(&set, GL_RG16F, GL_RG, GL_HALF_FLOAT ); + InsertES3FormatCombo(&set, GL_RG16F, GL_RG, GL_HALF_FLOAT_OES ); + InsertES3FormatCombo(&set, GL_RG32F, GL_RG, GL_FLOAT ); + InsertES3FormatCombo(&set, GL_RG16F, GL_RG, GL_FLOAT ); + InsertES3FormatCombo(&set, GL_RG8UI, GL_RG_INTEGER, GL_UNSIGNED_BYTE ); + InsertES3FormatCombo(&set, GL_RG8I, GL_RG_INTEGER, GL_BYTE ); + InsertES3FormatCombo(&set, GL_RG16UI, GL_RG_INTEGER, GL_UNSIGNED_SHORT ); + InsertES3FormatCombo(&set, GL_RG16I, GL_RG_INTEGER, GL_SHORT ); + InsertES3FormatCombo(&set, GL_RG32UI, GL_RG_INTEGER, GL_UNSIGNED_INT ); + InsertES3FormatCombo(&set, GL_RG32I, GL_RG_INTEGER, GL_INT ); + InsertES3FormatCombo(&set, GL_R8, GL_RED, GL_UNSIGNED_BYTE ); + InsertES3FormatCombo(&set, GL_R8_SNORM, GL_RED, GL_BYTE ); + InsertES3FormatCombo(&set, GL_R16F, GL_RED, GL_HALF_FLOAT ); + InsertES3FormatCombo(&set, GL_R16F, GL_RED, GL_HALF_FLOAT_OES ); + InsertES3FormatCombo(&set, GL_R32F, GL_RED, GL_FLOAT ); + InsertES3FormatCombo(&set, GL_R16F, GL_RED, GL_FLOAT ); + InsertES3FormatCombo(&set, GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE ); + InsertES3FormatCombo(&set, GL_R8I, GL_RED_INTEGER, GL_BYTE ); + InsertES3FormatCombo(&set, GL_R16UI, GL_RED_INTEGER, GL_UNSIGNED_SHORT ); + InsertES3FormatCombo(&set, GL_R16I, GL_RED_INTEGER, GL_SHORT ); + InsertES3FormatCombo(&set, GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT ); + InsertES3FormatCombo(&set, GL_R32I, GL_RED_INTEGER, GL_INT ); + + // Unsized formats + InsertES3FormatCombo(&set, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE ); + InsertES3FormatCombo(&set, GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4 ); + InsertES3FormatCombo(&set, GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1 ); + InsertES3FormatCombo(&set, GL_RGB, GL_RGB, GL_UNSIGNED_BYTE ); + InsertES3FormatCombo(&set, GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5 ); + InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE ); + InsertES3FormatCombo(&set, GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE ); + InsertES3FormatCombo(&set, GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE ); + InsertES3FormatCombo(&set, GL_SRGB_ALPHA_EXT, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE ); + InsertES3FormatCombo(&set, GL_SRGB_EXT, GL_SRGB_EXT, GL_UNSIGNED_BYTE ); + + // Depth stencil formats + InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT ); + InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT ); + InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT ); + InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT ); + InsertES3FormatCombo(&set, GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8 ); + InsertES3FormatCombo(&set, GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV); + + // From GL_EXT_sRGB + InsertES3FormatCombo(&set, GL_SRGB8_ALPHA8_EXT, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE ); + InsertES3FormatCombo(&set, GL_SRGB8, GL_SRGB_EXT, GL_UNSIGNED_BYTE ); + + // From GL_OES_texture_float + InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_FLOAT ); + InsertES3FormatCombo(&set, GL_LUMINANCE, GL_LUMINANCE, GL_FLOAT ); + InsertES3FormatCombo(&set, GL_ALPHA, GL_ALPHA, GL_FLOAT ); + + // From GL_OES_texture_half_float + InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT ); + InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES ); + InsertES3FormatCombo(&set, GL_LUMINANCE, GL_LUMINANCE, GL_HALF_FLOAT ); + InsertES3FormatCombo(&set, GL_LUMINANCE, GL_LUMINANCE, GL_HALF_FLOAT_OES ); + InsertES3FormatCombo(&set, GL_ALPHA, GL_ALPHA, GL_HALF_FLOAT ); + InsertES3FormatCombo(&set, GL_ALPHA, GL_ALPHA, GL_HALF_FLOAT_OES ); + + // From GL_EXT_texture_format_BGRA8888 + InsertES3FormatCombo(&set, GL_BGRA_EXT, GL_BGRA_EXT, GL_UNSIGNED_BYTE ); + + // From GL_EXT_texture_storage + // | Internal format | Format | Type | + // | | | | + InsertES3FormatCombo(&set, GL_ALPHA8_EXT, GL_ALPHA, GL_UNSIGNED_BYTE ); + InsertES3FormatCombo(&set, GL_LUMINANCE8_EXT, GL_LUMINANCE, GL_UNSIGNED_BYTE ); + InsertES3FormatCombo(&set, GL_LUMINANCE8_ALPHA8_EXT, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE ); + InsertES3FormatCombo(&set, GL_ALPHA32F_EXT, GL_ALPHA, GL_FLOAT ); + InsertES3FormatCombo(&set, GL_LUMINANCE32F_EXT, GL_LUMINANCE, GL_FLOAT ); + InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA32F_EXT, GL_LUMINANCE_ALPHA, GL_FLOAT ); + InsertES3FormatCombo(&set, GL_ALPHA16F_EXT, GL_ALPHA, GL_HALF_FLOAT ); + InsertES3FormatCombo(&set, GL_ALPHA16F_EXT, GL_ALPHA, GL_HALF_FLOAT_OES ); + InsertES3FormatCombo(&set, GL_LUMINANCE16F_EXT, GL_LUMINANCE, GL_HALF_FLOAT ); + InsertES3FormatCombo(&set, GL_LUMINANCE16F_EXT, GL_LUMINANCE, GL_HALF_FLOAT_OES ); + InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA16F_EXT, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT ); + InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA16F_EXT, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES ); + + // From GL_EXT_texture_storage and GL_EXT_texture_format_BGRA8888 + InsertES3FormatCombo(&set, GL_BGRA8_EXT, GL_BGRA_EXT, GL_UNSIGNED_BYTE ); + InsertES3FormatCombo(&set, GL_BGRA4_ANGLEX, GL_BGRA_EXT, GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT); + InsertES3FormatCombo(&set, GL_BGRA4_ANGLEX, GL_BGRA_EXT, GL_UNSIGNED_BYTE ); + InsertES3FormatCombo(&set, GL_BGR5_A1_ANGLEX, GL_BGRA_EXT, GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT); + InsertES3FormatCombo(&set, GL_BGR5_A1_ANGLEX, GL_BGRA_EXT, GL_UNSIGNED_BYTE ); + + // From GL_ANGLE_depth_texture + InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT32_OES, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT_24_8_OES ); + + // Compressed formats + // From ES 3.0.1 spec, table 3.16 + // | Internal format | Format | Type | + // | | | | + InsertES3FormatCombo(&set, GL_COMPRESSED_R11_EAC, GL_COMPRESSED_R11_EAC, GL_UNSIGNED_BYTE); + InsertES3FormatCombo(&set, GL_COMPRESSED_R11_EAC, GL_COMPRESSED_R11_EAC, GL_UNSIGNED_BYTE); + InsertES3FormatCombo(&set, GL_COMPRESSED_SIGNED_R11_EAC, GL_COMPRESSED_SIGNED_R11_EAC, GL_UNSIGNED_BYTE); + InsertES3FormatCombo(&set, GL_COMPRESSED_RG11_EAC, GL_COMPRESSED_RG11_EAC, GL_UNSIGNED_BYTE); + InsertES3FormatCombo(&set, GL_COMPRESSED_SIGNED_RG11_EAC, GL_COMPRESSED_SIGNED_RG11_EAC, GL_UNSIGNED_BYTE); + InsertES3FormatCombo(&set, GL_COMPRESSED_RGB8_ETC2, GL_COMPRESSED_RGB8_ETC2, GL_UNSIGNED_BYTE); + InsertES3FormatCombo(&set, GL_COMPRESSED_SRGB8_ETC2, GL_COMPRESSED_SRGB8_ETC2, GL_UNSIGNED_BYTE); + InsertES3FormatCombo(&set, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_UNSIGNED_BYTE); + InsertES3FormatCombo(&set, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_UNSIGNED_BYTE); + InsertES3FormatCombo(&set, GL_COMPRESSED_RGBA8_ETC2_EAC, GL_COMPRESSED_RGBA8_ETC2_EAC, GL_UNSIGNED_BYTE); + InsertES3FormatCombo(&set, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, GL_UNSIGNED_BYTE); + + + // From GL_EXT_texture_compression_dxt1 + InsertES3FormatCombo(&set, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE); + InsertES3FormatCombo(&set, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE); + + // From GL_ANGLE_texture_compression_dxt3 + InsertES3FormatCombo(&set, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, GL_UNSIGNED_BYTE); + + // From GL_ANGLE_texture_compression_dxt5 + InsertES3FormatCombo(&set, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, GL_UNSIGNED_BYTE); + + return set; +} + +static bool ValidateTexImageFormatCombination(gl::Context *context, GLenum internalFormat, GLenum format, GLenum type) +{ + // Note: dEQP 2013.4 expects an INVALID_VALUE error for TexImage3D with an invalid + // internal format. (dEQP-GLES3.functional.negative_api.texture.teximage3d) + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat); + if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions())) + { + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + + // The type and format are valid if any supported internal format has that type and format + bool formatSupported = false; + bool typeSupported = false; + + static const ES3FormatCombinationSet es3FormatSet = BuildES3FormatSet(); + for (ES3FormatCombinationSet::const_iterator i = es3FormatSet.begin(); i != es3FormatSet.end(); i++) + { + if (i->format == format || i->type == type) + { + const gl::InternalFormat &info = gl::GetInternalFormatInfo(i->internalFormat); + bool supported = info.textureSupport(context->getClientVersion(), context->getExtensions()); + if (supported && i->type == type) + { + typeSupported = true; + } + if (supported && i->format == format) + { + formatSupported = true; + } + + // Early-out if both type and format are supported now + if (typeSupported && formatSupported) + { + break; + } + } + } + + if (!typeSupported || !formatSupported) + { + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + + // Check if this is a valid format combination to load texture data + ES3FormatCombination searchFormat; + searchFormat.internalFormat = internalFormat; + searchFormat.format = format; + searchFormat.type = type; + + if (es3FormatSet.find(searchFormat) == es3FormatSet.end()) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + return true; +} + +bool ValidateES3TexImageParameters(Context *context, GLenum target, GLint level, GLenum internalformat, bool isCompressed, bool isSubImage, + GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, + GLint border, GLenum format, GLenum type, const GLvoid *pixels) +{ + if (!ValidTexture2DDestinationTarget(context, target)) + { + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + + // Validate image size + if (!ValidImageSize(context, target, level, width, height, depth)) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + + // Verify zero border + if (border != 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + + if (xoffset < 0 || yoffset < 0 || zoffset < 0 || + std::numeric_limits::max() - xoffset < width || + std::numeric_limits::max() - yoffset < height || + std::numeric_limits::max() - zoffset < depth) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + + const gl::Caps &caps = context->getCaps(); + + switch (target) + { + case GL_TEXTURE_2D: + if (static_cast(width) > (caps.max2DTextureSize >> level) || + static_cast(height) > (caps.max2DTextureSize >> level)) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + break; + + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: + if (!isSubImage && width != height) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + + if (static_cast(width) > (caps.maxCubeMapTextureSize >> level)) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + break; + + case GL_TEXTURE_3D: + if (static_cast(width) > (caps.max3DTextureSize >> level) || + static_cast(height) > (caps.max3DTextureSize >> level) || + static_cast(depth) > (caps.max3DTextureSize >> level)) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + break; + + case GL_TEXTURE_2D_ARRAY: + if (static_cast(width) > (caps.max2DTextureSize >> level) || + static_cast(height) > (caps.max2DTextureSize >> level) || + static_cast(depth) > (caps.maxArrayTextureLayers >> level)) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + + gl::Texture *texture = context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target); + if (!texture) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + if (texture->isImmutable() && !isSubImage) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + // Validate texture formats + GLenum actualInternalFormat = isSubImage ? texture->getInternalFormat(target, level) : internalformat; + const gl::InternalFormat &actualFormatInfo = gl::GetInternalFormatInfo(actualInternalFormat); + if (isCompressed) + { + if (!ValidCompressedImageSize(context, actualInternalFormat, width, height)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + if (!actualFormatInfo.compressed) + { + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + + if (target == GL_TEXTURE_3D) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + } + else + { + if (!ValidateTexImageFormatCombination(context, actualInternalFormat, format, type)) + { + return false; + } + + if (target == GL_TEXTURE_3D && (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + } + + // Validate sub image parameters + if (isSubImage) + { + if (isCompressed != actualFormatInfo.compressed) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + if (width == 0 || height == 0 || depth == 0) + { + return false; + } + + if (xoffset < 0 || yoffset < 0 || zoffset < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + + if (std::numeric_limits::max() - xoffset < width || + std::numeric_limits::max() - yoffset < height || + std::numeric_limits::max() - zoffset < depth) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + + if (static_cast(xoffset + width) > texture->getWidth(target, level) || + static_cast(yoffset + height) > texture->getHeight(target, level) || + static_cast(zoffset + depth) > texture->getDepth(target, level)) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + } + + // Check for pixel unpack buffer related API errors + gl::Buffer *pixelUnpackBuffer = context->getState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER); + if (pixelUnpackBuffer != NULL) + { + // ...the data would be unpacked from the buffer object such that the memory reads required + // would exceed the data store size. + size_t widthSize = static_cast(width); + size_t heightSize = static_cast(height); + size_t depthSize = static_cast(depth); + GLenum sizedFormat = GetSizedInternalFormat(actualInternalFormat, type); + + size_t pixelBytes = static_cast(gl::GetInternalFormatInfo(sizedFormat).pixelBytes); + + if (!rx::IsUnsignedMultiplicationSafe(widthSize, heightSize) || + !rx::IsUnsignedMultiplicationSafe(widthSize * heightSize, depthSize) || + !rx::IsUnsignedMultiplicationSafe(widthSize * heightSize * depthSize, pixelBytes)) + { + // Overflow past the end of the buffer + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedFormat); + size_t copyBytes = formatInfo.computeBlockSize(type, width, height); + size_t offset = reinterpret_cast(pixels); + + if (!rx::IsUnsignedAdditionSafe(offset, copyBytes) || + ((offset + copyBytes) > static_cast(pixelUnpackBuffer->getSize()))) + { + // Overflow past the end of the buffer + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + // ...data is not evenly divisible into the number of bytes needed to store in memory a datum + // indicated by type. + if (!isCompressed) + { + size_t dataBytesPerPixel = static_cast(gl::GetTypeInfo(type).bytes); + + if ((offset % dataBytesPerPixel) != 0) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + } + + // ...the buffer object's data store is currently mapped. + if (pixelUnpackBuffer->isMapped()) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + } + + return true; +} + +struct EffectiveInternalFormatInfo +{ + GLenum mEffectiveFormat; + GLenum mDestFormat; + GLuint mMinRedBits; + GLuint mMaxRedBits; + GLuint mMinGreenBits; + GLuint mMaxGreenBits; + GLuint mMinBlueBits; + GLuint mMaxBlueBits; + GLuint mMinAlphaBits; + GLuint mMaxAlphaBits; + + EffectiveInternalFormatInfo(GLenum effectiveFormat, GLenum destFormat, GLuint minRedBits, GLuint maxRedBits, + GLuint minGreenBits, GLuint maxGreenBits, GLuint minBlueBits, GLuint maxBlueBits, + GLuint minAlphaBits, GLuint maxAlphaBits) + : mEffectiveFormat(effectiveFormat), mDestFormat(destFormat), mMinRedBits(minRedBits), + mMaxRedBits(maxRedBits), mMinGreenBits(minGreenBits), mMaxGreenBits(maxGreenBits), + mMinBlueBits(minBlueBits), mMaxBlueBits(maxBlueBits), mMinAlphaBits(minAlphaBits), + mMaxAlphaBits(maxAlphaBits) {}; +}; + +typedef std::vector EffectiveInternalFormatList; + +static EffectiveInternalFormatList BuildSizedEffectiveInternalFormatList() +{ + EffectiveInternalFormatList list; + + // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141: Effective internal format coresponding to destination internal format and + // linear source buffer component sizes. + // | Source channel min/max sizes | + // Effective Internal Format | N/A | R | G | B | A | + list.push_back(EffectiveInternalFormatInfo(GL_ALPHA8_EXT, GL_NONE, 0, 0, 0, 0, 0, 0, 1, 8)); + list.push_back(EffectiveInternalFormatInfo(GL_R8, GL_NONE, 1, 8, 0, 0, 0, 0, 0, 0)); + list.push_back(EffectiveInternalFormatInfo(GL_RG8, GL_NONE, 1, 8, 1, 8, 0, 0, 0, 0)); + list.push_back(EffectiveInternalFormatInfo(GL_RGB565, GL_NONE, 1, 5, 1, 6, 1, 5, 0, 0)); + list.push_back(EffectiveInternalFormatInfo(GL_RGB8, GL_NONE, 6, 8, 7, 8, 6, 8, 0, 0)); + list.push_back(EffectiveInternalFormatInfo(GL_RGBA4, GL_NONE, 1, 4, 1, 4, 1, 4, 1, 4)); + list.push_back(EffectiveInternalFormatInfo(GL_RGB5_A1, GL_NONE, 5, 5, 5, 5, 5, 5, 1, 1)); + list.push_back(EffectiveInternalFormatInfo(GL_RGBA8, GL_NONE, 5, 8, 5, 8, 5, 8, 2, 8)); + list.push_back(EffectiveInternalFormatInfo(GL_RGB10_A2, GL_NONE, 9, 10, 9, 10, 9, 10, 2, 2)); + + return list; +} + +static EffectiveInternalFormatList BuildUnsizedEffectiveInternalFormatList() +{ + EffectiveInternalFormatList list; + + // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141: Effective internal format coresponding to destination internal format and + // linear source buffer component sizes. + // | Source channel min/max sizes | + // Effective Internal Format | Dest Format | R | G | B | A | + list.push_back(EffectiveInternalFormatInfo(GL_ALPHA8_EXT, GL_ALPHA, 0, UINT_MAX, 0, UINT_MAX, 0, UINT_MAX, 1, 8)); + list.push_back(EffectiveInternalFormatInfo(GL_LUMINANCE8_EXT, GL_LUMINANCE, 1, 8, 0, UINT_MAX, 0, UINT_MAX, 0, UINT_MAX)); + list.push_back(EffectiveInternalFormatInfo(GL_LUMINANCE8_ALPHA8_EXT, GL_LUMINANCE_ALPHA, 1, 8, 0, UINT_MAX, 0, UINT_MAX, 1, 8)); + list.push_back(EffectiveInternalFormatInfo(GL_RGB565, GL_RGB, 1, 5, 1, 6, 1, 5, 0, UINT_MAX)); + list.push_back(EffectiveInternalFormatInfo(GL_RGB8, GL_RGB, 6, 8, 7, 8, 6, 8, 0, UINT_MAX)); + list.push_back(EffectiveInternalFormatInfo(GL_RGBA4, GL_RGBA, 1, 4, 1, 4, 1, 4, 1, 4)); + list.push_back(EffectiveInternalFormatInfo(GL_RGB5_A1, GL_RGBA, 5, 5, 5, 5, 5, 5, 1, 1)); + list.push_back(EffectiveInternalFormatInfo(GL_RGBA8, GL_RGBA, 5, 8, 5, 8, 5, 8, 5, 8)); + + return list; +} + +static bool GetEffectiveInternalFormat(const InternalFormat &srcFormat, const InternalFormat &destFormat, + GLenum *outEffectiveFormat) +{ + const EffectiveInternalFormatList *list = NULL; + GLenum targetFormat = GL_NONE; + + if (destFormat.pixelBytes > 0) + { + static const EffectiveInternalFormatList sizedList = BuildSizedEffectiveInternalFormatList(); + list = &sizedList; + } + else + { + static const EffectiveInternalFormatList unsizedList = BuildUnsizedEffectiveInternalFormatList(); + list = &unsizedList; + targetFormat = destFormat.format; + } + + for (size_t curFormat = 0; curFormat < list->size(); ++curFormat) + { + const EffectiveInternalFormatInfo& formatInfo = list->at(curFormat); + if ((formatInfo.mDestFormat == targetFormat) && + (formatInfo.mMinRedBits <= srcFormat.redBits && formatInfo.mMaxRedBits >= srcFormat.redBits) && + (formatInfo.mMinGreenBits <= srcFormat.greenBits && formatInfo.mMaxGreenBits >= srcFormat.greenBits) && + (formatInfo.mMinBlueBits <= srcFormat.blueBits && formatInfo.mMaxBlueBits >= srcFormat.blueBits) && + (formatInfo.mMinAlphaBits <= srcFormat.alphaBits && formatInfo.mMaxAlphaBits >= srcFormat.alphaBits)) + { + *outEffectiveFormat = formatInfo.mEffectiveFormat; + return true; + } + } + + return false; +} + +struct CopyConversion +{ + GLenum mTextureFormat; + GLenum mFramebufferFormat; + + CopyConversion(GLenum textureFormat, GLenum framebufferFormat) + : mTextureFormat(textureFormat), mFramebufferFormat(framebufferFormat) { } + + bool operator<(const CopyConversion& other) const + { + return memcmp(this, &other, sizeof(CopyConversion)) < 0; + } +}; + +typedef std::set CopyConversionSet; + +static CopyConversionSet BuildValidES3CopyTexImageCombinations() +{ + CopyConversionSet set; + + // From ES 3.0.1 spec, table 3.15 + set.insert(CopyConversion(GL_ALPHA, GL_RGBA)); + set.insert(CopyConversion(GL_LUMINANCE, GL_RED)); + set.insert(CopyConversion(GL_LUMINANCE, GL_RG)); + set.insert(CopyConversion(GL_LUMINANCE, GL_RGB)); + set.insert(CopyConversion(GL_LUMINANCE, GL_RGBA)); + set.insert(CopyConversion(GL_LUMINANCE_ALPHA, GL_RGBA)); + set.insert(CopyConversion(GL_RED, GL_RED)); + set.insert(CopyConversion(GL_RED, GL_RG)); + set.insert(CopyConversion(GL_RED, GL_RGB)); + set.insert(CopyConversion(GL_RED, GL_RGBA)); + set.insert(CopyConversion(GL_RG, GL_RG)); + set.insert(CopyConversion(GL_RG, GL_RGB)); + set.insert(CopyConversion(GL_RG, GL_RGBA)); + set.insert(CopyConversion(GL_RGB, GL_RGB)); + set.insert(CopyConversion(GL_RGB, GL_RGBA)); + set.insert(CopyConversion(GL_RGBA, GL_RGBA)); + + // Necessary for ANGLE back-buffers + set.insert(CopyConversion(GL_ALPHA, GL_BGRA_EXT)); + set.insert(CopyConversion(GL_LUMINANCE, GL_BGRA_EXT)); + set.insert(CopyConversion(GL_LUMINANCE_ALPHA, GL_BGRA_EXT)); + set.insert(CopyConversion(GL_RED, GL_BGRA_EXT)); + set.insert(CopyConversion(GL_RG, GL_BGRA_EXT)); + set.insert(CopyConversion(GL_RGB, GL_BGRA_EXT)); + set.insert(CopyConversion(GL_RGBA, GL_BGRA_EXT)); + + set.insert(CopyConversion(GL_RED_INTEGER, GL_RED_INTEGER)); + set.insert(CopyConversion(GL_RED_INTEGER, GL_RG_INTEGER)); + set.insert(CopyConversion(GL_RED_INTEGER, GL_RGB_INTEGER)); + set.insert(CopyConversion(GL_RED_INTEGER, GL_RGBA_INTEGER)); + set.insert(CopyConversion(GL_RG_INTEGER, GL_RG_INTEGER)); + set.insert(CopyConversion(GL_RG_INTEGER, GL_RGB_INTEGER)); + set.insert(CopyConversion(GL_RG_INTEGER, GL_RGBA_INTEGER)); + set.insert(CopyConversion(GL_RGB_INTEGER, GL_RGB_INTEGER)); + set.insert(CopyConversion(GL_RGB_INTEGER, GL_RGBA_INTEGER)); + set.insert(CopyConversion(GL_RGBA_INTEGER, GL_RGBA_INTEGER)); + + return set; +} + +static bool IsValidES3CopyTexImageCombination(GLenum textureInternalFormat, GLenum frameBufferInternalFormat, GLuint readBufferHandle) +{ + const InternalFormat &textureInternalFormatInfo = GetInternalFormatInfo(textureInternalFormat); + const InternalFormat &framebufferInternalFormatInfo = GetInternalFormatInfo(frameBufferInternalFormat); + + static const CopyConversionSet conversionSet = BuildValidES3CopyTexImageCombinations(); + if (conversionSet.find(CopyConversion(textureInternalFormatInfo.format, framebufferInternalFormatInfo.format)) != conversionSet.end()) + { + // Section 3.8.5 of the GLES 3.0.3 spec states that source and destination formats + // must both be signed, unsigned, or fixed point and both source and destinations + // must be either both SRGB or both not SRGB. EXT_color_buffer_float adds allowed + // conversion between fixed and floating point. + + if ((textureInternalFormatInfo.colorEncoding == GL_SRGB) != (framebufferInternalFormatInfo.colorEncoding == GL_SRGB)) + { + return false; + } + + if (((textureInternalFormatInfo.componentType == GL_INT) != (framebufferInternalFormatInfo.componentType == GL_INT )) || + ((textureInternalFormatInfo.componentType == GL_UNSIGNED_INT) != (framebufferInternalFormatInfo.componentType == GL_UNSIGNED_INT))) + { + return false; + } + + if ((textureInternalFormatInfo.componentType == GL_UNSIGNED_NORMALIZED || + textureInternalFormatInfo.componentType == GL_SIGNED_NORMALIZED || + textureInternalFormatInfo.componentType == GL_FLOAT) && + !(framebufferInternalFormatInfo.componentType == GL_UNSIGNED_NORMALIZED || + framebufferInternalFormatInfo.componentType == GL_SIGNED_NORMALIZED || + framebufferInternalFormatInfo.componentType == GL_FLOAT)) + { + return false; + } + + // GLES specification 3.0.3, sec 3.8.5, pg 139-140: + // The effective internal format of the source buffer is determined with the following rules applied in order: + // * If the source buffer is a texture or renderbuffer that was created with a sized internal format then the + // effective internal format is the source buffer's sized internal format. + // * If the source buffer is a texture that was created with an unsized base internal format, then the + // effective internal format is the source image array's effective internal format, as specified by table + // 3.12, which is determined from the and that were used when the source image array was + // specified by TexImage*. + // * Otherwise the effective internal format is determined by the row in table 3.17 or 3.18 where + // Destination Internal Format matches internalformat and where the [source channel sizes] are consistent + // with the values of the source buffer's [channel sizes]. Table 3.17 is used if the + // FRAMEBUFFER_ATTACHMENT_ENCODING is LINEAR and table 3.18 is used if the FRAMEBUFFER_ATTACHMENT_ENCODING + // is SRGB. + const InternalFormat *sourceEffectiveFormat = NULL; + if (readBufferHandle != 0) + { + // Not the default framebuffer, therefore the read buffer must be a user-created texture or renderbuffer + if (framebufferInternalFormatInfo.pixelBytes > 0) + { + sourceEffectiveFormat = &framebufferInternalFormatInfo; + } + else + { + // Renderbuffers cannot be created with an unsized internal format, so this must be an unsized-format + // texture. We can use the same table we use when creating textures to get its effective sized format. + GLenum sizedInternalFormat = GetSizedInternalFormat(framebufferInternalFormatInfo.format, framebufferInternalFormatInfo.type); + sourceEffectiveFormat = &GetInternalFormatInfo(sizedInternalFormat); + } + } + else + { + // The effective internal format must be derived from the source framebuffer's channel sizes. + // This is done in GetEffectiveInternalFormat for linear buffers (table 3.17) + if (framebufferInternalFormatInfo.colorEncoding == GL_LINEAR) + { + GLenum effectiveFormat; + if (GetEffectiveInternalFormat(framebufferInternalFormatInfo, textureInternalFormatInfo, &effectiveFormat)) + { + sourceEffectiveFormat = &GetInternalFormatInfo(effectiveFormat); + } + else + { + return false; + } + } + else if (framebufferInternalFormatInfo.colorEncoding == GL_SRGB) + { + // SRGB buffers can only be copied to sized format destinations according to table 3.18 + if ((textureInternalFormatInfo.pixelBytes > 0) && + (framebufferInternalFormatInfo.redBits >= 1 && framebufferInternalFormatInfo.redBits <= 8) && + (framebufferInternalFormatInfo.greenBits >= 1 && framebufferInternalFormatInfo.greenBits <= 8) && + (framebufferInternalFormatInfo.blueBits >= 1 && framebufferInternalFormatInfo.blueBits <= 8) && + (framebufferInternalFormatInfo.alphaBits >= 1 && framebufferInternalFormatInfo.alphaBits <= 8)) + { + sourceEffectiveFormat = &GetInternalFormatInfo(GL_SRGB8_ALPHA8); + } + else + { + return false; + } + } + else + { + UNREACHABLE(); + return false; + } + } + + if (textureInternalFormatInfo.pixelBytes > 0) + { + // Section 3.8.5 of the GLES 3.0.3 spec, pg 139, requires that, if the destination format is sized, + // component sizes of the source and destination formats must exactly match + if (textureInternalFormatInfo.redBits != sourceEffectiveFormat->redBits || + textureInternalFormatInfo.greenBits != sourceEffectiveFormat->greenBits || + textureInternalFormatInfo.blueBits != sourceEffectiveFormat->blueBits || + textureInternalFormatInfo.alphaBits != sourceEffectiveFormat->alphaBits) + { + return false; + } + } + + + return true; // A conversion function exists, and no rule in the specification has precluded conversion + // between these formats. + } + + return false; +} + +bool ValidateES3CopyTexImageParameters(Context *context, GLenum target, GLint level, GLenum internalformat, + bool isSubImage, GLint xoffset, GLint yoffset, GLint zoffset, + GLint x, GLint y, GLsizei width, GLsizei height, GLint border) +{ + GLenum textureInternalFormat; + if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage, + xoffset, yoffset, zoffset, x, y, width, height, + border, &textureInternalFormat)) + { + return false; + } + + gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer(); + + if (framebuffer->checkStatus(context->getData()) != GL_FRAMEBUFFER_COMPLETE) + { + context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION)); + return false; + } + + if (context->getState().getReadFramebuffer()->id() != 0 && + framebuffer->getSamples(context->getData()) != 0) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + gl::FramebufferAttachment *source = framebuffer->getReadColorbuffer(); + GLenum colorbufferInternalFormat = source->getInternalFormat(); + + if (isSubImage) + { + if (!IsValidES3CopyTexImageCombination(textureInternalFormat, colorbufferInternalFormat, + context->getState().getReadFramebuffer()->id())) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + } + else + { + if (!gl::IsValidES3CopyTexImageCombination(internalformat, colorbufferInternalFormat, + context->getState().getReadFramebuffer()->id())) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + } + + // If width or height is zero, it is a no-op. Return false without setting an error. + return (width > 0 && height > 0); +} + +bool ValidateES3TexStorageParameters(Context *context, GLenum target, GLsizei levels, GLenum internalformat, + GLsizei width, GLsizei height, GLsizei depth) +{ + if (width < 1 || height < 1 || depth < 1 || levels < 1) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + + if (levels > gl::log2(std::max(std::max(width, height), depth)) + 1) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + const gl::Caps &caps = context->getCaps(); + + switch (target) + { + case GL_TEXTURE_2D: + { + if (static_cast(width) > caps.max2DTextureSize || + static_cast(height) > caps.max2DTextureSize) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + } + break; + + case GL_TEXTURE_CUBE_MAP: + { + if (width != height) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + + if (static_cast(width) > caps.maxCubeMapTextureSize) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + } + break; + + case GL_TEXTURE_3D: + { + if (static_cast(width) > caps.max3DTextureSize || + static_cast(height) > caps.max3DTextureSize || + static_cast(depth) > caps.max3DTextureSize) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + } + break; + + case GL_TEXTURE_2D_ARRAY: + { + if (static_cast(width) > caps.max2DTextureSize || + static_cast(height) > caps.max2DTextureSize || + static_cast(depth) > caps.maxArrayTextureLayers) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + } + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + + gl::Texture *texture = context->getTargetTexture(target); + if (!texture || texture->id() == 0) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + if (texture->isImmutable()) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat); + if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions())) + { + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + + if (formatInfo.pixelBytes == 0) + { + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + + return true; +} + +bool ValidateFramebufferTextureLayer(Context *context, GLenum target, GLenum attachment, + GLuint texture, GLint level, GLint layer) +{ + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + if (layer < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + + if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level)) + { + return false; + } + + const gl::Caps &caps = context->getCaps(); + if (texture != 0) + { + gl::Texture *tex = context->getTexture(texture); + ASSERT(tex); + + switch (tex->getTarget()) + { + case GL_TEXTURE_2D_ARRAY: + { + if (level > gl::log2(caps.max2DTextureSize)) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + + if (static_cast(layer) >= caps.maxArrayTextureLayers) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + } + break; + + case GL_TEXTURE_3D: + { + if (level > gl::log2(caps.max3DTextureSize)) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + + if (static_cast(layer) >= caps.max3DTextureSize) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + } + break; + + default: + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(tex->getInternalFormat(tex->getTarget(), level)); + if (internalFormatInfo.compressed) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + } + + return true; +} + +bool ValidES3ReadFormatType(Context *context, GLenum internalFormat, GLenum format, GLenum type) +{ + const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat); + + switch (format) + { + case GL_RGBA: + switch (type) + { + case GL_UNSIGNED_BYTE: + break; + case GL_UNSIGNED_INT_2_10_10_10_REV: + if (internalFormat != GL_RGB10_A2) + { + return false; + } + break; + case GL_FLOAT: + if (internalFormatInfo.componentType != GL_FLOAT) + { + return false; + } + break; + default: + return false; + } + break; + case GL_RGBA_INTEGER: + switch (type) + { + case GL_INT: + if (internalFormatInfo.componentType != GL_INT) + { + return false; + } + break; + case GL_UNSIGNED_INT: + if (internalFormatInfo.componentType != GL_UNSIGNED_INT) + { + return false; + } + break; + default: + return false; + } + break; + case GL_BGRA_EXT: + switch (type) + { + case GL_UNSIGNED_BYTE: + case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT: + case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT: + break; + default: + return false; + } + break; + case GL_RG_EXT: + case GL_RED_EXT: + if (!context->getExtensions().textureRG) + { + return false; + } + switch (type) + { + case GL_UNSIGNED_BYTE: + break; + default: + return false; + } + break; + default: + return false; + } + return true; +} + +bool ValidateES3RenderbufferStorageParameters(gl::Context *context, GLenum target, GLsizei samples, + GLenum internalformat, GLsizei width, GLsizei height) +{ + if (!ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width, height)) + { + return false; + } + + //The ES3 spec(section 4.4.2) states that the internal format must be sized and not an integer format if samples is greater than zero. + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat); + if ((formatInfo.componentType == GL_UNSIGNED_INT || formatInfo.componentType == GL_INT) && samples > 0) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + // The behavior is different than the ANGLE version, which would generate a GL_OUT_OF_MEMORY. + const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat); + if (static_cast(samples) > formatCaps.getMaxSamples()) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + + return true; +} + +bool ValidateInvalidateFramebufferParameters(Context *context, GLenum target, GLsizei numAttachments, + const GLenum* attachments) +{ + bool defaultFramebuffer = false; + + switch (target) + { + case GL_DRAW_FRAMEBUFFER: + case GL_FRAMEBUFFER: + defaultFramebuffer = context->getState().getDrawFramebuffer()->id() == 0; + break; + case GL_READ_FRAMEBUFFER: + defaultFramebuffer = context->getState().getReadFramebuffer()->id() == 0; + break; + default: + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + + for (int i = 0; i < numAttachments; ++i) + { + if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT15) + { + if (defaultFramebuffer) + { + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + + if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + } + else + { + switch (attachments[i]) + { + case GL_DEPTH_ATTACHMENT: + case GL_STENCIL_ATTACHMENT: + case GL_DEPTH_STENCIL_ATTACHMENT: + if (defaultFramebuffer) + { + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + break; + case GL_COLOR: + case GL_DEPTH: + case GL_STENCIL: + if (!defaultFramebuffer) + { + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + break; + default: + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + } + } + + return true; +} + +bool ValidateClearBuffer(Context *context) +{ + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + const gl::Framebuffer *fbo = context->getState().getDrawFramebuffer(); + if (!fbo || fbo->checkStatus(context->getData()) != GL_FRAMEBUFFER_COMPLETE) + { + context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION)); + return false; + } + + return true; +} + +bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint* params) +{ + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + return ValidateGetUniformBase(context, program, location); +} + +bool ValidateReadBuffer(Context *context, GLenum src) +{ + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + Framebuffer *readFBO = context->getState().getReadFramebuffer(); + + if (readFBO == nullptr) + { + context->recordError(gl::Error(GL_INVALID_OPERATION, "No active read framebuffer.")); + return false; + } + + if (src == GL_NONE) + { + return true; + } + + if (src != GL_BACK && (src < GL_COLOR_ATTACHMENT0 || src > GL_COLOR_ATTACHMENT15)) + { + context->recordError(gl::Error(GL_INVALID_ENUM, "Unknown enum for 'src' in ReadBuffer")); + return false; + } + + if (readFBO->id() == 0) + { + if (src != GL_BACK) + { + const char *errorMsg = "'src' must be GL_NONE or GL_BACK when reading from the default framebuffer."; + context->recordError(gl::Error(GL_INVALID_OPERATION, errorMsg)); + return false; + } + } + else + { + GLuint drawBuffer = static_cast(src - GL_COLOR_ATTACHMENT0); + + if (drawBuffer >= context->getCaps().maxDrawBuffers) + { + const char *errorMsg = "'src' is greater than MAX_DRAW_BUFFERS."; + context->recordError(gl::Error(GL_INVALID_OPERATION, errorMsg)); + return false; + } + } + + return true; +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/validationES3.h b/src/3rdparty/angle/src/libANGLE/validationES3.h new file mode 100644 index 0000000000..517cb5d27f --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/validationES3.h @@ -0,0 +1,49 @@ +// +// 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. +// + +// validationES3.h: Validation functions for OpenGL ES 3.0 entry point parameters + +#ifndef LIBANGLE_VALIDATION_ES3_H_ +#define LIBANGLE_VALIDATION_ES3_H_ + +#include + +namespace gl +{ + +class Context; + +bool ValidateES3TexImageParameters(Context *context, GLenum target, GLint level, GLenum internalformat, bool isCompressed, bool isSubImage, + GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, + GLint border, GLenum format, GLenum type, const GLvoid *pixels); + +bool ValidateES3CopyTexImageParameters(Context *context, GLenum target, GLint level, GLenum internalformat, + bool isSubImage, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, + GLsizei width, GLsizei height, GLint border); + +bool ValidateES3TexStorageParameters(Context *context, GLenum target, GLsizei levels, GLenum internalformat, + GLsizei width, GLsizei height, GLsizei depth); + +bool ValidateFramebufferTextureLayer(Context *context, GLenum target, GLenum attachment, + GLuint texture, GLint level, GLint layer); + +bool ValidES3ReadFormatType(Context *context, GLenum internalFormat, GLenum format, GLenum type); + +bool ValidateES3RenderbufferStorageParameters(Context *context, GLenum target, GLsizei samples, + GLenum internalformat, GLsizei width, GLsizei height); + +bool ValidateInvalidateFramebufferParameters(Context *context, GLenum target, GLsizei numAttachments, + const GLenum* attachments); + +bool ValidateClearBuffer(Context *context); + +bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint* params); + +bool ValidateReadBuffer(Context *context, GLenum mode); + +} + +#endif // LIBANGLE_VALIDATION_ES3_H_ diff --git a/src/3rdparty/angle/src/libEGL/AttributeMap.cpp b/src/3rdparty/angle/src/libEGL/AttributeMap.cpp deleted file mode 100644 index 28dd3d842e..0000000000 --- a/src/3rdparty/angle/src/libEGL/AttributeMap.cpp +++ /dev/null @@ -1,40 +0,0 @@ -// -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "libEGL/AttributeMap.h" - -namespace egl -{ - -AttributeMap::AttributeMap() -{ -} - -AttributeMap::AttributeMap(const EGLint *attributes) -{ - for (const EGLint *curAttrib = attributes; curAttrib[0] != EGL_NONE; curAttrib += 2) - { - insert(curAttrib[0], curAttrib[1]); - } -} - -void AttributeMap::insert(EGLint key, EGLint value) -{ - mAttributes[key] = value; -} - -bool AttributeMap::contains(EGLint key) const -{ - return (mAttributes.find(key) != mAttributes.end()); -} - -EGLint AttributeMap::get(EGLint key, EGLint defaultValue) const -{ - std::map::const_iterator iter = mAttributes.find(key); - return (mAttributes.find(key) != mAttributes.end()) ? iter->second : defaultValue; -} - -} diff --git a/src/3rdparty/angle/src/libEGL/AttributeMap.h b/src/3rdparty/angle/src/libEGL/AttributeMap.h deleted file mode 100644 index f2f082fe21..0000000000 --- a/src/3rdparty/angle/src/libEGL/AttributeMap.h +++ /dev/null @@ -1,33 +0,0 @@ -// -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef LIBEGL_ATTRIBUTEMAP_H_ -#define LIBEGL_ATTRIBUTEMAP_H_ - -#include - -#include - -namespace egl -{ - -class AttributeMap -{ - public: - AttributeMap(); - explicit AttributeMap(const EGLint *attributes); - - virtual void insert(EGLint key, EGLint value); - virtual bool contains(EGLint key) const; - virtual EGLint get(EGLint key, EGLint defaultValue) const; - - private: - std::map mAttributes; -}; - -} - -#endif // LIBEGL_ATTRIBUTEMAP_H_ diff --git a/src/3rdparty/angle/src/libEGL/Config.cpp b/src/3rdparty/angle/src/libEGL/Config.cpp deleted file mode 100644 index fdc41a95f0..0000000000 --- a/src/3rdparty/angle/src/libEGL/Config.cpp +++ /dev/null @@ -1,353 +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. -// - -// Config.cpp: Implements the egl::Config class, describing the format, type -// and size for an egl::Surface. Implements EGLConfig and related functionality. -// [EGL 1.4] section 3.4 page 15. - -#include "libEGL/Config.h" - -#include -#include - -#include "angle_gl.h" -#include - -#include "common/debug.h" - -using namespace std; - -namespace egl -{ -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 (desc.renderTargetFormat) - { - case GL_RGB5_A1: - mBufferSize = 16; - mRedSize = 5; - mGreenSize = 5; - mBlueSize = 5; - mAlphaSize = 1; - break; - case GL_BGR5_A1_ANGLEX: - mBufferSize = 16; - mRedSize = 5; - mGreenSize = 5; - mBlueSize = 5; - mAlphaSize = 1; - break; - case GL_RGBA8_OES: - mBufferSize = 32; - mRedSize = 8; - mGreenSize = 8; - mBlueSize = 8; - mAlphaSize = 8; - mBindToTextureRGBA = true; - break; - case GL_RGB565: - mBufferSize = 16; - mRedSize = 5; - mGreenSize = 6; - mBlueSize = 5; - mAlphaSize = 0; - break; - case GL_RGB8_OES: - mBufferSize = 32; - mRedSize = 8; - mGreenSize = 8; - mBlueSize = 8; - 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 - } - - mLuminanceSize = 0; - mAlphaMaskSize = 0; - mColorBufferType = EGL_RGB_BUFFER; - mConfigCaveat = (desc.fastConfig) ? EGL_NONE : EGL_SLOW_CONFIG; - mConfigID = 0; - mConformant = EGL_OPENGL_ES2_BIT; - - switch (desc.depthStencilFormat) - { - case GL_NONE: - mDepthSize = 0; - mStencilSize = 0; - break; - case GL_DEPTH_COMPONENT32_OES: - mDepthSize = 32; - mStencilSize = 0; - break; - case GL_DEPTH24_STENCIL8_OES: - mDepthSize = 24; - mStencilSize = 8; - break; - case GL_DEPTH_COMPONENT24_OES: - mDepthSize = 24; - mStencilSize = 0; - break; - case GL_DEPTH_COMPONENT16: - mDepthSize = 16; - mStencilSize = 0; - break; - default: - UNREACHABLE(); - } - - mLevel = 0; - mMatchNativePixmap = EGL_NONE; - mMaxPBufferWidth = texWidth; - mMaxPBufferHeight = texHeight; - mMaxPBufferPixels = texWidth*texHeight; - mMaxSwapInterval = maxInterval; - mMinSwapInterval = minInterval; - mNativeRenderable = EGL_FALSE; - mNativeVisualID = 0; - mNativeVisualType = 0; - mRenderableType = EGL_OPENGL_ES2_BIT; - mSampleBuffers = desc.multiSample ? 1 : 0; - mSamples = desc.multiSample; - mSurfaceType = EGL_PBUFFER_BIT | EGL_WINDOW_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT; - mTransparentType = EGL_NONE; - mTransparentRedValue = 0; - mTransparentGreenValue = 0; - mTransparentBlueValue = 0; - - if (desc.es3Capable) - { - mRenderableType |= EGL_OPENGL_ES3_BIT_KHR; - mConformant |= EGL_OPENGL_ES3_BIT_KHR; - } -} - -EGLConfig Config::getHandle() const -{ - return (EGLConfig)(size_t)mConfigID; -} - -SortConfig::SortConfig(const EGLint *attribList) - : mWantRed(false), mWantGreen(false), mWantBlue(false), mWantAlpha(false), mWantLuminance(false) -{ - scanForWantedComponents(attribList); -} - -void SortConfig::scanForWantedComponents(const EGLint *attribList) -{ - // [EGL] section 3.4.1 page 24 - // Sorting rule #3: by larger total number of color bits, not considering - // components that are 0 or don't-care. - for (const EGLint *attr = attribList; attr[0] != EGL_NONE; attr += 2) - { - if (attr[1] != 0 && attr[1] != EGL_DONT_CARE) - { - switch (attr[0]) - { - case EGL_RED_SIZE: mWantRed = true; break; - case EGL_GREEN_SIZE: mWantGreen = true; break; - case EGL_BLUE_SIZE: mWantBlue = true; break; - case EGL_ALPHA_SIZE: mWantAlpha = true; break; - case EGL_LUMINANCE_SIZE: mWantLuminance = true; break; - } - } - } -} - -EGLint SortConfig::wantedComponentsSize(const Config &config) const -{ - EGLint total = 0; - - if (mWantRed) total += config.mRedSize; - if (mWantGreen) total += config.mGreenSize; - if (mWantBlue) total += config.mBlueSize; - if (mWantAlpha) total += config.mAlphaSize; - if (mWantLuminance) total += config.mLuminanceSize; - - return total; -} - -bool SortConfig::operator()(const Config *x, const Config *y) const -{ - return (*this)(*x, *y); -} - -bool SortConfig::operator()(const Config &x, const Config &y) const -{ - #define SORT(attribute) \ - if (x.attribute != y.attribute) \ - { \ - return x.attribute < y.attribute; \ - } - - META_ASSERT(EGL_NONE < EGL_SLOW_CONFIG && EGL_SLOW_CONFIG < EGL_NON_CONFORMANT_CONFIG); - SORT(mConfigCaveat); - - META_ASSERT(EGL_RGB_BUFFER < EGL_LUMINANCE_BUFFER); - SORT(mColorBufferType); - - // By larger total number of color bits, only considering those that are requested to be > 0. - EGLint xComponentsSize = wantedComponentsSize(x); - EGLint yComponentsSize = wantedComponentsSize(y); - if (xComponentsSize != yComponentsSize) - { - return xComponentsSize > yComponentsSize; - } - - SORT(mBufferSize); - SORT(mSampleBuffers); - SORT(mSamples); - SORT(mDepthSize); - SORT(mStencilSize); - SORT(mAlphaMaskSize); - SORT(mNativeVisualType); - SORT(mConfigID); - - #undef SORT - - return false; -} - -// We'd like to use SortConfig to also eliminate duplicate configs. -// This works as long as we never have two configs with different per-RGB-component layouts, -// but the same total. -// 5551 and 565 are different because R+G+B is different. -// 5551 and 555 are different because bufferSize is different. -const EGLint ConfigSet::mSortAttribs[] = -{ - EGL_RED_SIZE, 1, - EGL_GREEN_SIZE, 1, - EGL_BLUE_SIZE, 1, - EGL_LUMINANCE_SIZE, 1, - // BUT NOT ALPHA - EGL_NONE -}; - -ConfigSet::ConfigSet() - : mSet(SortConfig(mSortAttribs)) -{ -} - -void ConfigSet::add(rx::ConfigDesc desc, EGLint minSwapInterval, EGLint maxSwapInterval, EGLint texWidth, EGLint texHeight) -{ - Config config(desc, minSwapInterval, maxSwapInterval, texWidth, texHeight); - mSet.insert(config); -} - -size_t ConfigSet::size() const -{ - return mSet.size(); -} - -bool ConfigSet::getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig) -{ - vector passed; - passed.reserve(mSet.size()); - - for (Iterator config = mSet.begin(); config != mSet.end(); config++) - { - bool match = true; - const EGLint *attribute = attribList; - - while (attribute[0] != EGL_NONE) - { - switch (attribute[0]) - { - case EGL_BUFFER_SIZE: match = config->mBufferSize >= attribute[1]; break; - case EGL_ALPHA_SIZE: match = config->mAlphaSize >= attribute[1]; break; - case EGL_BLUE_SIZE: match = config->mBlueSize >= attribute[1]; break; - case EGL_GREEN_SIZE: match = config->mGreenSize >= attribute[1]; break; - case EGL_RED_SIZE: match = config->mRedSize >= attribute[1]; break; - case EGL_DEPTH_SIZE: match = config->mDepthSize >= attribute[1]; break; - case EGL_STENCIL_SIZE: match = config->mStencilSize >= attribute[1]; break; - case EGL_CONFIG_CAVEAT: match = config->mConfigCaveat == (EGLenum) attribute[1]; break; - case EGL_CONFIG_ID: match = config->mConfigID == attribute[1]; break; - case EGL_LEVEL: match = config->mLevel >= attribute[1]; break; - case EGL_NATIVE_RENDERABLE: match = config->mNativeRenderable == (EGLBoolean) attribute[1]; break; - case EGL_NATIVE_VISUAL_TYPE: match = config->mNativeVisualType == attribute[1]; break; - case EGL_SAMPLES: match = config->mSamples >= attribute[1]; break; - case EGL_SAMPLE_BUFFERS: match = config->mSampleBuffers >= attribute[1]; break; - case EGL_SURFACE_TYPE: match = (config->mSurfaceType & attribute[1]) == attribute[1]; break; - case EGL_TRANSPARENT_TYPE: match = config->mTransparentType == (EGLenum) attribute[1]; break; - case EGL_TRANSPARENT_BLUE_VALUE: match = config->mTransparentBlueValue == attribute[1]; break; - case EGL_TRANSPARENT_GREEN_VALUE: match = config->mTransparentGreenValue == attribute[1]; break; - case EGL_TRANSPARENT_RED_VALUE: match = config->mTransparentRedValue == attribute[1]; break; - case EGL_BIND_TO_TEXTURE_RGB: match = config->mBindToTextureRGB == (EGLBoolean) attribute[1]; break; - case EGL_BIND_TO_TEXTURE_RGBA: match = config->mBindToTextureRGBA == (EGLBoolean) attribute[1]; break; - case EGL_MIN_SWAP_INTERVAL: match = config->mMinSwapInterval == attribute[1]; break; - case EGL_MAX_SWAP_INTERVAL: match = config->mMaxSwapInterval == attribute[1]; break; - case EGL_LUMINANCE_SIZE: match = config->mLuminanceSize >= attribute[1]; break; - case EGL_ALPHA_MASK_SIZE: match = config->mAlphaMaskSize >= attribute[1]; break; - case EGL_COLOR_BUFFER_TYPE: match = config->mColorBufferType == (EGLenum) attribute[1]; break; - case EGL_RENDERABLE_TYPE: match = (config->mRenderableType & attribute[1]) == attribute[1]; break; - case EGL_MATCH_NATIVE_PIXMAP: match = false; UNIMPLEMENTED(); break; - case EGL_CONFORMANT: match = (config->mConformant & attribute[1]) == attribute[1]; break; - case EGL_MAX_PBUFFER_WIDTH: match = config->mMaxPBufferWidth >= attribute[1]; break; - case EGL_MAX_PBUFFER_HEIGHT: match = config->mMaxPBufferHeight >= attribute[1]; break; - case EGL_MAX_PBUFFER_PIXELS: match = config->mMaxPBufferPixels >= attribute[1]; break; - default: - return false; - } - - if (!match) - { - break; - } - - attribute += 2; - } - - if (match) - { - passed.push_back(&*config); - } - } - - if (configs) - { - sort(passed.begin(), passed.end(), SortConfig(attribList)); - - EGLint index; - for (index = 0; index < configSize && index < static_cast(passed.size()); index++) - { - configs[index] = passed[index]->getHandle(); - } - - *numConfig = index; - } - else - { - *numConfig = passed.size(); - } - - return true; -} - -const egl::Config *ConfigSet::get(EGLConfig configHandle) -{ - for (Iterator config = mSet.begin(); config != mSet.end(); config++) - { - if (config->getHandle() == configHandle) - { - return &(*config); - } - } - - return NULL; -} -} diff --git a/src/3rdparty/angle/src/libEGL/Config.h b/src/3rdparty/angle/src/libEGL/Config.h deleted file mode 100644 index 98441142f4..0000000000 --- a/src/3rdparty/angle/src/libEGL/Config.h +++ /dev/null @@ -1,114 +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. -// - -// Config.h: Defines the egl::Config class, describing the format, type -// and size for an egl::Surface. Implements EGLConfig and related functionality. -// [EGL 1.4] section 3.4 page 15. - -#ifndef INCLUDE_CONFIG_H_ -#define INCLUDE_CONFIG_H_ - -#include - -#include - -#include "libGLESv2/renderer/Renderer.h" -#include "common/angleutils.h" - -namespace egl -{ -class Display; - -class Config -{ - public: - Config(rx::ConfigDesc desc, EGLint minSwapInterval, EGLint maxSwapInterval, EGLint texWidth, EGLint texHeight); - - EGLConfig getHandle() const; - - 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 - EGLint mGreenSize; // Bits of Green in the color buffer - EGLint mBlueSize; // Bits of Blue in the color buffer - EGLint mLuminanceSize; // Bits of Luminance in the color buffer - EGLint mAlphaSize; // Bits of Alpha in the color buffer - EGLint mAlphaMaskSize; // Bits of Alpha Mask in the mask buffer - EGLBoolean mBindToTextureRGB; // True if bindable to RGB textures. - EGLBoolean mBindToTextureRGBA; // True if bindable to RGBA textures. - EGLenum mColorBufferType; // Color buffer type - EGLenum mConfigCaveat; // Any caveats for the configuration - EGLint mConfigID; // Unique EGLConfig identifier - EGLint mConformant; // Whether contexts created with this config are conformant - EGLint mDepthSize; // Bits of Z in the depth buffer - EGLint mLevel; // Frame buffer level - EGLBoolean mMatchNativePixmap; // Match the native pixmap format - EGLint mMaxPBufferWidth; // Maximum width of pbuffer - EGLint mMaxPBufferHeight; // Maximum height of pbuffer - EGLint mMaxPBufferPixels; // Maximum size of pbuffer - EGLint mMaxSwapInterval; // Maximum swap interval - EGLint mMinSwapInterval; // Minimum swap interval - EGLBoolean mNativeRenderable; // EGL_TRUE if native rendering APIs can render to surface - EGLint mNativeVisualID; // Handle of corresponding native visual - EGLint mNativeVisualType; // Native visual type of the associated visual - EGLint mRenderableType; // Which client rendering APIs are supported. - EGLint mSampleBuffers; // Number of multisample buffers - EGLint mSamples; // Number of samples per pixel - EGLint mStencilSize; // Bits of Stencil in the stencil buffer - EGLint mSurfaceType; // Which types of EGL surfaces are supported. - EGLenum mTransparentType; // Type of transparency supported - EGLint mTransparentRedValue; // Transparent red value - EGLint mTransparentGreenValue; // Transparent green value - EGLint mTransparentBlueValue; // Transparent blue value -}; - -// Function object used by STL sorting routines for ordering Configs according to [EGL] section 3.4.1 page 24. -class SortConfig -{ - public: - explicit SortConfig(const EGLint *attribList); - - bool operator()(const Config *x, const Config *y) const; - bool operator()(const Config &x, const Config &y) const; - - private: - void scanForWantedComponents(const EGLint *attribList); - EGLint wantedComponentsSize(const Config &config) const; - - bool mWantRed; - bool mWantGreen; - bool mWantBlue; - bool mWantAlpha; - bool mWantLuminance; -}; - -class ConfigSet -{ - friend Display; - - public: - ConfigSet(); - - void add(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); - - private: - DISALLOW_COPY_AND_ASSIGN(ConfigSet); - - typedef std::set Set; - typedef Set::iterator Iterator; - Set mSet; - - static const EGLint mSortAttribs[]; -}; -} - -#endif // INCLUDE_CONFIG_H_ diff --git a/src/3rdparty/angle/src/libEGL/Display.cpp b/src/3rdparty/angle/src/libEGL/Display.cpp deleted file mode 100644 index eea93b1d87..0000000000 --- a/src/3rdparty/angle/src/libEGL/Display.cpp +++ /dev/null @@ -1,648 +0,0 @@ -// -// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Display.cpp: Implements the egl::Display class, representing the abstract -// display on which graphics are drawn. Implements EGLDisplay. -// [EGL 1.4] section 2.1.2 page 3. - -#include "libEGL/Display.h" - -#include -#include -#include -#include -#include - -#include "common/debug.h" -#include "common/mathutil.h" -#include "libGLESv2/main.h" -#include "libGLESv2/Context.h" -#include "libGLESv2/renderer/SwapChain.h" - -#include "libEGL/main.h" -#include "libEGL/Surface.h" - -namespace egl -{ - -typedef std::map DisplayMap; -static DisplayMap *GetDisplayMap() -{ - static DisplayMap displays; - return &displays; -} - -egl::Display *Display::getDisplay(EGLNativeDisplayType displayId, const AttributeMap &attribMap) -{ - Display *display = NULL; - - DisplayMap *displays = GetDisplayMap(); - DisplayMap::const_iterator iter = displays->find(displayId); - if (iter != displays->end()) - { - display = iter->second; - } - else - { - display = new egl::Display(displayId); - displays->insert(std::make_pair(displayId, display)); - } - - // Apply new attributes if the display is not initialized yet. - if (!display->isInitialized()) - { - display->setAttributes(attribMap); - } - - return display; -} - -Display::Display(EGLNativeDisplayType displayId) - : mDisplayId(displayId), - mAttributeMap(), - mRenderer(NULL) -{ -} - -Display::~Display() -{ - terminate(); - - DisplayMap *displays = GetDisplayMap(); - DisplayMap::iterator iter = displays->find(mDisplayId); - if (iter != displays->end()) - { - displays->erase(iter); - } -} - -void Display::setAttributes(const AttributeMap &attribMap) -{ - mAttributeMap = attribMap; -} - -Error Display::initialize() -{ - if (isInitialized()) - { - return Error(EGL_SUCCESS); - } - - mRenderer = glCreateRenderer(this, mDisplayId, mAttributeMap); - - if (!mRenderer) - { - terminate(); - return Error(EGL_NOT_INITIALIZED); - } - - //TODO(jmadill): should be part of caps? - EGLint minSwapInterval = mRenderer->getMinSwapInterval(); - EGLint maxSwapInterval = mRenderer->getMaxSwapInterval(); - EGLint maxTextureSize = mRenderer->getRendererCaps().max2DTextureSize; - - rx::ConfigDesc *descList; - int numConfigs = mRenderer->generateConfigs(&descList); - ConfigSet configSet; - - for (int i = 0; i < numConfigs; ++i) - { - configSet.add(descList[i], minSwapInterval, maxSwapInterval, maxTextureSize, maxTextureSize); - } - - // 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); - } - - mRenderer->deleteConfigs(descList); - descList = NULL; - - if (!isInitialized()) - { - terminate(); - return Error(EGL_NOT_INITIALIZED); - } - - initDisplayExtensionString(); - initVendorString(); - - return Error(EGL_SUCCESS); -} - -void Display::terminate() -{ - while (!mSurfaceSet.empty()) - { - destroySurface(*mSurfaceSet.begin()); - } - - while (!mContextSet.empty()) - { - destroyContext(*mContextSet.begin()); - } - - glDestroyRenderer(mRenderer); - mRenderer = NULL; - - mConfigSet.mSet.clear(); -} - -bool Display::getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig) -{ - return mConfigSet.getConfigs(configs, attribList, configSize, numConfig); -} - -bool Display::getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value) -{ - const egl::Config *configuration = mConfigSet.get(config); - - switch (attribute) - { - case EGL_BUFFER_SIZE: *value = configuration->mBufferSize; break; - case EGL_ALPHA_SIZE: *value = configuration->mAlphaSize; break; - case EGL_BLUE_SIZE: *value = configuration->mBlueSize; break; - case EGL_GREEN_SIZE: *value = configuration->mGreenSize; break; - case EGL_RED_SIZE: *value = configuration->mRedSize; break; - case EGL_DEPTH_SIZE: *value = configuration->mDepthSize; break; - case EGL_STENCIL_SIZE: *value = configuration->mStencilSize; break; - case EGL_CONFIG_CAVEAT: *value = configuration->mConfigCaveat; break; - case EGL_CONFIG_ID: *value = configuration->mConfigID; break; - case EGL_LEVEL: *value = configuration->mLevel; break; - case EGL_NATIVE_RENDERABLE: *value = configuration->mNativeRenderable; break; - case EGL_NATIVE_VISUAL_TYPE: *value = configuration->mNativeVisualType; break; - case EGL_SAMPLES: *value = configuration->mSamples; break; - case EGL_SAMPLE_BUFFERS: *value = configuration->mSampleBuffers; break; - case EGL_SURFACE_TYPE: *value = configuration->mSurfaceType; break; - case EGL_TRANSPARENT_TYPE: *value = configuration->mTransparentType; break; - case EGL_TRANSPARENT_BLUE_VALUE: *value = configuration->mTransparentBlueValue; break; - case EGL_TRANSPARENT_GREEN_VALUE: *value = configuration->mTransparentGreenValue; break; - case EGL_TRANSPARENT_RED_VALUE: *value = configuration->mTransparentRedValue; break; - case EGL_BIND_TO_TEXTURE_RGB: *value = configuration->mBindToTextureRGB; break; - case EGL_BIND_TO_TEXTURE_RGBA: *value = configuration->mBindToTextureRGBA; break; - case EGL_MIN_SWAP_INTERVAL: *value = configuration->mMinSwapInterval; break; - case EGL_MAX_SWAP_INTERVAL: *value = configuration->mMaxSwapInterval; break; - case EGL_LUMINANCE_SIZE: *value = configuration->mLuminanceSize; break; - case EGL_ALPHA_MASK_SIZE: *value = configuration->mAlphaMaskSize; break; - case EGL_COLOR_BUFFER_TYPE: *value = configuration->mColorBufferType; break; - case EGL_RENDERABLE_TYPE: *value = configuration->mRenderableType; break; - case EGL_MATCH_NATIVE_PIXMAP: *value = false; UNIMPLEMENTED(); break; - case EGL_CONFORMANT: *value = configuration->mConformant; break; - case EGL_MAX_PBUFFER_WIDTH: *value = configuration->mMaxPBufferWidth; break; - case EGL_MAX_PBUFFER_HEIGHT: *value = configuration->mMaxPBufferHeight; break; - case EGL_MAX_PBUFFER_PIXELS: *value = configuration->mMaxPBufferPixels; break; - default: - return false; - } - - return true; -} - - - -Error Display::createWindowSurface(EGLNativeWindowType window, EGLConfig config, const EGLint *attribList, EGLSurface *outSurface) -{ - const Config *configuration = mConfigSet.get(config); - EGLint postSubBufferSupported = EGL_FALSE; - - EGLint width = 0; - EGLint height = 0; - EGLint fixedSize = EGL_FALSE; - - if (attribList) - { - while (*attribList != EGL_NONE) - { - switch (attribList[0]) - { - case EGL_RENDER_BUFFER: - switch (attribList[1]) - { - case EGL_BACK_BUFFER: - break; - case EGL_SINGLE_BUFFER: - return Error(EGL_BAD_MATCH); // Rendering directly to front buffer not supported - default: - return Error(EGL_BAD_ATTRIBUTE); - } - break; - case EGL_POST_SUB_BUFFER_SUPPORTED_NV: - postSubBufferSupported = attribList[1]; - break; - case EGL_WIDTH: - width = attribList[1]; - break; - case EGL_HEIGHT: - height = attribList[1]; - break; - case EGL_FIXED_SIZE_ANGLE: - fixedSize = attribList[1]; - break; - case EGL_VG_COLORSPACE: - return Error(EGL_BAD_MATCH); - case EGL_VG_ALPHA_FORMAT: - return Error(EGL_BAD_MATCH); - default: - return Error(EGL_BAD_ATTRIBUTE); - } - - attribList += 2; - } - } - - if (width < 0 || height < 0) - { - return Error(EGL_BAD_PARAMETER); - } - - if (!fixedSize) - { - width = -1; - height = -1; - } - - if (hasExistingWindowSurface(window)) - { - return Error(EGL_BAD_ALLOC); - } - - if (mRenderer->testDeviceLost(false)) - { - Error error = restoreLostDevice(); - if (error.isError()) - { - return error; - } - } - - Surface *surface = new Surface(this, configuration, window, fixedSize, width, height, postSubBufferSupported); - Error error = surface->initialize(); - if (error.isError()) - { - SafeDelete(surface); - return error; - } - - mSurfaceSet.insert(surface); - - *outSurface = surface; - return Error(EGL_SUCCESS); -} - -Error Display::createOffscreenSurface(EGLConfig config, HANDLE shareHandle, const EGLint *attribList, EGLSurface *outSurface) -{ - EGLint width = 0, height = 0; - EGLenum textureFormat = EGL_NO_TEXTURE; - EGLenum textureTarget = EGL_NO_TEXTURE; - const Config *configuration = mConfigSet.get(config); - - if (attribList) - { - while (*attribList != EGL_NONE) - { - switch (attribList[0]) - { - case EGL_WIDTH: - width = attribList[1]; - break; - case EGL_HEIGHT: - height = attribList[1]; - break; - case EGL_LARGEST_PBUFFER: - if (attribList[1] != EGL_FALSE) - UNIMPLEMENTED(); // FIXME - break; - case EGL_TEXTURE_FORMAT: - switch (attribList[1]) - { - case EGL_NO_TEXTURE: - case EGL_TEXTURE_RGB: - case EGL_TEXTURE_RGBA: - textureFormat = attribList[1]; - break; - default: - return Error(EGL_BAD_ATTRIBUTE); - } - break; - case EGL_TEXTURE_TARGET: - switch (attribList[1]) - { - case EGL_NO_TEXTURE: - case EGL_TEXTURE_2D: - textureTarget = attribList[1]; - break; - default: - return Error(EGL_BAD_ATTRIBUTE); - } - break; - case EGL_MIPMAP_TEXTURE: - if (attribList[1] != EGL_FALSE) - return Error(EGL_BAD_ATTRIBUTE); - break; - case EGL_VG_COLORSPACE: - return Error(EGL_BAD_MATCH); - case EGL_VG_ALPHA_FORMAT: - return Error(EGL_BAD_MATCH); - default: - return Error(EGL_BAD_ATTRIBUTE); - } - - attribList += 2; - } - } - - if (width < 0 || height < 0) - { - return Error(EGL_BAD_PARAMETER); - } - - if (width == 0 || height == 0) - { - return Error(EGL_BAD_ATTRIBUTE); - } - - if (textureFormat != EGL_NO_TEXTURE && !mRenderer->getRendererExtensions().textureNPOT && (!gl::isPow2(width) || !gl::isPow2(height))) - { - return Error(EGL_BAD_MATCH); - } - - if ((textureFormat != EGL_NO_TEXTURE && textureTarget == EGL_NO_TEXTURE) || - (textureFormat == EGL_NO_TEXTURE && textureTarget != EGL_NO_TEXTURE)) - { - return Error(EGL_BAD_MATCH); - } - - if (!(configuration->mSurfaceType & EGL_PBUFFER_BIT)) - { - return Error(EGL_BAD_MATCH); - } - - if ((textureFormat == EGL_TEXTURE_RGB && configuration->mBindToTextureRGB != EGL_TRUE) || - (textureFormat == EGL_TEXTURE_RGBA && configuration->mBindToTextureRGBA != EGL_TRUE)) - { - return Error(EGL_BAD_ATTRIBUTE); - } - - if (mRenderer->testDeviceLost(false)) - { - Error error = restoreLostDevice(); - if (error.isError()) - { - return error; - } - } - - Surface *surface = new Surface(this, configuration, shareHandle, width, height, textureFormat, textureTarget); - Error error = surface->initialize(); - if (error.isError()) - { - SafeDelete(surface); - return error; - } - - mSurfaceSet.insert(surface); - - *outSurface = surface; - return Error(EGL_SUCCESS); -} - -Error Display::createContext(EGLConfig configHandle, EGLint clientVersion, const gl::Context *shareContext, bool notifyResets, - bool robustAccess, EGLContext *outContext) -{ - if (!mRenderer) - { - *outContext = EGL_NO_CONTEXT; - return Error(EGL_SUCCESS); - } - else if (mRenderer->testDeviceLost(false)) // Lost device - { - Error error = restoreLostDevice(); - if (error.isError()) - { - return error; - } - } - - //TODO(jmadill): shader model is not cross-platform - if (clientVersion > 2 && mRenderer->getMajorShaderModel() < 4) - { - return Error(EGL_BAD_CONFIG); - } - - gl::Context *context = glCreateContext(clientVersion, shareContext, mRenderer, notifyResets, robustAccess); - mContextSet.insert(context); - - *outContext = context; - return Error(EGL_SUCCESS); -} - -Error Display::restoreLostDevice() -{ - for (ContextSet::iterator ctx = mContextSet.begin(); ctx != mContextSet.end(); ctx++) - { - if ((*ctx)->isResetNotificationEnabled()) - { - // If reset notifications have been requested, application must delete all contexts first - return Error(EGL_CONTEXT_LOST); - } - } - - // Release surface resources to make the Reset() succeed - for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++) - { - (*surface)->release(); - } - - if (!mRenderer->resetDevice()) - { - return Error(EGL_BAD_ALLOC); - } - - // Restore any surfaces that may have been lost - for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++) - { - Error error = (*surface)->resetSwapChain(); - if (error.isError()) - { - return error; - } - } - - return Error(EGL_SUCCESS); -} - - -void Display::destroySurface(egl::Surface *surface) -{ - delete surface; - mSurfaceSet.erase(surface); -} - -void Display::destroyContext(gl::Context *context) -{ - glDestroyContext(context); - mContextSet.erase(context); -} - -void Display::notifyDeviceLost() -{ - for (ContextSet::iterator context = mContextSet.begin(); context != mContextSet.end(); context++) - { - (*context)->markContextLost(); - } -} - -void Display::recreateSwapChains() -{ - for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++) - { - (*surface)->getSwapChain()->recreate(); - } -} - -bool Display::isInitialized() const -{ - return mRenderer != NULL && mConfigSet.size() > 0; -} - -bool Display::isValidConfig(EGLConfig config) -{ - return mConfigSet.get(config) != NULL; -} - -bool Display::isValidContext(gl::Context *context) -{ - return mContextSet.find(context) != mContextSet.end(); -} - -bool Display::isValidSurface(egl::Surface *surface) -{ - return mSurfaceSet.find(surface) != mSurfaceSet.end(); -} - -bool Display::hasExistingWindowSurface(EGLNativeWindowType window) -{ - for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++) - { - if ((*surface)->getWindowHandle() == window) - { - return true; - } - } - - return false; -} - -std::string Display::generateClientExtensionString() -{ - std::vector extensions; - - extensions.push_back("EGL_EXT_client_extensions"); - - extensions.push_back("ANGLE_platform_angle"); - - if (supportsPlatformD3D()) - { - extensions.push_back("ANGLE_platform_angle_d3d"); - } - - if (supportsPlatformOpenGL()) - { - extensions.push_back("ANGLE_platform_angle_opengl"); - } - - std::ostringstream stream; - std::copy(extensions.begin(), extensions.end(), std::ostream_iterator(stream, " ")); - return stream.str(); -} - -void Display::initDisplayExtensionString() -{ - std::vector extensions; - - // Multi-vendor (EXT) extensions - extensions.push_back("EGL_EXT_create_context_robustness"); - - // ANGLE-specific extensions - if (mRenderer->getShareHandleSupport()) - { - extensions.push_back("EGL_ANGLE_d3d_share_handle_client_buffer"); - extensions.push_back("EGL_ANGLE_surface_d3d_texture_2d_share_handle"); - } - - extensions.push_back("EGL_ANGLE_query_surface_pointer"); - extensions.push_back("EGL_ANGLE_window_fixed_size"); - - if (mRenderer->getPostSubBufferSupport()) - { - extensions.push_back("EGL_NV_post_sub_buffer"); - } - -#if defined (ANGLE_TEST_CONFIG) - // TODO: complete support for the EGL_KHR_create_context extension - extensions.push_back("EGL_KHR_create_context"); -#endif - - std::ostringstream stream; - std::copy(extensions.begin(), extensions.end(), std::ostream_iterator(stream, " ")); - mDisplayExtensionString = stream.str(); -} - -const char *Display::getExtensionString(egl::Display *display) -{ - if (display != EGL_NO_DISPLAY) - { - return display->mDisplayExtensionString.c_str(); - } - else - { - static std::string clientExtensions = generateClientExtensionString(); - return clientExtensions.c_str(); - } -} - -bool Display::supportsPlatformD3D() -{ -#if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_D3D11) - return true; -#else - return false; -#endif -} - -bool Display::supportsPlatformOpenGL() -{ - return false; -} - -void Display::initVendorString() -{ - mVendorString = "Google Inc."; - - LUID adapterLuid = {0}; - - //TODO(jmadill): LUID is not cross-platform - if (mRenderer && mRenderer->getLUID(&adapterLuid)) - { - char adapterLuidString[64]; - sprintf_s(adapterLuidString, sizeof(adapterLuidString), " (adapter LUID: %08x%08x)", adapterLuid.HighPart, adapterLuid.LowPart); - - mVendorString += adapterLuidString; - } -} - -const char *Display::getVendorString() const -{ - return mVendorString.c_str(); -} - -} diff --git a/src/3rdparty/angle/src/libEGL/Display.h b/src/3rdparty/angle/src/libEGL/Display.h deleted file mode 100644 index b3ffcc84c5..0000000000 --- a/src/3rdparty/angle/src/libEGL/Display.h +++ /dev/null @@ -1,104 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Display.h: Defines the egl::Display class, representing the abstract -// display on which graphics are drawn. Implements EGLDisplay. -// [EGL 1.4] section 2.1.2 page 3. - -#ifndef LIBEGL_DISPLAY_H_ -#define LIBEGL_DISPLAY_H_ - -#include -#include - -#include "libEGL/Error.h" -#include "libEGL/Config.h" -#include "libEGL/AttributeMap.h" - -namespace gl -{ -class Context; -} - -namespace egl -{ -class Surface; - -class Display -{ - public: - ~Display(); - - Error initialize(); - void terminate(); - - static egl::Display *getDisplay(EGLNativeDisplayType displayId, const AttributeMap &attribMap); - - static const char *getExtensionString(egl::Display *display); - - static bool supportsPlatformD3D(); - static bool supportsPlatformOpenGL(); - - bool getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig); - bool getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value); - - Error createWindowSurface(EGLNativeWindowType window, EGLConfig config, const EGLint *attribList, EGLSurface *outSurface); - Error createOffscreenSurface(EGLConfig config, HANDLE shareHandle, const EGLint *attribList, EGLSurface *outSurface); - Error createContext(EGLConfig configHandle, EGLint clientVersion, const gl::Context *shareContext, bool notifyResets, - bool robustAccess, EGLContext *outContext); - - void destroySurface(egl::Surface *surface); - void destroyContext(gl::Context *context); - - bool isInitialized() const; - bool isValidConfig(EGLConfig config); - bool isValidContext(gl::Context *context); - bool isValidSurface(egl::Surface *surface); - bool hasExistingWindowSurface(EGLNativeWindowType window); - - rx::Renderer *getRenderer() { return mRenderer; }; - - // exported methods must be virtual - virtual void notifyDeviceLost(); - virtual void recreateSwapChains(); - - const char *getExtensionString() const; - const char *getVendorString() const; - EGLNativeDisplayType getDisplayId() const { return mDisplayId; } - - private: - DISALLOW_COPY_AND_ASSIGN(Display); - - Display(EGLNativeDisplayType displayId); - - void setAttributes(const AttributeMap &attribMap); - - Error restoreLostDevice(); - - EGLNativeDisplayType mDisplayId; - AttributeMap mAttributeMap; - - typedef std::set SurfaceSet; - SurfaceSet mSurfaceSet; - - ConfigSet mConfigSet; - - typedef std::set ContextSet; - ContextSet mContextSet; - - rx::Renderer *mRenderer; - - static std::string generateClientExtensionString(); - - void initDisplayExtensionString(); - std::string mDisplayExtensionString; - - void initVendorString(); - std::string mVendorString; -}; -} - -#endif // LIBEGL_DISPLAY_H_ diff --git a/src/3rdparty/angle/src/libEGL/Error.cpp b/src/3rdparty/angle/src/libEGL/Error.cpp deleted file mode 100644 index df5f163d32..0000000000 --- a/src/3rdparty/angle/src/libEGL/Error.cpp +++ /dev/null @@ -1,48 +0,0 @@ -// -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Error.cpp: Implements the egl::Error class which encapsulates an EGL error -// and optional error message. - -#include "libEGL/Error.h" - -#include "common/angleutils.h" - -#include - -namespace egl -{ - -Error::Error(EGLint errorCode) - : mCode(errorCode), - mMessage() -{ -} - -Error::Error(EGLint errorCode, const char *msg, ...) - : mCode(errorCode), - mMessage() -{ - va_list vararg; - va_start(vararg, msg); - mMessage = FormatString(msg, vararg); - va_end(vararg); -} - -Error::Error(const Error &other) - : mCode(other.mCode), - mMessage(other.mMessage) -{ -} - -Error &Error::operator=(const Error &other) -{ - mCode = other.mCode; - mMessage = other.mMessage; - return *this; -} - -} diff --git a/src/3rdparty/angle/src/libEGL/Error.h b/src/3rdparty/angle/src/libEGL/Error.h deleted file mode 100644 index 71805d2fb7..0000000000 --- a/src/3rdparty/angle/src/libEGL/Error.h +++ /dev/null @@ -1,39 +0,0 @@ -// -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Error.h: Defines the egl::Error class which encapsulates an EGL error -// and optional error message. - -#ifndef LIBEGL_ERROR_H_ -#define LIBEGL_ERROR_H_ - -#include - -#include - -namespace egl -{ - -class Error -{ - public: - explicit Error(EGLint errorCode); - Error(EGLint errorCode, const char *msg, ...); - Error(const Error &other); - Error &operator=(const Error &other); - - EGLint getCode() const { return mCode; } - bool isError() const { return (mCode != EGL_SUCCESS); } - - const std::string &getMessage() const { return mMessage; } - - private: - EGLint mCode; - std::string mMessage; -}; - -} - -#endif // LIBEGL_ERROR_H_ diff --git a/src/3rdparty/angle/src/libEGL/Surface.cpp b/src/3rdparty/angle/src/libEGL/Surface.cpp deleted file mode 100644 index b664a8530e..0000000000 --- a/src/3rdparty/angle/src/libEGL/Surface.cpp +++ /dev/null @@ -1,505 +0,0 @@ -// -// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Surface.cpp: Implements the egl::Surface class, representing a drawing surface -// such as the client area of a window, including any back buffers. -// Implements EGLSurface and related functionality. [EGL 1.4] section 2.2 page 3. - -#include - -#include - -#include "libEGL/Surface.h" - -#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" - -#include "common/NativeWindow.h" - -//TODO(jmadill): phase this out -#include "libGLESv2/renderer/d3d/RendererD3D.h" - -namespace egl -{ - -Surface::Surface(Display *display, const Config *config, EGLNativeWindowType window, EGLint fixedSize, EGLint width, EGLint height, EGLint postSubBufferSupported) - : mDisplay(display), mConfig(config), mNativeWindow(window, display->getDisplayId()), mPostSubBufferSupported(postSubBufferSupported) -{ - //TODO(jmadill): MANGLE refactor. (note, can't call makeRendererD3D because of dll export issues) - mRenderer = static_cast(mDisplay->getRenderer()); - mSwapChain = NULL; - mShareHandle = NULL; - mTexture = NULL; - mTextureFormat = EGL_NO_TEXTURE; - mTextureTarget = EGL_NO_TEXTURE; - - mPixelAspectRatio = (EGLint)(1.0 * EGL_DISPLAY_SCALING); // FIXME: Determine actual pixel aspect ratio - mRenderBuffer = EGL_BACK_BUFFER; - mSwapBehavior = EGL_BUFFER_PRESERVED; - mSwapInterval = -1; - mWidth = width; - mHeight = height; - mFixedWidth = mWidth; - mFixedHeight = mHeight; - setSwapInterval(1); - mFixedSize = fixedSize; - - subclassWindow(); -} - -Surface::Surface(Display *display, const Config *config, HANDLE shareHandle, EGLint width, EGLint height, EGLenum textureFormat, EGLenum textureType) - : mDisplay(display), mNativeWindow(NULL, NULL), mConfig(config), mShareHandle(shareHandle), mWidth(width), mHeight(height), mPostSubBufferSupported(EGL_FALSE) -{ - //TODO(jmadill): MANGLE refactor. (note, can't call makeRendererD3D because of dll export issues) - mRenderer = static_cast(mDisplay->getRenderer()); - mSwapChain = NULL; - mWindowSubclassed = false; - mTexture = NULL; - mTextureFormat = textureFormat; - mTextureTarget = textureType; - - mPixelAspectRatio = (EGLint)(1.0 * EGL_DISPLAY_SCALING); // FIXME: Determine actual pixel aspect ratio - mRenderBuffer = EGL_BACK_BUFFER; - mSwapBehavior = EGL_BUFFER_PRESERVED; - mSwapInterval = -1; - setSwapInterval(1); - // This constructor is for offscreen surfaces, which are always fixed-size. - mFixedSize = EGL_TRUE; - mFixedWidth = mWidth; - mFixedHeight = mHeight; -} - -Surface::~Surface() -{ - unsubclassWindow(); - release(); -} - -Error Surface::initialize() -{ - if (mNativeWindow.getNativeWindow()) - { - if (!mNativeWindow.initialize()) - { - return Error(EGL_BAD_SURFACE); - } - } - - Error error = resetSwapChain(); - if (error.isError()) - { - return error; - } - - return Error(EGL_SUCCESS); -} - -void Surface::release() -{ - delete mSwapChain; - mSwapChain = NULL; - - if (mTexture) - { - mTexture->releaseTexImage(); - mTexture = NULL; - } -} - -Error Surface::resetSwapChain() -{ - ASSERT(!mSwapChain); - - int width; - int height; - - if (!mFixedSize) - { - RECT windowRect; - if (!mNativeWindow.getClientRect(&windowRect)) - { - ASSERT(false); - - return Error(EGL_BAD_SURFACE, "Could not retrieve the window dimensions"); - } - - width = windowRect.right - windowRect.left; - height = windowRect.bottom - windowRect.top; - } - else - { - // non-window surface - size is determined at creation - width = mWidth; - height = mHeight; - } - - mSwapChain = mRenderer->createSwapChain(mNativeWindow, mShareHandle, - mConfig->mRenderTargetFormat, - mConfig->mDepthStencilFormat); - if (!mSwapChain) - { - return Error(EGL_BAD_ALLOC); - } - - Error error = resetSwapChain(width, height); - if (error.isError()) - { - SafeDelete(mSwapChain); - return error; - } - - return Error(EGL_SUCCESS); -} - -Error Surface::resizeSwapChain(int backbufferWidth, int backbufferHeight) -{ - ASSERT(mSwapChain); - -#if !defined(ANGLE_ENABLE_WINDOWS_STORE) - backbufferWidth = std::max(1, backbufferWidth); - backbufferHeight = std::max(1, backbufferHeight); -#endif - EGLint status = mSwapChain->resize(backbufferWidth, backbufferHeight); - - if (status == EGL_CONTEXT_LOST) - { - mDisplay->notifyDeviceLost(); - return Error(status); - } - else if (status != EGL_SUCCESS) - { - return Error(status); - } - - mWidth = backbufferWidth; - mHeight = backbufferHeight; - - return Error(EGL_SUCCESS); -} - -Error Surface::resetSwapChain(int backbufferWidth, int backbufferHeight) -{ - ASSERT(backbufferWidth >= 0 && backbufferHeight >= 0); - ASSERT(mSwapChain); - - EGLint status = mSwapChain->reset(std::max(1, backbufferWidth), std::max(1, backbufferHeight), mSwapInterval); - - if (status == EGL_CONTEXT_LOST) - { - mRenderer->notifyDeviceLost(); - return Error(status); - } - else if (status != EGL_SUCCESS) - { - return Error(status); - } - - mWidth = backbufferWidth; - mHeight = backbufferHeight; - mSwapIntervalDirty = false; - - return Error(EGL_SUCCESS); -} - -Error Surface::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) -{ - if (!mSwapChain) - { - return Error(EGL_SUCCESS); - } - - if (x + width > abs(mWidth)) - { - width = abs(mWidth) - x; - } - - if (y + height > abs(mHeight)) - { - height = abs(mHeight) - y; - } - - if (width == 0 || height == 0) - { - return Error(EGL_SUCCESS); - } - - ASSERT(width > 0); - ASSERT(height > 0); - - EGLint status = mSwapChain->swapRect(x, y, width, height); - - if (status == EGL_CONTEXT_LOST) - { - mRenderer->notifyDeviceLost(); - return Error(status); - } - else if (status != EGL_SUCCESS) - { - return Error(status); - } - - checkForOutOfDateSwapChain(); - - return Error(EGL_SUCCESS); -} - -EGLNativeWindowType Surface::getWindowHandle() -{ - return mNativeWindow.getNativeWindow(); -} - -#if !defined(ANGLE_ENABLE_WINDOWS_STORE) -#define kSurfaceProperty _TEXT("Egl::SurfaceOwner") -#define kParentWndProc _TEXT("Egl::SurfaceParentWndProc") - -static LRESULT CALLBACK SurfaceWindowProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) -{ - if (message == WM_SIZE) - { - Surface* surf = reinterpret_cast(GetProp(hwnd, kSurfaceProperty)); - if(surf) - { - surf->checkForOutOfDateSwapChain(); - } - } - WNDPROC prevWndFunc = reinterpret_cast(GetProp(hwnd, kParentWndProc)); - return CallWindowProc(prevWndFunc, hwnd, message, wparam, lparam); -} -#endif - -void Surface::subclassWindow() -{ -#if !defined(ANGLE_ENABLE_WINDOWS_STORE) - HWND window = mNativeWindow.getNativeWindow(); - if (!window) - { - return; - } - - DWORD processId; - DWORD threadId = GetWindowThreadProcessId(window, &processId); - if (processId != GetCurrentProcessId() || threadId != GetCurrentThreadId()) - { - return; - } - - SetLastError(0); - LONG_PTR oldWndProc = SetWindowLongPtr(window, GWLP_WNDPROC, reinterpret_cast(SurfaceWindowProc)); - if(oldWndProc == 0 && GetLastError() != ERROR_SUCCESS) - { - mWindowSubclassed = false; - return; - } - - SetProp(window, kSurfaceProperty, reinterpret_cast(this)); - SetProp(window, kParentWndProc, reinterpret_cast(oldWndProc)); - mWindowSubclassed = true; -#endif -} - -void Surface::unsubclassWindow() -{ - if(!mWindowSubclassed) - { - return; - } - -#if !defined(ANGLE_ENABLE_WINDOWS_STORE) - HWND window = mNativeWindow.getNativeWindow(); - if (!window) - { - return; - } - - // un-subclass - LONG_PTR parentWndFunc = reinterpret_cast(GetProp(window, kParentWndProc)); - - // Check the windowproc is still SurfaceWindowProc. - // If this assert fails, then it is likely the application has subclassed the - // hwnd as well and did not unsubclass before destroying its EGL context. The - // application should be modified to either subclass before initializing the - // EGL context, or to unsubclass before destroying the EGL context. - if(parentWndFunc) - { - LONG_PTR prevWndFunc = SetWindowLongPtr(window, GWLP_WNDPROC, parentWndFunc); - UNUSED_ASSERTION_VARIABLE(prevWndFunc); - ASSERT(prevWndFunc == reinterpret_cast(SurfaceWindowProc)); - } - - RemoveProp(window, kSurfaceProperty); - RemoveProp(window, kParentWndProc); -#endif - mWindowSubclassed = false; -} - -bool Surface::checkForOutOfDateSwapChain() -{ - RECT client; - int clientWidth = getWidth(); - int clientHeight = getHeight(); - bool sizeDirty = false; - if (!mFixedSize && !mNativeWindow.isIconic()) - { - // The window is automatically resized to 150x22 when it's minimized, but the swapchain shouldn't be resized - // because that's not a useful size to render to. - if (!mNativeWindow.getClientRect(&client)) - { - ASSERT(false); - return false; - } - - // Grow the buffer now, if the window has grown. We need to grow now to avoid losing information. - clientWidth = client.right - client.left; - clientHeight = client.bottom - client.top; - sizeDirty = clientWidth != getWidth() || clientHeight != getHeight(); - } - - if (mFixedSize && (mWidth != mFixedWidth || mHeight != mFixedHeight)) - { - clientWidth = mFixedWidth; - clientHeight = mFixedHeight; - sizeDirty = true; - } - - bool wasDirty = (mSwapIntervalDirty || sizeDirty); - - if (mSwapIntervalDirty) - { - resetSwapChain(clientWidth, clientHeight); - } - else if (sizeDirty) - { - resizeSwapChain(clientWidth, clientHeight); - } - - if (wasDirty) - { - if (static_cast(getCurrentDrawSurface()) == this) - { - glMakeCurrent(glGetCurrentContext(), static_cast(getCurrentDisplay()), this); - } - - return true; - } - - return false; -} - -Error Surface::swap() -{ - return swapRect(0, 0, abs(mWidth), abs(mHeight)); -} - -Error Surface::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) -{ - if (!mPostSubBufferSupported) - { - // Spec is not clear about how this should be handled. - return Error(EGL_SUCCESS); - } - - return swapRect(x, y, width, height); -} - -EGLint Surface::isPostSubBufferSupported() const -{ - return mPostSubBufferSupported; -} - -rx::SwapChain *Surface::getSwapChain() const -{ - return mSwapChain; -} - -void Surface::setSwapInterval(EGLint interval) -{ - if (mSwapInterval == interval) - { - return; - } - - mSwapInterval = interval; - mSwapInterval = std::max(mSwapInterval, mRenderer->getMinSwapInterval()); - mSwapInterval = std::min(mSwapInterval, mRenderer->getMaxSwapInterval()); - - mSwapIntervalDirty = true; -} - -EGLint Surface::getConfigID() const -{ - return mConfig->mConfigID; -} - -EGLint Surface::getWidth() const -{ - return mWidth; -} - -EGLint Surface::getHeight() const -{ - return mHeight; -} - -EGLint Surface::getPixelAspectRatio() const -{ - return mPixelAspectRatio; -} - -EGLenum Surface::getRenderBuffer() const -{ - return mRenderBuffer; -} - -EGLenum Surface::getSwapBehavior() const -{ - return mSwapBehavior; -} - -EGLenum Surface::getTextureFormat() const -{ - return mTextureFormat; -} - -EGLenum Surface::getTextureTarget() const -{ - return mTextureTarget; -} - -void Surface::setBoundTexture(gl::Texture2D *texture) -{ - mTexture = texture; -} - -gl::Texture2D *Surface::getBoundTexture() const -{ - return mTexture; -} - -EGLint Surface::isFixedSize() const -{ - return mFixedSize; -} - -void Surface::setFixedWidth(EGLint width) -{ - mFixedWidth = width; -} - -void Surface::setFixedHeight(EGLint height) -{ - mFixedHeight = height; -} - -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 deleted file mode 100644 index 46382d06e1..0000000000 --- a/src/3rdparty/angle/src/libEGL/Surface.h +++ /dev/null @@ -1,120 +0,0 @@ -// -// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Surface.h: Defines the egl::Surface class, representing a drawing surface -// such as the client area of a window, including any back buffers. -// Implements EGLSurface and related functionality. [EGL 1.4] section 2.2 page 3. - -#ifndef LIBEGL_SURFACE_H_ -#define LIBEGL_SURFACE_H_ - -#include "libEGL/Error.h" - -#include - -#include "common/angleutils.h" -#include "common/NativeWindow.h" - -namespace gl -{ -class Texture2D; -} -namespace rx -{ -class SwapChain; -class RendererD3D; //TODO(jmadill): remove this -} - -namespace egl -{ -class Display; -class Config; - -class Surface -{ - public: - Surface(Display *display, const egl::Config *config, EGLNativeWindowType window, EGLint fixedSize, EGLint width, EGLint height, EGLint postSubBufferSupported); - Surface(Display *display, const egl::Config *config, HANDLE shareHandle, EGLint width, EGLint height, EGLenum textureFormat, EGLenum textureTarget); - - virtual ~Surface(); - - Error initialize(); - void release(); - Error resetSwapChain(); - - EGLNativeWindowType getWindowHandle(); - Error swap(); - Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height); - - virtual EGLint isPostSubBufferSupported() const; - - virtual rx::SwapChain *getSwapChain() const; - - void setSwapInterval(EGLint interval); - bool checkForOutOfDateSwapChain(); // Returns true if swapchain changed due to resize or interval update - - virtual EGLint getConfigID() const; - virtual EGLint getWidth() const; - virtual EGLint getHeight() const; - virtual EGLint getPixelAspectRatio() const; - virtual EGLenum getRenderBuffer() const; - virtual EGLenum getSwapBehavior() const; - virtual EGLenum getTextureFormat() const; - virtual EGLenum getTextureTarget() const; - virtual EGLenum getFormat() const; - - virtual void setBoundTexture(gl::Texture2D *texture); - virtual gl::Texture2D *getBoundTexture() const; - - EGLint isFixedSize() const; - void setFixedWidth(EGLint width); - void setFixedHeight(EGLint height); - - private: - DISALLOW_COPY_AND_ASSIGN(Surface); - - Display *const mDisplay; - rx::RendererD3D *mRenderer; - - HANDLE mShareHandle; - rx::SwapChain *mSwapChain; - - void subclassWindow(); - void unsubclassWindow(); - Error resizeSwapChain(int backbufferWidth, int backbufferHeight); - Error resetSwapChain(int backbufferWidth, int backbufferHeight); - Error swapRect(EGLint x, EGLint y, EGLint width, EGLint height); - - rx::NativeWindow mNativeWindow; // Handler for the Window that the surface is created for. - bool mWindowSubclassed; // Indicates whether we successfully subclassed mWindow for WM_RESIZE hooking - const egl::Config *mConfig; // EGL config surface was created with - EGLint mHeight; // Height of surface - EGLint mWidth; // Width of surface - EGLint mFixedHeight; // Pending height of the surface - EGLint mFixedWidth; // Pending width of the surface -// EGLint horizontalResolution; // Horizontal dot pitch -// EGLint verticalResolution; // Vertical dot pitch -// EGLBoolean largestPBuffer; // If true, create largest pbuffer possible -// EGLBoolean mipmapTexture; // True if texture has mipmaps -// EGLint mipmapLevel; // Mipmap level to render to -// EGLenum multisampleResolve; // Multisample resolve behavior - EGLint mPixelAspectRatio; // Display aspect ratio - EGLenum mRenderBuffer; // Render buffer - EGLenum mSwapBehavior; // Buffer swap behavior - EGLenum mTextureFormat; // Format of texture: RGB, RGBA, or no texture - EGLenum mTextureTarget; // Type of texture: 2D or no texture -// EGLenum vgAlphaFormat; // Alpha format for OpenVG -// EGLenum vgColorSpace; // Color space for OpenVG - EGLint mSwapInterval; - EGLint mPostSubBufferSupported; - EGLint mFixedSize; - - bool mSwapIntervalDirty; - gl::Texture2D *mTexture; -}; -} - -#endif // LIBEGL_SURFACE_H_ diff --git a/src/3rdparty/angle/src/libEGL/libEGL.cpp b/src/3rdparty/angle/src/libEGL/libEGL.cpp index 68399d63a4..d09219e308 100644 --- a/src/3rdparty/angle/src/libEGL/libEGL.cpp +++ b/src/3rdparty/angle/src/libEGL/libEGL.cpp @@ -6,1258 +6,245 @@ // libEGL.cpp: Implements the exported EGL functions. -#undef EGLAPI -#define EGLAPI +#include "libGLESv2/entry_points_egl.h" +#include "libGLESv2/entry_points_egl_ext.h" -#include - -#include "common/debug.h" -#include "common/version.h" -#include "libGLESv2/Context.h" -#include "libGLESv2/Texture.h" -#include "libGLESv2/main.h" -#include "libGLESv2/renderer/SwapChain.h" -#if defined(ANGLE_ENABLE_D3D11) -# include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" -#endif - -#include "libEGL/main.h" -#include "libEGL/Display.h" -#include "libEGL/Surface.h" - -#include "common/NativeWindow.h" - -bool validateDisplay(egl::Display *display) +extern "C" { - if (display == EGL_NO_DISPLAY) - { - recordError(egl::Error(EGL_BAD_DISPLAY)); - return false; - } - - if (!display->isInitialized()) - { - recordError(egl::Error(EGL_NOT_INITIALIZED)); - return false; - } - return true; +EGLBoolean EGLAPIENTRY eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config) +{ + return egl::ChooseConfig(dpy, attrib_list, configs, config_size, num_config); } -bool validateConfig(egl::Display *display, EGLConfig config) +EGLBoolean EGLAPIENTRY eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target) { - if (!validateDisplay(display)) - { - return false; - } - - if (!display->isValidConfig(config)) - { - recordError(egl::Error(EGL_BAD_CONFIG)); - return false; - } - - return true; + return egl::CopyBuffers(dpy, surface, target); } -bool validateContext(egl::Display *display, gl::Context *context) +EGLContext EGLAPIENTRY eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list) { - if (!validateDisplay(display)) - { - return false; - } - - if (!display->isValidContext(context)) - { - recordError(egl::Error(EGL_BAD_CONTEXT)); - return false; - } - - return true; + return egl::CreateContext(dpy, config, share_context, attrib_list); } -bool validateSurface(egl::Display *display, egl::Surface *surface) +EGLSurface EGLAPIENTRY eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list) { - if (!validateDisplay(display)) - { - return false; - } - - if (!display->isValidSurface(surface)) - { - recordError(egl::Error(EGL_BAD_SURFACE)); - return false; - } - - return true; + return egl::CreatePbufferSurface(dpy, config, attrib_list); } -extern "C" -{ -EGLint __stdcall eglGetError(void) +EGLSurface EGLAPIENTRY eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list) { - EVENT("()"); - - EGLint error = egl::getCurrentError(); - recordError(egl::Error(EGL_SUCCESS)); - return error; + return egl::CreatePixmapSurface(dpy, config, pixmap, attrib_list); } -EGLDisplay __stdcall eglGetDisplay(EGLNativeDisplayType display_id) +EGLSurface EGLAPIENTRY eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list) { - EVENT("(EGLNativeDisplayType display_id = 0x%0.8p)", display_id); - - return egl::Display::getDisplay(display_id, egl::AttributeMap()); + return egl::CreateWindowSurface(dpy, config, win, attrib_list); } -EGLDisplay __stdcall eglGetPlatformDisplayEXT(EGLenum platform, void *native_display, const EGLint *attrib_list) +EGLBoolean EGLAPIENTRY eglDestroyContext(EGLDisplay dpy, EGLContext ctx) { - EVENT("(EGLenum platform = %d, void* native_display = 0x%0.8p, const EGLint* attrib_list = 0x%0.8p)", - platform, native_display, attrib_list); - - switch (platform) - { - case EGL_PLATFORM_ANGLE_ANGLE: - break; - - default: - recordError(egl::Error(EGL_BAD_CONFIG)); - return EGL_NO_DISPLAY; - } - - EGLNativeDisplayType displayId = static_cast(native_display); - -#if !defined(ANGLE_ENABLE_WINDOWS_STORE) - // Validate the display device context - if (WindowFromDC(displayId) == NULL) - { - recordError(egl::Error(EGL_SUCCESS)); - return EGL_NO_DISPLAY; - } -#endif - - EGLint platformType = EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE; - bool majorVersionSpecified = false; - bool minorVersionSpecified = false; - bool requestedWARP = false; - - if (attrib_list) - { - for (const EGLint *curAttrib = attrib_list; curAttrib[0] != EGL_NONE; curAttrib += 2) - { - switch (curAttrib[0]) - { - case EGL_PLATFORM_ANGLE_TYPE_ANGLE: - switch (curAttrib[1]) - { - case EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE: - break; - - case EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE: - case EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE: - if (!egl::Display::supportsPlatformD3D()) - { - recordError(egl::Error(EGL_SUCCESS)); - return EGL_NO_DISPLAY; - } - break; - - case EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE: - case EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE: - if (!egl::Display::supportsPlatformOpenGL()) - { - recordError(egl::Error(EGL_SUCCESS)); - return EGL_NO_DISPLAY; - } - break; - - default: - recordError(egl::Error(EGL_SUCCESS)); - return EGL_NO_DISPLAY; - } - platformType = curAttrib[1]; - break; - - case EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE: - if (curAttrib[1] != EGL_DONT_CARE) - { - majorVersionSpecified = true; - } - break; - - case EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE: - if (curAttrib[1] != EGL_DONT_CARE) - { - minorVersionSpecified = true; - } - break; - - case EGL_PLATFORM_ANGLE_USE_WARP_ANGLE: - if (!egl::Display::supportsPlatformD3D()) - { - recordError(egl::Error(EGL_SUCCESS)); - return EGL_NO_DISPLAY; - } - - switch (curAttrib[1]) - { - case EGL_FALSE: - case EGL_TRUE: - break; - - default: - recordError(egl::Error(EGL_SUCCESS)); - return EGL_NO_DISPLAY; - } - - requestedWARP = (curAttrib[1] == EGL_TRUE); - break; - - default: - break; - } - } - } - - if (!majorVersionSpecified && minorVersionSpecified) - { - recordError(egl::Error(EGL_BAD_ATTRIBUTE)); - return EGL_NO_DISPLAY; - } - - if (platformType != EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE && requestedWARP) - { - recordError(egl::Error(EGL_BAD_ATTRIBUTE)); - return EGL_NO_DISPLAY; - } - - recordError(egl::Error(EGL_SUCCESS)); - return egl::Display::getDisplay(displayId, egl::AttributeMap(attrib_list)); + return egl::DestroyContext(dpy, ctx); } -EGLBoolean __stdcall eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) +EGLBoolean EGLAPIENTRY eglDestroySurface(EGLDisplay dpy, EGLSurface surface) { - EVENT("(EGLDisplay dpy = 0x%0.8p, EGLint *major = 0x%0.8p, EGLint *minor = 0x%0.8p)", - dpy, major, minor); - - if (dpy == EGL_NO_DISPLAY) - { - recordError(egl::Error(EGL_BAD_DISPLAY)); - return EGL_FALSE; - } - - egl::Display *display = static_cast(dpy); - - egl::Error error = display->initialize(); - if (error.isError()) - { - recordError(error); - return EGL_FALSE; - } - - if (major) *major = 1; - if (minor) *minor = 4; - - recordError(egl::Error(EGL_SUCCESS)); - return EGL_TRUE; + return egl::DestroySurface(dpy, surface); } -EGLBoolean __stdcall eglTerminate(EGLDisplay dpy) +EGLBoolean EGLAPIENTRY eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value) { - EVENT("(EGLDisplay dpy = 0x%0.8p)", dpy); - - if (dpy == EGL_NO_DISPLAY) - { - recordError(egl::Error(EGL_BAD_DISPLAY)); - return EGL_FALSE; - } - - egl::Display *display = static_cast(dpy); - - display->terminate(); - - recordError(egl::Error(EGL_SUCCESS)); - return EGL_TRUE; + return egl::GetConfigAttrib(dpy, config, attribute, value); } -const char *__stdcall eglQueryString(EGLDisplay dpy, EGLint name) +EGLBoolean EGLAPIENTRY eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config) { - EVENT("(EGLDisplay dpy = 0x%0.8p, EGLint name = %d)", dpy, name); - - egl::Display *display = static_cast(dpy); - if (!(display == EGL_NO_DISPLAY && name == EGL_EXTENSIONS) && !validateDisplay(display)) - { - return NULL; - } - - const char *result; - switch (name) - { - case EGL_CLIENT_APIS: - result = "OpenGL_ES"; - break; - case EGL_EXTENSIONS: - result = egl::Display::getExtensionString(display); - break; - case EGL_VENDOR: - result = display->getVendorString(); - break; - case EGL_VERSION: - result = "1.4 (ANGLE " ANGLE_VERSION_STRING ")"; - break; - default: - recordError(egl::Error(EGL_BAD_PARAMETER)); - return NULL; - } - - recordError(egl::Error(EGL_SUCCESS)); - return result; + return egl::GetConfigs(dpy, configs, config_size, num_config); } -EGLBoolean __stdcall eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config) +EGLDisplay EGLAPIENTRY eglGetCurrentDisplay(void) { - EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig *configs = 0x%0.8p, " - "EGLint config_size = %d, EGLint *num_config = 0x%0.8p)", - dpy, configs, config_size, num_config); - - egl::Display *display = static_cast(dpy); - - if (!validateDisplay(display)) - { - return EGL_FALSE; - } - - if (!num_config) - { - recordError(egl::Error(EGL_BAD_PARAMETER)); - return EGL_FALSE; - } - - const EGLint attribList[] = {EGL_NONE}; - - if (!display->getConfigs(configs, attribList, config_size, num_config)) - { - recordError(egl::Error(EGL_BAD_ATTRIBUTE)); - return EGL_FALSE; - } - - recordError(egl::Error(EGL_SUCCESS)); - return EGL_TRUE; + return egl::GetCurrentDisplay(); } -EGLBoolean __stdcall eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config) +EGLSurface EGLAPIENTRY eglGetCurrentSurface(EGLint readdraw) { - EVENT("(EGLDisplay dpy = 0x%0.8p, const EGLint *attrib_list = 0x%0.8p, " - "EGLConfig *configs = 0x%0.8p, EGLint config_size = %d, EGLint *num_config = 0x%0.8p)", - dpy, attrib_list, configs, config_size, num_config); - - egl::Display *display = static_cast(dpy); - - if (!validateDisplay(display)) - { - return EGL_FALSE; - } - - if (!num_config) - { - recordError(egl::Error(EGL_BAD_PARAMETER)); - return EGL_FALSE; - } - - const EGLint attribList[] = {EGL_NONE}; - - if (!attrib_list) - { - attrib_list = attribList; - } - - display->getConfigs(configs, attrib_list, config_size, num_config); - - recordError(egl::Error(EGL_SUCCESS)); - return EGL_TRUE; + return egl::GetCurrentSurface(readdraw); } -EGLBoolean __stdcall eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value) +EGLDisplay EGLAPIENTRY eglGetDisplay(EGLNativeDisplayType display_id) { - EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLint attribute = %d, EGLint *value = 0x%0.8p)", - dpy, config, attribute, value); - - egl::Display *display = static_cast(dpy); - - if (!validateConfig(display, config)) - { - return EGL_FALSE; - } - - if (!display->getConfigAttrib(config, attribute, value)) - { - recordError(egl::Error(EGL_BAD_ATTRIBUTE)); - return EGL_FALSE; - } - - recordError(egl::Error(EGL_SUCCESS)); - return EGL_TRUE; + return egl::GetDisplay(display_id); } -EGLSurface __stdcall eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list) +EGLint EGLAPIENTRY eglGetError(void) { - EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLNativeWindowType win = 0x%0.8p, " - "const EGLint *attrib_list = 0x%0.8p)", dpy, config, win, attrib_list); - - egl::Display *display = static_cast(dpy); - - if (!validateConfig(display, config)) - { - return EGL_NO_SURFACE; - } - - if (!rx::IsValidEGLNativeWindowType(win)) - { - recordError(egl::Error(EGL_BAD_NATIVE_WINDOW)); - return EGL_NO_SURFACE; - } - - EGLSurface surface = EGL_NO_SURFACE; - egl::Error error = display->createWindowSurface(win, config, attrib_list, &surface); - if (error.isError()) - { - recordError(error); - return EGL_NO_SURFACE; - } - - return surface; + return egl::GetError(); } -EGLSurface __stdcall eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list) +EGLBoolean EGLAPIENTRY eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) { - EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, const EGLint *attrib_list = 0x%0.8p)", - dpy, config, attrib_list); - - egl::Display *display = static_cast(dpy); - - if (!validateConfig(display, config)) - { - return EGL_NO_SURFACE; - } - - EGLSurface surface = EGL_NO_SURFACE; - egl::Error error = display->createOffscreenSurface(config, NULL, attrib_list, &surface); - if (error.isError()) - { - recordError(error); - return EGL_NO_SURFACE; - } - - return surface; + return egl::Initialize(dpy, major, minor); } -EGLSurface __stdcall eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list) +EGLBoolean EGLAPIENTRY eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx) { - EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLNativePixmapType pixmap = 0x%0.8p, " - "const EGLint *attrib_list = 0x%0.8p)", dpy, config, pixmap, attrib_list); - - egl::Display *display = static_cast(dpy); - - if (!validateConfig(display, config)) - { - return EGL_NO_SURFACE; - } - - UNIMPLEMENTED(); // FIXME - - recordError(egl::Error(EGL_SUCCESS)); - return EGL_NO_SURFACE; + return egl::MakeCurrent(dpy, draw, read, ctx); } -EGLBoolean __stdcall eglDestroySurface(EGLDisplay dpy, EGLSurface surface) +EGLBoolean EGLAPIENTRY eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value) { - EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p)", dpy, surface); - - egl::Display *display = static_cast(dpy); - egl::Surface *eglSurface = static_cast(surface); - - if (!validateSurface(display, eglSurface)) - { - return EGL_FALSE; - } - - if (surface == EGL_NO_SURFACE) - { - recordError(egl::Error(EGL_BAD_SURFACE)); - return EGL_FALSE; - } - - display->destroySurface((egl::Surface*)surface); - - recordError(egl::Error(EGL_SUCCESS)); - return EGL_TRUE; + return egl::QueryContext(dpy, ctx, attribute, value); } -EGLBoolean __stdcall eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value) +const char* EGLAPIENTRY eglQueryString(EGLDisplay dpy, EGLint name) { - EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint attribute = %d, EGLint *value = 0x%0.8p)", - dpy, surface, attribute, value); - - egl::Display *display = static_cast(dpy); - egl::Surface *eglSurface = (egl::Surface*)surface; - - if (!validateSurface(display, eglSurface)) - { - return EGL_FALSE; - } - - if (surface == EGL_NO_SURFACE) - { - recordError(egl::Error(EGL_BAD_SURFACE)); - return EGL_FALSE; - } - - switch (attribute) - { - case EGL_VG_ALPHA_FORMAT: - UNIMPLEMENTED(); // FIXME - break; - case EGL_VG_COLORSPACE: - UNIMPLEMENTED(); // FIXME - break; - case EGL_CONFIG_ID: - *value = eglSurface->getConfigID(); - break; - case EGL_HEIGHT: - *value = eglSurface->getHeight(); - break; - case EGL_HORIZONTAL_RESOLUTION: - UNIMPLEMENTED(); // FIXME - break; - case EGL_LARGEST_PBUFFER: - UNIMPLEMENTED(); // FIXME - break; - case EGL_MIPMAP_TEXTURE: - UNIMPLEMENTED(); // FIXME - break; - case EGL_MIPMAP_LEVEL: - UNIMPLEMENTED(); // FIXME - break; - case EGL_MULTISAMPLE_RESOLVE: - UNIMPLEMENTED(); // FIXME - break; - case EGL_PIXEL_ASPECT_RATIO: - *value = eglSurface->getPixelAspectRatio(); - break; - case EGL_RENDER_BUFFER: - *value = eglSurface->getRenderBuffer(); - break; - case EGL_SWAP_BEHAVIOR: - *value = eglSurface->getSwapBehavior(); - break; - case EGL_TEXTURE_FORMAT: - *value = eglSurface->getTextureFormat(); - break; - case EGL_TEXTURE_TARGET: - *value = eglSurface->getTextureTarget(); - break; - case EGL_VERTICAL_RESOLUTION: - UNIMPLEMENTED(); // FIXME - break; - case EGL_WIDTH: - *value = eglSurface->getWidth(); - break; - case EGL_POST_SUB_BUFFER_SUPPORTED_NV: - *value = eglSurface->isPostSubBufferSupported(); - break; - case EGL_FIXED_SIZE_ANGLE: - *value = eglSurface->isFixedSize(); - break; - default: - recordError(egl::Error(EGL_BAD_ATTRIBUTE)); - return EGL_FALSE; - } - - recordError(egl::Error(EGL_SUCCESS)); - return EGL_TRUE; + return egl::QueryString(dpy, name); } -EGLBoolean __stdcall eglQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value) +EGLBoolean EGLAPIENTRY eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value) { - TRACE("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint attribute = %d, void **value = 0x%0.8p)", - dpy, surface, attribute, value); - - egl::Display *display = static_cast(dpy); - egl::Surface *eglSurface = (egl::Surface*)surface; - - switch (attribute) - { - case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE: - { - if (!validateSurface(display, eglSurface)) - { - return EGL_FALSE; - } - - if (surface == EGL_NO_SURFACE) - { - recordError(egl::Error(EGL_BAD_SURFACE)); - return EGL_FALSE; - } - - rx::SwapChain *swapchain = eglSurface->getSwapChain(); - *value = (void*) (swapchain ? swapchain->getShareHandle() : NULL); - } - break; -#if defined(ANGLE_ENABLE_D3D11) - case EGL_DEVICE_EXT: - { - if (!validateDisplay(display)) - { - return EGL_FALSE; - } - - rx::Renderer *renderer = display->getRenderer(); - if (!renderer) - { - *value = NULL; - break; - } - - if (renderer->getMajorShaderModel() < 4) - { - recordError(egl::Error(EGL_BAD_CONTEXT)); - return EGL_FALSE; - } - - *value = static_cast(renderer)->getDevice(); - } - break; -#endif - default: - recordError(egl::Error(EGL_BAD_ATTRIBUTE)); - return EGL_FALSE; - } - - recordError(egl::Error(EGL_SUCCESS)); - return EGL_TRUE; + return egl::QuerySurface(dpy, surface, attribute, value); } -EGLBoolean __stdcall eglBindAPI(EGLenum api) +EGLBoolean EGLAPIENTRY eglSwapBuffers(EGLDisplay dpy, EGLSurface surface) { - EVENT("(EGLenum api = 0x%X)", api); - - switch (api) - { - case EGL_OPENGL_API: - case EGL_OPENVG_API: - recordError(egl::Error(EGL_BAD_PARAMETER)); - return EGL_FALSE; // Not supported by this implementation - case EGL_OPENGL_ES_API: - break; - default: - recordError(egl::Error(EGL_BAD_PARAMETER)); - return EGL_FALSE; - } - - egl::setCurrentAPI(api); - - recordError(egl::Error(EGL_SUCCESS)); - return EGL_TRUE; + return egl::SwapBuffers(dpy, surface); } -EGLenum __stdcall eglQueryAPI(void) +EGLBoolean EGLAPIENTRY eglTerminate(EGLDisplay dpy) { - EVENT("()"); - - EGLenum API = egl::getCurrentAPI(); - - recordError(egl::Error(EGL_SUCCESS)); - return API; + return egl::Terminate(dpy); } -EGLBoolean __stdcall eglWaitClient(void) +EGLBoolean EGLAPIENTRY eglWaitGL(void) { - EVENT("()"); - - UNIMPLEMENTED(); // FIXME - - recordError(egl::Error(EGL_SUCCESS)); - return 0; + return egl::WaitGL(); } -EGLBoolean __stdcall eglReleaseThread(void) +EGLBoolean EGLAPIENTRY eglWaitNative(EGLint engine) { - EVENT("()"); - - eglMakeCurrent(EGL_NO_DISPLAY, EGL_NO_CONTEXT, EGL_NO_SURFACE, EGL_NO_SURFACE); - - recordError(egl::Error(EGL_SUCCESS)); - return EGL_TRUE; + return egl::WaitNative(engine); } -EGLSurface __stdcall eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list) +EGLBoolean EGLAPIENTRY eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) { - EVENT("(EGLDisplay dpy = 0x%0.8p, EGLenum buftype = 0x%X, EGLClientBuffer buffer = 0x%0.8p, " - "EGLConfig config = 0x%0.8p, const EGLint *attrib_list = 0x%0.8p)", - dpy, buftype, buffer, config, attrib_list); - - egl::Display *display = static_cast(dpy); - - if (!validateConfig(display, config)) - { - return EGL_NO_SURFACE; - } - - if (buftype != EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE || !buffer) - { - recordError(egl::Error(EGL_BAD_PARAMETER)); - return EGL_NO_SURFACE; - } - - EGLSurface surface = EGL_NO_SURFACE; - egl::Error error = display->createOffscreenSurface(config, (HANDLE)buffer, attrib_list, &surface); - if (error.isError()) - { - recordError(error); - return EGL_NO_SURFACE; - } - - return surface; + return egl::BindTexImage(dpy, surface, buffer); } -EGLBoolean __stdcall eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value) +EGLBoolean EGLAPIENTRY eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) { - EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint attribute = %d, EGLint value = %d)", - dpy, surface, attribute, value); - - egl::Display *display = static_cast(dpy); - egl::Surface *eglSurface = static_cast(surface); - - if (!validateSurface(display, eglSurface)) - { - return EGL_FALSE; - } - - switch (attribute) - { - case EGL_WIDTH: - if (!eglSurface->isFixedSize() || !value) { - recordError(egl::Error(EGL_BAD_PARAMETER)); - return EGL_FALSE; - } - eglSurface->setFixedWidth(value); - return EGL_TRUE; - case EGL_HEIGHT: - if (!eglSurface->isFixedSize() || !value) { - recordError(egl::Error(EGL_BAD_PARAMETER)); - return EGL_FALSE; - } - eglSurface->setFixedHeight(value); - return EGL_TRUE; - default: - break; - } - - UNIMPLEMENTED(); // FIXME - - recordError(egl::Error(EGL_SUCCESS)); - return EGL_TRUE; + return egl::ReleaseTexImage(dpy, surface, buffer); } -EGLBoolean __stdcall eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) +EGLBoolean EGLAPIENTRY eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value) { - EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint buffer = %d)", dpy, surface, buffer); - - egl::Display *display = static_cast(dpy); - egl::Surface *eglSurface = static_cast(surface); - - if (!validateSurface(display, eglSurface)) - { - return EGL_FALSE; - } - - if (buffer != EGL_BACK_BUFFER) - { - recordError(egl::Error(EGL_BAD_PARAMETER)); - return EGL_FALSE; - } - - if (surface == EGL_NO_SURFACE || eglSurface->getWindowHandle()) - { - recordError(egl::Error(EGL_BAD_SURFACE)); - return EGL_FALSE; - } - - if (eglSurface->getBoundTexture()) - { - recordError(egl::Error(EGL_BAD_ACCESS)); - return EGL_FALSE; - } - - if (eglSurface->getTextureFormat() == EGL_NO_TEXTURE) - { - recordError(egl::Error(EGL_BAD_MATCH)); - return EGL_FALSE; - } - - if (!glBindTexImage(eglSurface)) - { - recordError(egl::Error(EGL_BAD_MATCH)); - return EGL_FALSE; - } - - recordError(egl::Error(EGL_SUCCESS)); - return EGL_TRUE; + return egl::SurfaceAttrib(dpy, surface, attribute, value); } -EGLBoolean __stdcall eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) +EGLBoolean EGLAPIENTRY eglSwapInterval(EGLDisplay dpy, EGLint interval) { - EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint buffer = %d)", dpy, surface, buffer); - - egl::Display *display = static_cast(dpy); - egl::Surface *eglSurface = static_cast(surface); - - if (!validateSurface(display, eglSurface)) - { - return EGL_FALSE; - } - - if (buffer != EGL_BACK_BUFFER) - { - recordError(egl::Error(EGL_BAD_PARAMETER)); - return EGL_FALSE; - } - - if (surface == EGL_NO_SURFACE || eglSurface->getWindowHandle()) - { - recordError(egl::Error(EGL_BAD_SURFACE)); - return EGL_FALSE; - } - - if (eglSurface->getTextureFormat() == EGL_NO_TEXTURE) - { - recordError(egl::Error(EGL_BAD_MATCH)); - return EGL_FALSE; - } - - gl::Texture2D *texture = eglSurface->getBoundTexture(); - - if (texture) - { - texture->releaseTexImage(); - } - - recordError(egl::Error(EGL_SUCCESS)); - return EGL_TRUE; + return egl::SwapInterval(dpy, interval); } -EGLBoolean __stdcall eglSwapInterval(EGLDisplay dpy, EGLint interval) +EGLBoolean EGLAPIENTRY eglBindAPI(EGLenum api) { - EVENT("(EGLDisplay dpy = 0x%0.8p, EGLint interval = %d)", dpy, interval); - - egl::Display *display = static_cast(dpy); - - if (!validateDisplay(display)) - { - return EGL_FALSE; - } - - egl::Surface *draw_surface = static_cast(egl::getCurrentDrawSurface()); - - if (draw_surface == NULL) - { - recordError(egl::Error(EGL_BAD_SURFACE)); - return EGL_FALSE; - } - - draw_surface->setSwapInterval(interval); - - recordError(egl::Error(EGL_SUCCESS)); - return EGL_TRUE; + return egl::BindAPI(api); } -EGLContext __stdcall eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list) +EGLenum EGLAPIENTRY eglQueryAPI(void) { - EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLContext share_context = 0x%0.8p, " - "const EGLint *attrib_list = 0x%0.8p)", dpy, config, share_context, attrib_list); - - // Get the requested client version (default is 1) and check it is 2 or 3. - EGLint client_version = 1; - bool reset_notification = false; - bool robust_access = false; - - if (attrib_list) - { - for (const EGLint* attribute = attrib_list; attribute[0] != EGL_NONE; attribute += 2) - { - switch (attribute[0]) - { - case EGL_CONTEXT_CLIENT_VERSION: - client_version = attribute[1]; - break; - case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT: - if (attribute[1] == EGL_TRUE) - { - recordError(egl::Error(EGL_BAD_CONFIG)); // Unimplemented - return EGL_NO_CONTEXT; - // robust_access = true; - } - else if (attribute[1] != EGL_FALSE) - { - recordError(egl::Error(EGL_BAD_ATTRIBUTE)); - return 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) - { - recordError(egl::Error(EGL_BAD_ATTRIBUTE)); - return EGL_NO_CONTEXT; - } - break; - default: - recordError(egl::Error(EGL_BAD_ATTRIBUTE)); - return EGL_NO_CONTEXT; - } - } - } - - if (client_version != 2 && client_version != 3) - { - recordError(egl::Error(EGL_BAD_CONFIG)); - return EGL_NO_CONTEXT; - } - - egl::Display *display = static_cast(dpy); - - if (share_context) - { - gl::Context* sharedGLContext = static_cast(share_context); - - if (sharedGLContext->isResetNotificationEnabled() != reset_notification) - { - recordError(egl::Error(EGL_BAD_MATCH)); - return EGL_NO_CONTEXT; - } - - if (sharedGLContext->getClientVersion() != client_version) - { - recordError(egl::Error(EGL_BAD_CONTEXT)); - return EGL_NO_CONTEXT; - } - - // Can not share contexts between displays - if (sharedGLContext->getRenderer() != display->getRenderer()) - { - recordError(egl::Error(EGL_BAD_MATCH)); - return EGL_NO_CONTEXT; - } - } - - if (!validateConfig(display, config)) - { - return EGL_NO_CONTEXT; - } - - EGLContext context = EGL_NO_CONTEXT; - egl::Error error = display->createContext(config, client_version, static_cast(share_context), - reset_notification, robust_access, &context); - if (error.isError()) - { - recordError(error); - return EGL_NO_CONTEXT; - } - - return context; + return egl::QueryAPI(); } -EGLBoolean __stdcall eglDestroyContext(EGLDisplay dpy, EGLContext ctx) +EGLSurface EGLAPIENTRY eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list) { - EVENT("(EGLDisplay dpy = 0x%0.8p, EGLContext ctx = 0x%0.8p)", dpy, ctx); - - egl::Display *display = static_cast(dpy); - gl::Context *context = static_cast(ctx); - - if (!validateContext(display, context)) - { - return EGL_FALSE; - } - - if (ctx == EGL_NO_CONTEXT) - { - recordError(egl::Error(EGL_BAD_CONTEXT)); - return EGL_FALSE; - } - - display->destroyContext(context); - - recordError(egl::Error(EGL_SUCCESS)); - return EGL_TRUE; + return egl::CreatePbufferFromClientBuffer(dpy, buftype, buffer, config, attrib_list); } -EGLBoolean __stdcall eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx) +EGLBoolean EGLAPIENTRY eglReleaseThread(void) { - EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface draw = 0x%0.8p, EGLSurface read = 0x%0.8p, EGLContext ctx = 0x%0.8p)", - dpy, draw, read, ctx); - - egl::Display *display = static_cast(dpy); - gl::Context *context = static_cast(ctx); - - bool noContext = (ctx == EGL_NO_CONTEXT); - bool noSurface = (draw == EGL_NO_SURFACE || read == EGL_NO_SURFACE); - if (noContext != noSurface) - { - recordError(egl::Error(EGL_BAD_MATCH)); - return EGL_FALSE; - } - - if (ctx != EGL_NO_CONTEXT && !validateContext(display, context)) - { - return EGL_FALSE; - } - - if (dpy != EGL_NO_DISPLAY && display->isInitialized()) - { - rx::Renderer *renderer = display->getRenderer(); - if (renderer->testDeviceLost(true)) - { - return EGL_FALSE; - } - - if (renderer->isDeviceLost()) - { - recordError(egl::Error(EGL_CONTEXT_LOST)); - return EGL_FALSE; - } - } - - if ((draw != EGL_NO_SURFACE && !validateSurface(display, static_cast(draw))) || - (read != EGL_NO_SURFACE && !validateSurface(display, static_cast(read)))) - { - return EGL_FALSE; - } - - if (draw != read) - { - UNIMPLEMENTED(); // FIXME - } - - egl::setCurrentDisplay(dpy); - egl::setCurrentDrawSurface(draw); - egl::setCurrentReadSurface(read); - - glMakeCurrent(context, display, static_cast(draw)); - - recordError(egl::Error(EGL_SUCCESS)); - return EGL_TRUE; + return egl::ReleaseThread(); } -EGLContext __stdcall eglGetCurrentContext(void) +EGLBoolean EGLAPIENTRY eglWaitClient(void) { - EVENT("()"); - - EGLContext context = glGetCurrentContext(); - - recordError(egl::Error(EGL_SUCCESS)); - return context; + return egl::WaitClient(); } -EGLSurface __stdcall eglGetCurrentSurface(EGLint readdraw) +EGLContext EGLAPIENTRY eglGetCurrentContext(void) { - EVENT("(EGLint readdraw = %d)", readdraw); - - if (readdraw == EGL_READ) - { - recordError(egl::Error(EGL_SUCCESS)); - return egl::getCurrentReadSurface(); - } - else if (readdraw == EGL_DRAW) - { - recordError(egl::Error(EGL_SUCCESS)); - return egl::getCurrentDrawSurface(); - } - else - { - recordError(egl::Error(EGL_BAD_PARAMETER)); - return EGL_NO_SURFACE; - } + return egl::GetCurrentContext(); } -EGLDisplay __stdcall eglGetCurrentDisplay(void) +EGLSync EGLAPIENTRY eglCreateSync(EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list) { - EVENT("()"); - - EGLDisplay dpy = egl::getCurrentDisplay(); - - recordError(egl::Error(EGL_SUCCESS)); - return dpy; + return egl::CreateSync(dpy, type, attrib_list); } -EGLBoolean __stdcall eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value) +EGLBoolean EGLAPIENTRY eglDestroySync(EGLDisplay dpy, EGLSync sync) { - EVENT("(EGLDisplay dpy = 0x%0.8p, EGLContext ctx = 0x%0.8p, EGLint attribute = %d, EGLint *value = 0x%0.8p)", - dpy, ctx, attribute, value); - - egl::Display *display = static_cast(dpy); - gl::Context *context = static_cast(ctx); - - if (!validateContext(display, context)) - { - return EGL_FALSE; - } - - UNIMPLEMENTED(); // FIXME - - recordError(egl::Error(EGL_SUCCESS)); - return 0; + return egl::DestroySync(dpy, sync); } -EGLBoolean __stdcall eglWaitGL(void) +EGLint EGLAPIENTRY eglClientWaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout) { - EVENT("()"); - - UNIMPLEMENTED(); // FIXME - - recordError(egl::Error(EGL_SUCCESS)); - return 0; + return egl::ClientWaitSync(dpy, sync, flags, timeout); } -EGLBoolean __stdcall eglWaitNative(EGLint engine) +EGLBoolean EGLAPIENTRY eglGetSyncAttrib(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib *value) { - EVENT("(EGLint engine = %d)", engine); - - UNIMPLEMENTED(); // FIXME - - recordError(egl::Error(EGL_SUCCESS)); - return 0; + return egl::GetSyncAttrib(dpy, sync, attribute, value); } -EGLBoolean __stdcall eglSwapBuffers(EGLDisplay dpy, EGLSurface surface) +EGLImage EGLAPIENTRY eglCreateImage(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLAttrib *attrib_list) { - EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p)", dpy, surface); - - egl::Display *display = static_cast(dpy); - egl::Surface *eglSurface = (egl::Surface*)surface; - - if (!validateSurface(display, eglSurface)) - { - return EGL_FALSE; - } - - if (display->getRenderer()->isDeviceLost()) - { - recordError(egl::Error(EGL_CONTEXT_LOST)); - return EGL_FALSE; - } - - if (surface == EGL_NO_SURFACE) - { - recordError(egl::Error(EGL_BAD_SURFACE)); - return EGL_FALSE; - } - - egl::Error error = eglSurface->swap(); - if (error.isError()) - { - recordError(error); - return EGL_FALSE; - } - - recordError(egl::Error(EGL_SUCCESS)); - return EGL_TRUE; + return egl::CreateImage(dpy, ctx, target, buffer, attrib_list); } -EGLBoolean __stdcall eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target) +EGLBoolean EGLAPIENTRY eglDestroyImage(EGLDisplay dpy, EGLImage image) { - EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLNativePixmapType target = 0x%0.8p)", dpy, surface, target); - - egl::Display *display = static_cast(dpy); - egl::Surface *eglSurface = static_cast(surface); - - if (!validateSurface(display, eglSurface)) - { - return EGL_FALSE; - } - - if (display->getRenderer()->isDeviceLost()) - { - recordError(egl::Error(EGL_CONTEXT_LOST)); - return EGL_FALSE; - } - - UNIMPLEMENTED(); // FIXME - - recordError(egl::Error(EGL_SUCCESS)); - return 0; + return egl::DestroyImage(dpy, image); } -EGLBoolean __stdcall eglPostSubBufferNV(EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height) +EGLDisplay EGLAPIENTRY eglGetPlatformDisplay(EGLenum platform, void *native_display, const EGLAttrib *attrib_list) { - EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint x = %d, EGLint y = %d, EGLint width = %d, EGLint height = %d)", dpy, surface, x, y, width, height); - - if (x < 0 || y < 0 || width < 0 || height < 0) - { - recordError(egl::Error(EGL_BAD_PARAMETER)); - return EGL_FALSE; - } - - egl::Display *display = static_cast(dpy); - egl::Surface *eglSurface = static_cast(surface); - - if (!validateSurface(display, eglSurface)) - { - return EGL_FALSE; - } - - if (display->getRenderer()->isDeviceLost()) - { - recordError(egl::Error(EGL_CONTEXT_LOST)); - return EGL_FALSE; - } - - if (surface == EGL_NO_SURFACE) - { - recordError(egl::Error(EGL_BAD_SURFACE)); - return EGL_FALSE; - } + return egl::GetPlatformDisplay(platform, native_display, attrib_list); +} - egl::Error error = eglSurface->postSubBuffer(x, y, width, height); - if (error.isError()) - { - recordError(error); - return EGL_FALSE; - } +EGLSurface EGLAPIENTRY eglCreatePlatformWindowSurface(EGLDisplay dpy, EGLConfig config, void *native_window, const EGLAttrib *attrib_list) +{ + return egl::CreatePlatformWindowSurface(dpy, config, native_window, attrib_list); +} - recordError(egl::Error(EGL_SUCCESS)); - return EGL_TRUE; +EGLSurface EGLAPIENTRY eglCreatePlatformPixmapSurface(EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLAttrib *attrib_list) +{ + return egl::CreatePlatformPixmapSurface(dpy, config, native_pixmap, attrib_list); } -__eglMustCastToProperFunctionPointerType __stdcall eglGetProcAddress(const char *procname) +EGLBoolean EGLAPIENTRY eglWaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags) { - EVENT("(const char *procname = \"%s\")", procname); + return egl::WaitSync(dpy, sync, flags); +} - struct Extension - { - const char *name; - __eglMustCastToProperFunctionPointerType address; - }; +EGLBoolean EGLAPIENTRY eglQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value) +{ + return egl::QuerySurfacePointerANGLE(dpy, surface, attribute, value); +} - static const Extension eglExtensions[] = - { - { "eglQuerySurfacePointerANGLE", (__eglMustCastToProperFunctionPointerType)eglQuerySurfacePointerANGLE }, - { "eglPostSubBufferNV", (__eglMustCastToProperFunctionPointerType)eglPostSubBufferNV }, - { "eglGetPlatformDisplayEXT", (__eglMustCastToProperFunctionPointerType)eglGetPlatformDisplayEXT }, - { "", NULL }, - }; +EGLBoolean EGLAPIENTRY eglPostSubBufferNV(EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height) +{ + return egl::PostSubBufferNV(dpy, surface, x, y, width, height); +} - for (unsigned int ext = 0; ext < ArraySize(eglExtensions); ext++) - { - if (strcmp(procname, eglExtensions[ext].name) == 0) - { - return (__eglMustCastToProperFunctionPointerType)eglExtensions[ext].address; - } - } +EGLDisplay EGLAPIENTRY eglGetPlatformDisplayEXT(EGLenum platform, void *native_display, const EGLint *attrib_list) +{ + return egl::GetPlatformDisplayEXT(platform, native_display, attrib_list); +} - return glGetProcAddress(procname); +__eglMustCastToProperFunctionPointerType EGLAPIENTRY eglGetProcAddress(const char *procname) +{ + return egl::GetProcAddress(procname); } + } diff --git a/src/3rdparty/angle/src/libEGL/libEGL.def b/src/3rdparty/angle/src/libEGL/libEGL.def index d7949d0354..823cba2f88 100644 --- a/src/3rdparty/angle/src/libEGL/libEGL.def +++ b/src/3rdparty/angle/src/libEGL/libEGL.def @@ -39,3 +39,15 @@ EXPORTS eglGetPlatformDisplayEXT @35 eglQuerySurfacePointerANGLE @36 eglPostSubBufferNV @37 + + ; 1.5 entry points + eglCreateSync @38 + eglDestroySync @39 + eglClientWaitSync @40 + eglGetSyncAttrib @41 + eglCreateImage @42 + eglDestroyImage @43 + eglGetPlatformDisplay @44 + eglCreatePlatformWindowSurface @45 + eglCreatePlatformPixmapSurface @46 + eglWaitSync @47 diff --git a/src/3rdparty/angle/src/libEGL/libEGL.rc b/src/3rdparty/angle/src/libEGL/libEGL.rc deleted file mode 100644 index 65e0aa50c8..0000000000 --- a/src/3rdparty/angle/src/libEGL/libEGL.rc +++ /dev/null @@ -1,103 +0,0 @@ -// Microsoft Visual C++ generated resource script. -// -#include "resource.h" - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#include -#include "../common/version.h" - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// English (U.S.) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -#ifdef _WIN32 -LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US -#pragma code_page(1252) -#endif //_WIN32 - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE -BEGIN - "resource.h\0" -END - -2 TEXTINCLUDE -BEGIN - "#include ""afxres.h""\r\n" - "#include ""../common/version.h""\0" -END - -3 TEXTINCLUDE -BEGIN - "\r\n" - "\0" -END - -#endif // APSTUDIO_INVOKED - - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION ANGLE_MAJOR_VERSION,ANGLE_MINOR_VERSION,0,0 - PRODUCTVERSION ANGLE_MAJOR_VERSION,ANGLE_MINOR_VERSION,0,0 - FILEFLAGSMASK 0x17L -#ifdef _DEBUG - FILEFLAGS 0x1L -#else - FILEFLAGS 0x0L -#endif - FILEOS 0x4L - FILETYPE 0x2L - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904b0" - BEGIN - VALUE "FileDescription", "ANGLE libEGL Dynamic Link Library" - VALUE "FileVersion", ANGLE_VERSION_STRING - VALUE "InternalName", "libEGL" - VALUE "LegalCopyright", "Copyright (C) 2011 Google Inc." - VALUE "OriginalFilename", "libEGL.dll" - VALUE "PrivateBuild", ANGLE_VERSION_STRING - VALUE "ProductName", "ANGLE libEGL Dynamic Link Library" - VALUE "ProductVersion", ANGLE_VERSION_STRING - VALUE "Comments", "Build Date: " ANGLE_COMMIT_DATE - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x409, 1200 - END -END - -#endif // English (U.S.) resources -///////////////////////////////////////////////////////////////////////////// - - - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// - - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED diff --git a/src/3rdparty/angle/src/libEGL/libEGL_mingw32.def b/src/3rdparty/angle/src/libEGL/libEGL_mingw32.def index 492ad4d0cf..6a771a54b8 100644 --- a/src/3rdparty/angle/src/libEGL/libEGL_mingw32.def +++ b/src/3rdparty/angle/src/libEGL/libEGL_mingw32.def @@ -39,3 +39,15 @@ EXPORTS eglGetPlatformDisplayEXT@12 @35 eglQuerySurfacePointerANGLE@16 @36 eglPostSubBufferNV@24 @37 + + ; 1.5 entry points + eglCreateSync @38 + eglDestroySync @39 + eglClientWaitSync @40 + eglGetSyncAttrib @41 + eglCreateImage @42 + eglDestroyImage @43 + eglGetPlatformDisplay @44 + eglCreatePlatformWindowSurface @45 + eglCreatePlatformPixmapSurface @46 + eglWaitSync @47 diff --git a/src/3rdparty/angle/src/libEGL/libEGLd.def b/src/3rdparty/angle/src/libEGL/libEGLd.def index 0ebd27d0e1..cab7dc9d24 100644 --- a/src/3rdparty/angle/src/libEGL/libEGLd.def +++ b/src/3rdparty/angle/src/libEGL/libEGLd.def @@ -39,3 +39,15 @@ EXPORTS eglGetPlatformDisplayEXT @35 eglQuerySurfacePointerANGLE @36 eglPostSubBufferNV @37 + + ; 1.5 entry points + eglCreateSync @38 + eglDestroySync @39 + eglClientWaitSync @40 + eglGetSyncAttrib @41 + eglCreateImage @42 + eglDestroyImage @43 + eglGetPlatformDisplay @44 + eglCreatePlatformWindowSurface @45 + eglCreatePlatformPixmapSurface @46 + eglWaitSync @47 diff --git a/src/3rdparty/angle/src/libEGL/main.cpp b/src/3rdparty/angle/src/libEGL/main.cpp deleted file mode 100644 index e88cad775f..0000000000 --- a/src/3rdparty/angle/src/libEGL/main.cpp +++ /dev/null @@ -1,203 +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. -// - -// main.cpp: DLL entry point and management of thread-local data. - -#include "libEGL/main.h" - -#include "common/debug.h" -#include "common/tls.h" - -static TLSIndex currentTLS = TLS_OUT_OF_INDEXES; - -namespace egl -{ - -Current *AllocateCurrent() -{ - ASSERT(currentTLS != TLS_OUT_OF_INDEXES); - if (currentTLS == TLS_OUT_OF_INDEXES) - { - return NULL; - } - - Current *current = new Current(); - current->error = EGL_SUCCESS; - current->API = EGL_OPENGL_ES_API; - current->display = EGL_NO_DISPLAY; - current->drawSurface = EGL_NO_SURFACE; - current->readSurface = EGL_NO_SURFACE; - - if (!SetTLSValue(currentTLS, current)) - { - ERR("Could not set thread local storage."); - return NULL; - } - - return current; -} - -void DeallocateCurrent() -{ - Current *current = reinterpret_cast(GetTLSValue(currentTLS)); - SafeDelete(current); - SetTLSValue(currentTLS, NULL); -} - -} - -#ifndef QT_OPENGL_ES_2_ANGLE_STATIC - -extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved) -{ - switch (reason) - { - case DLL_PROCESS_ATTACH: - { -#if defined(ANGLE_ENABLE_DEBUG_TRACE) - FILE *debug = fopen(TRACE_OUTPUT_FILE, "rt"); - - if (debug) - { - fclose(debug); - debug = fopen(TRACE_OUTPUT_FILE, "wt"); // Erase - - if (debug) - { - fclose(debug); - } - } -#endif - - currentTLS = CreateTLSIndex(); - if (currentTLS == TLS_OUT_OF_INDEXES) - { - return FALSE; - } - -#ifdef ANGLE_ENABLE_DEBUG_ANNOTATIONS - gl::InitializeDebugAnnotations(); -#endif - } - // Fall through to initialize index - case DLL_THREAD_ATTACH: - { - egl::AllocateCurrent(); - } - break; - case DLL_THREAD_DETACH: - { - egl::DeallocateCurrent(); - } - break; - case DLL_PROCESS_DETACH: - { - egl::DeallocateCurrent(); - DestroyTLSIndex(currentTLS); - -#ifdef ANGLE_ENABLE_DEBUG_ANNOTATIONS - gl::UninitializeDebugAnnotations(); -#endif - } - break; - default: - break; - } - - return TRUE; -} - -#endif // !QT_OPENGL_ES_2_ANGLE_STATIC - -namespace egl -{ - -Current *GetCurrentData() -{ -#ifndef QT_OPENGL_ES_2_ANGLE_STATIC - Current *current = reinterpret_cast(GetTLSValue(currentTLS)); - - // ANGLE issue 488: when the dll is loaded after thread initialization, - // thread local storage (current) might not exist yet. - return (current ? current : AllocateCurrent()); -#else - // No precautions for thread safety taken as ANGLE is used single-threaded in Qt. - static Current current = { EGL_SUCCESS, EGL_OPENGL_ES_API, EGL_NO_DISPLAY, EGL_NO_SURFACE, EGL_NO_SURFACE }; - return ¤t; -#endif -} - -void recordError(const Error &error) -{ - Current *current = GetCurrentData(); - - current->error = error.getCode(); -} - -EGLint getCurrentError() -{ - Current *current = GetCurrentData(); - - return current->error; -} - -void setCurrentAPI(EGLenum API) -{ - Current *current = GetCurrentData(); - - current->API = API; -} - -EGLenum getCurrentAPI() -{ - Current *current = GetCurrentData(); - - return current->API; -} - -void setCurrentDisplay(EGLDisplay dpy) -{ - Current *current = GetCurrentData(); - - current->display = dpy; -} - -EGLDisplay getCurrentDisplay() -{ - Current *current = GetCurrentData(); - - return current->display; -} - -void setCurrentDrawSurface(EGLSurface surface) -{ - Current *current = GetCurrentData(); - - current->drawSurface = surface; -} - -EGLSurface getCurrentDrawSurface() -{ - Current *current = GetCurrentData(); - - return current->drawSurface; -} - -void setCurrentReadSurface(EGLSurface surface) -{ - Current *current = GetCurrentData(); - - current->readSurface = surface; -} - -EGLSurface getCurrentReadSurface() -{ - Current *current = GetCurrentData(); - - return current->readSurface; -} - -} diff --git a/src/3rdparty/angle/src/libEGL/main.h b/src/3rdparty/angle/src/libEGL/main.h deleted file mode 100644 index e5361a4a5e..0000000000 --- a/src/3rdparty/angle/src/libEGL/main.h +++ /dev/null @@ -1,45 +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. -// - -// main.h: Management of thread-local data. - -#ifndef LIBEGL_MAIN_H_ -#define LIBEGL_MAIN_H_ - -#include "libEGL/Error.h" - -#include -#include - -namespace egl -{ -struct Current -{ - EGLint error; - EGLenum API; - EGLDisplay display; - EGLSurface drawSurface; - EGLSurface readSurface; -}; - -void recordError(const Error &error); -EGLint getCurrentError(); - -void setCurrentAPI(EGLenum API); -EGLenum getCurrentAPI(); - -void setCurrentDisplay(EGLDisplay dpy); -EGLDisplay getCurrentDisplay(); - -void setCurrentDrawSurface(EGLSurface surface); -EGLSurface getCurrentDrawSurface(); - -void setCurrentReadSurface(EGLSurface surface); -EGLSurface getCurrentReadSurface(); - -} - -#endif // LIBEGL_MAIN_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/BinaryStream.h b/src/3rdparty/angle/src/libGLESv2/BinaryStream.h deleted file mode 100644 index 4f7f5f2c85..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/BinaryStream.h +++ /dev/null @@ -1,208 +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. -// - -// BinaryStream.h: Provides binary serialization of simple types. - -#ifndef LIBGLESV2_BINARYSTREAM_H_ -#define LIBGLESV2_BINARYSTREAM_H_ - -#include "common/angleutils.h" -#include "common/mathutil.h" - -#include -#include -#include -#include - -namespace gl -{ - -class BinaryInputStream -{ - public: - BinaryInputStream(const void *data, size_t length) - { - mError = false; - mOffset = 0; - mData = static_cast(data); - mLength = length; - } - - // readInt will generate an error for bool types - template - IntT readInt() - { - int value; - read(&value); - return static_cast(value); - } - - template - void readInt(IntT *outValue) - { - *outValue = readInt(); - } - - bool readBool() - { - int value; - read(&value); - return (value > 0); - } - - void readBool(bool *outValue) - { - *outValue = readBool(); - } - - void readBytes(unsigned char outArray[], size_t count) - { - read(outArray, count); - } - - std::string readString() - { - std::string outString; - readString(&outString); - return outString; - } - - void readString(std::string *v) - { - size_t length; - readInt(&length); - - if (mError) - { - return; - } - - if (mOffset + length > mLength) - { - mError = true; - return; - } - - v->assign(reinterpret_cast(mData) + mOffset, length); - mOffset += length; - } - - void skip(size_t length) - { - if (mOffset + length > mLength) - { - mError = true; - return; - } - - mOffset += length; - } - - size_t offset() const - { - return mOffset; - } - - bool error() const - { - return mError; - } - - bool endOfStream() const - { - return mOffset == mLength; - } - - const uint8_t *data() - { - return mData; - } - - private: - DISALLOW_COPY_AND_ASSIGN(BinaryInputStream); - bool mError; - size_t mOffset; - const uint8_t *mData; - size_t mLength; - - template - void read(T *v, size_t num) - { - META_ASSERT(std::is_fundamental::value); - - size_t length = num * sizeof(T); - - if (mOffset + length > mLength) - { - mError = true; - return; - } - - memcpy(v, mData + mOffset, length); - mOffset += length; - } - - template - void read(T *v) - { - read(v, 1); - } - -}; - -class BinaryOutputStream -{ - public: - BinaryOutputStream() - { - } - - // writeInt also handles bool types - template - void writeInt(IntT param) - { - ASSERT(rx::IsIntegerCastSafe(param)); - int intValue = static_cast(param); - write(&intValue, 1); - } - - void writeString(const std::string &v) - { - writeInt(v.length()); - write(v.c_str(), v.length()); - } - - void writeBytes(const unsigned char *bytes, size_t count) - { - write(bytes, count); - } - - size_t length() const - { - return mData.size(); - } - - const void* data() const - { - return mData.size() ? &mData[0] : NULL; - } - - private: - DISALLOW_COPY_AND_ASSIGN(BinaryOutputStream); - std::vector mData; - - template - void write(const T *v, size_t num) - { - META_ASSERT(std::is_fundamental::value); - const char *asBytes = reinterpret_cast(v); - mData.insert(mData.end(), asBytes, asBytes + num * sizeof(T)); - } - -}; -} - -#endif // LIBGLESV2_BINARYSTREAM_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/Buffer.cpp b/src/3rdparty/angle/src/libGLESv2/Buffer.cpp deleted file mode 100644 index 3b2a1a912a..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/Buffer.cpp +++ /dev/null @@ -1,128 +0,0 @@ -// -// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Buffer.cpp: Implements the gl::Buffer class, representing storage of vertex and/or -// index data. Implements GL buffer objects and related functionality. -// [OpenGL ES 2.0.24] section 2.9 page 21. - -#include "libGLESv2/Buffer.h" -#include "libGLESv2/renderer/BufferImpl.h" -#include "libGLESv2/renderer/Renderer.h" - -namespace gl -{ - -Buffer::Buffer(rx::BufferImpl *impl, GLuint id) - : RefCountObject(id), - mBuffer(impl), - mUsage(GL_DYNAMIC_DRAW), - mSize(0), - mAccessFlags(0), - mMapped(GL_FALSE), - mMapPointer(NULL), - mMapOffset(0), - mMapLength(0) -{ -} - -Buffer::~Buffer() -{ - SafeDelete(mBuffer); -} - -Error Buffer::bufferData(const void *data, GLsizeiptr size, GLenum usage) -{ - gl::Error error = mBuffer->setData(data, size, usage); - if (error.isError()) - { - return error; - } - - mIndexRangeCache.clear(); - mUsage = usage; - mSize = size; - - return error; -} - -Error Buffer::bufferSubData(const void *data, GLsizeiptr size, GLintptr offset) -{ - gl::Error error = mBuffer->setSubData(data, size, offset); - if (error.isError()) - { - return error; - } - - mIndexRangeCache.invalidateRange(offset, size); - - return error; -} - -Error Buffer::copyBufferSubData(Buffer* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size) -{ - gl::Error error = mBuffer->copySubData(source->getImplementation(), sourceOffset, destOffset, size); - if (error.isError()) - { - return error; - } - - mIndexRangeCache.invalidateRange(destOffset, size); - - return error; -} - -Error Buffer::mapRange(GLintptr offset, GLsizeiptr length, GLbitfield access) -{ - ASSERT(!mMapped); - ASSERT(offset + length <= mSize); - - Error error = mBuffer->map(offset, length, access, &mMapPointer); - if (error.isError()) - { - mMapPointer = NULL; - return error; - } - - mMapped = GL_TRUE; - mMapOffset = static_cast(offset); - mMapLength = static_cast(length); - mAccessFlags = static_cast(access); - - if ((access & GL_MAP_WRITE_BIT) > 0) - { - mIndexRangeCache.invalidateRange(offset, length); - } - - return error; -} - -Error Buffer::unmap() -{ - ASSERT(mMapped); - - Error error = mBuffer->unmap(); - if (error.isError()) - { - return error; - } - - mMapped = GL_FALSE; - mMapPointer = NULL; - mMapOffset = 0; - mMapLength = 0; - mAccessFlags = 0; - - return error; -} - -void Buffer::markTransformFeedbackUsage() -{ - // TODO: Only used by the DX11 backend. Refactor to a more appropriate place. - mBuffer->markTransformFeedbackUsage(); - mIndexRangeCache.clear(); -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/Buffer.h b/src/3rdparty/angle/src/libGLESv2/Buffer.h deleted file mode 100644 index daa862ca0d..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/Buffer.h +++ /dev/null @@ -1,74 +0,0 @@ -// -// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Buffer.h: Defines the gl::Buffer class, representing storage of vertex and/or -// index data. Implements GL buffer objects and related functionality. -// [OpenGL ES 2.0.24] section 2.9 page 21. - -#ifndef LIBGLESV2_BUFFER_H_ -#define LIBGLESV2_BUFFER_H_ - -#include "libGLESv2/Error.h" - -#include "common/angleutils.h" -#include "common/RefCountObject.h" -#include "libGLESv2/renderer/IndexRangeCache.h" - -namespace rx -{ -class BufferImpl; -}; - -namespace gl -{ - -class Buffer : public RefCountObject -{ - public: - Buffer(rx::BufferImpl *impl, GLuint id); - - virtual ~Buffer(); - - Error bufferData(const void *data, GLsizeiptr size, GLenum usage); - Error bufferSubData(const void *data, GLsizeiptr size, GLintptr offset); - Error copyBufferSubData(Buffer* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size); - Error mapRange(GLintptr offset, GLsizeiptr length, GLbitfield access); - Error unmap(); - - GLenum getUsage() const { return mUsage; } - GLint getAccessFlags() const { return mAccessFlags; } - GLboolean isMapped() const { return mMapped; } - GLvoid *getMapPointer() const { return mMapPointer; } - GLint64 getMapOffset() const { return mMapOffset; } - GLint64 getMapLength() const { return mMapLength; } - GLint64 getSize() const { return mSize; } - - rx::BufferImpl *getImplementation() const { return mBuffer; } - - void markTransformFeedbackUsage(); - - rx::IndexRangeCache *getIndexRangeCache() { return &mIndexRangeCache; } - const rx::IndexRangeCache *getIndexRangeCache() const { return &mIndexRangeCache; } - - private: - DISALLOW_COPY_AND_ASSIGN(Buffer); - - rx::BufferImpl *mBuffer; - - GLenum mUsage; - GLint64 mSize; - GLint mAccessFlags; - GLboolean mMapped; - GLvoid *mMapPointer; - GLint64 mMapOffset; - GLint64 mMapLength; - - rx::IndexRangeCache mIndexRangeCache; -}; - -} - -#endif // LIBGLESV2_BUFFER_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/Caps.cpp b/src/3rdparty/angle/src/libGLESv2/Caps.cpp deleted file mode 100644 index 983800c0e6..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/Caps.cpp +++ /dev/null @@ -1,425 +0,0 @@ -// -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "libGLESv2/Caps.h" -#include "common/debug.h" -#include "common/angleutils.h" - -#include "angle_gl.h" - -#include -#include - -namespace gl -{ - -TextureCaps::TextureCaps() - : texturable(false), - filterable(false), - renderable(false), - sampleCounts() -{ -} - -GLuint TextureCaps::getMaxSamples() const -{ - return !sampleCounts.empty() ? *sampleCounts.rbegin() : 0; -} - -GLuint TextureCaps::getNearestSamples(GLuint requestedSamples) const -{ - if (requestedSamples == 0) - { - return 0; - } - - for (SupportedSampleSet::const_iterator i = sampleCounts.begin(); i != sampleCounts.end(); i++) - { - GLuint samples = *i; - if (samples >= requestedSamples) - { - return samples; - } - } - - return 0; -} - -void TextureCapsMap::insert(GLenum internalFormat, const TextureCaps &caps) -{ - mCapsMap.insert(std::make_pair(internalFormat, caps)); -} - -void TextureCapsMap::remove(GLenum internalFormat) -{ - InternalFormatToCapsMap::iterator i = mCapsMap.find(internalFormat); - if (i != mCapsMap.end()) - { - mCapsMap.erase(i); - } -} - -const TextureCaps &TextureCapsMap::get(GLenum internalFormat) const -{ - static TextureCaps defaultUnsupportedTexture; - InternalFormatToCapsMap::const_iterator iter = mCapsMap.find(internalFormat); - return (iter != mCapsMap.end()) ? iter->second : defaultUnsupportedTexture; -} - -TextureCapsMap::const_iterator TextureCapsMap::begin() const -{ - return mCapsMap.begin(); -} - -TextureCapsMap::const_iterator TextureCapsMap::end() const -{ - return mCapsMap.end(); -} - -size_t TextureCapsMap::size() const -{ - return mCapsMap.size(); -} - -Extensions::Extensions() - : elementIndexUint(false), - packedDepthStencil(false), - getProgramBinary(false), - rgb8rgba8(false), - textureFormatBGRA8888(false), - readFormatBGRA(false), - pixelBufferObject(false), - mapBuffer(false), - mapBufferRange(false), - textureHalfFloat(false), - textureHalfFloatLinear(false), - textureFloat(false), - textureFloatLinear(false), - textureRG(false), - textureCompressionDXT1(false), - textureCompressionDXT3(false), - textureCompressionDXT5(false), - depthTextures(false), - textureNPOT(false), - drawBuffers(false), - textureStorage(false), - textureFilterAnisotropic(false), - maxTextureAnisotropy(false), - occlusionQueryBoolean(false), - fence(false), - timerQuery(false), - robustness(false), - blendMinMax(false), - framebufferBlit(false), - framebufferMultisample(false), - instancedArrays(false), - packReverseRowOrder(false), - standardDerivatives(false), - shaderTextureLOD(false), - fragDepth(false), - textureUsage(false), - translatedShaderSource(false), - colorBufferFloat(false) -{ -} - -static void InsertExtensionString(const std::string &extension, bool supported, std::vector *extensionVector) -{ - if (supported) - { - extensionVector->push_back(extension); - } -} - -std::vector Extensions::getStrings() const -{ - std::vector extensionStrings; - - // | Extension name | Supported flag | Output vector | - InsertExtensionString("GL_OES_element_index_uint", elementIndexUint, &extensionStrings); - InsertExtensionString("GL_OES_packed_depth_stencil", packedDepthStencil, &extensionStrings); - InsertExtensionString("GL_OES_get_program_binary", getProgramBinary, &extensionStrings); - InsertExtensionString("GL_OES_rgb8_rgba8", rgb8rgba8, &extensionStrings); - InsertExtensionString("GL_EXT_texture_format_BGRA8888", textureFormatBGRA8888, &extensionStrings); - InsertExtensionString("GL_EXT_read_format_bgra", readFormatBGRA, &extensionStrings); - InsertExtensionString("GL_NV_pixel_buffer_object", pixelBufferObject, &extensionStrings); - InsertExtensionString("GL_OES_mapbuffer", mapBuffer, &extensionStrings); - InsertExtensionString("GL_EXT_map_buffer_range", mapBufferRange, &extensionStrings); - InsertExtensionString("GL_OES_texture_half_float", textureHalfFloat, &extensionStrings); - InsertExtensionString("GL_OES_texture_half_float_linear", textureHalfFloatLinear, &extensionStrings); - InsertExtensionString("GL_OES_texture_float", textureFloat, &extensionStrings); - InsertExtensionString("GL_OES_texture_float_linear", textureFloatLinear, &extensionStrings); - InsertExtensionString("GL_EXT_texture_rg", textureRG, &extensionStrings); - InsertExtensionString("GL_EXT_texture_compression_dxt1", textureCompressionDXT1, &extensionStrings); - InsertExtensionString("GL_ANGLE_texture_compression_dxt3", textureCompressionDXT3, &extensionStrings); - InsertExtensionString("GL_ANGLE_texture_compression_dxt5", textureCompressionDXT5, &extensionStrings); - InsertExtensionString("GL_EXT_sRGB", sRGB, &extensionStrings); - InsertExtensionString("GL_ANGLE_depth_texture", depthTextures, &extensionStrings); - InsertExtensionString("GL_EXT_texture_storage", textureStorage, &extensionStrings); - InsertExtensionString("GL_OES_texture_npot", textureNPOT, &extensionStrings); - InsertExtensionString("GL_EXT_draw_buffers", drawBuffers, &extensionStrings); - InsertExtensionString("GL_EXT_texture_filter_anisotropic", textureFilterAnisotropic, &extensionStrings); - InsertExtensionString("GL_EXT_occlusion_query_boolean", occlusionQueryBoolean, &extensionStrings); - InsertExtensionString("GL_NV_fence", fence, &extensionStrings); - InsertExtensionString("GL_ANGLE_timer_query", timerQuery, &extensionStrings); - InsertExtensionString("GL_EXT_robustness", robustness, &extensionStrings); - InsertExtensionString("GL_EXT_blend_minmax", blendMinMax, &extensionStrings); - InsertExtensionString("GL_ANGLE_framebuffer_blit", framebufferBlit, &extensionStrings); - InsertExtensionString("GL_ANGLE_framebuffer_multisample", framebufferMultisample, &extensionStrings); - InsertExtensionString("GL_ANGLE_instanced_arrays", instancedArrays, &extensionStrings); - InsertExtensionString("GL_ANGLE_pack_reverse_row_order", packReverseRowOrder, &extensionStrings); - InsertExtensionString("GL_OES_standard_derivatives", standardDerivatives, &extensionStrings); - InsertExtensionString("GL_EXT_shader_texture_lod", shaderTextureLOD, &extensionStrings); - InsertExtensionString("GL_EXT_frag_depth", fragDepth, &extensionStrings); - InsertExtensionString("GL_ANGLE_texture_usage", textureUsage, &extensionStrings); - InsertExtensionString("GL_ANGLE_translated_shader_source", translatedShaderSource, &extensionStrings); - InsertExtensionString("GL_EXT_color_buffer_float", colorBufferFloat, &extensionStrings); - - return extensionStrings; -} - -static bool GetFormatSupport(const TextureCapsMap &textureCaps, const std::vector &requiredFormats, - bool requiresTexturing, bool requiresFiltering, bool requiresRendering) -{ - for (size_t i = 0; i < requiredFormats.size(); i++) - { - const TextureCaps &cap = textureCaps.get(requiredFormats[i]); - - if (requiresTexturing && !cap.texturable) - { - return false; - } - - if (requiresFiltering && !cap.filterable) - { - return false; - } - - if (requiresRendering && !cap.renderable) - { - return false; - } - } - - return true; -} - -// Checks for GL_OES_rgb8_rgba8 support -static bool DetermineRGB8AndRGBA8TextureSupport(const TextureCapsMap &textureCaps) -{ - std::vector requiredFormats; - requiredFormats.push_back(GL_RGB8); - requiredFormats.push_back(GL_RGBA8); - - return GetFormatSupport(textureCaps, requiredFormats, true, true, true); -} - -// Checks for GL_EXT_texture_format_BGRA8888 support -static bool DetermineBGRA8TextureSupport(const TextureCapsMap &textureCaps) -{ - std::vector requiredFormats; - requiredFormats.push_back(GL_BGRA8_EXT); - - return GetFormatSupport(textureCaps, requiredFormats, true, true, true); -} - -// Checks for GL_OES_texture_half_float support -static bool DetermineHalfFloatTextureSupport(const TextureCapsMap &textureCaps) -{ - std::vector requiredFormats; - requiredFormats.push_back(GL_RGB16F); - requiredFormats.push_back(GL_RGBA16F); - - return GetFormatSupport(textureCaps, requiredFormats, true, false, true); -} - -// Checks for GL_OES_texture_half_float_linear support -static bool DetermineHalfFloatTextureFilteringSupport(const TextureCapsMap &textureCaps) -{ - std::vector requiredFormats; - requiredFormats.push_back(GL_RGB16F); - requiredFormats.push_back(GL_RGBA16F); - - return GetFormatSupport(textureCaps, requiredFormats, true, true, false); -} - -// Checks for GL_OES_texture_float support -static bool DetermineFloatTextureSupport(const TextureCapsMap &textureCaps) -{ - std::vector requiredFormats; - requiredFormats.push_back(GL_RGB32F); - requiredFormats.push_back(GL_RGBA32F); - - return GetFormatSupport(textureCaps, requiredFormats, true, false, true); -} - -// Checks for GL_OES_texture_float_linear support -static bool DetermineFloatTextureFilteringSupport(const TextureCapsMap &textureCaps) -{ - std::vector requiredFormats; - requiredFormats.push_back(GL_RGB32F); - requiredFormats.push_back(GL_RGBA32F); - - return GetFormatSupport(textureCaps, requiredFormats, true, true, false); -} - -// Checks for GL_EXT_texture_rg support -static bool DetermineRGTextureSupport(const TextureCapsMap &textureCaps, bool checkHalfFloatFormats, bool checkFloatFormats) -{ - std::vector requiredFormats; - requiredFormats.push_back(GL_R8); - requiredFormats.push_back(GL_RG8); - if (checkHalfFloatFormats) - { - requiredFormats.push_back(GL_R16F); - requiredFormats.push_back(GL_RG16F); - } - if (checkFloatFormats) - { - requiredFormats.push_back(GL_R32F); - requiredFormats.push_back(GL_RG32F); - } - - return GetFormatSupport(textureCaps, requiredFormats, true, true, false); -} - -// Check for GL_EXT_texture_compression_dxt1 -static bool DetermineDXT1TextureSupport(const TextureCapsMap &textureCaps) -{ - std::vector requiredFormats; - requiredFormats.push_back(GL_COMPRESSED_RGB_S3TC_DXT1_EXT); - requiredFormats.push_back(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT); - - return GetFormatSupport(textureCaps, requiredFormats, true, true, false); -} - -// Check for GL_ANGLE_texture_compression_dxt3 -static bool DetermineDXT3TextureSupport(const TextureCapsMap &textureCaps) -{ - std::vector requiredFormats; - requiredFormats.push_back(GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE); - - return GetFormatSupport(textureCaps, requiredFormats, true, true, false); -} - -// Check for GL_ANGLE_texture_compression_dxt5 -static bool DetermineDXT5TextureSupport(const TextureCapsMap &textureCaps) -{ - std::vector requiredFormats; - requiredFormats.push_back(GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE); - - return GetFormatSupport(textureCaps, requiredFormats, true, true, false); -} - -// Check for GL_ANGLE_texture_compression_dxt5 -static bool DetermineSRGBTextureSupport(const TextureCapsMap &textureCaps) -{ - std::vector requiredFilterFormats; - requiredFilterFormats.push_back(GL_SRGB8); - requiredFilterFormats.push_back(GL_SRGB8_ALPHA8); - - std::vector requiredRenderFormats; - requiredRenderFormats.push_back(GL_SRGB8_ALPHA8); - - return GetFormatSupport(textureCaps, requiredFilterFormats, true, true, false) && - GetFormatSupport(textureCaps, requiredRenderFormats, true, false, true); -} - -// Check for GL_ANGLE_depth_texture -static bool DetermineDepthTextureSupport(const TextureCapsMap &textureCaps) -{ - std::vector requiredFormats; - requiredFormats.push_back(GL_DEPTH_COMPONENT16); - requiredFormats.push_back(GL_DEPTH_COMPONENT32_OES); - requiredFormats.push_back(GL_DEPTH24_STENCIL8_OES); - - return GetFormatSupport(textureCaps, requiredFormats, true, true, true); -} - -// Check for GL_EXT_color_buffer_float -static bool DetermineColorBufferFloatSupport(const TextureCapsMap &textureCaps) -{ - std::vector requiredFormats; - requiredFormats.push_back(GL_R16F); - requiredFormats.push_back(GL_RG16F); - requiredFormats.push_back(GL_RGBA16F); - requiredFormats.push_back(GL_R32F); - requiredFormats.push_back(GL_RG32F); - requiredFormats.push_back(GL_RGBA32F); - requiredFormats.push_back(GL_R11F_G11F_B10F); - - return GetFormatSupport(textureCaps, requiredFormats, true, false, true); -} - -void Extensions::setTextureExtensionSupport(const TextureCapsMap &textureCaps) -{ - rgb8rgba8 = DetermineRGB8AndRGBA8TextureSupport(textureCaps); - textureFormatBGRA8888 = DetermineBGRA8TextureSupport(textureCaps); - textureHalfFloat = DetermineHalfFloatTextureSupport(textureCaps); - textureHalfFloatLinear = DetermineHalfFloatTextureFilteringSupport(textureCaps); - textureFloat = DetermineFloatTextureSupport(textureCaps); - textureFloatLinear = DetermineFloatTextureFilteringSupport(textureCaps); - textureRG = DetermineRGTextureSupport(textureCaps, textureHalfFloat, textureFloat); - textureCompressionDXT1 = DetermineDXT1TextureSupport(textureCaps); - textureCompressionDXT3 = DetermineDXT3TextureSupport(textureCaps); - textureCompressionDXT5 = DetermineDXT5TextureSupport(textureCaps); - sRGB = DetermineSRGBTextureSupport(textureCaps); - depthTextures = DetermineDepthTextureSupport(textureCaps); - colorBufferFloat = DetermineColorBufferFloatSupport(textureCaps); -} - -Caps::Caps() - : maxElementIndex(0), - max3DTextureSize(0), - max2DTextureSize(0), - maxArrayTextureLayers(0), - maxLODBias(0), - maxCubeMapTextureSize(0), - maxRenderbufferSize(0), - maxDrawBuffers(0), - maxColorAttachments(0), - maxViewportWidth(0), - maxViewportHeight(0), - minAliasedPointSize(0), - maxAliasedPointSize(0), - minAliasedLineWidth(0), - // Table 6.29 - maxElementsIndices(0), - maxElementsVertices(0), - maxServerWaitTimeout(0), - // Table 6.31 - maxVertexAttributes(0), - maxVertexUniformComponents(0), - maxVertexUniformVectors(0), - maxVertexUniformBlocks(0), - maxVertexOutputComponents(0), - maxVertexTextureImageUnits(0), - // Table 6.32 - maxFragmentUniformComponents(0), - maxFragmentUniformVectors(0), - maxFragmentUniformBlocks(0), - maxFragmentInputComponents(0), - maxTextureImageUnits(0), - minProgramTexelOffset(0), - maxProgramTexelOffset(0), - - maxUniformBufferBindings(0), - maxUniformBlockSize(0), - uniformBufferOffsetAlignment(0), - maxCombinedUniformBlocks(0), - maxCombinedVertexUniformComponents(0), - maxCombinedFragmentUniformComponents(0), - maxVaryingComponents(0), - maxVaryingVectors(0), - maxCombinedTextureImageUnits(0), - - maxTransformFeedbackInterleavedComponents(0), - maxTransformFeedbackSeparateAttributes(0), - maxTransformFeedbackSeparateComponents(0) -{ -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/Caps.h b/src/3rdparty/angle/src/libGLESv2/Caps.h deleted file mode 100644 index a00e554176..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/Caps.h +++ /dev/null @@ -1,273 +0,0 @@ -#ifndef LIBGLESV2_CAPS_H -#define LIBGLESV2_CAPS_H - -// -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "angle_gl.h" - -#include -#include -#include -#include - -namespace gl -{ - -typedef std::set SupportedSampleSet; - -struct TextureCaps -{ - TextureCaps(); - - // Supports for basic texturing: glTexImage, glTexSubImage, etc - bool texturable; - - // Support for linear or anisotropic filtering - bool filterable; - - // Support for being used as a framebuffer attachment or renderbuffer format - bool renderable; - - SupportedSampleSet sampleCounts; - - // Get the maximum number of samples supported - GLuint getMaxSamples() const; - - // Get the number of supported samples that is at least as many as requested. Returns 0 if - // there are no sample counts available - GLuint getNearestSamples(GLuint requestedSamples) const; -}; - -class TextureCapsMap -{ - public: - typedef std::unordered_map::const_iterator const_iterator; - - void insert(GLenum internalFormat, const TextureCaps &caps); - void remove(GLenum internalFormat); - - const TextureCaps &get(GLenum internalFormat) const; - - const_iterator begin() const; - const_iterator end() const; - - size_t size() const; - - private: - typedef std::unordered_map InternalFormatToCapsMap; - InternalFormatToCapsMap mCapsMap; -}; - -struct Extensions -{ - Extensions(); - - // Generate a vector of supported extension strings - std::vector getStrings() const; - - // Set all texture related extension support based on the supported textures. - // Determines support for: - // GL_OES_rgb8_rgba8 - // GL_EXT_texture_format_BGRA8888 - // GL_OES_texture_half_float, GL_OES_texture_half_float_linear - // GL_OES_texture_float, GL_OES_texture_float_linear - // GL_EXT_texture_rg - // GL_EXT_texture_compression_dxt1, GL_ANGLE_texture_compression_dxt3, GL_ANGLE_texture_compression_dxt5 - // GL_EXT_sRGB - // GL_ANGLE_depth_texture - // GL_EXT_color_buffer_float - void setTextureExtensionSupport(const TextureCapsMap &textureCaps); - - // ES2 Extension support - - // GL_OES_element_index_uint - bool elementIndexUint; - - // GL_OES_packed_depth_stencil - bool packedDepthStencil; - - // GL_OES_get_program_binary - bool getProgramBinary; - - // GL_OES_rgb8_rgba8 - // Implies that TextureCaps for GL_RGB8 and GL_RGBA8 exist - bool rgb8rgba8; - - // GL_EXT_texture_format_BGRA8888 - // Implies that TextureCaps for GL_BGRA8 exist - bool textureFormatBGRA8888; - - // GL_EXT_read_format_bgra - bool readFormatBGRA; - - // GL_NV_pixel_buffer_object - bool pixelBufferObject; - - // GL_OES_mapbuffer and GL_EXT_map_buffer_range - bool mapBuffer; - bool mapBufferRange; - - // GL_OES_texture_half_float and GL_OES_texture_half_float_linear - // Implies that TextureCaps for GL_RGB16F, GL_RGBA16F, GL_ALPHA32F_EXT, GL_LUMINANCE32F_EXT and - // GL_LUMINANCE_ALPHA32F_EXT exist - bool textureHalfFloat; - bool textureHalfFloatLinear; - - // GL_OES_texture_float and GL_OES_texture_float_linear - // Implies that TextureCaps for GL_RGB32F, GL_RGBA32F, GL_ALPHA16F_EXT, GL_LUMINANCE16F_EXT and - // GL_LUMINANCE_ALPHA16F_EXT exist - bool textureFloat; - bool textureFloatLinear; - - // GL_EXT_texture_rg - // Implies that TextureCaps for GL_R8, GL_RG8 (and floating point R/RG texture formats if floating point extensions - // are also present) exist - bool textureRG; - - // GL_EXT_texture_compression_dxt1, GL_ANGLE_texture_compression_dxt3 and GL_ANGLE_texture_compression_dxt5 - // Implies that TextureCaps for GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT - // GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE and GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE - bool textureCompressionDXT1; - bool textureCompressionDXT3; - bool textureCompressionDXT5; - - // GL_EXT_sRGB - // Implies that TextureCaps for GL_SRGB8_ALPHA8 and GL_SRGB8 exist - // TODO: Don't advertise this extension in ES3 - bool sRGB; - - // GL_ANGLE_depth_texture - bool depthTextures; - - // GL_EXT_texture_storage - bool textureStorage; - - // GL_OES_texture_npot - bool textureNPOT; - - // GL_EXT_draw_buffers - bool drawBuffers; - - // GL_EXT_texture_filter_anisotropic - bool textureFilterAnisotropic; - GLfloat maxTextureAnisotropy; - - // GL_EXT_occlusion_query_boolean - bool occlusionQueryBoolean; - - // GL_NV_fence - bool fence; - - // GL_ANGLE_timer_query - bool timerQuery; - - // GL_EXT_robustness - bool robustness; - - // GL_EXT_blend_minmax - bool blendMinMax; - - // GL_ANGLE_framebuffer_blit - bool framebufferBlit; - - // GL_ANGLE_framebuffer_multisample - bool framebufferMultisample; - GLuint maxSamples; - - // GL_ANGLE_instanced_arrays - bool instancedArrays; - - // GL_ANGLE_pack_reverse_row_order - bool packReverseRowOrder; - - // GL_OES_standard_derivatives - bool standardDerivatives; - - // GL_EXT_shader_texture_lod - bool shaderTextureLOD; - - // GL_EXT_frag_depth - bool fragDepth; - - // GL_ANGLE_texture_usage - bool textureUsage; - - // GL_ANGLE_translated_shader_source - bool translatedShaderSource; - - // ES3 Extension support - - // GL_EXT_color_buffer_float - bool colorBufferFloat; -}; - -struct Caps -{ - Caps(); - - // Table 6.28, implementation dependent values - GLuint64 maxElementIndex; - GLuint max3DTextureSize; - GLuint max2DTextureSize; - GLuint maxArrayTextureLayers; - GLfloat maxLODBias; - GLuint maxCubeMapTextureSize; - GLuint maxRenderbufferSize; - GLuint maxDrawBuffers; - GLuint maxColorAttachments; - GLuint maxViewportWidth; - GLuint maxViewportHeight; - GLfloat minAliasedPointSize; - GLfloat maxAliasedPointSize; - GLfloat minAliasedLineWidth; - GLfloat maxAliasedLineWidth; - - // Table 6.29, implementation dependent values (cont.) - GLuint maxElementsIndices; - GLuint maxElementsVertices; - std::vector compressedTextureFormats; - std::vector programBinaryFormats; - std::vector shaderBinaryFormats; - GLuint64 maxServerWaitTimeout; - - // Table 6.31, implementation dependent vertex shader limits - GLuint maxVertexAttributes; - GLuint maxVertexUniformComponents; - GLuint maxVertexUniformVectors; - GLuint maxVertexUniformBlocks; - GLuint maxVertexOutputComponents; - GLuint maxVertexTextureImageUnits; - - // Table 6.32, implementation dependent fragment shader limits - GLuint maxFragmentUniformComponents; - GLuint maxFragmentUniformVectors; - GLuint maxFragmentUniformBlocks; - GLuint maxFragmentInputComponents; - GLuint maxTextureImageUnits; - GLint minProgramTexelOffset; - GLint maxProgramTexelOffset; - - // Table 6.33, implementation dependent aggregate shader limits - GLuint maxUniformBufferBindings; - GLuint64 maxUniformBlockSize; - GLuint uniformBufferOffsetAlignment; - GLuint maxCombinedUniformBlocks; - GLuint64 maxCombinedVertexUniformComponents; - GLuint64 maxCombinedFragmentUniformComponents; - GLuint maxVaryingComponents; - GLuint maxVaryingVectors; - GLuint maxCombinedTextureImageUnits; - - // Table 6.34, implementation dependent transform feedback limits - GLuint maxTransformFeedbackInterleavedComponents; - GLuint maxTransformFeedbackSeparateAttributes; - GLuint maxTransformFeedbackSeparateComponents; -}; - -} - -#endif // LIBGLESV2_CAPS_H diff --git a/src/3rdparty/angle/src/libGLESv2/Context.cpp b/src/3rdparty/angle/src/libGLESv2/Context.cpp deleted file mode 100644 index 3772da6f42..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/Context.cpp +++ /dev/null @@ -1,1769 +0,0 @@ -// -// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Context.cpp: Implements the gl::Context class, managing all GL state and performing -// rendering operations. It is the GLES2 specific implementation of EGLContext. - -#include "libGLESv2/Context.h" - -#include "common/utilities.h" -#include "common/platform.h" -#include "libGLESv2/Buffer.h" -#include "libGLESv2/Fence.h" -#include "libGLESv2/Framebuffer.h" -#include "libGLESv2/FramebufferAttachment.h" -#include "libGLESv2/Renderbuffer.h" -#include "libGLESv2/Program.h" -#include "libGLESv2/ProgramBinary.h" -#include "libGLESv2/Query.h" -#include "libGLESv2/ResourceManager.h" -#include "libGLESv2/Sampler.h" -#include "libGLESv2/Texture.h" -#include "libGLESv2/TransformFeedback.h" -#include "libGLESv2/VertexArray.h" -#include "libGLESv2/formatutils.h" -#include "libGLESv2/main.h" -#include "libGLESv2/validationES.h" -#include "libGLESv2/renderer/Renderer.h" - -#include "libEGL/Surface.h" - -#include -#include - -namespace gl -{ - -Context::Context(int clientVersion, const Context *shareContext, rx::Renderer *renderer, bool notifyResets, bool robustAccess) - : mRenderer(renderer) -{ - ASSERT(robustAccess == false); // Unimplemented - - initCaps(clientVersion); - mState.initialize(mCaps, clientVersion); - - mClientVersion = clientVersion; - - mFenceNVHandleAllocator.setBaseHandle(0); - - if (shareContext != NULL) - { - mResourceManager = shareContext->mResourceManager; - mResourceManager->addRef(); - } - else - { - mResourceManager = new ResourceManager(mRenderer); - } - - // [OpenGL ES 2.0.24] section 3.7 page 83: - // In the initial state, TEXTURE_2D and TEXTURE_CUBE_MAP have twodimensional - // and cube map texture state vectors respectively associated with them. - // In order that access to these initial textures not be lost, they are treated as texture - // objects all of whose names are 0. - - Texture2D *zeroTexture2D = new Texture2D(mRenderer->createTexture(GL_TEXTURE_2D), 0); - mZeroTextures[GL_TEXTURE_2D].set(zeroTexture2D); - - TextureCubeMap *zeroTextureCube = new TextureCubeMap(mRenderer->createTexture(GL_TEXTURE_CUBE_MAP), 0); - mZeroTextures[GL_TEXTURE_CUBE_MAP].set(zeroTextureCube); - - if (mClientVersion >= 3) - { - // TODO: These could also be enabled via extension - Texture3D *zeroTexture3D = new Texture3D(mRenderer->createTexture(GL_TEXTURE_3D), 0); - mZeroTextures[GL_TEXTURE_3D].set(zeroTexture3D); - - Texture2DArray *zeroTexture2DArray = new Texture2DArray(mRenderer->createTexture(GL_TEXTURE_2D_ARRAY), 0); - mZeroTextures[GL_TEXTURE_2D_ARRAY].set(zeroTexture2DArray); - } - - mState.initializeZeroTextures(mZeroTextures); - - bindVertexArray(0); - bindArrayBuffer(0); - bindElementArrayBuffer(0); - - bindReadFramebuffer(0); - bindDrawFramebuffer(0); - bindRenderbuffer(0); - - bindGenericUniformBuffer(0); - for (unsigned int i = 0; i < mCaps.maxCombinedUniformBlocks; i++) - { - bindIndexedUniformBuffer(0, i, 0, -1); - } - - bindGenericTransformFeedbackBuffer(0); - for (unsigned int i = 0; i < mCaps.maxTransformFeedbackSeparateAttributes; i++) - { - bindIndexedTransformFeedbackBuffer(0, i, 0, -1); - } - - bindCopyReadBuffer(0); - bindCopyWriteBuffer(0); - bindPixelPackBuffer(0); - bindPixelUnpackBuffer(0); - - // [OpenGL ES 3.0.2] section 2.14.1 pg 85: - // In the initial state, a default transform feedback object is bound and treated as - // a transform feedback object with a name of zero. That object is bound any time - // BindTransformFeedback is called with id of zero - mTransformFeedbackZero.set(new TransformFeedback(mRenderer->createTransformFeedback(), 0)); - bindTransformFeedback(0); - - mHasBeenCurrent = false; - mContextLost = false; - mResetStatus = GL_NO_ERROR; - mResetStrategy = (notifyResets ? GL_LOSE_CONTEXT_ON_RESET_EXT : GL_NO_RESET_NOTIFICATION_EXT); - mRobustAccess = robustAccess; -} - -Context::~Context() -{ - GLuint currentProgram = mState.getCurrentProgramId(); - if (currentProgram != 0) - { - Program *programObject = mResourceManager->getProgram(currentProgram); - if (programObject) - { - programObject->release(); - } - currentProgram = 0; - } - mState.setCurrentProgram(0, NULL); - - while (!mFramebufferMap.empty()) - { - deleteFramebuffer(mFramebufferMap.begin()->first); - } - - while (!mFenceNVMap.empty()) - { - deleteFenceNV(mFenceNVMap.begin()->first); - } - - while (!mQueryMap.empty()) - { - deleteQuery(mQueryMap.begin()->first); - } - - while (!mVertexArrayMap.empty()) - { - deleteVertexArray(mVertexArrayMap.begin()->first); - } - - mTransformFeedbackZero.set(NULL); - while (!mTransformFeedbackMap.empty()) - { - deleteTransformFeedback(mTransformFeedbackMap.begin()->first); - } - - for (TextureMap::iterator i = mZeroTextures.begin(); i != mZeroTextures.end(); i++) - { - i->second.set(NULL); - } - mZeroTextures.clear(); - - if (mResourceManager) - { - mResourceManager->release(); - } -} - -void Context::makeCurrent(egl::Surface *surface) -{ - if (!mHasBeenCurrent) - { - initRendererString(); - initExtensionStrings(); - - mState.setViewportParams(0, 0, surface->getWidth(), surface->getHeight()); - mState.setScissorParams(0, 0, surface->getWidth(), surface->getHeight()); - - mHasBeenCurrent = true; - } - - // Wrap the existing swapchain resources into GL objects and assign them to the '0' names - rx::SwapChain *swapchain = surface->getSwapChain(); - - rx::RenderbufferImpl *colorbufferZero = mRenderer->createRenderbuffer(swapchain, false); - rx::RenderbufferImpl *depthStencilbufferZero = mRenderer->createRenderbuffer(swapchain, true); - Framebuffer *framebufferZero = new DefaultFramebuffer(colorbufferZero, depthStencilbufferZero); - - setFramebufferZero(framebufferZero); -} - -// NOTE: this function should not assume that this context is current! -void Context::markContextLost() -{ - if (mResetStrategy == GL_LOSE_CONTEXT_ON_RESET_EXT) - mResetStatus = GL_UNKNOWN_CONTEXT_RESET_EXT; - mContextLost = true; -} - -bool Context::isContextLost() -{ - return mContextLost; -} - -GLuint Context::createBuffer() -{ - return mResourceManager->createBuffer(); -} - -GLuint Context::createProgram() -{ - return mResourceManager->createProgram(); -} - -GLuint Context::createShader(GLenum type) -{ - return mResourceManager->createShader(getData(), type); -} - -GLuint Context::createTexture() -{ - return mResourceManager->createTexture(); -} - -GLuint Context::createRenderbuffer() -{ - return mResourceManager->createRenderbuffer(); -} - -GLsync Context::createFenceSync() -{ - GLuint handle = mResourceManager->createFenceSync(); - - return reinterpret_cast(handle); -} - -GLuint Context::createVertexArray() -{ - GLuint handle = mVertexArrayHandleAllocator.allocate(); - - // Although the spec states VAO state is not initialized until the object is bound, - // we create it immediately. The resulting behaviour is transparent to the application, - // since it's not currently possible to access the state until the object is bound. - VertexArray *vertexArray = new VertexArray(mRenderer->createVertexArray(), handle, MAX_VERTEX_ATTRIBS); - mVertexArrayMap[handle] = vertexArray; - return handle; -} - -GLuint Context::createSampler() -{ - return mResourceManager->createSampler(); -} - -GLuint Context::createTransformFeedback() -{ - GLuint handle = mTransformFeedbackAllocator.allocate(); - TransformFeedback *transformFeedback = new TransformFeedback(mRenderer->createTransformFeedback(), handle); - transformFeedback->addRef(); - mTransformFeedbackMap[handle] = transformFeedback; - return handle; -} - -// Returns an unused framebuffer name -GLuint Context::createFramebuffer() -{ - GLuint handle = mFramebufferHandleAllocator.allocate(); - - mFramebufferMap[handle] = NULL; - - return handle; -} - -GLuint Context::createFenceNV() -{ - GLuint handle = mFenceNVHandleAllocator.allocate(); - - mFenceNVMap[handle] = new FenceNV(mRenderer->createFenceNV()); - - return handle; -} - -// Returns an unused query name -GLuint Context::createQuery() -{ - GLuint handle = mQueryHandleAllocator.allocate(); - - mQueryMap[handle] = NULL; - - return handle; -} - -void Context::deleteBuffer(GLuint buffer) -{ - if (mResourceManager->getBuffer(buffer)) - { - detachBuffer(buffer); - } - - mResourceManager->deleteBuffer(buffer); -} - -void Context::deleteShader(GLuint shader) -{ - mResourceManager->deleteShader(shader); -} - -void Context::deleteProgram(GLuint program) -{ - mResourceManager->deleteProgram(program); -} - -void Context::deleteTexture(GLuint texture) -{ - if (mResourceManager->getTexture(texture)) - { - detachTexture(texture); - } - - mResourceManager->deleteTexture(texture); -} - -void Context::deleteRenderbuffer(GLuint renderbuffer) -{ - if (mResourceManager->getRenderbuffer(renderbuffer)) - { - detachRenderbuffer(renderbuffer); - } - - mResourceManager->deleteRenderbuffer(renderbuffer); -} - -void Context::deleteFenceSync(GLsync fenceSync) -{ - // The spec specifies the underlying Fence object is not deleted until all current - // wait commands finish. However, since the name becomes invalid, we cannot query the fence, - // and since our API is currently designed for being called from a single thread, we can delete - // the fence immediately. - mResourceManager->deleteFenceSync(reinterpret_cast(fenceSync)); -} - -void Context::deleteVertexArray(GLuint vertexArray) -{ - VertexArrayMap::iterator vertexArrayObject = mVertexArrayMap.find(vertexArray); - - if (vertexArrayObject != mVertexArrayMap.end()) - { - detachVertexArray(vertexArray); - - mVertexArrayHandleAllocator.release(vertexArrayObject->first); - delete vertexArrayObject->second; - mVertexArrayMap.erase(vertexArrayObject); - } -} - -void Context::deleteSampler(GLuint sampler) -{ - if (mResourceManager->getSampler(sampler)) - { - detachSampler(sampler); - } - - mResourceManager->deleteSampler(sampler); -} - -void Context::deleteTransformFeedback(GLuint transformFeedback) -{ - TransformFeedbackMap::const_iterator iter = mTransformFeedbackMap.find(transformFeedback); - if (iter != mTransformFeedbackMap.end()) - { - detachTransformFeedback(transformFeedback); - mTransformFeedbackAllocator.release(transformFeedback); - iter->second->release(); - mTransformFeedbackMap.erase(iter); - } -} - -void Context::deleteFramebuffer(GLuint framebuffer) -{ - FramebufferMap::iterator framebufferObject = mFramebufferMap.find(framebuffer); - - if (framebufferObject != mFramebufferMap.end()) - { - detachFramebuffer(framebuffer); - - mFramebufferHandleAllocator.release(framebufferObject->first); - delete framebufferObject->second; - mFramebufferMap.erase(framebufferObject); - } -} - -void Context::deleteFenceNV(GLuint fence) -{ - FenceNVMap::iterator fenceObject = mFenceNVMap.find(fence); - - if (fenceObject != mFenceNVMap.end()) - { - mFenceNVHandleAllocator.release(fenceObject->first); - delete fenceObject->second; - mFenceNVMap.erase(fenceObject); - } -} - -void Context::deleteQuery(GLuint query) -{ - QueryMap::iterator queryObject = mQueryMap.find(query); - if (queryObject != mQueryMap.end()) - { - mQueryHandleAllocator.release(queryObject->first); - if (queryObject->second) - { - queryObject->second->release(); - } - mQueryMap.erase(queryObject); - } -} - -Buffer *Context::getBuffer(GLuint handle) -{ - return mResourceManager->getBuffer(handle); -} - -Shader *Context::getShader(GLuint handle) const -{ - return mResourceManager->getShader(handle); -} - -Program *Context::getProgram(GLuint handle) const -{ - return mResourceManager->getProgram(handle); -} - -Texture *Context::getTexture(GLuint handle) const -{ - return mResourceManager->getTexture(handle); -} - -Renderbuffer *Context::getRenderbuffer(GLuint handle) -{ - return mResourceManager->getRenderbuffer(handle); -} - -FenceSync *Context::getFenceSync(GLsync handle) const -{ - return mResourceManager->getFenceSync(reinterpret_cast(handle)); -} - -VertexArray *Context::getVertexArray(GLuint handle) const -{ - VertexArrayMap::const_iterator vertexArray = mVertexArrayMap.find(handle); - - if (vertexArray == mVertexArrayMap.end()) - { - return NULL; - } - else - { - return vertexArray->second; - } -} - -Sampler *Context::getSampler(GLuint handle) const -{ - return mResourceManager->getSampler(handle); -} - -TransformFeedback *Context::getTransformFeedback(GLuint handle) const -{ - if (handle == 0) - { - return mTransformFeedbackZero.get(); - } - else - { - TransformFeedbackMap::const_iterator iter = mTransformFeedbackMap.find(handle); - return (iter != mTransformFeedbackMap.end()) ? iter->second : NULL; - } -} - -bool Context::isSampler(GLuint samplerName) const -{ - return mResourceManager->isSampler(samplerName); -} - -void Context::bindArrayBuffer(unsigned int buffer) -{ - mResourceManager->checkBufferAllocation(buffer); - - mState.setArrayBufferBinding(getBuffer(buffer)); -} - -void Context::bindElementArrayBuffer(unsigned int buffer) -{ - mResourceManager->checkBufferAllocation(buffer); - - mState.getVertexArray()->setElementArrayBuffer(getBuffer(buffer)); -} - -void Context::bindTexture(GLenum target, GLuint handle) -{ - Texture *texture = NULL; - - if (handle == 0) - { - texture = mZeroTextures[target].get(); - } - else - { - mResourceManager->checkTextureAllocation(handle, target); - texture = getTexture(handle); - } - - ASSERT(texture); - - mState.setSamplerTexture(target, texture); -} - -void Context::bindReadFramebuffer(GLuint framebuffer) -{ - if (!getFramebuffer(framebuffer)) - { - mFramebufferMap[framebuffer] = new Framebuffer(framebuffer); - } - - mState.setReadFramebufferBinding(getFramebuffer(framebuffer)); -} - -void Context::bindDrawFramebuffer(GLuint framebuffer) -{ - if (!getFramebuffer(framebuffer)) - { - mFramebufferMap[framebuffer] = new Framebuffer(framebuffer); - } - - mState.setDrawFramebufferBinding(getFramebuffer(framebuffer)); -} - -void Context::bindRenderbuffer(GLuint renderbuffer) -{ - mResourceManager->checkRenderbufferAllocation(renderbuffer); - - mState.setRenderbufferBinding(getRenderbuffer(renderbuffer)); -} - -void Context::bindVertexArray(GLuint vertexArray) -{ - if (!getVertexArray(vertexArray)) - { - VertexArray *vertexArrayObject = new VertexArray(mRenderer->createVertexArray(), vertexArray, MAX_VERTEX_ATTRIBS); - mVertexArrayMap[vertexArray] = vertexArrayObject; - } - - mState.setVertexArrayBinding(getVertexArray(vertexArray)); -} - -void Context::bindSampler(GLuint textureUnit, GLuint sampler) -{ - ASSERT(textureUnit < mCaps.maxCombinedTextureImageUnits); - mResourceManager->checkSamplerAllocation(sampler); - - mState.setSamplerBinding(textureUnit, getSampler(sampler)); -} - -void Context::bindGenericUniformBuffer(GLuint buffer) -{ - mResourceManager->checkBufferAllocation(buffer); - - mState.setGenericUniformBufferBinding(getBuffer(buffer)); -} - -void Context::bindIndexedUniformBuffer(GLuint buffer, GLuint index, GLintptr offset, GLsizeiptr size) -{ - mResourceManager->checkBufferAllocation(buffer); - - mState.setIndexedUniformBufferBinding(index, getBuffer(buffer), offset, size); -} - -void Context::bindGenericTransformFeedbackBuffer(GLuint buffer) -{ - mResourceManager->checkBufferAllocation(buffer); - - mState.setGenericTransformFeedbackBufferBinding(getBuffer(buffer)); -} - -void Context::bindIndexedTransformFeedbackBuffer(GLuint buffer, GLuint index, GLintptr offset, GLsizeiptr size) -{ - mResourceManager->checkBufferAllocation(buffer); - - mState.setIndexedTransformFeedbackBufferBinding(index, getBuffer(buffer), offset, size); -} - -void Context::bindCopyReadBuffer(GLuint buffer) -{ - mResourceManager->checkBufferAllocation(buffer); - - mState.setCopyReadBufferBinding(getBuffer(buffer)); -} - -void Context::bindCopyWriteBuffer(GLuint buffer) -{ - mResourceManager->checkBufferAllocation(buffer); - - mState.setCopyWriteBufferBinding(getBuffer(buffer)); -} - -void Context::bindPixelPackBuffer(GLuint buffer) -{ - mResourceManager->checkBufferAllocation(buffer); - - mState.setPixelPackBufferBinding(getBuffer(buffer)); -} - -void Context::bindPixelUnpackBuffer(GLuint buffer) -{ - mResourceManager->checkBufferAllocation(buffer); - - mState.setPixelUnpackBufferBinding(getBuffer(buffer)); -} - -void Context::useProgram(GLuint program) -{ - GLuint priorProgramId = mState.getCurrentProgramId(); - Program *priorProgram = mResourceManager->getProgram(priorProgramId); - - if (priorProgramId != program) - { - mState.setCurrentProgram(program, mResourceManager->getProgram(program)); - - if (priorProgram) - { - priorProgram->release(); - } - } -} - -Error Context::linkProgram(GLuint program) -{ - Program *programObject = mResourceManager->getProgram(program); - - Error error = programObject->link(getData()); - if (error.isError()) - { - return error; - } - - // if the current program was relinked successfully we - // need to install the new executables - if (programObject->isLinked() && program == mState.getCurrentProgramId()) - { - mState.setCurrentProgramBinary(programObject->getProgramBinary()); - } - - return Error(GL_NO_ERROR); -} - -Error Context::setProgramBinary(GLuint program, GLenum binaryFormat, const void *binary, GLint length) -{ - Program *programObject = mResourceManager->getProgram(program); - - Error error = programObject->setProgramBinary(binaryFormat, binary, length); - if (error.isError()) - { - return error; - } - - // if the current program was reloaded successfully we - // need to install the new executables - if (programObject->isLinked() && program == mState.getCurrentProgramId()) - { - mState.setCurrentProgramBinary(programObject->getProgramBinary()); - } - - return Error(GL_NO_ERROR); -} - -void Context::bindTransformFeedback(GLuint transformFeedback) -{ - mState.setTransformFeedbackBinding(getTransformFeedback(transformFeedback)); -} - -Error Context::beginQuery(GLenum target, GLuint query) -{ - Query *queryObject = getQuery(query, true, target); - ASSERT(queryObject); - - // begin query - Error error = queryObject->begin(); - if (error.isError()) - { - return error; - } - - // set query as active for specified target only if begin succeeded - mState.setActiveQuery(target, queryObject); - - return Error(GL_NO_ERROR); -} - -Error Context::endQuery(GLenum target) -{ - Query *queryObject = mState.getActiveQuery(target); - ASSERT(queryObject); - - gl::Error error = queryObject->end(); - - // Always unbind the query, even if there was an error. This may delete the query object. - mState.setActiveQuery(target, NULL); - - return error; -} - -void Context::setFramebufferZero(Framebuffer *buffer) -{ - // First, check to see if the old default framebuffer - // was set for draw or read framebuffer, and change - // the bindings to point to the new one before deleting it. - if (mState.getDrawFramebuffer()->id() == 0) - { - mState.setDrawFramebufferBinding(buffer); - } - - if (mState.getReadFramebuffer()->id() == 0) - { - mState.setReadFramebufferBinding(buffer); - } - - delete mFramebufferMap[0]; - mFramebufferMap[0] = buffer; -} - -Framebuffer *Context::getFramebuffer(unsigned int handle) const -{ - FramebufferMap::const_iterator framebuffer = mFramebufferMap.find(handle); - - if (framebuffer == mFramebufferMap.end()) - { - return NULL; - } - else - { - return framebuffer->second; - } -} - -FenceNV *Context::getFenceNV(unsigned int handle) -{ - FenceNVMap::iterator fence = mFenceNVMap.find(handle); - - if (fence == mFenceNVMap.end()) - { - return NULL; - } - else - { - return fence->second; - } -} - -Query *Context::getQuery(unsigned int handle, bool create, GLenum type) -{ - QueryMap::iterator query = mQueryMap.find(handle); - - if (query == mQueryMap.end()) - { - return NULL; - } - else - { - if (!query->second && create) - { - query->second = new Query(mRenderer->createQuery(type), handle); - query->second->addRef(); - } - return query->second; - } -} - -Texture *Context::getTargetTexture(GLenum target) const -{ - if (!ValidTextureTarget(this, target)) - { - return NULL; - } - - switch (target) - { - case GL_TEXTURE_2D: return getTexture2D(); - case GL_TEXTURE_CUBE_MAP: return getTextureCubeMap(); - case GL_TEXTURE_3D: return getTexture3D(); - case GL_TEXTURE_2D_ARRAY: return getTexture2DArray(); - default: return NULL; - } -} - -Texture2D *Context::getTexture2D() const -{ - return static_cast(getSamplerTexture(mState.getActiveSampler(), GL_TEXTURE_2D)); -} - -TextureCubeMap *Context::getTextureCubeMap() const -{ - return static_cast(getSamplerTexture(mState.getActiveSampler(), GL_TEXTURE_CUBE_MAP)); -} - -Texture3D *Context::getTexture3D() const -{ - return static_cast(getSamplerTexture(mState.getActiveSampler(), GL_TEXTURE_3D)); -} - -Texture2DArray *Context::getTexture2DArray() const -{ - return static_cast(getSamplerTexture(mState.getActiveSampler(), GL_TEXTURE_2D_ARRAY)); -} - -Texture *Context::getSamplerTexture(unsigned int sampler, GLenum type) const -{ - return mState.getSamplerTexture(sampler, type); -} - -void Context::getBooleanv(GLenum pname, GLboolean *params) -{ - switch (pname) - { - case GL_SHADER_COMPILER: *params = GL_TRUE; break; - case GL_CONTEXT_ROBUST_ACCESS_EXT: *params = mRobustAccess ? GL_TRUE : GL_FALSE; break; - default: - mState.getBooleanv(pname, params); - break; - } -} - -void Context::getFloatv(GLenum pname, GLfloat *params) -{ - // Queries about context capabilities and maximums are answered by Context. - // Queries about current GL state values are answered by State. - switch (pname) - { - case GL_ALIASED_LINE_WIDTH_RANGE: - params[0] = mCaps.minAliasedLineWidth; - params[1] = mCaps.maxAliasedLineWidth; - break; - case GL_ALIASED_POINT_SIZE_RANGE: - params[0] = mCaps.minAliasedPointSize; - params[1] = mCaps.maxAliasedPointSize; - break; - case GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT: - ASSERT(mExtensions.textureFilterAnisotropic); - *params = mExtensions.maxTextureAnisotropy; - break; - default: - mState.getFloatv(pname, params); - break; - } -} - -void Context::getIntegerv(GLenum pname, GLint *params) -{ - // Queries about context capabilities and maximums are answered by Context. - // Queries about current GL state values are answered by State. - - switch (pname) - { - case GL_MAX_VERTEX_ATTRIBS: *params = mCaps.maxVertexAttributes; break; - case GL_MAX_VERTEX_UNIFORM_VECTORS: *params = mCaps.maxVertexUniformVectors; break; - case GL_MAX_VERTEX_UNIFORM_COMPONENTS: *params = mCaps.maxVertexUniformComponents; break; - case GL_MAX_VARYING_VECTORS: *params = mCaps.maxVaryingVectors; break; - case GL_MAX_VARYING_COMPONENTS: *params = mCaps.maxVertexOutputComponents; break; - case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: *params = mCaps.maxCombinedTextureImageUnits; break; - case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: *params = mCaps.maxVertexTextureImageUnits; break; - case GL_MAX_TEXTURE_IMAGE_UNITS: *params = mCaps.maxTextureImageUnits; break; - case GL_MAX_FRAGMENT_UNIFORM_VECTORS: *params = mCaps.maxFragmentUniformVectors; break; - case GL_MAX_FRAGMENT_UNIFORM_COMPONENTS: *params = mCaps.maxFragmentInputComponents; break; - case GL_MAX_RENDERBUFFER_SIZE: *params = mCaps.maxRenderbufferSize; break; - case GL_MAX_COLOR_ATTACHMENTS_EXT: *params = mCaps.maxColorAttachments; break; - case GL_MAX_DRAW_BUFFERS_EXT: *params = mCaps.maxDrawBuffers; break; - //case GL_FRAMEBUFFER_BINDING: // now equivalent to GL_DRAW_FRAMEBUFFER_BINDING_ANGLE - case GL_SUBPIXEL_BITS: *params = 4; break; - case GL_MAX_TEXTURE_SIZE: *params = mCaps.max2DTextureSize; break; - case GL_MAX_CUBE_MAP_TEXTURE_SIZE: *params = mCaps.maxCubeMapTextureSize; break; - case GL_MAX_3D_TEXTURE_SIZE: *params = mCaps.max3DTextureSize; break; - case GL_MAX_ARRAY_TEXTURE_LAYERS: *params = mCaps.maxArrayTextureLayers; break; - case GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT: *params = mCaps.uniformBufferOffsetAlignment; break; - case GL_MAX_UNIFORM_BUFFER_BINDINGS: *params = mCaps.maxUniformBufferBindings; break; - case GL_MAX_VERTEX_UNIFORM_BLOCKS: *params = mCaps.maxVertexUniformBlocks; break; - case GL_MAX_FRAGMENT_UNIFORM_BLOCKS: *params = mCaps.maxFragmentUniformBlocks; break; - case GL_MAX_COMBINED_UNIFORM_BLOCKS: *params = mCaps.maxCombinedTextureImageUnits; break; - case GL_MAJOR_VERSION: *params = mClientVersion; break; - case GL_MINOR_VERSION: *params = 0; break; - case GL_MAX_ELEMENTS_INDICES: *params = mCaps.maxElementsIndices; break; - case GL_MAX_ELEMENTS_VERTICES: *params = mCaps.maxElementsVertices; break; - case GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS: *params = mCaps.maxTransformFeedbackInterleavedComponents; break; - case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS: *params = mCaps.maxTransformFeedbackSeparateAttributes; break; - case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS: *params = mCaps.maxTransformFeedbackSeparateComponents; break; - case GL_NUM_COMPRESSED_TEXTURE_FORMATS: *params = mCaps.compressedTextureFormats.size(); break; - case GL_MAX_SAMPLES_ANGLE: *params = mExtensions.maxSamples; break; - case GL_IMPLEMENTATION_COLOR_READ_TYPE: - case GL_IMPLEMENTATION_COLOR_READ_FORMAT: - { - GLenum internalFormat, format, type; - getCurrentReadFormatType(&internalFormat, &format, &type); - if (pname == GL_IMPLEMENTATION_COLOR_READ_FORMAT) - *params = format; - else - *params = type; - } - break; - case GL_MAX_VIEWPORT_DIMS: - { - params[0] = mCaps.maxViewportWidth; - params[1] = mCaps.maxViewportHeight; - } - break; - case GL_COMPRESSED_TEXTURE_FORMATS: - std::copy(mCaps.compressedTextureFormats.begin(), mCaps.compressedTextureFormats.end(), params); - break; - case GL_RESET_NOTIFICATION_STRATEGY_EXT: - *params = mResetStrategy; - break; - case GL_NUM_SHADER_BINARY_FORMATS: - *params = mCaps.shaderBinaryFormats.size(); - break; - case GL_SHADER_BINARY_FORMATS: - std::copy(mCaps.shaderBinaryFormats.begin(), mCaps.shaderBinaryFormats.end(), params); - break; - case GL_NUM_PROGRAM_BINARY_FORMATS: - *params = mCaps.programBinaryFormats.size(); - break; - case GL_PROGRAM_BINARY_FORMATS: - std::copy(mCaps.programBinaryFormats.begin(), mCaps.programBinaryFormats.end(), params); - break; - case GL_NUM_EXTENSIONS: - *params = static_cast(mExtensionStrings.size()); - break; - default: - mState.getIntegerv(getData(), pname, params); - break; - } -} - -void Context::getInteger64v(GLenum pname, GLint64 *params) -{ - // Queries about context capabilities and maximums are answered by Context. - // Queries about current GL state values are answered by State. - switch (pname) - { - case GL_MAX_ELEMENT_INDEX: - *params = mCaps.maxElementIndex; - break; - case GL_MAX_UNIFORM_BLOCK_SIZE: - *params = mCaps.maxUniformBlockSize; - break; - case GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS: - *params = mCaps.maxCombinedVertexUniformComponents; - break; - case GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS: - *params = mCaps.maxCombinedFragmentUniformComponents; - break; - case GL_MAX_SERVER_WAIT_TIMEOUT: - *params = mCaps.maxServerWaitTimeout; - break; - default: - UNREACHABLE(); - break; - } -} - -bool Context::getIndexedIntegerv(GLenum target, GLuint index, GLint *data) -{ - // Queries about context capabilities and maximums are answered by Context. - // Queries about current GL state values are answered by State. - // Indexed integer queries all refer to current state, so this function is a - // mere passthrough. - return mState.getIndexedIntegerv(target, index, data); -} - -bool Context::getIndexedInteger64v(GLenum target, GLuint index, GLint64 *data) -{ - // Queries about context capabilities and maximums are answered by Context. - // Queries about current GL state values are answered by State. - // Indexed integer queries all refer to current state, so this function is a - // mere passthrough. - return mState.getIndexedInteger64v(target, index, data); -} - -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 - // if returned from Context::getIntegerv. Since this conversion is already implemented - // in the case that one calls glGetIntegerv to retrieve a float-typed state variable, we - // place DEPTH_CLEAR_VALUE with the floats. This should make no difference to the calling - // application. - switch (pname) - { - case GL_COMPRESSED_TEXTURE_FORMATS: - { - *type = GL_INT; - *numParams = mCaps.compressedTextureFormats.size(); - } - return true; - case GL_PROGRAM_BINARY_FORMATS_OES: - { - *type = GL_INT; - *numParams = mCaps.programBinaryFormats.size(); - } - return true; - case GL_SHADER_BINARY_FORMATS: - { - *type = GL_INT; - *numParams = mCaps.shaderBinaryFormats.size(); - } - return true; - case GL_MAX_VERTEX_ATTRIBS: - case GL_MAX_VERTEX_UNIFORM_VECTORS: - case GL_MAX_VARYING_VECTORS: - case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: - case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: - case GL_MAX_TEXTURE_IMAGE_UNITS: - case GL_MAX_FRAGMENT_UNIFORM_VECTORS: - case GL_MAX_RENDERBUFFER_SIZE: - case GL_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: - //case GL_FRAMEBUFFER_BINDING: // equivalent to DRAW_FRAMEBUFFER_BINDING_ANGLE - case GL_DRAW_FRAMEBUFFER_BINDING_ANGLE: - case GL_READ_FRAMEBUFFER_BINDING_ANGLE: - case GL_RENDERBUFFER_BINDING: - case GL_CURRENT_PROGRAM: - case GL_PACK_ALIGNMENT: - case GL_PACK_REVERSE_ROW_ORDER_ANGLE: - case GL_UNPACK_ALIGNMENT: - case GL_GENERATE_MIPMAP_HINT: - case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES: - case GL_RED_BITS: - case GL_GREEN_BITS: - case GL_BLUE_BITS: - case GL_ALPHA_BITS: - case GL_DEPTH_BITS: - case GL_STENCIL_BITS: - case GL_ELEMENT_ARRAY_BUFFER_BINDING: - case GL_CULL_FACE_MODE: - case GL_FRONT_FACE: - case GL_ACTIVE_TEXTURE: - case GL_STENCIL_FUNC: - case GL_STENCIL_VALUE_MASK: - case GL_STENCIL_REF: - case GL_STENCIL_FAIL: - case GL_STENCIL_PASS_DEPTH_FAIL: - case GL_STENCIL_PASS_DEPTH_PASS: - case GL_STENCIL_BACK_FUNC: - case GL_STENCIL_BACK_VALUE_MASK: - case GL_STENCIL_BACK_REF: - case GL_STENCIL_BACK_FAIL: - case GL_STENCIL_BACK_PASS_DEPTH_FAIL: - case GL_STENCIL_BACK_PASS_DEPTH_PASS: - case GL_DEPTH_FUNC: - case GL_BLEND_SRC_RGB: - case GL_BLEND_SRC_ALPHA: - case GL_BLEND_DST_RGB: - case GL_BLEND_DST_ALPHA: - case GL_BLEND_EQUATION_RGB: - case GL_BLEND_EQUATION_ALPHA: - case GL_STENCIL_WRITEMASK: - case GL_STENCIL_BACK_WRITEMASK: - case GL_STENCIL_CLEAR_VALUE: - case GL_SUBPIXEL_BITS: - case GL_MAX_TEXTURE_SIZE: - case GL_MAX_CUBE_MAP_TEXTURE_SIZE: - case GL_SAMPLE_BUFFERS: - case GL_SAMPLES: - case GL_IMPLEMENTATION_COLOR_READ_TYPE: - case GL_IMPLEMENTATION_COLOR_READ_FORMAT: - case GL_TEXTURE_BINDING_2D: - case GL_TEXTURE_BINDING_CUBE_MAP: - case GL_RESET_NOTIFICATION_STRATEGY_EXT: - case GL_NUM_PROGRAM_BINARY_FORMATS_OES: - { - *type = GL_INT; - *numParams = 1; - } - return true; - case GL_MAX_SAMPLES_ANGLE: - { - if (mExtensions.framebufferMultisample) - { - *type = GL_INT; - *numParams = 1; - } - else - { - return false; - } - } - return true; - case GL_PIXEL_PACK_BUFFER_BINDING: - case GL_PIXEL_UNPACK_BUFFER_BINDING: - { - if (mExtensions.pixelBufferObject) - { - *type = GL_INT; - *numParams = 1; - } - else - { - return false; - } - } - return true; - case GL_MAX_VIEWPORT_DIMS: - { - *type = GL_INT; - *numParams = 2; - } - return true; - case GL_VIEWPORT: - case GL_SCISSOR_BOX: - { - *type = GL_INT; - *numParams = 4; - } - return true; - case GL_SHADER_COMPILER: - case GL_SAMPLE_COVERAGE_INVERT: - case GL_DEPTH_WRITEMASK: - case GL_CULL_FACE: // CULL_FACE through DITHER are natural to IsEnabled, - case GL_POLYGON_OFFSET_FILL: // but can be retrieved through the Get{Type}v queries. - case GL_SAMPLE_ALPHA_TO_COVERAGE: // For this purpose, they are treated here as bool-natural - case GL_SAMPLE_COVERAGE: - case GL_SCISSOR_TEST: - case GL_STENCIL_TEST: - case GL_DEPTH_TEST: - case GL_BLEND: - case GL_DITHER: - case GL_CONTEXT_ROBUST_ACCESS_EXT: - { - *type = GL_BOOL; - *numParams = 1; - } - return true; - case GL_COLOR_WRITEMASK: - { - *type = GL_BOOL; - *numParams = 4; - } - return true; - case GL_POLYGON_OFFSET_FACTOR: - case GL_POLYGON_OFFSET_UNITS: - case GL_SAMPLE_COVERAGE_VALUE: - case GL_DEPTH_CLEAR_VALUE: - case GL_LINE_WIDTH: - { - *type = GL_FLOAT; - *numParams = 1; - } - return true; - case GL_ALIASED_LINE_WIDTH_RANGE: - case GL_ALIASED_POINT_SIZE_RANGE: - case GL_DEPTH_RANGE: - { - *type = GL_FLOAT; - *numParams = 2; - } - return true; - case GL_COLOR_CLEAR_VALUE: - case GL_BLEND_COLOR: - { - *type = GL_FLOAT; - *numParams = 4; - } - return true; - case GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT: - if (!mExtensions.maxTextureAnisotropy) - { - return false; - } - *type = GL_FLOAT; - *numParams = 1; - return true; - } - - if (mClientVersion < 3) - { - return false; - } - - // Check for ES3.0+ parameter names - switch (pname) - { - case GL_MAX_UNIFORM_BUFFER_BINDINGS: - case GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT: - case GL_UNIFORM_BUFFER_BINDING: - case GL_TRANSFORM_FEEDBACK_BINDING: - case GL_COPY_READ_BUFFER_BINDING: - case GL_COPY_WRITE_BUFFER_BINDING: - case GL_TEXTURE_BINDING_3D: - case GL_TEXTURE_BINDING_2D_ARRAY: - case GL_MAX_3D_TEXTURE_SIZE: - case GL_MAX_ARRAY_TEXTURE_LAYERS: - case GL_MAX_VERTEX_UNIFORM_BLOCKS: - case GL_MAX_FRAGMENT_UNIFORM_BLOCKS: - case GL_MAX_COMBINED_UNIFORM_BLOCKS: - case GL_MAX_VARYING_COMPONENTS: - case GL_VERTEX_ARRAY_BINDING: - case GL_MAX_VERTEX_UNIFORM_COMPONENTS: - case GL_MAX_FRAGMENT_UNIFORM_COMPONENTS: - case GL_NUM_EXTENSIONS: - case GL_MAJOR_VERSION: - case GL_MINOR_VERSION: - case GL_MAX_ELEMENTS_INDICES: - case GL_MAX_ELEMENTS_VERTICES: - case GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS: - case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS: - case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS: - { - *type = GL_INT; - *numParams = 1; - } - return true; - - case GL_MAX_ELEMENT_INDEX: - case GL_MAX_UNIFORM_BLOCK_SIZE: - case GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS: - case GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS: - case GL_MAX_SERVER_WAIT_TIMEOUT: - { - *type = GL_INT_64_ANGLEX; - *numParams = 1; - } - return true; - - case GL_TRANSFORM_FEEDBACK_ACTIVE: - case GL_TRANSFORM_FEEDBACK_PAUSED: - { - *type = GL_BOOL; - *numParams = 1; - } - return true; - } - - return false; -} - -bool Context::getIndexedQueryParameterInfo(GLenum target, GLenum *type, unsigned int *numParams) -{ - if (mClientVersion < 3) - { - return false; - } - - switch (target) - { - case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: - case GL_UNIFORM_BUFFER_BINDING: - { - *type = GL_INT; - *numParams = 1; - } - return true; - case GL_TRANSFORM_FEEDBACK_BUFFER_START: - case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE: - case GL_UNIFORM_BUFFER_START: - case GL_UNIFORM_BUFFER_SIZE: - { - *type = GL_INT_64_ANGLEX; - *numParams = 1; - } - } - - return false; -} - -Error Context::clear(GLbitfield mask) -{ - if (mState.isRasterizerDiscardEnabled()) - { - return Error(GL_NO_ERROR); - } - - return mRenderer->clear(getData(), mask); -} - -Error Context::clearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *values) -{ - if (mState.isRasterizerDiscardEnabled()) - { - return Error(GL_NO_ERROR); - } - - return mRenderer->clearBufferfv(getData(), buffer, drawbuffer, values); -} - -Error Context::clearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *values) -{ - if (mState.isRasterizerDiscardEnabled()) - { - return Error(GL_NO_ERROR); - } - - return mRenderer->clearBufferuiv(getData(), buffer, drawbuffer, values); -} - -Error Context::clearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *values) -{ - if (mState.isRasterizerDiscardEnabled()) - { - return Error(GL_NO_ERROR); - } - - return mRenderer->clearBufferiv(getData(), buffer, drawbuffer, values); -} - -Error Context::clearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) -{ - if (mState.isRasterizerDiscardEnabled()) - { - return Error(GL_NO_ERROR); - } - - return mRenderer->clearBufferfi(getData(), buffer, drawbuffer, depth, stencil); -} - -Error Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, - GLenum format, GLenum type, GLsizei *bufSize, void* pixels) -{ - return mRenderer->readPixels(getData(), x, y, width, height, format, type, bufSize, pixels); -} - -Error Context::drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instances) -{ - return mRenderer->drawArrays(getData(), mode, first, count, instances); -} - -Error Context::drawElements(GLenum mode, GLsizei count, GLenum type, - const GLvoid *indices, GLsizei instances, - const rx::RangeUI &indexRange) -{ - return mRenderer->drawElements(getData(), mode, count, type, indices, instances, indexRange); -} - -// Implements glFlush when block is false, glFinish when block is true -Error Context::sync(bool block) -{ - return mRenderer->sync(block); -} - -void Context::recordError(const Error &error) -{ - if (error.isError()) - { - mErrors.insert(error.getCode()); - } -} - -// Get one of the recorded errors and clear its flag, if any. -// [OpenGL ES 2.0.24] section 2.5 page 13. -GLenum Context::getError() -{ - if (mErrors.empty()) - { - return GL_NO_ERROR; - } - else - { - GLenum error = *mErrors.begin(); - mErrors.erase(mErrors.begin()); - return error; - } -} - -GLenum Context::getResetStatus() -{ - //TODO(jmadill): needs MANGLE reworking - if (mResetStatus == GL_NO_ERROR && !mContextLost) - { - // 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) - { - ASSERT(mContextLost); - - if (mRenderer->testDeviceResettable()) - { - mResetStatus = GL_NO_ERROR; - } - } - - return status; -} - -bool Context::isResetNotificationEnabled() -{ - return (mResetStrategy == GL_LOSE_CONTEXT_ON_RESET_EXT); -} - -int Context::getClientVersion() const -{ - return mClientVersion; -} - -const Caps &Context::getCaps() const -{ - return mCaps; -} - -const TextureCapsMap &Context::getTextureCaps() const -{ - return mTextureCaps; -} - -const Extensions &Context::getExtensions() const -{ - return mExtensions; -} - -void Context::getCurrentReadFormatType(GLenum *internalFormat, GLenum *format, GLenum *type) -{ - Framebuffer *framebuffer = mState.getReadFramebuffer(); - ASSERT(framebuffer && framebuffer->completeness(getData()) == GL_FRAMEBUFFER_COMPLETE); - - FramebufferAttachment *attachment = framebuffer->getReadColorbuffer(); - ASSERT(attachment); - - GLenum actualFormat = attachment->getActualFormat(); - const InternalFormat &actualFormatInfo = GetInternalFormatInfo(actualFormat); - - *internalFormat = actualFormat; - *format = actualFormatInfo.format; - *type = actualFormatInfo.type; -} - -void Context::detachTexture(GLuint texture) -{ - // Simple pass-through to State's detachTexture method, as textures do not require - // allocation map management either here or in the resource manager at detach time. - // Zero textures are held by the Context, and we don't attempt to request them from - // the State. - mState.detachTexture(mZeroTextures, texture); -} - -void Context::detachBuffer(GLuint buffer) -{ - // Buffer detachment is handled by Context, because the buffer must also be - // attached from any VAOs in existence, and Context holds the VAO map. - - // [OpenGL ES 2.0.24] section 2.9 page 22: - // If a buffer object is deleted while it is bound, all bindings to that object in the current context - // (i.e. in the thread that called Delete-Buffers) are reset to zero. - - mState.removeArrayBufferBinding(buffer); - - // mark as freed among the vertex array objects - for (auto vaoIt = mVertexArrayMap.begin(); vaoIt != mVertexArrayMap.end(); vaoIt++) - { - vaoIt->second->detachBuffer(buffer); - } -} - -void Context::detachFramebuffer(GLuint framebuffer) -{ - // Framebuffer detachment is handled by Context, because 0 is a valid - // Framebuffer object, and a pointer to it must be passed from Context - // to State at binding time. - - // [OpenGL ES 2.0.24] section 4.4 page 107: - // If a framebuffer that is currently bound to the target FRAMEBUFFER is deleted, it is as though - // BindFramebuffer had been executed with the target of FRAMEBUFFER and framebuffer of zero. - - if (mState.removeReadFramebufferBinding(framebuffer)) - { - bindReadFramebuffer(0); - } - - if (mState.removeDrawFramebufferBinding(framebuffer)) - { - bindDrawFramebuffer(0); - } -} - -void Context::detachRenderbuffer(GLuint renderbuffer) -{ - mState.detachRenderbuffer(renderbuffer); -} - -void Context::detachVertexArray(GLuint vertexArray) -{ - // Vertex array detachment is handled by Context, because 0 is a valid - // VAO, and a pointer to it must be passed from Context to State at - // binding time. - - // [OpenGL ES 3.0.2] section 2.10 page 43: - // If a vertex array object that is currently bound is deleted, the binding - // for that object reverts to zero and the default vertex array becomes current. - if (mState.removeVertexArrayBinding(vertexArray)) - { - bindVertexArray(0); - } -} - -void Context::detachTransformFeedback(GLuint transformFeedback) -{ - mState.detachTransformFeedback(transformFeedback); -} - -void Context::detachSampler(GLuint sampler) -{ - mState.detachSampler(sampler); -} - -void Context::setVertexAttribDivisor(GLuint index, GLuint divisor) -{ - mState.getVertexArray()->setVertexAttribDivisor(index, divisor); -} - -void Context::samplerParameteri(GLuint sampler, GLenum pname, GLint param) -{ - mResourceManager->checkSamplerAllocation(sampler); - - Sampler *samplerObject = getSampler(sampler); - ASSERT(samplerObject); - - switch (pname) - { - case GL_TEXTURE_MIN_FILTER: samplerObject->setMinFilter(static_cast(param)); break; - case GL_TEXTURE_MAG_FILTER: samplerObject->setMagFilter(static_cast(param)); break; - case GL_TEXTURE_WRAP_S: samplerObject->setWrapS(static_cast(param)); break; - case GL_TEXTURE_WRAP_T: samplerObject->setWrapT(static_cast(param)); break; - case GL_TEXTURE_WRAP_R: samplerObject->setWrapR(static_cast(param)); break; - case GL_TEXTURE_MIN_LOD: samplerObject->setMinLod(static_cast(param)); break; - case GL_TEXTURE_MAX_LOD: samplerObject->setMaxLod(static_cast(param)); break; - case GL_TEXTURE_COMPARE_MODE: samplerObject->setComparisonMode(static_cast(param)); break; - case GL_TEXTURE_COMPARE_FUNC: samplerObject->setComparisonFunc(static_cast(param)); break; - default: UNREACHABLE(); break; - } -} - -void Context::samplerParameterf(GLuint sampler, GLenum pname, GLfloat param) -{ - mResourceManager->checkSamplerAllocation(sampler); - - Sampler *samplerObject = getSampler(sampler); - ASSERT(samplerObject); - - switch (pname) - { - case GL_TEXTURE_MIN_FILTER: samplerObject->setMinFilter(uiround(param)); break; - case GL_TEXTURE_MAG_FILTER: samplerObject->setMagFilter(uiround(param)); break; - case GL_TEXTURE_WRAP_S: samplerObject->setWrapS(uiround(param)); break; - case GL_TEXTURE_WRAP_T: samplerObject->setWrapT(uiround(param)); break; - case GL_TEXTURE_WRAP_R: samplerObject->setWrapR(uiround(param)); break; - case GL_TEXTURE_MIN_LOD: samplerObject->setMinLod(param); break; - case GL_TEXTURE_MAX_LOD: samplerObject->setMaxLod(param); break; - case GL_TEXTURE_COMPARE_MODE: samplerObject->setComparisonMode(uiround(param)); break; - case GL_TEXTURE_COMPARE_FUNC: samplerObject->setComparisonFunc(uiround(param)); break; - default: UNREACHABLE(); break; - } -} - -GLint Context::getSamplerParameteri(GLuint sampler, GLenum pname) -{ - mResourceManager->checkSamplerAllocation(sampler); - - Sampler *samplerObject = getSampler(sampler); - ASSERT(samplerObject); - - switch (pname) - { - case GL_TEXTURE_MIN_FILTER: return static_cast(samplerObject->getMinFilter()); - case GL_TEXTURE_MAG_FILTER: return static_cast(samplerObject->getMagFilter()); - case GL_TEXTURE_WRAP_S: return static_cast(samplerObject->getWrapS()); - case GL_TEXTURE_WRAP_T: return static_cast(samplerObject->getWrapT()); - case GL_TEXTURE_WRAP_R: return static_cast(samplerObject->getWrapR()); - case GL_TEXTURE_MIN_LOD: return uiround(samplerObject->getMinLod()); - case GL_TEXTURE_MAX_LOD: return uiround(samplerObject->getMaxLod()); - case GL_TEXTURE_COMPARE_MODE: return static_cast(samplerObject->getComparisonMode()); - case GL_TEXTURE_COMPARE_FUNC: return static_cast(samplerObject->getComparisonFunc()); - default: UNREACHABLE(); return 0; - } -} - -GLfloat Context::getSamplerParameterf(GLuint sampler, GLenum pname) -{ - mResourceManager->checkSamplerAllocation(sampler); - - Sampler *samplerObject = getSampler(sampler); - ASSERT(samplerObject); - - switch (pname) - { - case GL_TEXTURE_MIN_FILTER: return static_cast(samplerObject->getMinFilter()); - case GL_TEXTURE_MAG_FILTER: return static_cast(samplerObject->getMagFilter()); - case GL_TEXTURE_WRAP_S: return static_cast(samplerObject->getWrapS()); - case GL_TEXTURE_WRAP_T: return static_cast(samplerObject->getWrapT()); - case GL_TEXTURE_WRAP_R: return static_cast(samplerObject->getWrapR()); - case GL_TEXTURE_MIN_LOD: return samplerObject->getMinLod(); - case GL_TEXTURE_MAX_LOD: return samplerObject->getMaxLod(); - case GL_TEXTURE_COMPARE_MODE: return static_cast(samplerObject->getComparisonMode()); - case GL_TEXTURE_COMPARE_FUNC: return static_cast(samplerObject->getComparisonFunc()); - default: UNREACHABLE(); return 0; - } -} - -void Context::initRendererString() -{ - std::ostringstream rendererString; - rendererString << "ANGLE ("; - rendererString << mRenderer->getRendererDescription(); - rendererString << ")"; - - mRendererString = MakeStaticString(rendererString.str()); -} - -const std::string &Context::getRendererString() const -{ - return mRendererString; -} - -void Context::initExtensionStrings() -{ - mExtensionStrings = mExtensions.getStrings(); - - std::ostringstream combinedStringStream; - std::copy(mExtensionStrings.begin(), mExtensionStrings.end(), std::ostream_iterator(combinedStringStream, " ")); - mExtensionString = combinedStringStream.str(); -} - -const std::string &Context::getExtensionString() const -{ - return mExtensionString; -} - -const std::string &Context::getExtensionString(size_t idx) const -{ - return mExtensionStrings[idx]; -} - -size_t Context::getExtensionStringCount() const -{ - return mExtensionStrings.size(); -} - -Error Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, - GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, - GLbitfield mask, GLenum filter) -{ - return mRenderer->blitFramebuffer(getData(), srcX0, srcY0, srcX1, srcY1, - dstX0, dstY0, dstX1, dstY1, mask, filter); -} - -void Context::releaseShaderCompiler() -{ - mRenderer->releaseShaderCompiler(); -} - -void Context::initCaps(GLuint clientVersion) -{ - mCaps = mRenderer->getRendererCaps(); - - mExtensions = mRenderer->getRendererExtensions(); - - if (clientVersion < 3) - { - // Disable ES3+ extensions - mExtensions.colorBufferFloat = false; - } - - if (clientVersion > 2) - { - // FIXME(geofflang): Don't support EXT_sRGB in non-ES2 contexts - //mExtensions.sRGB = false; - } - - // Apply implementation limits - mCaps.maxVertexAttributes = std::min(mCaps.maxVertexAttributes, MAX_VERTEX_ATTRIBS); - mCaps.maxVertexUniformBlocks = std::min(mCaps.maxVertexUniformBlocks, IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS); - mCaps.maxVertexOutputComponents = std::min(mCaps.maxVertexOutputComponents, IMPLEMENTATION_MAX_VARYING_VECTORS * 4); - - mCaps.maxFragmentInputComponents = std::min(mCaps.maxFragmentInputComponents, IMPLEMENTATION_MAX_VARYING_VECTORS * 4); - - GLuint maxSamples = 0; - mCaps.compressedTextureFormats.clear(); - - const TextureCapsMap &rendererFormats = mRenderer->getRendererTextureCaps(); - for (TextureCapsMap::const_iterator i = rendererFormats.begin(); i != rendererFormats.end(); i++) - { - GLenum format = i->first; - TextureCaps formatCaps = i->second; - - const InternalFormat &formatInfo = GetInternalFormatInfo(format); - - // Update the format caps based on the client version and extensions - formatCaps.texturable = formatInfo.textureSupport(clientVersion, mExtensions); - formatCaps.renderable = formatInfo.renderSupport(clientVersion, mExtensions); - formatCaps.filterable = formatInfo.filterSupport(clientVersion, mExtensions); - - // OpenGL ES does not support multisampling with integer formats - if (!formatInfo.renderSupport || formatInfo.componentType == GL_INT || formatInfo.componentType == GL_UNSIGNED_INT) - { - formatCaps.sampleCounts.clear(); - } - maxSamples = std::max(maxSamples, formatCaps.getMaxSamples()); - - if (formatCaps.texturable && formatInfo.compressed) - { - mCaps.compressedTextureFormats.push_back(format); - } - - mTextureCaps.insert(format, formatCaps); - } - - mExtensions.maxSamples = maxSamples; -} - -Data Context::getData() const -{ - return Data(mClientVersion, mState, mCaps, mTextureCaps, mExtensions, mResourceManager); -} - -} - -extern "C" -{ -gl::Context *glCreateContext(int clientVersion, const gl::Context *shareContext, rx::Renderer *renderer, bool notifyResets, bool robustAccess) -{ - return new gl::Context(clientVersion, shareContext, renderer, notifyResets, robustAccess); -} - -void glDestroyContext(gl::Context *context) -{ - delete context; - - if (context == gl::getContext()) - { - gl::makeCurrent(NULL, NULL, NULL); - } -} - -void glMakeCurrent(gl::Context *context, egl::Display *display, egl::Surface *surface) -{ - gl::makeCurrent(context, display, surface); -} - -gl::Context *glGetCurrentContext() -{ - return gl::getContext(); -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/Context.h b/src/3rdparty/angle/src/libGLESv2/Context.h deleted file mode 100644 index 0699592d91..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/Context.h +++ /dev/null @@ -1,291 +0,0 @@ -// -// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Context.h: Defines the gl::Context class, managing all GL state and performing -// rendering operations. It is the GLES2 specific implementation of EGLContext. - -#ifndef LIBGLESV2_CONTEXT_H_ -#define LIBGLESV2_CONTEXT_H_ - -#include "common/angleutils.h" -#include "common/RefCountObject.h" -#include "libGLESv2/Caps.h" -#include "libGLESv2/Constants.h" -#include "libGLESv2/Data.h" -#include "libGLESv2/Error.h" -#include "libGLESv2/HandleAllocator.h" -#include "libGLESv2/VertexAttribute.h" -#include "libGLESv2/angletypes.h" - -#include "angle_gl.h" - -#include -#include -#include -#include -#include - -namespace rx -{ -class Renderer; -} - -namespace egl -{ -class Surface; -} - -namespace gl -{ -class Shader; -class Program; -class ProgramBinary; -class Texture; -class Texture2D; -class TextureCubeMap; -class Texture3D; -class Texture2DArray; -class Framebuffer; -class Renderbuffer; -class FenceNV; -class FenceSync; -class Query; -class ResourceManager; -class Buffer; -struct VertexAttribute; -class VertexArray; -class Sampler; -class TransformFeedback; - -class Context -{ - public: - Context(int clientVersion, const Context *shareContext, rx::Renderer *renderer, bool notifyResets, bool robustAccess); - - virtual ~Context(); - - void makeCurrent(egl::Surface *surface); - - virtual void markContextLost(); - bool isContextLost(); - - // These create and destroy methods are merely pass-throughs to - // ResourceManager, which owns these object types - GLuint createBuffer(); - GLuint createShader(GLenum type); - GLuint createProgram(); - GLuint createTexture(); - GLuint createRenderbuffer(); - GLuint createSampler(); - GLuint createTransformFeedback(); - GLsync createFenceSync(); - - void deleteBuffer(GLuint buffer); - void deleteShader(GLuint shader); - void deleteProgram(GLuint program); - void deleteTexture(GLuint texture); - void deleteRenderbuffer(GLuint renderbuffer); - void deleteSampler(GLuint sampler); - void deleteTransformFeedback(GLuint transformFeedback); - void deleteFenceSync(GLsync fenceSync); - - // Framebuffers are owned by the Context, so these methods do not pass through - GLuint createFramebuffer(); - void deleteFramebuffer(GLuint framebuffer); - - // NV Fences are owned by the Context. - GLuint createFenceNV(); - void deleteFenceNV(GLuint fence); - - // Queries are owned by the Context; - GLuint createQuery(); - void deleteQuery(GLuint query); - - // Vertex arrays are owned by the Context - GLuint createVertexArray(); - void deleteVertexArray(GLuint vertexArray); - - void bindArrayBuffer(GLuint buffer); - void bindElementArrayBuffer(GLuint buffer); - void bindTexture(GLenum target, GLuint handle); - void bindReadFramebuffer(GLuint framebuffer); - void bindDrawFramebuffer(GLuint framebuffer); - void bindRenderbuffer(GLuint renderbuffer); - void bindVertexArray(GLuint vertexArray); - void bindSampler(GLuint textureUnit, GLuint sampler); - void bindGenericUniformBuffer(GLuint buffer); - void bindIndexedUniformBuffer(GLuint buffer, GLuint index, GLintptr offset, GLsizeiptr size); - void bindGenericTransformFeedbackBuffer(GLuint buffer); - void bindIndexedTransformFeedbackBuffer(GLuint buffer, GLuint index, GLintptr offset, GLsizeiptr size); - void bindCopyReadBuffer(GLuint buffer); - void bindCopyWriteBuffer(GLuint buffer); - void bindPixelPackBuffer(GLuint buffer); - void bindPixelUnpackBuffer(GLuint buffer); - void useProgram(GLuint program); - Error linkProgram(GLuint program); - Error setProgramBinary(GLuint program, GLenum binaryFormat, const void *binary, GLint length); - void bindTransformFeedback(GLuint transformFeedback); - - Error beginQuery(GLenum target, GLuint query); - Error endQuery(GLenum target); - - void setFramebufferZero(Framebuffer *framebuffer); - - void setVertexAttribDivisor(GLuint index, GLuint divisor); - - void samplerParameteri(GLuint sampler, GLenum pname, GLint param); - void samplerParameterf(GLuint sampler, GLenum pname, GLfloat param); - GLint getSamplerParameteri(GLuint sampler, GLenum pname); - GLfloat getSamplerParameterf(GLuint sampler, GLenum pname); - - Buffer *getBuffer(GLuint handle); - FenceNV *getFenceNV(GLuint handle); - FenceSync *getFenceSync(GLsync handle) const; - Shader *getShader(GLuint handle) const; - Program *getProgram(GLuint handle) const; - Texture *getTexture(GLuint handle) const; - Framebuffer *getFramebuffer(GLuint handle) const; - Renderbuffer *getRenderbuffer(GLuint handle); - VertexArray *getVertexArray(GLuint handle) const; - Sampler *getSampler(GLuint handle) const; - Query *getQuery(GLuint handle, bool create, GLenum type); - TransformFeedback *getTransformFeedback(GLuint handle) const; - - Texture *getTargetTexture(GLenum target) const; - Texture2D *getTexture2D() const; - TextureCubeMap *getTextureCubeMap() const; - Texture3D *getTexture3D() const; - Texture2DArray *getTexture2DArray() const; - - Texture *getSamplerTexture(unsigned int sampler, GLenum type) const; - - bool isSampler(GLuint samplerName) const; - - void getBooleanv(GLenum pname, GLboolean *params); - void getFloatv(GLenum pname, GLfloat *params); - void getIntegerv(GLenum pname, GLint *params); - void getInteger64v(GLenum pname, GLint64 *params); - - bool getIndexedIntegerv(GLenum target, GLuint index, GLint *data); - bool getIndexedInteger64v(GLenum target, GLuint index, GLint64 *data); - - bool getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *numParams); - bool getIndexedQueryParameterInfo(GLenum target, GLenum *type, unsigned int *numParams); - - Error clear(GLbitfield mask); - Error clearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *values); - Error clearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *values); - Error clearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *values); - Error clearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil); - - Error readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei *bufSize, void* pixels); - Error drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instances); - Error drawElements(GLenum mode, GLsizei count, GLenum type, - const GLvoid *indices, GLsizei instances, - const rx::RangeUI &indexRange); - Error sync(bool block); // flush/finish - - void recordError(const Error &error); - - GLenum getError(); - GLenum getResetStatus(); - virtual bool isResetNotificationEnabled(); - - virtual int getClientVersion() const; - - const Caps &getCaps() const; - const TextureCapsMap &getTextureCaps() const; - const Extensions &getExtensions() const; - - const std::string &getRendererString() const; - - const std::string &getExtensionString() const; - const std::string &getExtensionString(size_t idx) const; - size_t getExtensionStringCount() const; - - void getCurrentReadFormatType(GLenum *internalFormat, GLenum *format, GLenum *type); - - Error blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, - GLbitfield mask, GLenum filter); - - rx::Renderer *getRenderer() { return mRenderer; } - - State &getState() { return mState; } - const State &getState() const { return mState; } - - Data getData() const; - - void releaseShaderCompiler(); - - private: - DISALLOW_COPY_AND_ASSIGN(Context); - - void detachBuffer(GLuint buffer); - void detachTexture(GLuint texture); - void detachFramebuffer(GLuint framebuffer); - void detachRenderbuffer(GLuint renderbuffer); - void detachVertexArray(GLuint vertexArray); - void detachTransformFeedback(GLuint transformFeedback); - void detachSampler(GLuint sampler); - - void initRendererString(); - void initExtensionStrings(); - - void initCaps(GLuint clientVersion); - - // Caps to use for validation - Caps mCaps; - TextureCapsMap mTextureCaps; - Extensions mExtensions; - - rx::Renderer *const mRenderer; - State mState; - - int mClientVersion; - - TextureMap mZeroTextures; - - typedef std::unordered_map FramebufferMap; - FramebufferMap mFramebufferMap; - HandleAllocator mFramebufferHandleAllocator; - - typedef std::unordered_map FenceNVMap; - FenceNVMap mFenceNVMap; - HandleAllocator mFenceNVHandleAllocator; - - typedef std::unordered_map QueryMap; - QueryMap mQueryMap; - HandleAllocator mQueryHandleAllocator; - - typedef std::unordered_map VertexArrayMap; - VertexArrayMap mVertexArrayMap; - HandleAllocator mVertexArrayHandleAllocator; - - BindingPointer mTransformFeedbackZero; - typedef std::unordered_map TransformFeedbackMap; - TransformFeedbackMap mTransformFeedbackMap; - HandleAllocator mTransformFeedbackAllocator; - - std::string mRendererString; - std::string mExtensionString; - std::vector mExtensionStrings; - - // Recorded errors - typedef std::set ErrorSet; - ErrorSet mErrors; - - // Current/lost context flags - bool mHasBeenCurrent; - bool mContextLost; - GLenum mResetStatus; - GLenum mResetStrategy; - bool mRobustAccess; - - ResourceManager *mResourceManager; -}; -} - -#endif // INCLUDE_CONTEXT_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/Data.cpp b/src/3rdparty/angle/src/libGLESv2/Data.cpp deleted file mode 100644 index 3ddf591d77..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/Data.cpp +++ /dev/null @@ -1,51 +0,0 @@ -// -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Data.cpp: Container class for all GL relevant state, caps and objects - -#include "libGLESv2/Data.h" -#include "libGLESv2/ResourceManager.h" - -namespace gl -{ - -Data::Data(GLint clientVersionIn, const State &stateIn, const Caps &capsIn, - const TextureCapsMap &textureCapsIn, const Extensions &extensionsIn, - const ResourceManager *resourceManagerIn) - : clientVersion(clientVersionIn), - state(&stateIn), - caps(&capsIn), - textureCaps(&textureCapsIn), - extensions(&extensionsIn), - resourceManager(resourceManagerIn) -{} - -Data::~Data() -{ -} - -Data::Data(const Data &other) - : clientVersion(other.clientVersion), - state(other.state), - caps(other.caps), - textureCaps(other.textureCaps), - extensions(other.extensions), - resourceManager(other.resourceManager) -{ -} - -Data &Data::operator=(const Data &other) -{ - clientVersion = other.clientVersion; - state = other.state; - caps = other.caps; - textureCaps = other.textureCaps; - extensions = other.extensions; - resourceManager = other.resourceManager; - return *this; -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/Data.h b/src/3rdparty/angle/src/libGLESv2/Data.h deleted file mode 100644 index 9234403e13..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/Data.h +++ /dev/null @@ -1,38 +0,0 @@ -// -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Data.h: Container class for all GL relevant state, caps and objects - -#ifndef LIBGLESV2_DATA_H_ -#define LIBGLESV2_DATA_H_ - -#include "libGLESv2/State.h" - -namespace gl -{ - -struct Data -{ - public: - Data(GLint clientVersion, const State &state, const Caps &caps, - const TextureCapsMap &textureCaps, const Extensions &extensions, - const ResourceManager *resourceManager); - ~Data(); - - Data(const Data &other); - Data &operator=(const Data &other); - - GLint clientVersion; - const State *state; - const Caps *caps; - const TextureCapsMap *textureCaps; - const Extensions *extensions; - const ResourceManager *resourceManager; -}; - -} - -#endif // LIBGLESV2_DATA_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/Error.cpp b/src/3rdparty/angle/src/libGLESv2/Error.cpp deleted file mode 100644 index cc7d17eb37..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/Error.cpp +++ /dev/null @@ -1,48 +0,0 @@ -// -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Error.cpp: Implements the gl::Error class which encapsulates an OpenGL error -// and optional error message. - -#include "libGLESv2/Error.h" - -#include "common/angleutils.h" - -#include - -namespace gl -{ - -Error::Error(GLenum errorCode) - : mCode(errorCode), - mMessage() -{ -} - -Error::Error(GLenum errorCode, const char *msg, ...) - : mCode(errorCode), - mMessage() -{ - va_list vararg; - va_start(vararg, msg); - mMessage = FormatString(msg, vararg); - va_end(vararg); -} - -Error::Error(const Error &other) - : mCode(other.mCode), - mMessage(other.mMessage) -{ -} - -Error &Error::operator=(const Error &other) -{ - mCode = other.mCode; - mMessage = other.mMessage; - return *this; -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/Error.h b/src/3rdparty/angle/src/libGLESv2/Error.h deleted file mode 100644 index b70b5a531c..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/Error.h +++ /dev/null @@ -1,39 +0,0 @@ -// -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Error.h: Defines the gl::Error class which encapsulates an OpenGL error -// and optional error message. - -#ifndef LIBGLESV2_ERROR_H_ -#define LIBGLESV2_ERROR_H_ - -#include "angle_gl.h" - -#include - -namespace gl -{ - -class Error -{ - public: - explicit Error(GLenum errorCode); - Error(GLenum errorCode, const char *msg, ...); - Error(const Error &other); - Error &operator=(const Error &other); - - GLenum getCode() const { return mCode; } - bool isError() const { return (mCode != GL_NO_ERROR); } - - const std::string &getMessage() const { return mMessage; } - - private: - GLenum mCode; - std::string mMessage; -}; - -} - -#endif // LIBGLESV2_ERROR_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/Fence.cpp b/src/3rdparty/angle/src/libGLESv2/Fence.cpp deleted file mode 100644 index 966a327de5..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/Fence.cpp +++ /dev/null @@ -1,116 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Fence.cpp: Implements the gl::FenceNV and gl::FenceSync classes, which support the GL_NV_fence -// extension and GLES3 sync objects. - -#include "libGLESv2/Fence.h" -#include "libGLESv2/renderer/FenceImpl.h" -#include "libGLESv2/renderer/Renderer.h" -#include "libGLESv2/main.h" -#include "common/utilities.h" - -#include "angle_gl.h" - -namespace gl -{ - -FenceNV::FenceNV(rx::FenceNVImpl *impl) - : mFence(impl), - mIsSet(false), - mStatus(GL_FALSE), - mCondition(GL_NONE) -{ -} - -FenceNV::~FenceNV() -{ - SafeDelete(mFence); -} - -GLboolean FenceNV::isFence() const -{ - // GL_NV_fence spec: - // A name returned by GenFencesNV, but not yet set via SetFenceNV, is not the name of an existing fence. - return (mIsSet ? GL_TRUE : GL_FALSE); -} - -Error FenceNV::setFence(GLenum condition) -{ - Error error = mFence->set(); - if (error.isError()) - { - return error; - } - - mCondition = condition; - mStatus = GL_FALSE; - mIsSet = true; - - return Error(GL_NO_ERROR); -} - -Error FenceNV::testFence(GLboolean *outResult) -{ - // Flush the command buffer by default - Error error = mFence->test(true, &mStatus); - if (error.isError()) - { - return error; - } - - *outResult = mStatus; - return Error(GL_NO_ERROR); -} - -Error FenceNV::finishFence() -{ - ASSERT(mIsSet); - - return mFence->finishFence(&mStatus); -} - -FenceSync::FenceSync(rx::FenceSyncImpl *impl, GLuint id) - : RefCountObject(id), - mFence(impl), - mCondition(GL_NONE) -{ -} - -FenceSync::~FenceSync() -{ - SafeDelete(mFence); -} - -Error FenceSync::set(GLenum condition) -{ - Error error = mFence->set(); - if (error.isError()) - { - return error; - } - - mCondition = condition; - return Error(GL_NO_ERROR); -} - -Error FenceSync::clientWait(GLbitfield flags, GLuint64 timeout, GLenum *outResult) -{ - ASSERT(mCondition != GL_NONE); - return mFence->clientWait(flags, timeout, outResult); -} - -Error FenceSync::serverWait(GLbitfield flags, GLuint64 timeout) -{ - return mFence->serverWait(flags, timeout); -} - -Error FenceSync::getStatus(GLint *outResult) const -{ - return mFence->getStatus(outResult); -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/Fence.h b/src/3rdparty/angle/src/libGLESv2/Fence.h deleted file mode 100644 index fd565e96a6..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/Fence.h +++ /dev/null @@ -1,75 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Fence.h: Defines the gl::FenceNV and gl::FenceSync classes, which support the GL_NV_fence -// extension and GLES3 sync objects. - -#ifndef LIBGLESV2_FENCE_H_ -#define LIBGLESV2_FENCE_H_ - -#include "libGLESv2/Error.h" - -#include "common/angleutils.h" -#include "common/RefCountObject.h" - -namespace rx -{ -class FenceNVImpl; -class FenceSyncImpl; -} - -namespace gl -{ - -class FenceNV -{ - public: - explicit FenceNV(rx::FenceNVImpl *impl); - virtual ~FenceNV(); - - GLboolean isFence() const; - Error setFence(GLenum condition); - Error testFence(GLboolean *outResult); - Error finishFence(); - - GLboolean getStatus() const { return mStatus; } - GLuint getCondition() const { return mCondition; } - - private: - DISALLOW_COPY_AND_ASSIGN(FenceNV); - - rx::FenceNVImpl *mFence; - - bool mIsSet; - - GLboolean mStatus; - GLenum mCondition; -}; - -class FenceSync : public RefCountObject -{ - public: - explicit FenceSync(rx::FenceSyncImpl *impl, GLuint id); - virtual ~FenceSync(); - - Error set(GLenum condition); - Error clientWait(GLbitfield flags, GLuint64 timeout, GLenum *outResult); - Error serverWait(GLbitfield flags, GLuint64 timeout); - Error getStatus(GLint *outResult) const; - - GLuint getCondition() const { return mCondition; } - - private: - DISALLOW_COPY_AND_ASSIGN(FenceSync); - - rx::FenceSyncImpl *mFence; - - GLenum mCondition; -}; - -} - -#endif // LIBGLESV2_FENCE_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/Float16ToFloat32.cpp b/src/3rdparty/angle/src/libGLESv2/Float16ToFloat32.cpp deleted file mode 100644 index 5bf7b3fce8..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/Float16ToFloat32.cpp +++ /dev/null @@ -1,2203 +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 is automatically generated. - -namespace gl -{ - -const static unsigned g_mantissa[2048] = { - 0x00000000, - 0x33800000, - 0x34000000, - 0x34400000, - 0x34800000, - 0x34a00000, - 0x34c00000, - 0x34e00000, - 0x35000000, - 0x35100000, - 0x35200000, - 0x35300000, - 0x35400000, - 0x35500000, - 0x35600000, - 0x35700000, - 0x35800000, - 0x35880000, - 0x35900000, - 0x35980000, - 0x35a00000, - 0x35a80000, - 0x35b00000, - 0x35b80000, - 0x35c00000, - 0x35c80000, - 0x35d00000, - 0x35d80000, - 0x35e00000, - 0x35e80000, - 0x35f00000, - 0x35f80000, - 0x36000000, - 0x36040000, - 0x36080000, - 0x360c0000, - 0x36100000, - 0x36140000, - 0x36180000, - 0x361c0000, - 0x36200000, - 0x36240000, - 0x36280000, - 0x362c0000, - 0x36300000, - 0x36340000, - 0x36380000, - 0x363c0000, - 0x36400000, - 0x36440000, - 0x36480000, - 0x364c0000, - 0x36500000, - 0x36540000, - 0x36580000, - 0x365c0000, - 0x36600000, - 0x36640000, - 0x36680000, - 0x366c0000, - 0x36700000, - 0x36740000, - 0x36780000, - 0x367c0000, - 0x36800000, - 0x36820000, - 0x36840000, - 0x36860000, - 0x36880000, - 0x368a0000, - 0x368c0000, - 0x368e0000, - 0x36900000, - 0x36920000, - 0x36940000, - 0x36960000, - 0x36980000, - 0x369a0000, - 0x369c0000, - 0x369e0000, - 0x36a00000, - 0x36a20000, - 0x36a40000, - 0x36a60000, - 0x36a80000, - 0x36aa0000, - 0x36ac0000, - 0x36ae0000, - 0x36b00000, - 0x36b20000, - 0x36b40000, - 0x36b60000, - 0x36b80000, - 0x36ba0000, - 0x36bc0000, - 0x36be0000, - 0x36c00000, - 0x36c20000, - 0x36c40000, - 0x36c60000, - 0x36c80000, - 0x36ca0000, - 0x36cc0000, - 0x36ce0000, - 0x36d00000, - 0x36d20000, - 0x36d40000, - 0x36d60000, - 0x36d80000, - 0x36da0000, - 0x36dc0000, - 0x36de0000, - 0x36e00000, - 0x36e20000, - 0x36e40000, - 0x36e60000, - 0x36e80000, - 0x36ea0000, - 0x36ec0000, - 0x36ee0000, - 0x36f00000, - 0x36f20000, - 0x36f40000, - 0x36f60000, - 0x36f80000, - 0x36fa0000, - 0x36fc0000, - 0x36fe0000, - 0x37000000, - 0x37010000, - 0x37020000, - 0x37030000, - 0x37040000, - 0x37050000, - 0x37060000, - 0x37070000, - 0x37080000, - 0x37090000, - 0x370a0000, - 0x370b0000, - 0x370c0000, - 0x370d0000, - 0x370e0000, - 0x370f0000, - 0x37100000, - 0x37110000, - 0x37120000, - 0x37130000, - 0x37140000, - 0x37150000, - 0x37160000, - 0x37170000, - 0x37180000, - 0x37190000, - 0x371a0000, - 0x371b0000, - 0x371c0000, - 0x371d0000, - 0x371e0000, - 0x371f0000, - 0x37200000, - 0x37210000, - 0x37220000, - 0x37230000, - 0x37240000, - 0x37250000, - 0x37260000, - 0x37270000, - 0x37280000, - 0x37290000, - 0x372a0000, - 0x372b0000, - 0x372c0000, - 0x372d0000, - 0x372e0000, - 0x372f0000, - 0x37300000, - 0x37310000, - 0x37320000, - 0x37330000, - 0x37340000, - 0x37350000, - 0x37360000, - 0x37370000, - 0x37380000, - 0x37390000, - 0x373a0000, - 0x373b0000, - 0x373c0000, - 0x373d0000, - 0x373e0000, - 0x373f0000, - 0x37400000, - 0x37410000, - 0x37420000, - 0x37430000, - 0x37440000, - 0x37450000, - 0x37460000, - 0x37470000, - 0x37480000, - 0x37490000, - 0x374a0000, - 0x374b0000, - 0x374c0000, - 0x374d0000, - 0x374e0000, - 0x374f0000, - 0x37500000, - 0x37510000, - 0x37520000, - 0x37530000, - 0x37540000, - 0x37550000, - 0x37560000, - 0x37570000, - 0x37580000, - 0x37590000, - 0x375a0000, - 0x375b0000, - 0x375c0000, - 0x375d0000, - 0x375e0000, - 0x375f0000, - 0x37600000, - 0x37610000, - 0x37620000, - 0x37630000, - 0x37640000, - 0x37650000, - 0x37660000, - 0x37670000, - 0x37680000, - 0x37690000, - 0x376a0000, - 0x376b0000, - 0x376c0000, - 0x376d0000, - 0x376e0000, - 0x376f0000, - 0x37700000, - 0x37710000, - 0x37720000, - 0x37730000, - 0x37740000, - 0x37750000, - 0x37760000, - 0x37770000, - 0x37780000, - 0x37790000, - 0x377a0000, - 0x377b0000, - 0x377c0000, - 0x377d0000, - 0x377e0000, - 0x377f0000, - 0x37800000, - 0x37808000, - 0x37810000, - 0x37818000, - 0x37820000, - 0x37828000, - 0x37830000, - 0x37838000, - 0x37840000, - 0x37848000, - 0x37850000, - 0x37858000, - 0x37860000, - 0x37868000, - 0x37870000, - 0x37878000, - 0x37880000, - 0x37888000, - 0x37890000, - 0x37898000, - 0x378a0000, - 0x378a8000, - 0x378b0000, - 0x378b8000, - 0x378c0000, - 0x378c8000, - 0x378d0000, - 0x378d8000, - 0x378e0000, - 0x378e8000, - 0x378f0000, - 0x378f8000, - 0x37900000, - 0x37908000, - 0x37910000, - 0x37918000, - 0x37920000, - 0x37928000, - 0x37930000, - 0x37938000, - 0x37940000, - 0x37948000, - 0x37950000, - 0x37958000, - 0x37960000, - 0x37968000, - 0x37970000, - 0x37978000, - 0x37980000, - 0x37988000, - 0x37990000, - 0x37998000, - 0x379a0000, - 0x379a8000, - 0x379b0000, - 0x379b8000, - 0x379c0000, - 0x379c8000, - 0x379d0000, - 0x379d8000, - 0x379e0000, - 0x379e8000, - 0x379f0000, - 0x379f8000, - 0x37a00000, - 0x37a08000, - 0x37a10000, - 0x37a18000, - 0x37a20000, - 0x37a28000, - 0x37a30000, - 0x37a38000, - 0x37a40000, - 0x37a48000, - 0x37a50000, - 0x37a58000, - 0x37a60000, - 0x37a68000, - 0x37a70000, - 0x37a78000, - 0x37a80000, - 0x37a88000, - 0x37a90000, - 0x37a98000, - 0x37aa0000, - 0x37aa8000, - 0x37ab0000, - 0x37ab8000, - 0x37ac0000, - 0x37ac8000, - 0x37ad0000, - 0x37ad8000, - 0x37ae0000, - 0x37ae8000, - 0x37af0000, - 0x37af8000, - 0x37b00000, - 0x37b08000, - 0x37b10000, - 0x37b18000, - 0x37b20000, - 0x37b28000, - 0x37b30000, - 0x37b38000, - 0x37b40000, - 0x37b48000, - 0x37b50000, - 0x37b58000, - 0x37b60000, - 0x37b68000, - 0x37b70000, - 0x37b78000, - 0x37b80000, - 0x37b88000, - 0x37b90000, - 0x37b98000, - 0x37ba0000, - 0x37ba8000, - 0x37bb0000, - 0x37bb8000, - 0x37bc0000, - 0x37bc8000, - 0x37bd0000, - 0x37bd8000, - 0x37be0000, - 0x37be8000, - 0x37bf0000, - 0x37bf8000, - 0x37c00000, - 0x37c08000, - 0x37c10000, - 0x37c18000, - 0x37c20000, - 0x37c28000, - 0x37c30000, - 0x37c38000, - 0x37c40000, - 0x37c48000, - 0x37c50000, - 0x37c58000, - 0x37c60000, - 0x37c68000, - 0x37c70000, - 0x37c78000, - 0x37c80000, - 0x37c88000, - 0x37c90000, - 0x37c98000, - 0x37ca0000, - 0x37ca8000, - 0x37cb0000, - 0x37cb8000, - 0x37cc0000, - 0x37cc8000, - 0x37cd0000, - 0x37cd8000, - 0x37ce0000, - 0x37ce8000, - 0x37cf0000, - 0x37cf8000, - 0x37d00000, - 0x37d08000, - 0x37d10000, - 0x37d18000, - 0x37d20000, - 0x37d28000, - 0x37d30000, - 0x37d38000, - 0x37d40000, - 0x37d48000, - 0x37d50000, - 0x37d58000, - 0x37d60000, - 0x37d68000, - 0x37d70000, - 0x37d78000, - 0x37d80000, - 0x37d88000, - 0x37d90000, - 0x37d98000, - 0x37da0000, - 0x37da8000, - 0x37db0000, - 0x37db8000, - 0x37dc0000, - 0x37dc8000, - 0x37dd0000, - 0x37dd8000, - 0x37de0000, - 0x37de8000, - 0x37df0000, - 0x37df8000, - 0x37e00000, - 0x37e08000, - 0x37e10000, - 0x37e18000, - 0x37e20000, - 0x37e28000, - 0x37e30000, - 0x37e38000, - 0x37e40000, - 0x37e48000, - 0x37e50000, - 0x37e58000, - 0x37e60000, - 0x37e68000, - 0x37e70000, - 0x37e78000, - 0x37e80000, - 0x37e88000, - 0x37e90000, - 0x37e98000, - 0x37ea0000, - 0x37ea8000, - 0x37eb0000, - 0x37eb8000, - 0x37ec0000, - 0x37ec8000, - 0x37ed0000, - 0x37ed8000, - 0x37ee0000, - 0x37ee8000, - 0x37ef0000, - 0x37ef8000, - 0x37f00000, - 0x37f08000, - 0x37f10000, - 0x37f18000, - 0x37f20000, - 0x37f28000, - 0x37f30000, - 0x37f38000, - 0x37f40000, - 0x37f48000, - 0x37f50000, - 0x37f58000, - 0x37f60000, - 0x37f68000, - 0x37f70000, - 0x37f78000, - 0x37f80000, - 0x37f88000, - 0x37f90000, - 0x37f98000, - 0x37fa0000, - 0x37fa8000, - 0x37fb0000, - 0x37fb8000, - 0x37fc0000, - 0x37fc8000, - 0x37fd0000, - 0x37fd8000, - 0x37fe0000, - 0x37fe8000, - 0x37ff0000, - 0x37ff8000, - 0x38000000, - 0x38004000, - 0x38008000, - 0x3800c000, - 0x38010000, - 0x38014000, - 0x38018000, - 0x3801c000, - 0x38020000, - 0x38024000, - 0x38028000, - 0x3802c000, - 0x38030000, - 0x38034000, - 0x38038000, - 0x3803c000, - 0x38040000, - 0x38044000, - 0x38048000, - 0x3804c000, - 0x38050000, - 0x38054000, - 0x38058000, - 0x3805c000, - 0x38060000, - 0x38064000, - 0x38068000, - 0x3806c000, - 0x38070000, - 0x38074000, - 0x38078000, - 0x3807c000, - 0x38080000, - 0x38084000, - 0x38088000, - 0x3808c000, - 0x38090000, - 0x38094000, - 0x38098000, - 0x3809c000, - 0x380a0000, - 0x380a4000, - 0x380a8000, - 0x380ac000, - 0x380b0000, - 0x380b4000, - 0x380b8000, - 0x380bc000, - 0x380c0000, - 0x380c4000, - 0x380c8000, - 0x380cc000, - 0x380d0000, - 0x380d4000, - 0x380d8000, - 0x380dc000, - 0x380e0000, - 0x380e4000, - 0x380e8000, - 0x380ec000, - 0x380f0000, - 0x380f4000, - 0x380f8000, - 0x380fc000, - 0x38100000, - 0x38104000, - 0x38108000, - 0x3810c000, - 0x38110000, - 0x38114000, - 0x38118000, - 0x3811c000, - 0x38120000, - 0x38124000, - 0x38128000, - 0x3812c000, - 0x38130000, - 0x38134000, - 0x38138000, - 0x3813c000, - 0x38140000, - 0x38144000, - 0x38148000, - 0x3814c000, - 0x38150000, - 0x38154000, - 0x38158000, - 0x3815c000, - 0x38160000, - 0x38164000, - 0x38168000, - 0x3816c000, - 0x38170000, - 0x38174000, - 0x38178000, - 0x3817c000, - 0x38180000, - 0x38184000, - 0x38188000, - 0x3818c000, - 0x38190000, - 0x38194000, - 0x38198000, - 0x3819c000, - 0x381a0000, - 0x381a4000, - 0x381a8000, - 0x381ac000, - 0x381b0000, - 0x381b4000, - 0x381b8000, - 0x381bc000, - 0x381c0000, - 0x381c4000, - 0x381c8000, - 0x381cc000, - 0x381d0000, - 0x381d4000, - 0x381d8000, - 0x381dc000, - 0x381e0000, - 0x381e4000, - 0x381e8000, - 0x381ec000, - 0x381f0000, - 0x381f4000, - 0x381f8000, - 0x381fc000, - 0x38200000, - 0x38204000, - 0x38208000, - 0x3820c000, - 0x38210000, - 0x38214000, - 0x38218000, - 0x3821c000, - 0x38220000, - 0x38224000, - 0x38228000, - 0x3822c000, - 0x38230000, - 0x38234000, - 0x38238000, - 0x3823c000, - 0x38240000, - 0x38244000, - 0x38248000, - 0x3824c000, - 0x38250000, - 0x38254000, - 0x38258000, - 0x3825c000, - 0x38260000, - 0x38264000, - 0x38268000, - 0x3826c000, - 0x38270000, - 0x38274000, - 0x38278000, - 0x3827c000, - 0x38280000, - 0x38284000, - 0x38288000, - 0x3828c000, - 0x38290000, - 0x38294000, - 0x38298000, - 0x3829c000, - 0x382a0000, - 0x382a4000, - 0x382a8000, - 0x382ac000, - 0x382b0000, - 0x382b4000, - 0x382b8000, - 0x382bc000, - 0x382c0000, - 0x382c4000, - 0x382c8000, - 0x382cc000, - 0x382d0000, - 0x382d4000, - 0x382d8000, - 0x382dc000, - 0x382e0000, - 0x382e4000, - 0x382e8000, - 0x382ec000, - 0x382f0000, - 0x382f4000, - 0x382f8000, - 0x382fc000, - 0x38300000, - 0x38304000, - 0x38308000, - 0x3830c000, - 0x38310000, - 0x38314000, - 0x38318000, - 0x3831c000, - 0x38320000, - 0x38324000, - 0x38328000, - 0x3832c000, - 0x38330000, - 0x38334000, - 0x38338000, - 0x3833c000, - 0x38340000, - 0x38344000, - 0x38348000, - 0x3834c000, - 0x38350000, - 0x38354000, - 0x38358000, - 0x3835c000, - 0x38360000, - 0x38364000, - 0x38368000, - 0x3836c000, - 0x38370000, - 0x38374000, - 0x38378000, - 0x3837c000, - 0x38380000, - 0x38384000, - 0x38388000, - 0x3838c000, - 0x38390000, - 0x38394000, - 0x38398000, - 0x3839c000, - 0x383a0000, - 0x383a4000, - 0x383a8000, - 0x383ac000, - 0x383b0000, - 0x383b4000, - 0x383b8000, - 0x383bc000, - 0x383c0000, - 0x383c4000, - 0x383c8000, - 0x383cc000, - 0x383d0000, - 0x383d4000, - 0x383d8000, - 0x383dc000, - 0x383e0000, - 0x383e4000, - 0x383e8000, - 0x383ec000, - 0x383f0000, - 0x383f4000, - 0x383f8000, - 0x383fc000, - 0x38400000, - 0x38404000, - 0x38408000, - 0x3840c000, - 0x38410000, - 0x38414000, - 0x38418000, - 0x3841c000, - 0x38420000, - 0x38424000, - 0x38428000, - 0x3842c000, - 0x38430000, - 0x38434000, - 0x38438000, - 0x3843c000, - 0x38440000, - 0x38444000, - 0x38448000, - 0x3844c000, - 0x38450000, - 0x38454000, - 0x38458000, - 0x3845c000, - 0x38460000, - 0x38464000, - 0x38468000, - 0x3846c000, - 0x38470000, - 0x38474000, - 0x38478000, - 0x3847c000, - 0x38480000, - 0x38484000, - 0x38488000, - 0x3848c000, - 0x38490000, - 0x38494000, - 0x38498000, - 0x3849c000, - 0x384a0000, - 0x384a4000, - 0x384a8000, - 0x384ac000, - 0x384b0000, - 0x384b4000, - 0x384b8000, - 0x384bc000, - 0x384c0000, - 0x384c4000, - 0x384c8000, - 0x384cc000, - 0x384d0000, - 0x384d4000, - 0x384d8000, - 0x384dc000, - 0x384e0000, - 0x384e4000, - 0x384e8000, - 0x384ec000, - 0x384f0000, - 0x384f4000, - 0x384f8000, - 0x384fc000, - 0x38500000, - 0x38504000, - 0x38508000, - 0x3850c000, - 0x38510000, - 0x38514000, - 0x38518000, - 0x3851c000, - 0x38520000, - 0x38524000, - 0x38528000, - 0x3852c000, - 0x38530000, - 0x38534000, - 0x38538000, - 0x3853c000, - 0x38540000, - 0x38544000, - 0x38548000, - 0x3854c000, - 0x38550000, - 0x38554000, - 0x38558000, - 0x3855c000, - 0x38560000, - 0x38564000, - 0x38568000, - 0x3856c000, - 0x38570000, - 0x38574000, - 0x38578000, - 0x3857c000, - 0x38580000, - 0x38584000, - 0x38588000, - 0x3858c000, - 0x38590000, - 0x38594000, - 0x38598000, - 0x3859c000, - 0x385a0000, - 0x385a4000, - 0x385a8000, - 0x385ac000, - 0x385b0000, - 0x385b4000, - 0x385b8000, - 0x385bc000, - 0x385c0000, - 0x385c4000, - 0x385c8000, - 0x385cc000, - 0x385d0000, - 0x385d4000, - 0x385d8000, - 0x385dc000, - 0x385e0000, - 0x385e4000, - 0x385e8000, - 0x385ec000, - 0x385f0000, - 0x385f4000, - 0x385f8000, - 0x385fc000, - 0x38600000, - 0x38604000, - 0x38608000, - 0x3860c000, - 0x38610000, - 0x38614000, - 0x38618000, - 0x3861c000, - 0x38620000, - 0x38624000, - 0x38628000, - 0x3862c000, - 0x38630000, - 0x38634000, - 0x38638000, - 0x3863c000, - 0x38640000, - 0x38644000, - 0x38648000, - 0x3864c000, - 0x38650000, - 0x38654000, - 0x38658000, - 0x3865c000, - 0x38660000, - 0x38664000, - 0x38668000, - 0x3866c000, - 0x38670000, - 0x38674000, - 0x38678000, - 0x3867c000, - 0x38680000, - 0x38684000, - 0x38688000, - 0x3868c000, - 0x38690000, - 0x38694000, - 0x38698000, - 0x3869c000, - 0x386a0000, - 0x386a4000, - 0x386a8000, - 0x386ac000, - 0x386b0000, - 0x386b4000, - 0x386b8000, - 0x386bc000, - 0x386c0000, - 0x386c4000, - 0x386c8000, - 0x386cc000, - 0x386d0000, - 0x386d4000, - 0x386d8000, - 0x386dc000, - 0x386e0000, - 0x386e4000, - 0x386e8000, - 0x386ec000, - 0x386f0000, - 0x386f4000, - 0x386f8000, - 0x386fc000, - 0x38700000, - 0x38704000, - 0x38708000, - 0x3870c000, - 0x38710000, - 0x38714000, - 0x38718000, - 0x3871c000, - 0x38720000, - 0x38724000, - 0x38728000, - 0x3872c000, - 0x38730000, - 0x38734000, - 0x38738000, - 0x3873c000, - 0x38740000, - 0x38744000, - 0x38748000, - 0x3874c000, - 0x38750000, - 0x38754000, - 0x38758000, - 0x3875c000, - 0x38760000, - 0x38764000, - 0x38768000, - 0x3876c000, - 0x38770000, - 0x38774000, - 0x38778000, - 0x3877c000, - 0x38780000, - 0x38784000, - 0x38788000, - 0x3878c000, - 0x38790000, - 0x38794000, - 0x38798000, - 0x3879c000, - 0x387a0000, - 0x387a4000, - 0x387a8000, - 0x387ac000, - 0x387b0000, - 0x387b4000, - 0x387b8000, - 0x387bc000, - 0x387c0000, - 0x387c4000, - 0x387c8000, - 0x387cc000, - 0x387d0000, - 0x387d4000, - 0x387d8000, - 0x387dc000, - 0x387e0000, - 0x387e4000, - 0x387e8000, - 0x387ec000, - 0x387f0000, - 0x387f4000, - 0x387f8000, - 0x387fc000, - 0x38000000, - 0x38002000, - 0x38004000, - 0x38006000, - 0x38008000, - 0x3800a000, - 0x3800c000, - 0x3800e000, - 0x38010000, - 0x38012000, - 0x38014000, - 0x38016000, - 0x38018000, - 0x3801a000, - 0x3801c000, - 0x3801e000, - 0x38020000, - 0x38022000, - 0x38024000, - 0x38026000, - 0x38028000, - 0x3802a000, - 0x3802c000, - 0x3802e000, - 0x38030000, - 0x38032000, - 0x38034000, - 0x38036000, - 0x38038000, - 0x3803a000, - 0x3803c000, - 0x3803e000, - 0x38040000, - 0x38042000, - 0x38044000, - 0x38046000, - 0x38048000, - 0x3804a000, - 0x3804c000, - 0x3804e000, - 0x38050000, - 0x38052000, - 0x38054000, - 0x38056000, - 0x38058000, - 0x3805a000, - 0x3805c000, - 0x3805e000, - 0x38060000, - 0x38062000, - 0x38064000, - 0x38066000, - 0x38068000, - 0x3806a000, - 0x3806c000, - 0x3806e000, - 0x38070000, - 0x38072000, - 0x38074000, - 0x38076000, - 0x38078000, - 0x3807a000, - 0x3807c000, - 0x3807e000, - 0x38080000, - 0x38082000, - 0x38084000, - 0x38086000, - 0x38088000, - 0x3808a000, - 0x3808c000, - 0x3808e000, - 0x38090000, - 0x38092000, - 0x38094000, - 0x38096000, - 0x38098000, - 0x3809a000, - 0x3809c000, - 0x3809e000, - 0x380a0000, - 0x380a2000, - 0x380a4000, - 0x380a6000, - 0x380a8000, - 0x380aa000, - 0x380ac000, - 0x380ae000, - 0x380b0000, - 0x380b2000, - 0x380b4000, - 0x380b6000, - 0x380b8000, - 0x380ba000, - 0x380bc000, - 0x380be000, - 0x380c0000, - 0x380c2000, - 0x380c4000, - 0x380c6000, - 0x380c8000, - 0x380ca000, - 0x380cc000, - 0x380ce000, - 0x380d0000, - 0x380d2000, - 0x380d4000, - 0x380d6000, - 0x380d8000, - 0x380da000, - 0x380dc000, - 0x380de000, - 0x380e0000, - 0x380e2000, - 0x380e4000, - 0x380e6000, - 0x380e8000, - 0x380ea000, - 0x380ec000, - 0x380ee000, - 0x380f0000, - 0x380f2000, - 0x380f4000, - 0x380f6000, - 0x380f8000, - 0x380fa000, - 0x380fc000, - 0x380fe000, - 0x38100000, - 0x38102000, - 0x38104000, - 0x38106000, - 0x38108000, - 0x3810a000, - 0x3810c000, - 0x3810e000, - 0x38110000, - 0x38112000, - 0x38114000, - 0x38116000, - 0x38118000, - 0x3811a000, - 0x3811c000, - 0x3811e000, - 0x38120000, - 0x38122000, - 0x38124000, - 0x38126000, - 0x38128000, - 0x3812a000, - 0x3812c000, - 0x3812e000, - 0x38130000, - 0x38132000, - 0x38134000, - 0x38136000, - 0x38138000, - 0x3813a000, - 0x3813c000, - 0x3813e000, - 0x38140000, - 0x38142000, - 0x38144000, - 0x38146000, - 0x38148000, - 0x3814a000, - 0x3814c000, - 0x3814e000, - 0x38150000, - 0x38152000, - 0x38154000, - 0x38156000, - 0x38158000, - 0x3815a000, - 0x3815c000, - 0x3815e000, - 0x38160000, - 0x38162000, - 0x38164000, - 0x38166000, - 0x38168000, - 0x3816a000, - 0x3816c000, - 0x3816e000, - 0x38170000, - 0x38172000, - 0x38174000, - 0x38176000, - 0x38178000, - 0x3817a000, - 0x3817c000, - 0x3817e000, - 0x38180000, - 0x38182000, - 0x38184000, - 0x38186000, - 0x38188000, - 0x3818a000, - 0x3818c000, - 0x3818e000, - 0x38190000, - 0x38192000, - 0x38194000, - 0x38196000, - 0x38198000, - 0x3819a000, - 0x3819c000, - 0x3819e000, - 0x381a0000, - 0x381a2000, - 0x381a4000, - 0x381a6000, - 0x381a8000, - 0x381aa000, - 0x381ac000, - 0x381ae000, - 0x381b0000, - 0x381b2000, - 0x381b4000, - 0x381b6000, - 0x381b8000, - 0x381ba000, - 0x381bc000, - 0x381be000, - 0x381c0000, - 0x381c2000, - 0x381c4000, - 0x381c6000, - 0x381c8000, - 0x381ca000, - 0x381cc000, - 0x381ce000, - 0x381d0000, - 0x381d2000, - 0x381d4000, - 0x381d6000, - 0x381d8000, - 0x381da000, - 0x381dc000, - 0x381de000, - 0x381e0000, - 0x381e2000, - 0x381e4000, - 0x381e6000, - 0x381e8000, - 0x381ea000, - 0x381ec000, - 0x381ee000, - 0x381f0000, - 0x381f2000, - 0x381f4000, - 0x381f6000, - 0x381f8000, - 0x381fa000, - 0x381fc000, - 0x381fe000, - 0x38200000, - 0x38202000, - 0x38204000, - 0x38206000, - 0x38208000, - 0x3820a000, - 0x3820c000, - 0x3820e000, - 0x38210000, - 0x38212000, - 0x38214000, - 0x38216000, - 0x38218000, - 0x3821a000, - 0x3821c000, - 0x3821e000, - 0x38220000, - 0x38222000, - 0x38224000, - 0x38226000, - 0x38228000, - 0x3822a000, - 0x3822c000, - 0x3822e000, - 0x38230000, - 0x38232000, - 0x38234000, - 0x38236000, - 0x38238000, - 0x3823a000, - 0x3823c000, - 0x3823e000, - 0x38240000, - 0x38242000, - 0x38244000, - 0x38246000, - 0x38248000, - 0x3824a000, - 0x3824c000, - 0x3824e000, - 0x38250000, - 0x38252000, - 0x38254000, - 0x38256000, - 0x38258000, - 0x3825a000, - 0x3825c000, - 0x3825e000, - 0x38260000, - 0x38262000, - 0x38264000, - 0x38266000, - 0x38268000, - 0x3826a000, - 0x3826c000, - 0x3826e000, - 0x38270000, - 0x38272000, - 0x38274000, - 0x38276000, - 0x38278000, - 0x3827a000, - 0x3827c000, - 0x3827e000, - 0x38280000, - 0x38282000, - 0x38284000, - 0x38286000, - 0x38288000, - 0x3828a000, - 0x3828c000, - 0x3828e000, - 0x38290000, - 0x38292000, - 0x38294000, - 0x38296000, - 0x38298000, - 0x3829a000, - 0x3829c000, - 0x3829e000, - 0x382a0000, - 0x382a2000, - 0x382a4000, - 0x382a6000, - 0x382a8000, - 0x382aa000, - 0x382ac000, - 0x382ae000, - 0x382b0000, - 0x382b2000, - 0x382b4000, - 0x382b6000, - 0x382b8000, - 0x382ba000, - 0x382bc000, - 0x382be000, - 0x382c0000, - 0x382c2000, - 0x382c4000, - 0x382c6000, - 0x382c8000, - 0x382ca000, - 0x382cc000, - 0x382ce000, - 0x382d0000, - 0x382d2000, - 0x382d4000, - 0x382d6000, - 0x382d8000, - 0x382da000, - 0x382dc000, - 0x382de000, - 0x382e0000, - 0x382e2000, - 0x382e4000, - 0x382e6000, - 0x382e8000, - 0x382ea000, - 0x382ec000, - 0x382ee000, - 0x382f0000, - 0x382f2000, - 0x382f4000, - 0x382f6000, - 0x382f8000, - 0x382fa000, - 0x382fc000, - 0x382fe000, - 0x38300000, - 0x38302000, - 0x38304000, - 0x38306000, - 0x38308000, - 0x3830a000, - 0x3830c000, - 0x3830e000, - 0x38310000, - 0x38312000, - 0x38314000, - 0x38316000, - 0x38318000, - 0x3831a000, - 0x3831c000, - 0x3831e000, - 0x38320000, - 0x38322000, - 0x38324000, - 0x38326000, - 0x38328000, - 0x3832a000, - 0x3832c000, - 0x3832e000, - 0x38330000, - 0x38332000, - 0x38334000, - 0x38336000, - 0x38338000, - 0x3833a000, - 0x3833c000, - 0x3833e000, - 0x38340000, - 0x38342000, - 0x38344000, - 0x38346000, - 0x38348000, - 0x3834a000, - 0x3834c000, - 0x3834e000, - 0x38350000, - 0x38352000, - 0x38354000, - 0x38356000, - 0x38358000, - 0x3835a000, - 0x3835c000, - 0x3835e000, - 0x38360000, - 0x38362000, - 0x38364000, - 0x38366000, - 0x38368000, - 0x3836a000, - 0x3836c000, - 0x3836e000, - 0x38370000, - 0x38372000, - 0x38374000, - 0x38376000, - 0x38378000, - 0x3837a000, - 0x3837c000, - 0x3837e000, - 0x38380000, - 0x38382000, - 0x38384000, - 0x38386000, - 0x38388000, - 0x3838a000, - 0x3838c000, - 0x3838e000, - 0x38390000, - 0x38392000, - 0x38394000, - 0x38396000, - 0x38398000, - 0x3839a000, - 0x3839c000, - 0x3839e000, - 0x383a0000, - 0x383a2000, - 0x383a4000, - 0x383a6000, - 0x383a8000, - 0x383aa000, - 0x383ac000, - 0x383ae000, - 0x383b0000, - 0x383b2000, - 0x383b4000, - 0x383b6000, - 0x383b8000, - 0x383ba000, - 0x383bc000, - 0x383be000, - 0x383c0000, - 0x383c2000, - 0x383c4000, - 0x383c6000, - 0x383c8000, - 0x383ca000, - 0x383cc000, - 0x383ce000, - 0x383d0000, - 0x383d2000, - 0x383d4000, - 0x383d6000, - 0x383d8000, - 0x383da000, - 0x383dc000, - 0x383de000, - 0x383e0000, - 0x383e2000, - 0x383e4000, - 0x383e6000, - 0x383e8000, - 0x383ea000, - 0x383ec000, - 0x383ee000, - 0x383f0000, - 0x383f2000, - 0x383f4000, - 0x383f6000, - 0x383f8000, - 0x383fa000, - 0x383fc000, - 0x383fe000, - 0x38400000, - 0x38402000, - 0x38404000, - 0x38406000, - 0x38408000, - 0x3840a000, - 0x3840c000, - 0x3840e000, - 0x38410000, - 0x38412000, - 0x38414000, - 0x38416000, - 0x38418000, - 0x3841a000, - 0x3841c000, - 0x3841e000, - 0x38420000, - 0x38422000, - 0x38424000, - 0x38426000, - 0x38428000, - 0x3842a000, - 0x3842c000, - 0x3842e000, - 0x38430000, - 0x38432000, - 0x38434000, - 0x38436000, - 0x38438000, - 0x3843a000, - 0x3843c000, - 0x3843e000, - 0x38440000, - 0x38442000, - 0x38444000, - 0x38446000, - 0x38448000, - 0x3844a000, - 0x3844c000, - 0x3844e000, - 0x38450000, - 0x38452000, - 0x38454000, - 0x38456000, - 0x38458000, - 0x3845a000, - 0x3845c000, - 0x3845e000, - 0x38460000, - 0x38462000, - 0x38464000, - 0x38466000, - 0x38468000, - 0x3846a000, - 0x3846c000, - 0x3846e000, - 0x38470000, - 0x38472000, - 0x38474000, - 0x38476000, - 0x38478000, - 0x3847a000, - 0x3847c000, - 0x3847e000, - 0x38480000, - 0x38482000, - 0x38484000, - 0x38486000, - 0x38488000, - 0x3848a000, - 0x3848c000, - 0x3848e000, - 0x38490000, - 0x38492000, - 0x38494000, - 0x38496000, - 0x38498000, - 0x3849a000, - 0x3849c000, - 0x3849e000, - 0x384a0000, - 0x384a2000, - 0x384a4000, - 0x384a6000, - 0x384a8000, - 0x384aa000, - 0x384ac000, - 0x384ae000, - 0x384b0000, - 0x384b2000, - 0x384b4000, - 0x384b6000, - 0x384b8000, - 0x384ba000, - 0x384bc000, - 0x384be000, - 0x384c0000, - 0x384c2000, - 0x384c4000, - 0x384c6000, - 0x384c8000, - 0x384ca000, - 0x384cc000, - 0x384ce000, - 0x384d0000, - 0x384d2000, - 0x384d4000, - 0x384d6000, - 0x384d8000, - 0x384da000, - 0x384dc000, - 0x384de000, - 0x384e0000, - 0x384e2000, - 0x384e4000, - 0x384e6000, - 0x384e8000, - 0x384ea000, - 0x384ec000, - 0x384ee000, - 0x384f0000, - 0x384f2000, - 0x384f4000, - 0x384f6000, - 0x384f8000, - 0x384fa000, - 0x384fc000, - 0x384fe000, - 0x38500000, - 0x38502000, - 0x38504000, - 0x38506000, - 0x38508000, - 0x3850a000, - 0x3850c000, - 0x3850e000, - 0x38510000, - 0x38512000, - 0x38514000, - 0x38516000, - 0x38518000, - 0x3851a000, - 0x3851c000, - 0x3851e000, - 0x38520000, - 0x38522000, - 0x38524000, - 0x38526000, - 0x38528000, - 0x3852a000, - 0x3852c000, - 0x3852e000, - 0x38530000, - 0x38532000, - 0x38534000, - 0x38536000, - 0x38538000, - 0x3853a000, - 0x3853c000, - 0x3853e000, - 0x38540000, - 0x38542000, - 0x38544000, - 0x38546000, - 0x38548000, - 0x3854a000, - 0x3854c000, - 0x3854e000, - 0x38550000, - 0x38552000, - 0x38554000, - 0x38556000, - 0x38558000, - 0x3855a000, - 0x3855c000, - 0x3855e000, - 0x38560000, - 0x38562000, - 0x38564000, - 0x38566000, - 0x38568000, - 0x3856a000, - 0x3856c000, - 0x3856e000, - 0x38570000, - 0x38572000, - 0x38574000, - 0x38576000, - 0x38578000, - 0x3857a000, - 0x3857c000, - 0x3857e000, - 0x38580000, - 0x38582000, - 0x38584000, - 0x38586000, - 0x38588000, - 0x3858a000, - 0x3858c000, - 0x3858e000, - 0x38590000, - 0x38592000, - 0x38594000, - 0x38596000, - 0x38598000, - 0x3859a000, - 0x3859c000, - 0x3859e000, - 0x385a0000, - 0x385a2000, - 0x385a4000, - 0x385a6000, - 0x385a8000, - 0x385aa000, - 0x385ac000, - 0x385ae000, - 0x385b0000, - 0x385b2000, - 0x385b4000, - 0x385b6000, - 0x385b8000, - 0x385ba000, - 0x385bc000, - 0x385be000, - 0x385c0000, - 0x385c2000, - 0x385c4000, - 0x385c6000, - 0x385c8000, - 0x385ca000, - 0x385cc000, - 0x385ce000, - 0x385d0000, - 0x385d2000, - 0x385d4000, - 0x385d6000, - 0x385d8000, - 0x385da000, - 0x385dc000, - 0x385de000, - 0x385e0000, - 0x385e2000, - 0x385e4000, - 0x385e6000, - 0x385e8000, - 0x385ea000, - 0x385ec000, - 0x385ee000, - 0x385f0000, - 0x385f2000, - 0x385f4000, - 0x385f6000, - 0x385f8000, - 0x385fa000, - 0x385fc000, - 0x385fe000, - 0x38600000, - 0x38602000, - 0x38604000, - 0x38606000, - 0x38608000, - 0x3860a000, - 0x3860c000, - 0x3860e000, - 0x38610000, - 0x38612000, - 0x38614000, - 0x38616000, - 0x38618000, - 0x3861a000, - 0x3861c000, - 0x3861e000, - 0x38620000, - 0x38622000, - 0x38624000, - 0x38626000, - 0x38628000, - 0x3862a000, - 0x3862c000, - 0x3862e000, - 0x38630000, - 0x38632000, - 0x38634000, - 0x38636000, - 0x38638000, - 0x3863a000, - 0x3863c000, - 0x3863e000, - 0x38640000, - 0x38642000, - 0x38644000, - 0x38646000, - 0x38648000, - 0x3864a000, - 0x3864c000, - 0x3864e000, - 0x38650000, - 0x38652000, - 0x38654000, - 0x38656000, - 0x38658000, - 0x3865a000, - 0x3865c000, - 0x3865e000, - 0x38660000, - 0x38662000, - 0x38664000, - 0x38666000, - 0x38668000, - 0x3866a000, - 0x3866c000, - 0x3866e000, - 0x38670000, - 0x38672000, - 0x38674000, - 0x38676000, - 0x38678000, - 0x3867a000, - 0x3867c000, - 0x3867e000, - 0x38680000, - 0x38682000, - 0x38684000, - 0x38686000, - 0x38688000, - 0x3868a000, - 0x3868c000, - 0x3868e000, - 0x38690000, - 0x38692000, - 0x38694000, - 0x38696000, - 0x38698000, - 0x3869a000, - 0x3869c000, - 0x3869e000, - 0x386a0000, - 0x386a2000, - 0x386a4000, - 0x386a6000, - 0x386a8000, - 0x386aa000, - 0x386ac000, - 0x386ae000, - 0x386b0000, - 0x386b2000, - 0x386b4000, - 0x386b6000, - 0x386b8000, - 0x386ba000, - 0x386bc000, - 0x386be000, - 0x386c0000, - 0x386c2000, - 0x386c4000, - 0x386c6000, - 0x386c8000, - 0x386ca000, - 0x386cc000, - 0x386ce000, - 0x386d0000, - 0x386d2000, - 0x386d4000, - 0x386d6000, - 0x386d8000, - 0x386da000, - 0x386dc000, - 0x386de000, - 0x386e0000, - 0x386e2000, - 0x386e4000, - 0x386e6000, - 0x386e8000, - 0x386ea000, - 0x386ec000, - 0x386ee000, - 0x386f0000, - 0x386f2000, - 0x386f4000, - 0x386f6000, - 0x386f8000, - 0x386fa000, - 0x386fc000, - 0x386fe000, - 0x38700000, - 0x38702000, - 0x38704000, - 0x38706000, - 0x38708000, - 0x3870a000, - 0x3870c000, - 0x3870e000, - 0x38710000, - 0x38712000, - 0x38714000, - 0x38716000, - 0x38718000, - 0x3871a000, - 0x3871c000, - 0x3871e000, - 0x38720000, - 0x38722000, - 0x38724000, - 0x38726000, - 0x38728000, - 0x3872a000, - 0x3872c000, - 0x3872e000, - 0x38730000, - 0x38732000, - 0x38734000, - 0x38736000, - 0x38738000, - 0x3873a000, - 0x3873c000, - 0x3873e000, - 0x38740000, - 0x38742000, - 0x38744000, - 0x38746000, - 0x38748000, - 0x3874a000, - 0x3874c000, - 0x3874e000, - 0x38750000, - 0x38752000, - 0x38754000, - 0x38756000, - 0x38758000, - 0x3875a000, - 0x3875c000, - 0x3875e000, - 0x38760000, - 0x38762000, - 0x38764000, - 0x38766000, - 0x38768000, - 0x3876a000, - 0x3876c000, - 0x3876e000, - 0x38770000, - 0x38772000, - 0x38774000, - 0x38776000, - 0x38778000, - 0x3877a000, - 0x3877c000, - 0x3877e000, - 0x38780000, - 0x38782000, - 0x38784000, - 0x38786000, - 0x38788000, - 0x3878a000, - 0x3878c000, - 0x3878e000, - 0x38790000, - 0x38792000, - 0x38794000, - 0x38796000, - 0x38798000, - 0x3879a000, - 0x3879c000, - 0x3879e000, - 0x387a0000, - 0x387a2000, - 0x387a4000, - 0x387a6000, - 0x387a8000, - 0x387aa000, - 0x387ac000, - 0x387ae000, - 0x387b0000, - 0x387b2000, - 0x387b4000, - 0x387b6000, - 0x387b8000, - 0x387ba000, - 0x387bc000, - 0x387be000, - 0x387c0000, - 0x387c2000, - 0x387c4000, - 0x387c6000, - 0x387c8000, - 0x387ca000, - 0x387cc000, - 0x387ce000, - 0x387d0000, - 0x387d2000, - 0x387d4000, - 0x387d6000, - 0x387d8000, - 0x387da000, - 0x387dc000, - 0x387de000, - 0x387e0000, - 0x387e2000, - 0x387e4000, - 0x387e6000, - 0x387e8000, - 0x387ea000, - 0x387ec000, - 0x387ee000, - 0x387f0000, - 0x387f2000, - 0x387f4000, - 0x387f6000, - 0x387f8000, - 0x387fa000, - 0x387fc000, - 0x387fe000, -}; - -const static unsigned g_exponent[64] = { - 0x00000000, - 0x00800000, - 0x01000000, - 0x01800000, - 0x02000000, - 0x02800000, - 0x03000000, - 0x03800000, - 0x04000000, - 0x04800000, - 0x05000000, - 0x05800000, - 0x06000000, - 0x06800000, - 0x07000000, - 0x07800000, - 0x08000000, - 0x08800000, - 0x09000000, - 0x09800000, - 0x0a000000, - 0x0a800000, - 0x0b000000, - 0x0b800000, - 0x0c000000, - 0x0c800000, - 0x0d000000, - 0x0d800000, - 0x0e000000, - 0x0e800000, - 0x0f000000, - 0x47800000, - 0x80000000, - 0x80800000, - 0x81000000, - 0x81800000, - 0x82000000, - 0x82800000, - 0x83000000, - 0x83800000, - 0x84000000, - 0x84800000, - 0x85000000, - 0x85800000, - 0x86000000, - 0x86800000, - 0x87000000, - 0x87800000, - 0x88000000, - 0x88800000, - 0x89000000, - 0x89800000, - 0x8a000000, - 0x8a800000, - 0x8b000000, - 0x8b800000, - 0x8c000000, - 0x8c800000, - 0x8d000000, - 0x8d800000, - 0x8e000000, - 0x8e800000, - 0x8f000000, - 0xc7800000, -}; - -const static unsigned g_offset[64] = { - 0x00000000, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000000, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, -}; - -float float16ToFloat32(unsigned short h) -{ - 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/Float16ToFloat32.py b/src/3rdparty/angle/src/libGLESv2/Float16ToFloat32.py deleted file mode 100644 index cf039bfc21..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/Float16ToFloat32.py +++ /dev/null @@ -1,78 +0,0 @@ -# Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -# - -# This script generates a function that converts 16-bit precision floating -# point numbers to 32-bit. -# It is based on ftp://ftp.fox-toolkit.org/pub/fasthalffloatconversion.pdf. - -def convertMantissa(i): - if i == 0: - return 0 - elif i < 1024: - m = i << 13 - e = 0 - while not (m & 0x00800000): - e -= 0x00800000 - m = m << 1 - m &= ~0x00800000 - e += 0x38800000 - return m | e - else: - return 0x38000000 + ((i - 1024) << 13) - -def convertExponent(i): - if i == 0: - return 0 - elif i in range(1, 31): - return i << 23 - elif i == 31: - return 0x47800000 - elif i == 32: - return 0x80000000 - elif i in range(33, 63): - return 0x80000000 + ((i - 32) << 23) - else: - return 0xC7800000 - -def convertOffset(i): - if i == 0 or i == 32: - return 0 - else: - return 1024 - -print """// -// 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 automatically generated. - -namespace gl -{ -""" - -print "const static unsigned g_mantissa[2048] = {" -for i in range(0, 2048): - print " %#010x," % convertMantissa(i) -print "};\n" - -print "const static unsigned g_exponent[64] = {" -for i in range(0, 64): - print " %#010x," % convertExponent(i) -print "};\n" - -print "const static unsigned g_offset[64] = {" -for i in range(0, 64): - 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]; - return *(float*) &i32; -} -} -""" diff --git a/src/3rdparty/angle/src/libGLESv2/Framebuffer.cpp b/src/3rdparty/angle/src/libGLESv2/Framebuffer.cpp deleted file mode 100644 index 3d57262e3c..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/Framebuffer.cpp +++ /dev/null @@ -1,672 +0,0 @@ -// -// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Framebuffer.cpp: Implements the gl::Framebuffer class. Implements GL framebuffer -// objects and related functionality. [OpenGL ES 2.0.24] section 4.4 page 105. - -#include "libGLESv2/Framebuffer.h" -#include "libGLESv2/main.h" -#include "libGLESv2/formatutils.h" -#include "libGLESv2/Texture.h" -#include "libGLESv2/Context.h" -#include "libGLESv2/Renderbuffer.h" -#include "libGLESv2/FramebufferAttachment.h" -#include "libGLESv2/renderer/Renderer.h" -#include "libGLESv2/renderer/RenderTarget.h" -#include "libGLESv2/renderer/RenderbufferImpl.h" -#include "libGLESv2/renderer/Workarounds.h" -#include "libGLESv2/renderer/d3d/TextureD3D.h" -#include "libGLESv2/renderer/d3d/RenderbufferD3D.h" - -#include "common/utilities.h" - -namespace rx -{ -// TODO: Move these functions, and the D3D-specific header inclusions above, -// to FramebufferD3D. -gl::Error GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment, RenderTarget **outRT) -{ - if (attachment->isTexture()) - { - gl::Texture *texture = attachment->getTexture(); - ASSERT(texture); - TextureD3D *textureD3D = TextureD3D::makeTextureD3D(texture->getImplementation()); - const gl::ImageIndex *index = attachment->getTextureImageIndex(); - ASSERT(index); - return textureD3D->getRenderTarget(*index, outRT); - } - else - { - gl::Renderbuffer *renderbuffer = attachment->getRenderbuffer(); - ASSERT(renderbuffer); - RenderbufferD3D *renderbufferD3D = RenderbufferD3D::makeRenderbufferD3D(renderbuffer->getImplementation()); - *outRT = renderbufferD3D->getRenderTarget(); - return gl::Error(GL_NO_ERROR); - } -} - -// Note: RenderTarget serials should ideally be in the RenderTargets themselves. -unsigned int GetAttachmentSerial(gl::FramebufferAttachment *attachment) -{ - if (attachment->isTexture()) - { - gl::Texture *texture = attachment->getTexture(); - ASSERT(texture); - TextureD3D *textureD3D = TextureD3D::makeTextureD3D(texture->getImplementation()); - const gl::ImageIndex *index = attachment->getTextureImageIndex(); - ASSERT(index); - return textureD3D->getRenderTargetSerial(*index); - } - - gl::Renderbuffer *renderbuffer = attachment->getRenderbuffer(); - ASSERT(renderbuffer); - RenderbufferD3D *renderbufferD3D = RenderbufferD3D::makeRenderbufferD3D(renderbuffer->getImplementation()); - return renderbufferD3D->getRenderTargetSerial(); -} - -} - -namespace gl -{ - -Framebuffer::Framebuffer(GLuint id) - : mId(id), - mReadBufferState(GL_COLOR_ATTACHMENT0_EXT), - mDepthbuffer(NULL), - mStencilbuffer(NULL) -{ - for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) - { - mColorbuffers[colorAttachment] = NULL; - mDrawBufferStates[colorAttachment] = GL_NONE; - } - mDrawBufferStates[0] = GL_COLOR_ATTACHMENT0_EXT; -} - -Framebuffer::~Framebuffer() -{ - for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) - { - SafeDelete(mColorbuffers[colorAttachment]); - } - SafeDelete(mDepthbuffer); - SafeDelete(mStencilbuffer); -} - -void Framebuffer::detachTexture(GLuint textureId) -{ - for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) - { - FramebufferAttachment *attachment = mColorbuffers[colorAttachment]; - - if (attachment && attachment->isTextureWithId(textureId)) - { - SafeDelete(mColorbuffers[colorAttachment]); - } - } - - if (mDepthbuffer && mDepthbuffer->isTextureWithId(textureId)) - { - SafeDelete(mDepthbuffer); - } - - if (mStencilbuffer && mStencilbuffer->isTextureWithId(textureId)) - { - SafeDelete(mStencilbuffer); - } -} - -void Framebuffer::detachRenderbuffer(GLuint renderbufferId) -{ - for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) - { - FramebufferAttachment *attachment = mColorbuffers[colorAttachment]; - - if (attachment && attachment->isRenderbufferWithId(renderbufferId)) - { - SafeDelete(mColorbuffers[colorAttachment]); - } - } - - if (mDepthbuffer && mDepthbuffer->isRenderbufferWithId(renderbufferId)) - { - SafeDelete(mDepthbuffer); - } - - if (mStencilbuffer && mStencilbuffer->isRenderbufferWithId(renderbufferId)) - { - SafeDelete(mStencilbuffer); - } -} - -FramebufferAttachment *Framebuffer::getColorbuffer(unsigned int colorAttachment) const -{ - ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS); - return mColorbuffers[colorAttachment]; -} - -FramebufferAttachment *Framebuffer::getDepthbuffer() const -{ - return mDepthbuffer; -} - -FramebufferAttachment *Framebuffer::getStencilbuffer() const -{ - return mStencilbuffer; -} - -FramebufferAttachment *Framebuffer::getDepthStencilBuffer() const -{ - return (hasValidDepthStencil() ? mDepthbuffer : NULL); -} - -FramebufferAttachment *Framebuffer::getDepthOrStencilbuffer() const -{ - FramebufferAttachment *depthstencilbuffer = mDepthbuffer; - - if (!depthstencilbuffer) - { - depthstencilbuffer = mStencilbuffer; - } - - return depthstencilbuffer; -} - -FramebufferAttachment *Framebuffer::getReadColorbuffer() const -{ - // Will require more logic if glReadBuffers is supported - return mColorbuffers[0]; -} - -GLenum Framebuffer::getReadColorbufferType() const -{ - // Will require more logic if glReadBuffers is supported - return (mColorbuffers[0] ? mColorbuffers[0]->type() : GL_NONE); -} - -FramebufferAttachment *Framebuffer::getFirstColorbuffer() const -{ - for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) - { - if (mColorbuffers[colorAttachment]) - { - return mColorbuffers[colorAttachment]; - } - } - - return NULL; -} - -FramebufferAttachment *Framebuffer::getAttachment(GLenum attachment) const -{ - if (attachment >= GL_COLOR_ATTACHMENT0 && attachment <= GL_COLOR_ATTACHMENT15) - { - return getColorbuffer(attachment - GL_COLOR_ATTACHMENT0); - } - else - { - switch (attachment) - { - case GL_DEPTH_ATTACHMENT: - return getDepthbuffer(); - case GL_STENCIL_ATTACHMENT: - return getStencilbuffer(); - case GL_DEPTH_STENCIL_ATTACHMENT: - return getDepthStencilBuffer(); - default: - UNREACHABLE(); - return NULL; - } - } -} - -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 (mColorbuffers[colorAttachment] && 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 -{ - return (mStencilbuffer && mStencilbuffer->getStencilSize() > 0); -} - -bool Framebuffer::usingExtendedDrawBuffers() const -{ - for (unsigned int colorAttachment = 1; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) - { - if (isEnabledColorAttachment(colorAttachment)) - { - return true; - } - } - - return false; -} - -GLenum Framebuffer::completeness(const gl::Data &data) const -{ - int width = 0; - int height = 0; - unsigned int colorbufferSize = 0; - int samples = -1; - bool missingAttachment = true; - - for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) - { - const FramebufferAttachment *colorbuffer = mColorbuffers[colorAttachment]; - - if (colorbuffer) - { - if (colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0) - { - return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; - } - - GLenum internalformat = colorbuffer->getInternalFormat(); - const TextureCaps &formatCaps = data.textureCaps->get(internalformat); - const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat); - if (colorbuffer->isTexture()) - { - if (!formatCaps.renderable) - { - return GL_FRAMEBUFFER_UNSUPPORTED; - } - - if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0) - { - return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; - } - } - else - { - if (!formatCaps.renderable || formatInfo.depthBits > 0 || formatInfo.stencilBits > 0) - { - return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; - } - } - - 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; - } - - // in GLES 2.0, all color attachments attachments must have the same number of bitplanes - // in GLES 3.0, there is no such restriction - if (data.clientVersion < 3) - { - if (formatInfo.pixelBytes != colorbufferSize) - { - return GL_FRAMEBUFFER_UNSUPPORTED; - } - } - - // D3D11 does not allow for overlapping RenderTargetViews, so ensure uniqueness - for (unsigned int previousColorAttachment = 0; previousColorAttachment < colorAttachment; previousColorAttachment++) - { - const FramebufferAttachment *previousAttachment = mColorbuffers[previousColorAttachment]; - - if (previousAttachment && - (colorbuffer->id() == previousAttachment->id() && - colorbuffer->type() == previousAttachment->type())) - { - return GL_FRAMEBUFFER_UNSUPPORTED; - } - } - } - else - { - width = colorbuffer->getWidth(); - height = colorbuffer->getHeight(); - samples = colorbuffer->getSamples(); - colorbufferSize = formatInfo.pixelBytes; - missingAttachment = false; - } - } - } - - if (mDepthbuffer) - { - if (mDepthbuffer->getWidth() == 0 || mDepthbuffer->getHeight() == 0) - { - return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; - } - - GLenum internalformat = mDepthbuffer->getInternalFormat(); - const TextureCaps &formatCaps = data.textureCaps->get(internalformat); - const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat); - if (mDepthbuffer->isTexture()) - { - // depth texture attachments require OES/ANGLE_depth_texture - if (!data.extensions->depthTextures) - { - return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; - } - - if (!formatCaps.renderable) - { - return GL_FRAMEBUFFER_UNSUPPORTED; - } - - if (formatInfo.depthBits == 0) - { - return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; - } - } - else - { - if (!formatCaps.renderable || formatInfo.depthBits == 0) - { - return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; - } - } - - if (missingAttachment) - { - width = mDepthbuffer->getWidth(); - height = mDepthbuffer->getHeight(); - samples = mDepthbuffer->getSamples(); - missingAttachment = false; - } - else if (width != mDepthbuffer->getWidth() || height != mDepthbuffer->getHeight()) - { - return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS; - } - else if (samples != mDepthbuffer->getSamples()) - { - return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE; - } - } - - if (mStencilbuffer) - { - if (mStencilbuffer->getWidth() == 0 || mStencilbuffer->getHeight() == 0) - { - return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; - } - - GLenum internalformat = mStencilbuffer->getInternalFormat(); - const TextureCaps &formatCaps = data.textureCaps->get(internalformat); - const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat); - if (mStencilbuffer->isTexture()) - { - // texture stencil attachments come along as part - // of OES_packed_depth_stencil + OES/ANGLE_depth_texture - if (!data.extensions->depthTextures) - { - return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; - } - - if (!formatCaps.renderable) - { - return GL_FRAMEBUFFER_UNSUPPORTED; - } - - if (formatInfo.stencilBits == 0) - { - return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; - } - } - else - { - if (!formatCaps.renderable || formatInfo.stencilBits == 0) - { - return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; - } - } - - if (missingAttachment) - { - width = mStencilbuffer->getWidth(); - height = mStencilbuffer->getHeight(); - samples = mStencilbuffer->getSamples(); - missingAttachment = false; - } - else if (width != mStencilbuffer->getWidth() || height != mStencilbuffer->getHeight()) - { - return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS; - } - else if (samples != mStencilbuffer->getSamples()) - { - return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE; - } - } - - // if we have both a depth and stencil buffer, they must refer to the same object - // since we only support packed_depth_stencil and not separate depth and stencil - if (mDepthbuffer && mStencilbuffer && !hasValidDepthStencil()) - { - return GL_FRAMEBUFFER_UNSUPPORTED; - } - - // we need to have at least one attachment to be complete - if (missingAttachment) - { - return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT; - } - - return GL_FRAMEBUFFER_COMPLETE; -} - -Error Framebuffer::invalidate(const Caps &caps, GLsizei numAttachments, const GLenum *attachments) -{ - GLuint maxDimension = caps.maxRenderbufferSize; - return invalidateSub(numAttachments, attachments, 0, 0, maxDimension, maxDimension); -} - -Error Framebuffer::invalidateSub(GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height) -{ - for (GLsizei attachIndex = 0; attachIndex < numAttachments; ++attachIndex) - { - GLenum attachmentTarget = attachments[attachIndex]; - - FramebufferAttachment *attachment = (attachmentTarget == GL_DEPTH_STENCIL_ATTACHMENT) ? getDepthOrStencilbuffer() - : getAttachment(attachmentTarget); - - if (attachment) - { - rx::RenderTarget *renderTarget = NULL; - Error error = rx::GetAttachmentRenderTarget(attachment, &renderTarget); - if (error.isError()) - { - return error; - } - - renderTarget->invalidate(x, y, width, height); - } - } - - return Error(GL_NO_ERROR); -} - -DefaultFramebuffer::DefaultFramebuffer(rx::RenderbufferImpl *colorbuffer, rx::RenderbufferImpl *depthStencil) - : Framebuffer(0) -{ - Renderbuffer *colorRenderbuffer = new Renderbuffer(colorbuffer, 0); - mColorbuffers[0] = new RenderbufferAttachment(GL_BACK, colorRenderbuffer); - - Renderbuffer *depthStencilBuffer = new Renderbuffer(depthStencil, 0); - - // Make a new attachment objects to ensure we do not double-delete - // See angle issue 686 - mDepthbuffer = (depthStencilBuffer->getDepthSize() != 0 ? new RenderbufferAttachment(GL_DEPTH_ATTACHMENT, depthStencilBuffer) : NULL); - mStencilbuffer = (depthStencilBuffer->getStencilSize() != 0 ? new RenderbufferAttachment(GL_STENCIL_ATTACHMENT, depthStencilBuffer) : NULL); - - mDrawBufferStates[0] = GL_BACK; - mReadBufferState = GL_BACK; -} - -int Framebuffer::getSamples(const gl::Data &data) const -{ - if (completeness(data) == GL_FRAMEBUFFER_COMPLETE) - { - // 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 (mColorbuffers[colorAttachment]) - { - return mColorbuffers[colorAttachment]->getSamples(); - } - } - } - - return 0; -} - -bool Framebuffer::hasValidDepthStencil() const -{ - // A valid depth-stencil attachment has the same resource bound to both the - // depth and stencil attachment points. - return (mDepthbuffer && mStencilbuffer && - mDepthbuffer->type() == mStencilbuffer->type() && - mDepthbuffer->id() == mStencilbuffer->id()); -} - -ColorbufferInfo Framebuffer::getColorbuffersForRender(const rx::Workarounds &workarounds) const -{ - ColorbufferInfo colorbuffersForRender; - - for (size_t colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; ++colorAttachment) - { - GLenum drawBufferState = mDrawBufferStates[colorAttachment]; - FramebufferAttachment *colorbuffer = mColorbuffers[colorAttachment]; - - if (colorbuffer != NULL && drawBufferState != GL_NONE) - { - ASSERT(drawBufferState == GL_BACK || drawBufferState == (GL_COLOR_ATTACHMENT0_EXT + colorAttachment)); - colorbuffersForRender.push_back(colorbuffer); - } - else if (!workarounds.mrtPerfWorkaround) - { - colorbuffersForRender.push_back(NULL); - } - } - - return colorbuffersForRender; -} - -void Framebuffer::setTextureAttachment(GLenum attachment, Texture *texture, const ImageIndex &imageIndex) -{ - setAttachment(attachment, new TextureAttachment(attachment, texture, imageIndex)); -} - -void Framebuffer::setRenderbufferAttachment(GLenum attachment, Renderbuffer *renderbuffer) -{ - setAttachment(attachment, new RenderbufferAttachment(attachment, renderbuffer)); -} - -void Framebuffer::setNULLAttachment(GLenum attachment) -{ - setAttachment(attachment, NULL); -} - -void Framebuffer::setAttachment(GLenum attachment, FramebufferAttachment *attachmentObj) -{ - if (attachment >= GL_COLOR_ATTACHMENT0 && attachment < (GL_COLOR_ATTACHMENT0 + IMPLEMENTATION_MAX_DRAW_BUFFERS)) - { - size_t colorAttachment = attachment - GL_COLOR_ATTACHMENT0; - SafeDelete(mColorbuffers[colorAttachment]); - mColorbuffers[colorAttachment] = attachmentObj; - } - else if (attachment == GL_DEPTH_ATTACHMENT) - { - SafeDelete(mDepthbuffer); - mDepthbuffer = attachmentObj; - } - else if (attachment == GL_STENCIL_ATTACHMENT) - { - SafeDelete(mStencilbuffer); - mStencilbuffer = attachmentObj; - } - else if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) - { - SafeDelete(mDepthbuffer); - SafeDelete(mStencilbuffer); - - // ensure this is a legitimate depth+stencil format - if (attachmentObj && attachmentObj->getDepthSize() > 0 && attachmentObj->getStencilSize() > 0) - { - mDepthbuffer = attachmentObj; - - // Make a new attachment object to ensure we do not double-delete - // See angle issue 686 - if (attachmentObj->isTexture()) - { - mStencilbuffer = new TextureAttachment(GL_DEPTH_STENCIL_ATTACHMENT, attachmentObj->getTexture(), - *attachmentObj->getTextureImageIndex()); - } - else - { - mStencilbuffer = new RenderbufferAttachment(GL_DEPTH_STENCIL_ATTACHMENT, attachmentObj->getRenderbuffer()); - } - } - } - else - { - UNREACHABLE(); - } -} - -GLenum DefaultFramebuffer::completeness(const gl::Data &) const -{ - // 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; -} - -FramebufferAttachment *DefaultFramebuffer::getAttachment(GLenum attachment) const -{ - switch (attachment) - { - case GL_COLOR: - case GL_BACK: - return getColorbuffer(0); - case GL_DEPTH: - return getDepthbuffer(); - case GL_STENCIL: - return getStencilbuffer(); - case GL_DEPTH_STENCIL: - return getDepthStencilBuffer(); - default: - UNREACHABLE(); - return NULL; - } -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/Framebuffer.h b/src/3rdparty/angle/src/libGLESv2/Framebuffer.h deleted file mode 100644 index d0fe8935ea..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/Framebuffer.h +++ /dev/null @@ -1,126 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Framebuffer.h: Defines the gl::Framebuffer class. Implements GL framebuffer -// objects and related functionality. [OpenGL ES 2.0.24] section 4.4 page 105. - -#ifndef LIBGLESV2_FRAMEBUFFER_H_ -#define LIBGLESV2_FRAMEBUFFER_H_ - -#include "libGLESv2/Error.h" - -#include "common/angleutils.h" -#include "common/RefCountObject.h" -#include "Constants.h" - -#include - -namespace rx -{ -class RenderbufferImpl; -struct Workarounds; -} - -namespace gl -{ -class FramebufferAttachment; -class Texture; -class Renderbuffer; -struct ImageIndex; -struct Caps; -struct Extensions; -class TextureCapsMap; -struct Data; - -typedef std::vector ColorbufferInfo; - -class Framebuffer -{ - public: - Framebuffer(GLuint id); - virtual ~Framebuffer(); - - GLuint id() const { return mId; } - - void setTextureAttachment(GLenum attachment, Texture *texture, const ImageIndex &imageIndex); - void setRenderbufferAttachment(GLenum attachment, Renderbuffer *renderbuffer); - void setNULLAttachment(GLenum attachment); - - void detachTexture(GLuint texture); - void detachRenderbuffer(GLuint renderbuffer); - - FramebufferAttachment *getColorbuffer(unsigned int colorAttachment) const; - FramebufferAttachment *getDepthbuffer() const; - FramebufferAttachment *getStencilbuffer() const; - FramebufferAttachment *getDepthStencilBuffer() const; - FramebufferAttachment *getDepthOrStencilbuffer() const; - FramebufferAttachment *getReadColorbuffer() const; - GLenum getReadColorbufferType() const; - FramebufferAttachment *getFirstColorbuffer() const; - - virtual FramebufferAttachment *getAttachment(GLenum attachment) const; - - GLenum getDrawBufferState(unsigned int colorAttachment) const; - void setDrawBufferState(unsigned int colorAttachment, GLenum drawBuffer); - - bool isEnabledColorAttachment(unsigned int colorAttachment) const; - bool hasEnabledColorAttachment() const; - bool hasStencil() const; - int getSamples(const gl::Data &data) const; - bool usingExtendedDrawBuffers() const; - - virtual GLenum completeness(const gl::Data &data) const; - bool hasValidDepthStencil() const; - - Error invalidate(const Caps &caps, GLsizei numAttachments, const GLenum *attachments); - Error invalidateSub(GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height); - - // Use this method to retrieve the color buffer map when doing rendering. - // It will apply a workaround for poor shader performance on some systems - // by compacting the list to skip NULL values. - ColorbufferInfo getColorbuffersForRender(const rx::Workarounds &workarounds) const; - - protected: - GLuint mId; - - FramebufferAttachment *mColorbuffers[IMPLEMENTATION_MAX_DRAW_BUFFERS]; - GLenum mDrawBufferStates[IMPLEMENTATION_MAX_DRAW_BUFFERS]; - GLenum mReadBufferState; - - FramebufferAttachment *mDepthbuffer; - FramebufferAttachment *mStencilbuffer; - - private: - DISALLOW_COPY_AND_ASSIGN(Framebuffer); - - void setAttachment(GLenum attachment, FramebufferAttachment *attachmentObj); -}; - -class DefaultFramebuffer : public Framebuffer -{ - public: - DefaultFramebuffer(rx::RenderbufferImpl *colorbuffer, rx::RenderbufferImpl *depthStencil); - - GLenum completeness(const gl::Data &data) const override; - virtual FramebufferAttachment *getAttachment(GLenum attachment) const; - - private: - DISALLOW_COPY_AND_ASSIGN(DefaultFramebuffer); -}; - -} - -namespace rx -{ -class RenderTarget; - -// TODO: place this in FramebufferD3D.h -gl::Error GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment, RenderTarget **outRT); -unsigned int GetAttachmentSerial(gl::FramebufferAttachment *attachment); - -} - -#endif // LIBGLESV2_FRAMEBUFFER_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/FramebufferAttachment.cpp b/src/3rdparty/angle/src/libGLESv2/FramebufferAttachment.cpp deleted file mode 100644 index 894884a6d8..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/FramebufferAttachment.cpp +++ /dev/null @@ -1,230 +0,0 @@ -// -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// FramebufferAttachment.cpp: the gl::FramebufferAttachment class and its derived classes -// objects and related functionality. [OpenGL ES 2.0.24] section 4.4.3 page 108. - -#include "libGLESv2/FramebufferAttachment.h" -#include "libGLESv2/Texture.h" -#include "libGLESv2/formatutils.h" -#include "libGLESv2/Renderbuffer.h" -#include "libGLESv2/renderer/RenderTarget.h" -#include "libGLESv2/renderer/Renderer.h" -#include "libGLESv2/renderer/d3d/TextureStorage.h" - -#include "common/utilities.h" - -namespace gl -{ - -////// FramebufferAttachment Implementation ////// - -FramebufferAttachment::FramebufferAttachment(GLenum binding) - : mBinding(binding) -{ -} - -FramebufferAttachment::~FramebufferAttachment() -{ -} - -GLuint FramebufferAttachment::getRedSize() const -{ - return (GetInternalFormatInfo(getInternalFormat()).redBits > 0) ? GetInternalFormatInfo(getActualFormat()).redBits : 0; -} - -GLuint FramebufferAttachment::getGreenSize() const -{ - return (GetInternalFormatInfo(getInternalFormat()).greenBits > 0) ? GetInternalFormatInfo(getActualFormat()).greenBits : 0; -} - -GLuint FramebufferAttachment::getBlueSize() const -{ - return (GetInternalFormatInfo(getInternalFormat()).blueBits > 0) ? GetInternalFormatInfo(getActualFormat()).blueBits : 0; -} - -GLuint FramebufferAttachment::getAlphaSize() const -{ - return (GetInternalFormatInfo(getInternalFormat()).alphaBits > 0) ? GetInternalFormatInfo(getActualFormat()).alphaBits : 0; -} - -GLuint FramebufferAttachment::getDepthSize() const -{ - return (GetInternalFormatInfo(getInternalFormat()).depthBits > 0) ? GetInternalFormatInfo(getActualFormat()).depthBits : 0; -} - -GLuint FramebufferAttachment::getStencilSize() const -{ - return (GetInternalFormatInfo(getInternalFormat()).stencilBits > 0) ? GetInternalFormatInfo(getActualFormat()).stencilBits : 0; -} - -GLenum FramebufferAttachment::getComponentType() const -{ - return GetInternalFormatInfo(getActualFormat()).componentType; -} - -GLenum FramebufferAttachment::getColorEncoding() const -{ - return GetInternalFormatInfo(getActualFormat()).colorEncoding; -} - -bool FramebufferAttachment::isTexture() const -{ - return (type() != GL_RENDERBUFFER); -} - -///// TextureAttachment Implementation //////// - -TextureAttachment::TextureAttachment(GLenum binding, Texture *texture, const ImageIndex &index) - : FramebufferAttachment(binding), - mIndex(index) -{ - mTexture.set(texture); -} - -TextureAttachment::~TextureAttachment() -{ - mTexture.set(NULL); -} - -GLsizei TextureAttachment::getSamples() const -{ - return 0; -} - -GLuint TextureAttachment::id() const -{ - return mTexture->id(); -} - -GLsizei TextureAttachment::getWidth() const -{ - return mTexture->getWidth(mIndex); -} - -GLsizei TextureAttachment::getHeight() const -{ - return mTexture->getHeight(mIndex); -} - -GLenum TextureAttachment::getInternalFormat() const -{ - return mTexture->getInternalFormat(mIndex); -} - -GLenum TextureAttachment::getActualFormat() const -{ - return mTexture->getActualFormat(mIndex); -} - -GLenum TextureAttachment::type() const -{ - return mIndex.type; -} - -GLint TextureAttachment::mipLevel() const -{ - return mIndex.mipIndex; -} - -GLint TextureAttachment::layer() const -{ - return mIndex.layerIndex; -} - -Texture *TextureAttachment::getTexture() -{ - return mTexture.get(); -} - -const ImageIndex *TextureAttachment::getTextureImageIndex() const -{ - return &mIndex; -} - -Renderbuffer *TextureAttachment::getRenderbuffer() -{ - UNREACHABLE(); - return NULL; -} - -////// RenderbufferAttachment Implementation ////// - -RenderbufferAttachment::RenderbufferAttachment(GLenum binding, Renderbuffer *renderbuffer) - : FramebufferAttachment(binding) -{ - ASSERT(renderbuffer); - mRenderbuffer.set(renderbuffer); -} - -RenderbufferAttachment::~RenderbufferAttachment() -{ - mRenderbuffer.set(NULL); -} - -GLsizei RenderbufferAttachment::getWidth() const -{ - return mRenderbuffer->getWidth(); -} - -GLsizei RenderbufferAttachment::getHeight() const -{ - return mRenderbuffer->getHeight(); -} - -GLenum RenderbufferAttachment::getInternalFormat() const -{ - return mRenderbuffer->getInternalFormat(); -} - -GLenum RenderbufferAttachment::getActualFormat() const -{ - return mRenderbuffer->getActualFormat(); -} - -GLsizei RenderbufferAttachment::getSamples() const -{ - return mRenderbuffer->getSamples(); -} - -GLuint RenderbufferAttachment::id() const -{ - return mRenderbuffer->id(); -} - -GLenum RenderbufferAttachment::type() const -{ - return GL_RENDERBUFFER; -} - -GLint RenderbufferAttachment::mipLevel() const -{ - return 0; -} - -GLint RenderbufferAttachment::layer() const -{ - return 0; -} - -Texture *RenderbufferAttachment::getTexture() -{ - UNREACHABLE(); - return NULL; -} - -const ImageIndex *RenderbufferAttachment::getTextureImageIndex() const -{ - UNREACHABLE(); - return NULL; -} - -Renderbuffer *RenderbufferAttachment::getRenderbuffer() -{ - return mRenderbuffer.get(); -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/FramebufferAttachment.h b/src/3rdparty/angle/src/libGLESv2/FramebufferAttachment.h deleted file mode 100644 index 8d2dafa7ee..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/FramebufferAttachment.h +++ /dev/null @@ -1,132 +0,0 @@ -// -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// FramebufferAttachment.h: Defines the wrapper class gl::FramebufferAttachment, as well as the -// objects and related functionality. [OpenGL ES 2.0.24] section 4.4.3 page 108. - -#ifndef LIBGLESV2_FRAMEBUFFERATTACHMENT_H_ -#define LIBGLESV2_FRAMEBUFFERATTACHMENT_H_ - -#include "common/angleutils.h" -#include "common/RefCountObject.h" -#include "Texture.h" - -#include "angle_gl.h" - -namespace gl -{ -class Renderbuffer; - -// FramebufferAttachment implements a GL framebuffer attachment. -// Attachments are "light" containers, which store pointers to ref-counted GL objects. -// We support GL texture (2D/3D/Cube/2D array) and renderbuffer object attachments. -// Note: Our old naming scheme used the term "Renderbuffer" for both GL renderbuffers and for -// framebuffer attachments, which confused their usage. - -class FramebufferAttachment -{ - public: - explicit FramebufferAttachment(GLenum binding); - virtual ~FramebufferAttachment(); - - // Helper methods - GLuint getRedSize() const; - GLuint getGreenSize() const; - GLuint getBlueSize() const; - GLuint getAlphaSize() const; - GLuint getDepthSize() const; - GLuint getStencilSize() const; - GLenum getComponentType() const; - GLenum getColorEncoding() const; - bool isTexture() const; - - bool isTextureWithId(GLuint textureId) const { return isTexture() && id() == textureId; } - bool isRenderbufferWithId(GLuint renderbufferId) const { return !isTexture() && id() == renderbufferId; } - - GLenum getBinding() const { return mBinding; } - - // Child class interface - virtual GLsizei getWidth() const = 0; - virtual GLsizei getHeight() const = 0; - virtual GLenum getInternalFormat() const = 0; - virtual GLenum getActualFormat() const = 0; - virtual GLsizei getSamples() const = 0; - - virtual GLuint id() const = 0; - virtual GLenum type() const = 0; - virtual GLint mipLevel() const = 0; - virtual GLint layer() const = 0; - - virtual Texture *getTexture() = 0; - virtual const ImageIndex *getTextureImageIndex() const = 0; - virtual Renderbuffer *getRenderbuffer() = 0; - - private: - DISALLOW_COPY_AND_ASSIGN(FramebufferAttachment); - - GLenum mBinding; -}; - -class TextureAttachment : public FramebufferAttachment -{ - public: - TextureAttachment(GLenum binding, Texture *texture, const ImageIndex &index); - virtual ~TextureAttachment(); - - virtual GLsizei getSamples() const; - virtual GLuint id() const; - - virtual GLsizei getWidth() const; - virtual GLsizei getHeight() const; - virtual GLenum getInternalFormat() const; - virtual GLenum getActualFormat() const; - - virtual GLenum type() const; - virtual GLint mipLevel() const; - virtual GLint layer() const; - - virtual Texture *getTexture(); - virtual const ImageIndex *getTextureImageIndex() const; - virtual Renderbuffer *getRenderbuffer(); - - private: - DISALLOW_COPY_AND_ASSIGN(TextureAttachment); - - BindingPointer mTexture; - ImageIndex mIndex; -}; - -class RenderbufferAttachment : public FramebufferAttachment -{ - public: - RenderbufferAttachment(GLenum binding, Renderbuffer *renderbuffer); - - virtual ~RenderbufferAttachment(); - - virtual GLsizei getWidth() const; - virtual GLsizei getHeight() const; - virtual GLenum getInternalFormat() const; - virtual GLenum getActualFormat() const; - virtual GLsizei getSamples() const; - - virtual GLuint id() const; - virtual GLenum type() const; - virtual GLint mipLevel() const; - virtual GLint layer() const; - - virtual Texture *getTexture(); - virtual const ImageIndex *getTextureImageIndex() const; - virtual Renderbuffer *getRenderbuffer(); - - private: - DISALLOW_COPY_AND_ASSIGN(RenderbufferAttachment); - - BindingPointer mRenderbuffer; -}; - -} - -#endif // LIBGLESV2_FRAMEBUFFERATTACHMENT_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/HandleAllocator.cpp b/src/3rdparty/angle/src/libGLESv2/HandleAllocator.cpp deleted file mode 100644 index c498f8a178..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/HandleAllocator.cpp +++ /dev/null @@ -1,63 +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. -// - -// HandleAllocator.cpp: Implements the gl::HandleAllocator class, which is used -// to allocate GL handles. - -#include "libGLESv2/HandleAllocator.h" - -#include "libGLESv2/main.h" - -namespace gl -{ - -HandleAllocator::HandleAllocator() : mBaseValue(1), mNextValue(1) -{ -} - -HandleAllocator::~HandleAllocator() -{ -} - -void HandleAllocator::setBaseHandle(GLuint value) -{ - ASSERT(mBaseValue == mNextValue); - mBaseValue = value; - mNextValue = value; -} - -GLuint HandleAllocator::allocate() -{ - if (mFreeValues.size()) - { - GLuint handle = mFreeValues.back(); - mFreeValues.pop_back(); - return handle; - } - return mNextValue++; -} - -void HandleAllocator::release(GLuint handle) -{ - if (handle == mNextValue - 1) - { - // Don't drop below base value - if(mNextValue > mBaseValue) - { - mNextValue--; - } - } - else - { - // Only free handles that we own - don't drop below the base value - if (handle >= mBaseValue) - { - mFreeValues.push_back(handle); - } - } -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/HandleAllocator.h b/src/3rdparty/angle/src/libGLESv2/HandleAllocator.h deleted file mode 100644 index a89cc86775..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/HandleAllocator.h +++ /dev/null @@ -1,44 +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. -// - -// HandleAllocator.h: Defines the gl::HandleAllocator class, which is used to -// allocate GL handles. - -#ifndef LIBGLESV2_HANDLEALLOCATOR_H_ -#define LIBGLESV2_HANDLEALLOCATOR_H_ - -#include "common/angleutils.h" - -#include "angle_gl.h" - -#include - -namespace gl -{ - -class HandleAllocator -{ - public: - HandleAllocator(); - virtual ~HandleAllocator(); - - void setBaseHandle(GLuint value); - - GLuint allocate(); - void release(GLuint handle); - - private: - DISALLOW_COPY_AND_ASSIGN(HandleAllocator); - - GLuint mBaseValue; - GLuint mNextValue; - typedef std::vector HandleList; - HandleList mFreeValues; -}; - -} - -#endif // LIBGLESV2_HANDLEALLOCATOR_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/ImageIndex.cpp b/src/3rdparty/angle/src/libGLESv2/ImageIndex.cpp deleted file mode 100644 index b45cd9c169..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/ImageIndex.cpp +++ /dev/null @@ -1,148 +0,0 @@ -// -// Copyright 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// ImageIndex.cpp: Implementation for ImageIndex methods. - -#include "libGLESv2/ImageIndex.h" -#include "libGLESv2/Texture.h" -#include "common/utilities.h" - -namespace gl -{ - -ImageIndex::ImageIndex(const ImageIndex &other) - : type(other.type), - mipIndex(other.mipIndex), - layerIndex(other.layerIndex) -{} - -ImageIndex &ImageIndex::operator=(const ImageIndex &other) -{ - type = other.type; - mipIndex = other.mipIndex; - layerIndex = other.layerIndex; - return *this; -} - -ImageIndex ImageIndex::Make2D(GLint mipIndex) -{ - return ImageIndex(GL_TEXTURE_2D, mipIndex, ENTIRE_LEVEL); -} - -ImageIndex ImageIndex::MakeCube(GLenum target, GLint mipIndex) -{ - ASSERT(gl::IsCubemapTextureTarget(target)); - return ImageIndex(target, mipIndex, TextureCubeMap::targetToLayerIndex(target)); -} - -ImageIndex ImageIndex::Make2DArray(GLint mipIndex, GLint layerIndex) -{ - return ImageIndex(GL_TEXTURE_2D_ARRAY, mipIndex, layerIndex); -} - -ImageIndex ImageIndex::Make3D(GLint mipIndex, GLint layerIndex) -{ - return ImageIndex(GL_TEXTURE_3D, mipIndex, layerIndex); -} - -ImageIndex ImageIndex::MakeInvalid() -{ - return ImageIndex(GL_NONE, -1, -1); -} - -ImageIndex::ImageIndex(GLenum typeIn, GLint mipIndexIn, GLint layerIndexIn) - : type(typeIn), - mipIndex(mipIndexIn), - layerIndex(layerIndexIn) -{} - -ImageIndexIterator ImageIndexIterator::Make2D(GLint minMip, GLint maxMip) -{ - return ImageIndexIterator(GL_TEXTURE_2D, rx::Range(minMip, maxMip), - rx::Range(ImageIndex::ENTIRE_LEVEL, ImageIndex::ENTIRE_LEVEL), NULL); -} - -ImageIndexIterator ImageIndexIterator::MakeCube(GLint minMip, GLint maxMip) -{ - return ImageIndexIterator(GL_TEXTURE_CUBE_MAP, rx::Range(minMip, maxMip), rx::Range(0, 6), NULL); -} - -ImageIndexIterator ImageIndexIterator::Make3D(GLint minMip, GLint maxMip, - GLint minLayer, GLint maxLayer) -{ - return ImageIndexIterator(GL_TEXTURE_3D, rx::Range(minMip, maxMip), rx::Range(minLayer, maxLayer), NULL); -} - -ImageIndexIterator ImageIndexIterator::Make2DArray(GLint minMip, GLint maxMip, - const GLsizei *layerCounts) -{ - return ImageIndexIterator(GL_TEXTURE_2D_ARRAY, rx::Range(minMip, maxMip), - rx::Range(0, IMPLEMENTATION_MAX_2D_ARRAY_TEXTURE_LAYERS), layerCounts); -} - -ImageIndexIterator::ImageIndexIterator(GLenum type, const rx::Range &mipRange, - const rx::Range &layerRange, const GLsizei *layerCounts) - : mType(type), - mMipRange(mipRange), - mLayerRange(layerRange), - mLayerCounts(layerCounts), - mCurrentMip(mipRange.start), - mCurrentLayer(layerRange.start) -{} - -GLint ImageIndexIterator::maxLayer() const -{ - return (mLayerCounts ? static_cast(mLayerCounts[mCurrentMip]) : mLayerRange.end); -} - -ImageIndex ImageIndexIterator::next() -{ - ASSERT(hasNext()); - - ImageIndex value = current(); - - // Iterate layers in the inner loop for now. We can add switchable - // layer or mip iteration if we need it. - - if (mCurrentLayer != ImageIndex::ENTIRE_LEVEL) - { - if (mCurrentLayer < maxLayer()-1) - { - mCurrentLayer++; - } - else if (mCurrentMip < mMipRange.end-1) - { - mCurrentMip++; - mCurrentLayer = mLayerRange.start; - } - } - else if (mCurrentMip < mMipRange.end-1) - { - mCurrentMip++; - mCurrentLayer = mLayerRange.start; - } - - return value; -} - -ImageIndex ImageIndexIterator::current() const -{ - ImageIndex value(mType, mCurrentMip, mCurrentLayer); - - if (mType == GL_TEXTURE_CUBE_MAP) - { - value.type = TextureCubeMap::layerIndexToTarget(mCurrentLayer); - } - - return value; -} - -bool ImageIndexIterator::hasNext() const -{ - return (mCurrentMip < mMipRange.end || mCurrentLayer < maxLayer()); -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/ImageIndex.h b/src/3rdparty/angle/src/libGLESv2/ImageIndex.h deleted file mode 100644 index 8bb14fd555..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/ImageIndex.h +++ /dev/null @@ -1,68 +0,0 @@ -// -// Copyright 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// ImageIndex.h: A helper struct for indexing into an Image array - -#ifndef LIBGLESV2_IMAGE_INDEX_H_ -#define LIBGLESV2_IMAGE_INDEX_H_ - -#include "angle_gl.h" -#include "common/mathutil.h" - -namespace gl -{ - -struct ImageIndex -{ - GLenum type; - GLint mipIndex; - GLint layerIndex; - - ImageIndex(GLenum typeIn, GLint mipIndexIn, GLint layerIndexIn); - ImageIndex(const ImageIndex &other); - ImageIndex &operator=(const ImageIndex &other); - - bool hasLayer() const { return layerIndex != ENTIRE_LEVEL; } - - static ImageIndex Make2D(GLint mipIndex); - static ImageIndex MakeCube(GLenum target, GLint mipIndex); - static ImageIndex Make2DArray(GLint mipIndex, GLint layerIndex); - static ImageIndex Make3D(GLint mipIndex, GLint layerIndex = ENTIRE_LEVEL); - static ImageIndex MakeInvalid(); - - static const GLint ENTIRE_LEVEL = static_cast(-1); -}; - -class ImageIndexIterator -{ - public: - static ImageIndexIterator Make2D(GLint minMip, GLint maxMip); - static ImageIndexIterator MakeCube(GLint minMip, GLint maxMip); - static ImageIndexIterator Make3D(GLint minMip, GLint maxMip, GLint minLayer, GLint maxLayer); - static ImageIndexIterator Make2DArray(GLint minMip, GLint maxMip, const GLsizei *layerCounts); - - ImageIndex next(); - ImageIndex current() const; - bool hasNext() const; - - private: - - ImageIndexIterator(GLenum type, const rx::Range &mipRange, - const rx::Range &layerRange, const GLsizei *layerCounts); - - GLint maxLayer() const; - - GLenum mType; - rx::Range mMipRange; - rx::Range mLayerRange; - const GLsizei *mLayerCounts; - GLint mCurrentMip; - GLint mCurrentLayer; -}; - -} - -#endif // LIBGLESV2_IMAGE_INDEX_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/Program.cpp b/src/3rdparty/angle/src/libGLESv2/Program.cpp deleted file mode 100644 index 3faa8c56f6..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/Program.cpp +++ /dev/null @@ -1,668 +0,0 @@ -// -// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Program.cpp: Implements the gl::Program class. Implements GL program objects -// and related functionality. [OpenGL ES 2.0.24] section 2.10.3 page 28. - -#include "libGLESv2/Program.h" -#include "libGLESv2/ProgramBinary.h" -#include "libGLESv2/ResourceManager.h" -#include "libGLESv2/renderer/Renderer.h" - -namespace gl -{ -const char * const g_fakepath = "C:\\fakepath"; - -AttributeBindings::AttributeBindings() -{ -} - -AttributeBindings::~AttributeBindings() -{ -} - -InfoLog::InfoLog() : mInfoLog(NULL) -{ -} - -InfoLog::~InfoLog() -{ - delete[] mInfoLog; -} - - -int InfoLog::getLength() const -{ - if (!mInfoLog) - { - return 0; - } - else - { - return strlen(mInfoLog) + 1; - } -} - -void InfoLog::getLog(GLsizei bufSize, GLsizei *length, char *infoLog) -{ - int index = 0; - - if (bufSize > 0) - { - if (mInfoLog) - { - index = std::min(bufSize - 1, (int)strlen(mInfoLog)); - memcpy(infoLog, mInfoLog, index); - } - - infoLog[index] = '\0'; - } - - if (length) - { - *length = index; - } -} - -// append a santized message to the program info log. -// The D3D compiler includes a fake file path in some of the warning or error -// messages, so lets remove all occurrences of this fake file path from the log. -void InfoLog::appendSanitized(const char *message) -{ - std::string msg(message); - - size_t found; - do - { - found = msg.find(g_fakepath); - if (found != std::string::npos) - { - msg.erase(found, strlen(g_fakepath)); - } - } - while (found != std::string::npos); - - append("%s", msg.c_str()); -} - -void InfoLog::append(const char *format, ...) -{ - if (!format) - { - return; - } - - va_list vararg; - va_start(vararg, format); - size_t infoLength = vsnprintf(NULL, 0, format, vararg); - va_end(vararg); - - char *logPointer = NULL; - - if (!mInfoLog) - { - mInfoLog = new char[infoLength + 2]; - logPointer = mInfoLog; - } - else - { - size_t currentlogLength = strlen(mInfoLog); - char *newLog = new char[currentlogLength + infoLength + 2]; - strcpy(newLog, mInfoLog); - - delete[] mInfoLog; - mInfoLog = newLog; - - logPointer = mInfoLog + currentlogLength; - } - - va_start(vararg, format); - vsnprintf(logPointer, infoLength, format, vararg); - va_end(vararg); - - logPointer[infoLength] = 0; - strcpy(logPointer + infoLength, "\n"); -} - -void InfoLog::reset() -{ - if (mInfoLog) - { - delete [] mInfoLog; - mInfoLog = NULL; - } -} - -Program::Program(rx::Renderer *renderer, ResourceManager *manager, GLuint handle) : mResourceManager(manager), mHandle(handle) -{ - mFragmentShader = NULL; - mVertexShader = NULL; - mProgramBinary.set(NULL); - mDeleteStatus = false; - mLinked = false; - mRefCount = 0; - mRenderer = renderer; - - resetUniformBlockBindings(); -} - -Program::~Program() -{ - unlink(true); - - if (mVertexShader != NULL) - { - mVertexShader->release(); - } - - if (mFragmentShader != NULL) - { - mFragmentShader->release(); - } -} - -bool Program::attachShader(Shader *shader) -{ - if (shader->getType() == GL_VERTEX_SHADER) - { - if (mVertexShader) - { - return false; - } - - mVertexShader = shader; - mVertexShader->addRef(); - } - else if (shader->getType() == GL_FRAGMENT_SHADER) - { - if (mFragmentShader) - { - return false; - } - - mFragmentShader = shader; - mFragmentShader->addRef(); - } - else UNREACHABLE(); - - return true; -} - -bool Program::detachShader(Shader *shader) -{ - if (shader->getType() == GL_VERTEX_SHADER) - { - if (mVertexShader != shader) - { - return false; - } - - mVertexShader->release(); - mVertexShader = NULL; - } - else if (shader->getType() == GL_FRAGMENT_SHADER) - { - if (mFragmentShader != shader) - { - return false; - } - - mFragmentShader->release(); - mFragmentShader = NULL; - } - else UNREACHABLE(); - - return true; -} - -int Program::getAttachedShadersCount() const -{ - return (mVertexShader ? 1 : 0) + (mFragmentShader ? 1 : 0); -} - -void AttributeBindings::bindAttributeLocation(GLuint index, const char *name) -{ - if (index < MAX_VERTEX_ATTRIBS) - { - for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) - { - mAttributeBinding[i].erase(name); - } - - mAttributeBinding[index].insert(name); - } -} - -void Program::bindAttributeLocation(GLuint index, const char *name) -{ - mAttributeBindings.bindAttributeLocation(index, name); -} - -// Links the HLSL code of the vertex and pixel shader by matching up their varyings, -// compiling them into binaries, determining the attribute mappings, and collecting -// a list of uniforms -Error Program::link(const Data &data) -{ - unlink(false); - - mInfoLog.reset(); - resetUniformBlockBindings(); - - mProgramBinary.set(new ProgramBinary(mRenderer->createProgram())); - LinkResult result = mProgramBinary->link(data, mInfoLog, mAttributeBindings, mFragmentShader, mVertexShader, - mTransformFeedbackVaryings, mTransformFeedbackBufferMode); - if (result.error.isError()) - { - return result.error; - } - - mLinked = result.linkSuccess; - return gl::Error(GL_NO_ERROR); -} - -int AttributeBindings::getAttributeBinding(const std::string &name) const -{ - for (int location = 0; location < MAX_VERTEX_ATTRIBS; location++) - { - if (mAttributeBinding[location].find(name) != mAttributeBinding[location].end()) - { - return location; - } - } - - return -1; -} - -// Returns the program object to an unlinked state, before re-linking, or at destruction -void Program::unlink(bool destroy) -{ - if (destroy) // Object being destructed - { - if (mFragmentShader) - { - mFragmentShader->release(); - mFragmentShader = NULL; - } - - if (mVertexShader) - { - mVertexShader->release(); - mVertexShader = NULL; - } - } - - mProgramBinary.set(NULL); - mLinked = false; -} - -bool Program::isLinked() -{ - return mLinked; -} - -ProgramBinary* Program::getProgramBinary() const -{ - return mProgramBinary.get(); -} - -Error Program::setProgramBinary(GLenum binaryFormat, const void *binary, GLsizei length) -{ - unlink(false); - - mInfoLog.reset(); - - mProgramBinary.set(new ProgramBinary(mRenderer->createProgram())); - LinkResult result = mProgramBinary->load(mInfoLog, binaryFormat, binary, length); - if (result.error.isError()) - { - mProgramBinary.set(NULL); - return result.error; - } - - mLinked = result.linkSuccess; - return Error(GL_NO_ERROR); -} - -void Program::release() -{ - mRefCount--; - - if (mRefCount == 0 && mDeleteStatus) - { - mResourceManager->deleteProgram(mHandle); - } -} - -void Program::addRef() -{ - mRefCount++; -} - -unsigned int Program::getRefCount() const -{ - return mRefCount; -} - -GLint Program::getProgramBinaryLength() const -{ - ProgramBinary *programBinary = mProgramBinary.get(); - if (programBinary) - { - return programBinary->getLength(); - } - else - { - return 0; - } -} - -int Program::getInfoLogLength() const -{ - return mInfoLog.getLength(); -} - -void Program::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) -{ - return mInfoLog.getLog(bufSize, length, infoLog); -} - -void Program::getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders) -{ - int total = 0; - - if (mVertexShader) - { - if (total < maxCount) - { - shaders[total] = mVertexShader->getHandle(); - } - - total++; - } - - if (mFragmentShader) - { - if (total < maxCount) - { - shaders[total] = mFragmentShader->getHandle(); - } - - total++; - } - - if (count) - { - *count = total; - } -} - -void Program::getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) -{ - ProgramBinary *programBinary = getProgramBinary(); - if (programBinary) - { - programBinary->getActiveAttribute(index, bufsize, length, size, type, name); - } - else - { - if (bufsize > 0) - { - name[0] = '\0'; - } - - if (length) - { - *length = 0; - } - - *type = GL_NONE; - *size = 1; - } -} - -GLint Program::getActiveAttributeCount() -{ - ProgramBinary *programBinary = getProgramBinary(); - if (programBinary) - { - return programBinary->getActiveAttributeCount(); - } - else - { - return 0; - } -} - -GLint Program::getActiveAttributeMaxLength() -{ - ProgramBinary *programBinary = getProgramBinary(); - if (programBinary) - { - return programBinary->getActiveAttributeMaxLength(); - } - else - { - return 0; - } -} - -void Program::getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) -{ - ProgramBinary *programBinary = getProgramBinary(); - if (programBinary) - { - return programBinary->getActiveUniform(index, bufsize, length, size, type, name); - } - else - { - if (bufsize > 0) - { - name[0] = '\0'; - } - - if (length) - { - *length = 0; - } - - *size = 0; - *type = GL_NONE; - } -} - -GLint Program::getActiveUniformCount() -{ - ProgramBinary *programBinary = getProgramBinary(); - if (programBinary) - { - return programBinary->getActiveUniformCount(); - } - else - { - return 0; - } -} - -GLint Program::getActiveUniformMaxLength() -{ - ProgramBinary *programBinary = getProgramBinary(); - if (programBinary) - { - return programBinary->getActiveUniformMaxLength(); - } - else - { - return 0; - } -} - -void Program::flagForDeletion() -{ - mDeleteStatus = true; -} - -bool Program::isFlaggedForDeletion() const -{ - return mDeleteStatus; -} - -void Program::validate(const Caps &caps) -{ - mInfoLog.reset(); - - ProgramBinary *programBinary = getProgramBinary(); - if (isLinked() && programBinary) - { - programBinary->validate(mInfoLog, caps); - } - else - { - mInfoLog.append("Program has not been successfully linked."); - } -} - -bool Program::isValidated() const -{ - ProgramBinary *programBinary = mProgramBinary.get(); - if (programBinary) - { - return programBinary->isValidated(); - } - else - { - return false; - } -} - -GLint Program::getActiveUniformBlockCount() -{ - ProgramBinary *programBinary = getProgramBinary(); - if (programBinary) - { - return static_cast(programBinary->getActiveUniformBlockCount()); - } - else - { - return 0; - } -} - -GLint Program::getActiveUniformBlockMaxLength() -{ - ProgramBinary *programBinary = getProgramBinary(); - if (programBinary) - { - return static_cast(programBinary->getActiveUniformBlockMaxLength()); - } - else - { - return 0; - } -} - -void Program::bindUniformBlock(GLuint uniformBlockIndex, GLuint uniformBlockBinding) -{ - mUniformBlockBindings[uniformBlockIndex] = uniformBlockBinding; -} - -GLuint Program::getUniformBlockBinding(GLuint uniformBlockIndex) const -{ - return mUniformBlockBindings[uniformBlockIndex]; -} - -void Program::resetUniformBlockBindings() -{ - for (unsigned int blockId = 0; blockId < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS; blockId++) - { - mUniformBlockBindings[blockId] = 0; - } -} - -void Program::setTransformFeedbackVaryings(GLsizei count, const GLchar *const *varyings, GLenum bufferMode) -{ - mTransformFeedbackVaryings.resize(count); - for (GLsizei i = 0; i < count; i++) - { - mTransformFeedbackVaryings[i] = varyings[i]; - } - - mTransformFeedbackBufferMode = bufferMode; -} - -void Program::getTransformFeedbackVarying(GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name) const -{ - ProgramBinary *programBinary = getProgramBinary(); - if (programBinary && index < programBinary->getTransformFeedbackVaryingCount()) - { - const LinkedVarying &varying = programBinary->getTransformFeedbackVarying(index); - GLsizei lastNameIdx = std::min(bufSize - 1, static_cast(varying.name.length())); - if (length) - { - *length = lastNameIdx; - } - if (size) - { - *size = varying.size; - } - if (type) - { - *type = varying.type; - } - if (name) - { - memcpy(name, varying.name.c_str(), lastNameIdx); - name[lastNameIdx] = '\0'; - } - } -} - -GLsizei Program::getTransformFeedbackVaryingCount() const -{ - ProgramBinary *programBinary = getProgramBinary(); - if (programBinary) - { - return static_cast(programBinary->getTransformFeedbackVaryingCount()); - } - else - { - return 0; - } -} - -GLsizei Program::getTransformFeedbackVaryingMaxLength() const -{ - ProgramBinary *programBinary = getProgramBinary(); - if (programBinary) - { - GLsizei maxSize = 0; - for (size_t i = 0; i < programBinary->getTransformFeedbackVaryingCount(); i++) - { - const LinkedVarying &varying = programBinary->getTransformFeedbackVarying(i); - maxSize = std::max(maxSize, static_cast(varying.name.length() + 1)); - } - - return maxSize; - } - else - { - return 0; - } -} - -GLenum Program::getTransformFeedbackBufferMode() const -{ - ProgramBinary *programBinary = getProgramBinary(); - if (programBinary) - { - return programBinary->getTransformFeedbackBufferMode(); - } - else - { - return mTransformFeedbackBufferMode; - } -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/Program.h b/src/3rdparty/angle/src/libGLESv2/Program.h deleted file mode 100644 index b92349eeef..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/Program.h +++ /dev/null @@ -1,151 +0,0 @@ -// -// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Program.h: Defines the gl::Program class. Implements GL program objects -// and related functionality. [OpenGL ES 2.0.24] section 2.10.3 page 28. - -#ifndef LIBGLESV2_PROGRAM_H_ -#define LIBGLESV2_PROGRAM_H_ - -#include "common/angleutils.h" -#include "common/RefCountObject.h" -#include "libGLESv2/Constants.h" -#include "libGLESv2/ProgramBinary.h" - -#include - -#include -#include -#include - -namespace rx -{ -class Renderer; -} - -namespace gl -{ -struct Caps; -struct Data; -class ResourceManager; -class Shader; - -extern const char * const g_fakepath; - -class AttributeBindings -{ - public: - AttributeBindings(); - ~AttributeBindings(); - - void bindAttributeLocation(GLuint index, const char *name); - int getAttributeBinding(const std::string &name) const; - - private: - std::set mAttributeBinding[MAX_VERTEX_ATTRIBS]; -}; - -class InfoLog -{ - public: - InfoLog(); - ~InfoLog(); - - int getLength() const; - void getLog(GLsizei bufSize, GLsizei *length, char *infoLog); - - void appendSanitized(const char *message); - void append(const char *info, ...); - void reset(); - private: - DISALLOW_COPY_AND_ASSIGN(InfoLog); - char *mInfoLog; -}; - -class Program -{ - public: - Program(rx::Renderer *renderer, ResourceManager *manager, GLuint handle); - - ~Program(); - - bool attachShader(Shader *shader); - bool detachShader(Shader *shader); - int getAttachedShadersCount() const; - - void bindAttributeLocation(GLuint index, const char *name); - - Error link(const Data &data); - bool isLinked(); - Error setProgramBinary(GLenum binaryFormat, const void *binary, GLsizei length); - ProgramBinary *getProgramBinary() const; - - int getInfoLogLength() const; - void getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog); - void getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders); - - void getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name); - GLint getActiveAttributeCount(); - GLint getActiveAttributeMaxLength(); - - void getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name); - GLint getActiveUniformCount(); - GLint getActiveUniformMaxLength(); - - GLint getActiveUniformBlockCount(); - GLint getActiveUniformBlockMaxLength(); - - void bindUniformBlock(GLuint uniformBlockIndex, GLuint uniformBlockBinding); - GLuint getUniformBlockBinding(GLuint uniformBlockIndex) const; - - void setTransformFeedbackVaryings(GLsizei count, const GLchar *const *varyings, GLenum bufferMode); - void getTransformFeedbackVarying(GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name) const; - GLsizei getTransformFeedbackVaryingCount() const; - GLsizei getTransformFeedbackVaryingMaxLength() const; - GLenum getTransformFeedbackBufferMode() const; - - void addRef(); - void release(); - unsigned int getRefCount() const; - void flagForDeletion(); - bool isFlaggedForDeletion() const; - - void validate(const Caps &caps); - bool isValidated() const; - - GLint getProgramBinaryLength() const; - - private: - DISALLOW_COPY_AND_ASSIGN(Program); - - void unlink(bool destroy = false); - void resetUniformBlockBindings(); - - Shader *mFragmentShader; - Shader *mVertexShader; - - AttributeBindings mAttributeBindings; - - GLuint mUniformBlockBindings[IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS]; - - std::vector mTransformFeedbackVaryings; - GLuint mTransformFeedbackBufferMode; - - BindingPointer mProgramBinary; - bool mLinked; - bool mDeleteStatus; // Flag to indicate that the program can be deleted when no longer in use - - unsigned int mRefCount; - - ResourceManager *mResourceManager; - rx::Renderer *mRenderer; - const GLuint mHandle; - - InfoLog mInfoLog; -}; -} - -#endif // LIBGLESV2_PROGRAM_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp b/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp deleted file mode 100644 index 6d64b38b56..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp +++ /dev/null @@ -1,1233 +0,0 @@ -// -// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Program.cpp: Implements the gl::Program class. Implements GL program objects -// and related functionality. [OpenGL ES 2.0.24] section 2.10.3 page 28. - -#include "libGLESv2/BinaryStream.h" -#include "libGLESv2/ProgramBinary.h" -#include "libGLESv2/Framebuffer.h" -#include "libGLESv2/FramebufferAttachment.h" -#include "libGLESv2/Renderbuffer.h" -#include "libGLESv2/renderer/ShaderExecutable.h" - -#include "common/debug.h" -#include "common/version.h" -#include "common/utilities.h" -#include "common/platform.h" - -#include "libGLESv2/main.h" -#include "libGLESv2/Shader.h" -#include "libGLESv2/Program.h" -#include "libGLESv2/renderer/ProgramImpl.h" -#include "libGLESv2/renderer/d3d/ShaderD3D.h" -#include "libGLESv2/Context.h" -#include "libGLESv2/Buffer.h" -#include "common/blocklayout.h" -#include "common/features.h" - -namespace gl -{ - -namespace -{ - -unsigned int ParseAndStripArrayIndex(std::string* name) -{ - unsigned int subscript = GL_INVALID_INDEX; - - // Strip any trailing array operator and retrieve the subscript - size_t open = name->find_last_of('['); - size_t close = name->find_last_of(']'); - if (open != std::string::npos && close == name->length() - 1) - { - subscript = atoi(name->substr(open + 1).c_str()); - name->erase(open); - } - - return subscript; -} - -} - -VariableLocation::VariableLocation(const std::string &name, unsigned int element, unsigned int index) - : name(name), element(element), index(index) -{ -} - -LinkedVarying::LinkedVarying() -{ -} - -LinkedVarying::LinkedVarying(const std::string &name, GLenum type, GLsizei size, const std::string &semanticName, - unsigned int semanticIndex, unsigned int semanticIndexCount) - : name(name), type(type), size(size), semanticName(semanticName), semanticIndex(semanticIndex), semanticIndexCount(semanticIndexCount) -{ -} - -LinkResult::LinkResult(bool linkSuccess, const Error &error) - : linkSuccess(linkSuccess), - error(error) -{ -} - -unsigned int ProgramBinary::mCurrentSerial = 1; - -ProgramBinary::ProgramBinary(rx::ProgramImpl *impl) - : RefCountObject(0), - mProgram(impl), - mValidated(false), - mSerial(issueSerial()) -{ - ASSERT(impl); - - for (int index = 0; index < MAX_VERTEX_ATTRIBS; index++) - { - mSemanticIndex[index] = -1; - } -} - -ProgramBinary::~ProgramBinary() -{ - reset(); - SafeDelete(mProgram); -} - -unsigned int ProgramBinary::getSerial() const -{ - return mSerial; -} - -unsigned int ProgramBinary::issueSerial() -{ - return mCurrentSerial++; -} - -GLuint ProgramBinary::getAttributeLocation(const char *name) -{ - if (name) - { - for (int index = 0; index < MAX_VERTEX_ATTRIBS; index++) - { - if (mLinkedAttribute[index].name == std::string(name)) - { - return index; - } - } - } - - return -1; -} - -int ProgramBinary::getSemanticIndex(int attributeIndex) -{ - ASSERT(attributeIndex >= 0 && attributeIndex < MAX_VERTEX_ATTRIBS); - - return mSemanticIndex[attributeIndex]; -} - -// Returns one more than the highest sampler index used. -GLint ProgramBinary::getUsedSamplerRange(SamplerType type) -{ - return mProgram->getUsedSamplerRange(type); -} - -bool ProgramBinary::usesPointSize() const -{ - return mProgram->usesPointSize(); -} - -GLint ProgramBinary::getSamplerMapping(SamplerType type, unsigned int samplerIndex, const Caps &caps) -{ - return mProgram->getSamplerMapping(type, samplerIndex, caps); -} - -GLenum ProgramBinary::getSamplerTextureType(SamplerType type, unsigned int samplerIndex) -{ - return mProgram->getSamplerTextureType(type, samplerIndex); -} - -GLint ProgramBinary::getUniformLocation(std::string name) -{ - return mProgram->getUniformLocation(name); -} - -GLuint ProgramBinary::getUniformIndex(std::string name) -{ - return mProgram->getUniformIndex(name); -} - -GLuint ProgramBinary::getUniformBlockIndex(std::string name) -{ - return mProgram->getUniformBlockIndex(name); -} - -UniformBlock *ProgramBinary::getUniformBlockByIndex(GLuint blockIndex) -{ - return mProgram->getUniformBlockByIndex(blockIndex); -} - -GLint ProgramBinary::getFragDataLocation(const char *name) const -{ - std::string baseName(name); - unsigned int arrayIndex; - arrayIndex = ParseAndStripArrayIndex(&baseName); - - for (auto locationIt = mOutputVariables.begin(); locationIt != mOutputVariables.end(); locationIt++) - { - const VariableLocation &outputVariable = locationIt->second; - - if (outputVariable.name == baseName && (arrayIndex == GL_INVALID_INDEX || arrayIndex == outputVariable.element)) - { - return static_cast(locationIt->first); - } - } - - return -1; -} - -size_t ProgramBinary::getTransformFeedbackVaryingCount() const -{ - return mProgram->getTransformFeedbackLinkedVaryings().size(); -} - -const LinkedVarying &ProgramBinary::getTransformFeedbackVarying(size_t idx) const -{ - return mProgram->getTransformFeedbackLinkedVaryings()[idx]; -} - -GLenum ProgramBinary::getTransformFeedbackBufferMode() const -{ - return mProgram->getTransformFeedbackBufferMode(); -} - -void ProgramBinary::setUniform1fv(GLint location, GLsizei count, const GLfloat *v) { - mProgram->setUniform1fv(location, count, v); -} - -void ProgramBinary::setUniform2fv(GLint location, GLsizei count, const GLfloat *v) { - mProgram->setUniform2fv(location, count, v); -} - -void ProgramBinary::setUniform3fv(GLint location, GLsizei count, const GLfloat *v) { - mProgram->setUniform3fv(location, count, v); -} - -void ProgramBinary::setUniform4fv(GLint location, GLsizei count, const GLfloat *v) { - mProgram->setUniform4fv(location, count, v); -} - -void ProgramBinary::setUniform1iv(GLint location, GLsizei count, const GLint *v) { - mProgram->setUniform1iv(location, count, v); -} - -void ProgramBinary::setUniform2iv(GLint location, GLsizei count, const GLint *v) { - mProgram->setUniform2iv(location, count, v); -} - -void ProgramBinary::setUniform3iv(GLint location, GLsizei count, const GLint *v) { - mProgram->setUniform3iv(location, count, v); -} - -void ProgramBinary::setUniform4iv(GLint location, GLsizei count, const GLint *v) { - mProgram->setUniform4iv(location, count, v); -} - -void ProgramBinary::setUniform1uiv(GLint location, GLsizei count, const GLuint *v) { - mProgram->setUniform1uiv(location, count, v); -} - -void ProgramBinary::setUniform2uiv(GLint location, GLsizei count, const GLuint *v) { - mProgram->setUniform2uiv(location, count, v); -} - -void ProgramBinary::setUniform3uiv(GLint location, GLsizei count, const GLuint *v) { - mProgram->setUniform3uiv(location, count, v); -} - -void ProgramBinary::setUniform4uiv(GLint location, GLsizei count, const GLuint *v) { - mProgram->setUniform4uiv(location, count, v); -} - -void ProgramBinary::setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) { - mProgram->setUniformMatrix2fv(location, count, transpose, v); -} - -void ProgramBinary::setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) { - mProgram->setUniformMatrix3fv(location, count, transpose, v); -} - -void ProgramBinary::setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) { - mProgram->setUniformMatrix4fv(location, count, transpose, v); -} - -void ProgramBinary::setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) { - mProgram->setUniformMatrix2x3fv(location, count, transpose, v); -} - -void ProgramBinary::setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) { - mProgram->setUniformMatrix2x4fv(location, count, transpose, v); -} - -void ProgramBinary::setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) { - mProgram->setUniformMatrix3x2fv(location, count, transpose, v); -} - -void ProgramBinary::setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) { - mProgram->setUniformMatrix3x4fv(location, count, transpose, v); -} - -void ProgramBinary::setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) { - mProgram->setUniformMatrix4x2fv(location, count, transpose, v); -} - -void ProgramBinary::setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) { - mProgram->setUniformMatrix4x3fv(location, count, transpose, v); -} - -void ProgramBinary::getUniformfv(GLint location, GLfloat *v) { - mProgram->getUniformfv(location, v); -} - -void ProgramBinary::getUniformiv(GLint location, GLint *v) { - mProgram->getUniformiv(location, v); -} - -void ProgramBinary::getUniformuiv(GLint location, GLuint *v) { - mProgram->getUniformuiv(location, v); -} - -void ProgramBinary::updateSamplerMapping() -{ - return mProgram->updateSamplerMapping(); -} - -// Applies all the uniforms set for this program object to the renderer -Error ProgramBinary::applyUniforms() -{ - return mProgram->applyUniforms(); -} - -Error ProgramBinary::applyUniformBuffers(const std::vector boundBuffers, const Caps &caps) -{ - return mProgram->applyUniformBuffers(boundBuffers, caps); -} - -bool ProgramBinary::linkVaryings(InfoLog &infoLog, Shader *fragmentShader, Shader *vertexShader) -{ - std::vector &fragmentVaryings = fragmentShader->getVaryings(); - std::vector &vertexVaryings = vertexShader->getVaryings(); - - for (size_t fragVaryingIndex = 0; fragVaryingIndex < fragmentVaryings.size(); fragVaryingIndex++) - { - PackedVarying *input = &fragmentVaryings[fragVaryingIndex]; - bool matched = false; - - // Built-in varyings obey special rules - if (input->isBuiltIn()) - { - continue; - } - - for (size_t vertVaryingIndex = 0; vertVaryingIndex < vertexVaryings.size(); vertVaryingIndex++) - { - PackedVarying *output = &vertexVaryings[vertVaryingIndex]; - if (output->name == input->name) - { - if (!linkValidateVaryings(infoLog, output->name, *input, *output)) - { - return false; - } - - output->registerIndex = input->registerIndex; - output->columnIndex = input->columnIndex; - - matched = true; - break; - } - } - - // We permit unmatched, unreferenced varyings - if (!matched && input->staticUse) - { - infoLog.append("Fragment varying %s does not match any vertex varying", input->name.c_str()); - return false; - } - } - - return true; -} - -LinkResult ProgramBinary::load(InfoLog &infoLog, GLenum binaryFormat, const void *binary, GLsizei length) -{ -#if ANGLE_PROGRAM_BINARY_LOAD == ANGLE_DISABLED - return LinkResult(false, Error(GL_NO_ERROR)); -#else - ASSERT(binaryFormat == mProgram->getBinaryFormat()); - - reset(); - - BinaryInputStream stream(binary, length); - - GLenum format = stream.readInt(); - if (format != mProgram->getBinaryFormat()) - { - infoLog.append("Invalid program binary format."); - return LinkResult(false, Error(GL_NO_ERROR)); - } - - int majorVersion = stream.readInt(); - int minorVersion = stream.readInt(); - if (majorVersion != ANGLE_MAJOR_VERSION || minorVersion != ANGLE_MINOR_VERSION) - { - infoLog.append("Invalid program binary version."); - return LinkResult(false, Error(GL_NO_ERROR)); - } - - unsigned char commitString[ANGLE_COMMIT_HASH_SIZE]; - stream.readBytes(commitString, ANGLE_COMMIT_HASH_SIZE); - if (memcmp(commitString, ANGLE_COMMIT_HASH, sizeof(unsigned char) * ANGLE_COMMIT_HASH_SIZE) != 0) - { - infoLog.append("Invalid program binary version."); - return LinkResult(false, Error(GL_NO_ERROR)); - } - - int compileFlags = stream.readInt(); - if (compileFlags != ANGLE_COMPILE_OPTIMIZATION_LEVEL) - { - infoLog.append("Mismatched compilation flags."); - return LinkResult(false, Error(GL_NO_ERROR)); - } - - for (int i = 0; i < MAX_VERTEX_ATTRIBS; ++i) - { - stream.readInt(&mLinkedAttribute[i].type); - stream.readString(&mLinkedAttribute[i].name); - stream.readInt(&mProgram->getShaderAttributes()[i].type); - stream.readString(&mProgram->getShaderAttributes()[i].name); - stream.readInt(&mSemanticIndex[i]); - } - - initAttributesByLayout(); - - LinkResult result = mProgram->load(infoLog, &stream); - if (result.error.isError() || !result.linkSuccess) - { - return result; - } - - return LinkResult(true, Error(GL_NO_ERROR)); -#endif // #if ANGLE_PROGRAM_BINARY_LOAD == ANGLE_ENABLED -} - -Error ProgramBinary::save(GLenum *binaryFormat, void *binary, GLsizei bufSize, GLsizei *length) -{ - if (binaryFormat) - { - *binaryFormat = mProgram->getBinaryFormat(); - } - - BinaryOutputStream stream; - - stream.writeInt(mProgram->getBinaryFormat()); - stream.writeInt(ANGLE_MAJOR_VERSION); - stream.writeInt(ANGLE_MINOR_VERSION); - stream.writeBytes(reinterpret_cast(ANGLE_COMMIT_HASH), ANGLE_COMMIT_HASH_SIZE); - stream.writeInt(ANGLE_COMPILE_OPTIMIZATION_LEVEL); - - for (unsigned int i = 0; i < MAX_VERTEX_ATTRIBS; ++i) - { - stream.writeInt(mLinkedAttribute[i].type); - stream.writeString(mLinkedAttribute[i].name); - stream.writeInt(mProgram->getShaderAttributes()[i].type); - stream.writeString(mProgram->getShaderAttributes()[i].name); - stream.writeInt(mSemanticIndex[i]); - } - - mProgram->save(&stream); - - GLsizei streamLength = stream.length(); - const void *streamData = stream.data(); - - if (streamLength > bufSize) - { - if (length) - { - *length = 0; - } - - // TODO: This should be moved to the validation layer but computing the size of the binary before saving - // it causes the save to happen twice. It may be possible to write the binary to a separate buffer, validate - // sizes and then copy it. - return Error(GL_INVALID_OPERATION); - } - - if (binary) - { - char *ptr = (char*) binary; - - memcpy(ptr, streamData, streamLength); - ptr += streamLength; - - ASSERT(ptr - streamLength == binary); - } - - if (length) - { - *length = streamLength; - } - - return Error(GL_NO_ERROR); -} - -GLint ProgramBinary::getLength() -{ - GLint length; - Error error = save(NULL, NULL, INT_MAX, &length); - if (error.isError()) - { - return 0; - } - - return length; -} - -LinkResult ProgramBinary::link(const Data &data, InfoLog &infoLog, const AttributeBindings &attributeBindings, - Shader *fragmentShader, Shader *vertexShader, - const std::vector &transformFeedbackVaryings, - GLenum transformFeedbackBufferMode) -{ - if (!fragmentShader || !fragmentShader->isCompiled()) - { - return LinkResult(false, Error(GL_NO_ERROR)); - } - ASSERT(fragmentShader->getType() == GL_FRAGMENT_SHADER); - - if (!vertexShader || !vertexShader->isCompiled()) - { - return LinkResult(false, Error(GL_NO_ERROR)); - } - ASSERT(vertexShader->getType() == GL_VERTEX_SHADER); - - reset(); - - int registers; - std::vector linkedVaryings; - LinkResult result = mProgram->link(data, infoLog, fragmentShader, vertexShader, transformFeedbackVaryings, transformFeedbackBufferMode, - ®isters, &linkedVaryings, &mOutputVariables); - if (result.error.isError() || !result.linkSuccess) - { - return result; - } - - if (!linkAttributes(infoLog, attributeBindings, vertexShader)) - { - return LinkResult(false, Error(GL_NO_ERROR)); - } - - if (!mProgram->linkUniforms(infoLog, *vertexShader, *fragmentShader, *data.caps)) - { - return LinkResult(false, Error(GL_NO_ERROR)); - } - - if (!linkUniformBlocks(infoLog, *vertexShader, *fragmentShader, *data.caps)) - { - return LinkResult(false, Error(GL_NO_ERROR)); - } - - if (!gatherTransformFeedbackLinkedVaryings(infoLog, linkedVaryings, transformFeedbackVaryings, - transformFeedbackBufferMode, &mProgram->getTransformFeedbackLinkedVaryings(), *data.caps)) - { - return LinkResult(false, Error(GL_NO_ERROR)); - } - - // TODO: The concept of "executables" is D3D only, and as such this belongs in ProgramD3D. It must be called, - // however, last in this function, so it can't simply be moved to ProgramD3D::link without further shuffling. - result = mProgram->compileProgramExecutables(infoLog, fragmentShader, vertexShader, registers); - if (result.error.isError() || !result.linkSuccess) - { - infoLog.append("Failed to create D3D shaders."); - reset(); - return result; - } - - return LinkResult(true, Error(GL_NO_ERROR)); -} - -bool ProgramBinary::linkUniformBlocks(gl::InfoLog &infoLog, const gl::Shader &vertexShader, const gl::Shader &fragmentShader, - const gl::Caps &caps) -{ - const std::vector &vertexInterfaceBlocks = vertexShader.getInterfaceBlocks(); - const std::vector &fragmentInterfaceBlocks = fragmentShader.getInterfaceBlocks(); - - // Check that interface blocks defined in the vertex and fragment shaders are identical - typedef std::map UniformBlockMap; - UniformBlockMap linkedUniformBlocks; - - for (unsigned int blockIndex = 0; blockIndex < vertexInterfaceBlocks.size(); blockIndex++) - { - const sh::InterfaceBlock &vertexInterfaceBlock = vertexInterfaceBlocks[blockIndex]; - linkedUniformBlocks[vertexInterfaceBlock.name] = &vertexInterfaceBlock; - } - - for (unsigned int blockIndex = 0; blockIndex < fragmentInterfaceBlocks.size(); blockIndex++) - { - const sh::InterfaceBlock &fragmentInterfaceBlock = fragmentInterfaceBlocks[blockIndex]; - UniformBlockMap::const_iterator entry = linkedUniformBlocks.find(fragmentInterfaceBlock.name); - if (entry != linkedUniformBlocks.end()) - { - const sh::InterfaceBlock &vertexInterfaceBlock = *entry->second; - if (!areMatchingInterfaceBlocks(infoLog, vertexInterfaceBlock, fragmentInterfaceBlock)) - { - return false; - } - } - } - - for (unsigned int blockIndex = 0; blockIndex < vertexInterfaceBlocks.size(); blockIndex++) - { - const sh::InterfaceBlock &interfaceBlock = vertexInterfaceBlocks[blockIndex]; - - // Note: shared and std140 layouts are always considered active - if (interfaceBlock.staticUse || interfaceBlock.layout != sh::BLOCKLAYOUT_PACKED) - { - if (!mProgram->defineUniformBlock(infoLog, vertexShader, interfaceBlock, caps)) - { - return false; - } - } - } - - for (unsigned int blockIndex = 0; blockIndex < fragmentInterfaceBlocks.size(); blockIndex++) - { - const sh::InterfaceBlock &interfaceBlock = fragmentInterfaceBlocks[blockIndex]; - - // Note: shared and std140 layouts are always considered active - if (interfaceBlock.staticUse || interfaceBlock.layout != sh::BLOCKLAYOUT_PACKED) - { - if (!mProgram->defineUniformBlock(infoLog, fragmentShader, interfaceBlock, caps)) - { - return false; - } - } - } - - return true; -} - -bool ProgramBinary::areMatchingInterfaceBlocks(gl::InfoLog &infoLog, const sh::InterfaceBlock &vertexInterfaceBlock, - const sh::InterfaceBlock &fragmentInterfaceBlock) -{ - const char* blockName = vertexInterfaceBlock.name.c_str(); - - // validate blocks for the same member types - if (vertexInterfaceBlock.fields.size() != fragmentInterfaceBlock.fields.size()) - { - infoLog.append("Types for interface block '%s' differ between vertex and fragment shaders", blockName); - return false; - } - - if (vertexInterfaceBlock.arraySize != fragmentInterfaceBlock.arraySize) - { - infoLog.append("Array sizes differ for interface block '%s' between vertex and fragment shaders", blockName); - return false; - } - - if (vertexInterfaceBlock.layout != fragmentInterfaceBlock.layout || vertexInterfaceBlock.isRowMajorLayout != fragmentInterfaceBlock.isRowMajorLayout) - { - infoLog.append("Layout qualifiers differ for interface block '%s' between vertex and fragment shaders", blockName); - return false; - } - - const unsigned int numBlockMembers = vertexInterfaceBlock.fields.size(); - for (unsigned int blockMemberIndex = 0; blockMemberIndex < numBlockMembers; blockMemberIndex++) - { - const sh::InterfaceBlockField &vertexMember = vertexInterfaceBlock.fields[blockMemberIndex]; - const sh::InterfaceBlockField &fragmentMember = fragmentInterfaceBlock.fields[blockMemberIndex]; - - if (vertexMember.name != fragmentMember.name) - { - infoLog.append("Name mismatch for field %d of interface block '%s': (in vertex: '%s', in fragment: '%s')", - blockMemberIndex, blockName, vertexMember.name.c_str(), fragmentMember.name.c_str()); - return false; - } - - std::string memberName = "interface block '" + vertexInterfaceBlock.name + "' member '" + vertexMember.name + "'"; - if (!gl::ProgramBinary::linkValidateInterfaceBlockFields(infoLog, memberName, vertexMember, fragmentMember)) - { - return false; - } - } - - return true; -} - -// Determines the mapping between GL attributes and Direct3D 9 vertex stream usage indices -bool ProgramBinary::linkAttributes(InfoLog &infoLog, const AttributeBindings &attributeBindings, const Shader *vertexShader) -{ - const rx::ShaderD3D *vertexShaderD3D = rx::ShaderD3D::makeShaderD3D(vertexShader->getImplementation()); - - unsigned int usedLocations = 0; - const std::vector &shaderAttributes = vertexShader->getActiveAttributes(); - - // Link attributes that have a binding location - for (unsigned int attributeIndex = 0; attributeIndex < shaderAttributes.size(); attributeIndex++) - { - const sh::Attribute &attribute = shaderAttributes[attributeIndex]; - - ASSERT(attribute.staticUse); - - const int location = attribute.location == -1 ? attributeBindings.getAttributeBinding(attribute.name) : attribute.location; - - mProgram->getShaderAttributes()[attributeIndex] = attribute; - - if (location != -1) // Set by glBindAttribLocation or by location layout qualifier - { - const int rows = VariableRegisterCount(attribute.type); - - if (rows + location > MAX_VERTEX_ATTRIBS) - { - infoLog.append("Active attribute (%s) at location %d is too big to fit", attribute.name.c_str(), location); - - return false; - } - - for (int row = 0; row < rows; row++) - { - const int rowLocation = location + row; - sh::ShaderVariable &linkedAttribute = mLinkedAttribute[rowLocation]; - - // In GLSL 3.00, attribute aliasing produces a link error - // In GLSL 1.00, attribute aliasing is allowed - if (mProgram->getShaderVersion() >= 300) - { - if (!linkedAttribute.name.empty()) - { - infoLog.append("Attribute '%s' aliases attribute '%s' at location %d", attribute.name.c_str(), linkedAttribute.name.c_str(), rowLocation); - return false; - } - } - - linkedAttribute = attribute; - usedLocations |= 1 << rowLocation; - } - } - } - - // Link attributes that don't have a binding location - for (unsigned int attributeIndex = 0; attributeIndex < shaderAttributes.size(); attributeIndex++) - { - const sh::Attribute &attribute = shaderAttributes[attributeIndex]; - - ASSERT(attribute.staticUse); - - const int location = attribute.location == -1 ? attributeBindings.getAttributeBinding(attribute.name) : attribute.location; - - if (location == -1) // Not set by glBindAttribLocation or by location layout qualifier - { - int rows = VariableRegisterCount(attribute.type); - int availableIndex = AllocateFirstFreeBits(&usedLocations, rows, MAX_VERTEX_ATTRIBS); - - if (availableIndex == -1 || availableIndex + rows > MAX_VERTEX_ATTRIBS) - { - infoLog.append("Too many active attributes (%s)", attribute.name.c_str()); - - return false; // Fail to link - } - - mLinkedAttribute[availableIndex] = attribute; - } - } - - for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; ) - { - int index = vertexShaderD3D->getSemanticIndex(mLinkedAttribute[attributeIndex].name); - int rows = VariableRegisterCount(mLinkedAttribute[attributeIndex].type); - - for (int r = 0; r < rows; r++) - { - mSemanticIndex[attributeIndex++] = index++; - } - } - - initAttributesByLayout(); - - return true; -} - -bool ProgramBinary::linkValidateVariablesBase(InfoLog &infoLog, const std::string &variableName, const sh::ShaderVariable &vertexVariable, - const sh::ShaderVariable &fragmentVariable, bool validatePrecision) -{ - if (vertexVariable.type != fragmentVariable.type) - { - infoLog.append("Types for %s differ between vertex and fragment shaders", variableName.c_str()); - return false; - } - if (vertexVariable.arraySize != fragmentVariable.arraySize) - { - infoLog.append("Array sizes for %s differ between vertex and fragment shaders", variableName.c_str()); - return false; - } - if (validatePrecision && vertexVariable.precision != fragmentVariable.precision) - { - infoLog.append("Precisions for %s differ between vertex and fragment shaders", variableName.c_str()); - return false; - } - - if (vertexVariable.fields.size() != fragmentVariable.fields.size()) - { - infoLog.append("Structure lengths for %s differ between vertex and fragment shaders", variableName.c_str()); - return false; - } - const unsigned int numMembers = vertexVariable.fields.size(); - for (unsigned int memberIndex = 0; memberIndex < numMembers; memberIndex++) - { - const sh::ShaderVariable &vertexMember = vertexVariable.fields[memberIndex]; - const sh::ShaderVariable &fragmentMember = fragmentVariable.fields[memberIndex]; - - if (vertexMember.name != fragmentMember.name) - { - infoLog.append("Name mismatch for field '%d' of %s: (in vertex: '%s', in fragment: '%s')", - memberIndex, variableName.c_str(), - vertexMember.name.c_str(), fragmentMember.name.c_str()); - return false; - } - - const std::string memberName = variableName.substr(0, variableName.length() - 1) + "." + - vertexMember.name + "'"; - - if (!linkValidateVariablesBase(infoLog, vertexMember.name, vertexMember, fragmentMember, validatePrecision)) - { - return false; - } - } - - return true; -} - -bool ProgramBinary::linkValidateUniforms(InfoLog &infoLog, const std::string &uniformName, const sh::Uniform &vertexUniform, const sh::Uniform &fragmentUniform) -{ - if (!linkValidateVariablesBase(infoLog, uniformName, vertexUniform, fragmentUniform, true)) - { - return false; - } - - return true; -} - -bool ProgramBinary::linkValidateVaryings(InfoLog &infoLog, const std::string &varyingName, const sh::Varying &vertexVarying, const sh::Varying &fragmentVarying) -{ - if (!linkValidateVariablesBase(infoLog, varyingName, vertexVarying, fragmentVarying, false)) - { - return false; - } - - if (vertexVarying.interpolation != fragmentVarying.interpolation) - { - infoLog.append("Interpolation types for %s differ between vertex and fragment shaders", varyingName.c_str()); - return false; - } - - return true; -} - -bool ProgramBinary::linkValidateInterfaceBlockFields(InfoLog &infoLog, const std::string &uniformName, const sh::InterfaceBlockField &vertexUniform, const sh::InterfaceBlockField &fragmentUniform) -{ - if (!linkValidateVariablesBase(infoLog, uniformName, vertexUniform, fragmentUniform, true)) - { - return false; - } - - if (vertexUniform.isRowMajorLayout != fragmentUniform.isRowMajorLayout) - { - infoLog.append("Matrix packings for %s differ between vertex and fragment shaders", uniformName.c_str()); - return false; - } - - return true; -} - -bool ProgramBinary::gatherTransformFeedbackLinkedVaryings(InfoLog &infoLog, const std::vector &linkedVaryings, - const std::vector &transformFeedbackVaryingNames, - GLenum transformFeedbackBufferMode, - std::vector *outTransformFeedbackLinkedVaryings, - const Caps &caps) const -{ - size_t totalComponents = 0; - - // Gather the linked varyings that are used for transform feedback, they should all exist. - outTransformFeedbackLinkedVaryings->clear(); - for (size_t i = 0; i < transformFeedbackVaryingNames.size(); i++) - { - bool found = false; - for (size_t j = 0; j < linkedVaryings.size(); j++) - { - if (transformFeedbackVaryingNames[i] == linkedVaryings[j].name) - { - for (size_t k = 0; k < outTransformFeedbackLinkedVaryings->size(); k++) - { - if (outTransformFeedbackLinkedVaryings->at(k).name == linkedVaryings[j].name) - { - infoLog.append("Two transform feedback varyings specify the same output variable (%s).", linkedVaryings[j].name.c_str()); - return false; - } - } - - size_t componentCount = linkedVaryings[j].semanticIndexCount * 4; - if (transformFeedbackBufferMode == GL_SEPARATE_ATTRIBS && - componentCount > caps.maxTransformFeedbackSeparateComponents) - { - infoLog.append("Transform feedback varying's %s components (%u) exceed the maximum separate components (%u).", - linkedVaryings[j].name.c_str(), componentCount, caps.maxTransformFeedbackSeparateComponents); - return false; - } - - totalComponents += componentCount; - - outTransformFeedbackLinkedVaryings->push_back(linkedVaryings[j]); - found = true; - break; - } - } - - // All transform feedback varyings are expected to exist since packVaryings checks for them. - ASSERT(found); - } - - if (transformFeedbackBufferMode == GL_INTERLEAVED_ATTRIBS && totalComponents > caps.maxTransformFeedbackInterleavedComponents) - { - infoLog.append("Transform feedback varying total components (%u) exceed the maximum interleaved components (%u).", - totalComponents, caps.maxTransformFeedbackInterleavedComponents); - return false; - } - - return true; -} - -bool ProgramBinary::isValidated() const -{ - return mValidated; -} - -void ProgramBinary::getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const -{ - // Skip over inactive attributes - unsigned int activeAttribute = 0; - unsigned int attribute; - for (attribute = 0; attribute < MAX_VERTEX_ATTRIBS; attribute++) - { - if (mLinkedAttribute[attribute].name.empty()) - { - continue; - } - - if (activeAttribute == index) - { - break; - } - - activeAttribute++; - } - - if (bufsize > 0) - { - const char *string = mLinkedAttribute[attribute].name.c_str(); - - strncpy(name, string, bufsize); - name[bufsize - 1] = '\0'; - - if (length) - { - *length = strlen(name); - } - } - - *size = 1; // Always a single 'type' instance - - *type = mLinkedAttribute[attribute].type; -} - -GLint ProgramBinary::getActiveAttributeCount() const -{ - int count = 0; - - for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++) - { - if (!mLinkedAttribute[attributeIndex].name.empty()) - { - count++; - } - } - - return count; -} - -GLint ProgramBinary::getActiveAttributeMaxLength() const -{ - int maxLength = 0; - - for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++) - { - if (!mLinkedAttribute[attributeIndex].name.empty()) - { - maxLength = std::max((int)(mLinkedAttribute[attributeIndex].name.length() + 1), maxLength); - } - } - - return maxLength; -} - -void ProgramBinary::getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const -{ - ASSERT(index < mProgram->getUniforms().size()); // index must be smaller than getActiveUniformCount() - - if (bufsize > 0) - { - std::string string = mProgram->getUniforms()[index]->name; - - if (mProgram->getUniforms()[index]->isArray()) - { - string += "[0]"; - } - - strncpy(name, string.c_str(), bufsize); - name[bufsize - 1] = '\0'; - - if (length) - { - *length = strlen(name); - } - } - - *size = mProgram->getUniforms()[index]->elementCount(); - - *type = mProgram->getUniforms()[index]->type; -} - -GLint ProgramBinary::getActiveUniformCount() const -{ - return mProgram->getUniforms().size(); -} - -GLint ProgramBinary::getActiveUniformMaxLength() const -{ - int maxLength = 0; - - unsigned int numUniforms = mProgram->getUniforms().size(); - for (unsigned int uniformIndex = 0; uniformIndex < numUniforms; uniformIndex++) - { - if (!mProgram->getUniforms()[uniformIndex]->name.empty()) - { - int length = (int)(mProgram->getUniforms()[uniformIndex]->name.length() + 1); - if (mProgram->getUniforms()[uniformIndex]->isArray()) - { - length += 3; // Counting in "[0]". - } - maxLength = std::max(length, maxLength); - } - } - - return maxLength; -} - -GLint ProgramBinary::getActiveUniformi(GLuint index, GLenum pname) const -{ - const gl::LinkedUniform& uniform = *mProgram->getUniforms()[index]; - - switch (pname) - { - case GL_UNIFORM_TYPE: return static_cast(uniform.type); - case GL_UNIFORM_SIZE: return static_cast(uniform.elementCount()); - case GL_UNIFORM_NAME_LENGTH: return static_cast(uniform.name.size() + 1 + (uniform.isArray() ? 3 : 0)); - case GL_UNIFORM_BLOCK_INDEX: return uniform.blockIndex; - - case GL_UNIFORM_OFFSET: return uniform.blockInfo.offset; - case GL_UNIFORM_ARRAY_STRIDE: return uniform.blockInfo.arrayStride; - case GL_UNIFORM_MATRIX_STRIDE: return uniform.blockInfo.matrixStride; - case GL_UNIFORM_IS_ROW_MAJOR: return static_cast(uniform.blockInfo.isRowMajorMatrix); - - default: - UNREACHABLE(); - break; - } - return 0; -} - -bool ProgramBinary::isValidUniformLocation(GLint location) const -{ - ASSERT(rx::IsIntegerCastSafe(mProgram->getUniformIndices().size())); - return (location >= 0 && location < static_cast(mProgram->getUniformIndices().size())); -} - -LinkedUniform *ProgramBinary::getUniformByLocation(GLint location) const -{ - return mProgram->getUniformByLocation(location); -} - -LinkedUniform *ProgramBinary::getUniformByName(const std::string &name) const -{ - return mProgram->getUniformByName(name); -} - -void ProgramBinary::getActiveUniformBlockName(GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName) const -{ - ASSERT(uniformBlockIndex < mProgram->getUniformBlocks().size()); // index must be smaller than getActiveUniformBlockCount() - - const UniformBlock &uniformBlock = *mProgram->getUniformBlocks()[uniformBlockIndex]; - - if (bufSize > 0) - { - std::string string = uniformBlock.name; - - if (uniformBlock.isArrayElement()) - { - string += ArrayString(uniformBlock.elementIndex); - } - - strncpy(uniformBlockName, string.c_str(), bufSize); - uniformBlockName[bufSize - 1] = '\0'; - - if (length) - { - *length = strlen(uniformBlockName); - } - } -} - -void ProgramBinary::getActiveUniformBlockiv(GLuint uniformBlockIndex, GLenum pname, GLint *params) const -{ - ASSERT(uniformBlockIndex < mProgram->getUniformBlocks().size()); // index must be smaller than getActiveUniformBlockCount() - - const UniformBlock &uniformBlock = *mProgram->getUniformBlocks()[uniformBlockIndex]; - - switch (pname) - { - case GL_UNIFORM_BLOCK_DATA_SIZE: - *params = static_cast(uniformBlock.dataSize); - break; - case GL_UNIFORM_BLOCK_NAME_LENGTH: - *params = static_cast(uniformBlock.name.size() + 1 + (uniformBlock.isArrayElement() ? 3 : 0)); - break; - case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS: - *params = static_cast(uniformBlock.memberUniformIndexes.size()); - break; - case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES: - { - for (unsigned int blockMemberIndex = 0; blockMemberIndex < uniformBlock.memberUniformIndexes.size(); blockMemberIndex++) - { - params[blockMemberIndex] = static_cast(uniformBlock.memberUniformIndexes[blockMemberIndex]); - } - } - break; - case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER: - *params = static_cast(uniformBlock.isReferencedByVertexShader()); - break; - case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER: - *params = static_cast(uniformBlock.isReferencedByFragmentShader()); - break; - default: UNREACHABLE(); - } -} - -GLuint ProgramBinary::getActiveUniformBlockCount() const -{ - return mProgram->getUniformBlocks().size(); -} - -GLuint ProgramBinary::getActiveUniformBlockMaxLength() const -{ - unsigned int maxLength = 0; - - unsigned int numUniformBlocks = mProgram->getUniformBlocks().size(); - for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < numUniformBlocks; uniformBlockIndex++) - { - const UniformBlock &uniformBlock = *mProgram->getUniformBlocks()[uniformBlockIndex]; - if (!uniformBlock.name.empty()) - { - const unsigned int length = uniformBlock.name.length() + 1; - - // Counting in "[0]". - const unsigned int arrayLength = (uniformBlock.isArrayElement() ? 3 : 0); - - maxLength = std::max(length + arrayLength, maxLength); - } - } - - return maxLength; -} - -void ProgramBinary::validate(InfoLog &infoLog, const Caps &caps) -{ - applyUniforms(); - if (!validateSamplers(&infoLog, caps)) - { - mValidated = false; - } - else - { - mValidated = true; - } -} - -bool ProgramBinary::validateSamplers(InfoLog *infoLog, const Caps &caps) -{ - return mProgram->validateSamplers(infoLog, caps); -} - -struct AttributeSorter -{ - AttributeSorter(const int (&semanticIndices)[MAX_VERTEX_ATTRIBS]) - : originalIndices(semanticIndices) - { - } - - bool operator()(int a, int b) - { - if (originalIndices[a] == -1) return false; - if (originalIndices[b] == -1) return true; - return (originalIndices[a] < originalIndices[b]); - } - - const int (&originalIndices)[MAX_VERTEX_ATTRIBS]; -}; - -void ProgramBinary::initAttributesByLayout() -{ - for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) - { - mAttributesByLayout[i] = i; - } - - std::sort(&mAttributesByLayout[0], &mAttributesByLayout[MAX_VERTEX_ATTRIBS], AttributeSorter(mSemanticIndex)); -} - -void ProgramBinary::sortAttributesByLayout(rx::TranslatedAttribute attributes[MAX_VERTEX_ATTRIBS], int sortedSemanticIndices[MAX_VERTEX_ATTRIBS]) const -{ - rx::TranslatedAttribute oldTranslatedAttributes[MAX_VERTEX_ATTRIBS]; - - for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) - { - oldTranslatedAttributes[i] = attributes[i]; - } - - for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) - { - int oldIndex = mAttributesByLayout[i]; - sortedSemanticIndices[i] = oldIndex; - attributes[i] = oldTranslatedAttributes[oldIndex]; - } -} - -void ProgramBinary::reset() -{ - mOutputVariables.clear(); - - mProgram->reset(); - - mValidated = false; -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/ProgramBinary.h b/src/3rdparty/angle/src/libGLESv2/ProgramBinary.h deleted file mode 100644 index 3142d66c6d..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/ProgramBinary.h +++ /dev/null @@ -1,237 +0,0 @@ -// -// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Program.h: Defines the gl::Program class. Implements GL program objects -// and related functionality. [OpenGL ES 2.0.24] section 2.10.3 page 28. - -#ifndef LIBGLESV2_PROGRAM_BINARY_H_ -#define LIBGLESV2_PROGRAM_BINARY_H_ - -#include "common/RefCountObject.h" -#include "angletypes.h" -#include "common/mathutil.h" -#include "libGLESv2/Uniform.h" -#include "libGLESv2/Shader.h" -#include "libGLESv2/Constants.h" -#include "libGLESv2/renderer/d3d/VertexDataManager.h" -#include "libGLESv2/renderer/d3d/DynamicHLSL.h" - -#include "angle_gl.h" - -#include -#include - -namespace sh -{ -class HLSLBlockEncoder; -} - -#include -#include -#include - -#include -#include - -namespace rx -{ -class ShaderExecutable; -struct TranslatedAttribute; -class UniformStorage; -class ProgramImpl; -} - -namespace gl -{ -struct Caps; -class Shader; -class InfoLog; -class AttributeBindings; -class Buffer; -class Framebuffer; -struct Data; - -// Struct used for correlating uniforms/elements of uniform arrays to handles -struct VariableLocation -{ - VariableLocation() - { - } - - VariableLocation(const std::string &name, unsigned int element, unsigned int index); - - std::string name; - unsigned int element; - unsigned int index; -}; - -struct LinkedVarying -{ - LinkedVarying(); - LinkedVarying(const std::string &name, GLenum type, GLsizei size, const std::string &semanticName, - unsigned int semanticIndex, unsigned int semanticIndexCount); - - // Original GL name - std::string name; - - GLenum type; - GLsizei size; - - // DirectX semantic information - std::string semanticName; - unsigned int semanticIndex; - unsigned int semanticIndexCount; -}; - -struct LinkResult -{ - bool linkSuccess; - Error error; - - LinkResult(bool linkSuccess, const Error &error); -}; - -// This is the result of linking a program. It is the state that would be passed to ProgramBinary. -class ProgramBinary : public RefCountObject -{ - public: - explicit ProgramBinary(rx::ProgramImpl *impl); - ~ProgramBinary(); - - rx::ProgramImpl *getImplementation() { return mProgram; } - const rx::ProgramImpl *getImplementation() const { return mProgram; } - - GLuint getAttributeLocation(const char *name); - int getSemanticIndex(int attributeIndex); - - GLint getSamplerMapping(SamplerType type, unsigned int samplerIndex, const Caps &caps); - GLenum getSamplerTextureType(SamplerType type, unsigned int samplerIndex); - GLint getUsedSamplerRange(SamplerType type); - bool usesPointSize() const; - - GLint getUniformLocation(std::string name); - GLuint getUniformIndex(std::string name); - GLuint getUniformBlockIndex(std::string name); - void setUniform1fv(GLint location, GLsizei count, const GLfloat *v); - void setUniform2fv(GLint location, GLsizei count, const GLfloat *v); - void setUniform3fv(GLint location, GLsizei count, const GLfloat *v); - void setUniform4fv(GLint location, GLsizei count, const GLfloat *v); - void setUniform1iv(GLint location, GLsizei count, const GLint *v); - void setUniform2iv(GLint location, GLsizei count, const GLint *v); - void setUniform3iv(GLint location, GLsizei count, const GLint *v); - void setUniform4iv(GLint location, GLsizei count, const GLint *v); - void setUniform1uiv(GLint location, GLsizei count, const GLuint *v); - void setUniform2uiv(GLint location, GLsizei count, const GLuint *v); - void setUniform3uiv(GLint location, GLsizei count, const GLuint *v); - void setUniform4uiv(GLint location, GLsizei count, const GLuint *v); - void setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); - void setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); - void setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); - void setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); - void setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); - void setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); - void setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); - void setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); - void setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); - - void getUniformfv(GLint location, GLfloat *params); - void getUniformiv(GLint location, GLint *params); - void getUniformuiv(GLint location, GLuint *params); - - Error applyUniforms(); - Error applyUniformBuffers(const std::vector boundBuffers, const Caps &caps); - - LinkResult load(InfoLog &infoLog, GLenum binaryFormat, const void *binary, GLsizei length); - Error save(GLenum *binaryFormat, void *binary, GLsizei bufSize, GLsizei *length); - GLint getLength(); - - LinkResult link(const Data &data, InfoLog &infoLog, const AttributeBindings &attributeBindings, - Shader *fragmentShader, Shader *vertexShader, - const std::vector &transformFeedbackVaryings, - GLenum transformFeedbackBufferMode); - - 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) const; - GLint getActiveUniformCount() const; - GLint getActiveUniformMaxLength() const; - GLint getActiveUniformi(GLuint index, GLenum pname) const; - bool isValidUniformLocation(GLint location) const; - LinkedUniform *getUniformByLocation(GLint location) const; - LinkedUniform *getUniformByName(const std::string &name) const; - - void getActiveUniformBlockName(GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName) const; - void getActiveUniformBlockiv(GLuint uniformBlockIndex, GLenum pname, GLint *params) const; - GLuint getActiveUniformBlockCount() const; - GLuint getActiveUniformBlockMaxLength() const; - UniformBlock *getUniformBlockByIndex(GLuint blockIndex); - - GLint getFragDataLocation(const char *name) const; - - size_t getTransformFeedbackVaryingCount() const; - const LinkedVarying &getTransformFeedbackVarying(size_t idx) const; - GLenum getTransformFeedbackBufferMode() const; - - void validate(InfoLog &infoLog, const Caps &caps); - bool validateSamplers(InfoLog *infoLog, const Caps &caps); - bool isValidated() const; - void updateSamplerMapping(); - - unsigned int getSerial() const; - - void initAttributesByLayout(); - void sortAttributesByLayout(rx::TranslatedAttribute attributes[MAX_VERTEX_ATTRIBS], int sortedSemanticIndices[MAX_VERTEX_ATTRIBS]) const; - - static bool linkVaryings(InfoLog &infoLog, Shader *fragmentShader, Shader *vertexShader); - static bool linkValidateUniforms(InfoLog &infoLog, const std::string &uniformName, const sh::Uniform &vertexUniform, const sh::Uniform &fragmentUniform); - static bool linkValidateInterfaceBlockFields(InfoLog &infoLog, const std::string &uniformName, const sh::InterfaceBlockField &vertexUniform, const sh::InterfaceBlockField &fragmentUniform); - - private: - DISALLOW_COPY_AND_ASSIGN(ProgramBinary); - - void reset(); - - bool linkAttributes(InfoLog &infoLog, const AttributeBindings &attributeBindings, const Shader *vertexShader); - bool linkUniformBlocks(InfoLog &infoLog, const Shader &vertexShader, const Shader &fragmentShader, const Caps &caps); - bool areMatchingInterfaceBlocks(gl::InfoLog &infoLog, const sh::InterfaceBlock &vertexInterfaceBlock, - const sh::InterfaceBlock &fragmentInterfaceBlock); - - static bool linkValidateVariablesBase(InfoLog &infoLog, - const std::string &variableName, - const sh::ShaderVariable &vertexVariable, - const sh::ShaderVariable &fragmentVariable, - bool validatePrecision); - - static bool linkValidateVaryings(InfoLog &infoLog, const std::string &varyingName, const sh::Varying &vertexVarying, const sh::Varying &fragmentVarying); - bool gatherTransformFeedbackLinkedVaryings(InfoLog &infoLog, const std::vector &linkedVaryings, - const std::vector &transformFeedbackVaryingNames, - GLenum transformFeedbackBufferMode, - std::vector *outTransformFeedbackLinkedVaryings, - const Caps &caps) const; - bool assignUniformBlockRegister(InfoLog &infoLog, UniformBlock *uniformBlock, GLenum shader, unsigned int registerIndex, const Caps &caps); - void defineOutputVariables(Shader *fragmentShader); - - rx::ProgramImpl *mProgram; - - sh::Attribute mLinkedAttribute[MAX_VERTEX_ATTRIBS]; - int mSemanticIndex[MAX_VERTEX_ATTRIBS]; - int mAttributesByLayout[MAX_VERTEX_ATTRIBS]; - - std::map mOutputVariables; - - bool mValidated; - - const unsigned int mSerial; - - static unsigned int issueSerial(); - static unsigned int mCurrentSerial; -}; - -} - -#endif // LIBGLESV2_PROGRAM_BINARY_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/Query.cpp b/src/3rdparty/angle/src/libGLESv2/Query.cpp deleted file mode 100644 index 4ee3525509..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/Query.cpp +++ /dev/null @@ -1,50 +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. -// - -// Query.cpp: Implements the gl::Query class - -#include "libGLESv2/Query.h" -#include "libGLESv2/renderer/QueryImpl.h" - -namespace gl -{ -Query::Query(rx::QueryImpl *impl, GLuint id) - : RefCountObject(id), - mQuery(impl) -{ -} - -Query::~Query() -{ - SafeDelete(mQuery); -} - -Error Query::begin() -{ - return mQuery->begin(); -} - -Error Query::end() -{ - return mQuery->end(); -} - -Error Query::getResult(GLuint *params) -{ - return mQuery->getResult(params); -} - -Error Query::isResultAvailable(GLuint *available) -{ - return mQuery->isResultAvailable(available); -} - -GLenum Query::getType() const -{ - return mQuery->getType(); -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/Query.h b/src/3rdparty/angle/src/libGLESv2/Query.h deleted file mode 100644 index a7ec404f85..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/Query.h +++ /dev/null @@ -1,48 +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. -// - -// Query.h: Defines the gl::Query class - -#ifndef LIBGLESV2_QUERY_H_ -#define LIBGLESV2_QUERY_H_ - -#include "libGLESv2/Error.h" -#include "common/angleutils.h" -#include "common/RefCountObject.h" - -#include "angle_gl.h" - -namespace rx -{ -class QueryImpl; -} - -namespace gl -{ - -class Query : public RefCountObject -{ - public: - Query(rx::QueryImpl *impl, GLuint id); - virtual ~Query(); - - Error begin(); - Error end(); - - Error getResult(GLuint *params); - Error isResultAvailable(GLuint *available); - - GLenum getType() const; - - private: - DISALLOW_COPY_AND_ASSIGN(Query); - - rx::QueryImpl *mQuery; -}; - -} - -#endif // LIBGLESV2_QUERY_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/Renderbuffer.cpp b/src/3rdparty/angle/src/libGLESv2/Renderbuffer.cpp deleted file mode 100644 index 911a389dfa..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/Renderbuffer.cpp +++ /dev/null @@ -1,119 +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. -// - -// Renderbuffer.cpp: Implements the renderer-agnostic gl::Renderbuffer class, -// GL renderbuffer objects and related functionality. -// [OpenGL ES 2.0.24] section 4.4.3 page 108. - -#include "libGLESv2/Renderbuffer.h" -#include "libGLESv2/Texture.h" -#include "libGLESv2/formatutils.h" -#include "libGLESv2/FramebufferAttachment.h" -#include "libGLESv2/renderer/d3d/RendererD3D.h" -#include "libGLESv2/renderer/RenderTarget.h" -#include "libGLESv2/renderer/RenderbufferImpl.h" - -#include "common/utilities.h" - -namespace gl -{ -Renderbuffer::Renderbuffer(rx::RenderbufferImpl *impl, GLuint id) - : RefCountObject(id), - mRenderbuffer(impl) -{ - ASSERT(mRenderbuffer); - - mWidth = mRenderbuffer->getWidth(); - mHeight = mRenderbuffer->getHeight(); - mInternalFormat = mRenderbuffer->getInternalFormat(); - mActualFormat = mRenderbuffer->getActualFormat(); - mSamples = mRenderbuffer->getSamples(); -} - -Renderbuffer::~Renderbuffer() -{ - SafeDelete(mRenderbuffer); -} - -Error Renderbuffer::setStorage(GLsizei width, GLsizei height, GLenum internalformat, GLsizei samples) -{ - Error error = mRenderbuffer->setStorage(width, height, internalformat, samples); - if (error.isError()) - { - return error; - } - - mWidth = width; - mHeight = height; - mInternalFormat = internalformat; - mSamples = samples; - mActualFormat = mRenderbuffer->getActualFormat(); - - return Error(GL_NO_ERROR); -} - -rx::RenderbufferImpl *Renderbuffer::getImplementation() -{ - ASSERT(mRenderbuffer); - return mRenderbuffer; -} - -GLsizei Renderbuffer::getWidth() const -{ - return mWidth; -} - -GLsizei Renderbuffer::getHeight() const -{ - return mHeight; -} - -GLenum Renderbuffer::getInternalFormat() const -{ - return mInternalFormat; -} - -GLenum Renderbuffer::getActualFormat() const -{ - return mActualFormat; -} - -GLsizei Renderbuffer::getSamples() const -{ - return mSamples; -} - -GLuint Renderbuffer::getRedSize() const -{ - return GetInternalFormatInfo(getActualFormat()).redBits; -} - -GLuint Renderbuffer::getGreenSize() const -{ - return GetInternalFormatInfo(getActualFormat()).greenBits; -} - -GLuint Renderbuffer::getBlueSize() const -{ - return GetInternalFormatInfo(getActualFormat()).blueBits; -} - -GLuint Renderbuffer::getAlphaSize() const -{ - return GetInternalFormatInfo(getActualFormat()).alphaBits; -} - -GLuint Renderbuffer::getDepthSize() const -{ - return GetInternalFormatInfo(getActualFormat()).depthBits; -} - -GLuint Renderbuffer::getStencilSize() const -{ - return GetInternalFormatInfo(getActualFormat()).stencilBits; -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/Renderbuffer.h b/src/3rdparty/angle/src/libGLESv2/Renderbuffer.h deleted file mode 100644 index e9f12af3ce..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/Renderbuffer.h +++ /dev/null @@ -1,71 +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. -// - -// Renderbuffer.h: Defines the renderer-agnostic container class gl::Renderbuffer. -// Implements GL renderbuffer objects and related functionality. -// [OpenGL ES 2.0.24] section 4.4.3 page 108. - -#ifndef LIBGLESV2_RENDERBUFFER_H_ -#define LIBGLESV2_RENDERBUFFER_H_ - -#include "angle_gl.h" - -#include "libGLESv2/Error.h" - -#include "common/angleutils.h" -#include "common/RefCountObject.h" - -namespace rx -{ -class RenderbufferImpl; -} - -namespace gl -{ -class FramebufferAttachment; - -// A GL renderbuffer object is usually used as a depth or stencil buffer attachment -// for a framebuffer object. The renderbuffer itself is a distinct GL object, see -// FramebufferAttachment and Framebuffer for how they are applied to an FBO via an -// attachment point. - -class Renderbuffer : public RefCountObject -{ - public: - Renderbuffer(rx::RenderbufferImpl *impl, GLuint id); - virtual ~Renderbuffer(); - - Error setStorage(GLsizei width, GLsizei height, GLenum internalformat, GLsizei samples); - - rx::RenderbufferImpl *getImplementation(); - - GLsizei getWidth() const; - GLsizei getHeight() const; - GLenum getInternalFormat() const; - GLenum getActualFormat() const; - GLsizei getSamples() const; - GLuint getRedSize() const; - GLuint getGreenSize() const; - GLuint getBlueSize() const; - GLuint getAlphaSize() const; - GLuint getDepthSize() const; - GLuint getStencilSize() const; - - private: - DISALLOW_COPY_AND_ASSIGN(Renderbuffer); - - rx::RenderbufferImpl *mRenderbuffer; - - GLsizei mWidth; - GLsizei mHeight; - GLenum mInternalFormat; - GLenum mActualFormat; - GLsizei mSamples; -}; - -} - -#endif // LIBGLESV2_RENDERBUFFER_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/ResourceManager.cpp b/src/3rdparty/angle/src/libGLESv2/ResourceManager.cpp deleted file mode 100644 index 38d53cad81..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/ResourceManager.cpp +++ /dev/null @@ -1,427 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// ResourceManager.cpp: Implements the gl::ResourceManager class, which tracks and -// retrieves objects which may be shared by multiple Contexts. - -#include "libGLESv2/ResourceManager.h" - -#include "libGLESv2/Buffer.h" -#include "libGLESv2/Program.h" -#include "libGLESv2/Renderbuffer.h" -#include "libGLESv2/Shader.h" -#include "libGLESv2/Texture.h" -#include "libGLESv2/Sampler.h" -#include "libGLESv2/Fence.h" -#include "libGLESv2/renderer/Renderer.h" - -namespace gl -{ -ResourceManager::ResourceManager(rx::Renderer *renderer) - : mRenderer(renderer), - mRefCount(1) -{ -} - -ResourceManager::~ResourceManager() -{ - while (!mBufferMap.empty()) - { - deleteBuffer(mBufferMap.begin()->first); - } - - while (!mProgramMap.empty()) - { - deleteProgram(mProgramMap.begin()->first); - } - - while (!mShaderMap.empty()) - { - deleteShader(mShaderMap.begin()->first); - } - - while (!mRenderbufferMap.empty()) - { - deleteRenderbuffer(mRenderbufferMap.begin()->first); - } - - while (!mTextureMap.empty()) - { - deleteTexture(mTextureMap.begin()->first); - } - - while (!mSamplerMap.empty()) - { - deleteSampler(mSamplerMap.begin()->first); - } - - while (!mFenceSyncMap.empty()) - { - deleteFenceSync(mFenceSyncMap.begin()->first); - } -} - -void ResourceManager::addRef() -{ - mRefCount++; -} - -void ResourceManager::release() -{ - if (--mRefCount == 0) - { - delete this; - } -} - -// Returns an unused buffer name -GLuint ResourceManager::createBuffer() -{ - GLuint handle = mBufferHandleAllocator.allocate(); - - mBufferMap[handle] = NULL; - - return handle; -} - -// Returns an unused shader/program name -GLuint ResourceManager::createShader(const gl::Data &data, GLenum type) -{ - GLuint handle = mProgramShaderHandleAllocator.allocate(); - - if (type == GL_VERTEX_SHADER || type == GL_FRAGMENT_SHADER) - { - mShaderMap[handle] = new Shader(this, mRenderer->createShader(data, type), type, handle); - } - else UNREACHABLE(); - - return handle; -} - -// Returns an unused program/shader name -GLuint ResourceManager::createProgram() -{ - GLuint handle = mProgramShaderHandleAllocator.allocate(); - - mProgramMap[handle] = new Program(mRenderer, this, handle); - - return handle; -} - -// Returns an unused texture name -GLuint ResourceManager::createTexture() -{ - GLuint handle = mTextureHandleAllocator.allocate(); - - mTextureMap[handle] = NULL; - - return handle; -} - -// Returns an unused renderbuffer name -GLuint ResourceManager::createRenderbuffer() -{ - GLuint handle = mRenderbufferHandleAllocator.allocate(); - - mRenderbufferMap[handle] = NULL; - - return handle; -} - -// Returns an unused sampler name -GLuint ResourceManager::createSampler() -{ - GLuint handle = mSamplerHandleAllocator.allocate(); - - mSamplerMap[handle] = NULL; - - return handle; -} - -// Returns the next unused fence name, and allocates the fence -GLuint ResourceManager::createFenceSync() -{ - GLuint handle = mFenceSyncHandleAllocator.allocate(); - - FenceSync *fenceSync = new FenceSync(mRenderer->createFenceSync(), handle); - fenceSync->addRef(); - mFenceSyncMap[handle] = fenceSync; - - return handle; -} - -void ResourceManager::deleteBuffer(GLuint buffer) -{ - BufferMap::iterator bufferObject = mBufferMap.find(buffer); - - if (bufferObject != mBufferMap.end()) - { - mBufferHandleAllocator.release(bufferObject->first); - if (bufferObject->second) bufferObject->second->release(); - mBufferMap.erase(bufferObject); - } -} - -void ResourceManager::deleteShader(GLuint shader) -{ - ShaderMap::iterator shaderObject = mShaderMap.find(shader); - - if (shaderObject != mShaderMap.end()) - { - if (shaderObject->second->getRefCount() == 0) - { - mProgramShaderHandleAllocator.release(shaderObject->first); - delete shaderObject->second; - mShaderMap.erase(shaderObject); - } - else - { - shaderObject->second->flagForDeletion(); - } - } -} - -void ResourceManager::deleteProgram(GLuint program) -{ - ProgramMap::iterator programObject = mProgramMap.find(program); - - if (programObject != mProgramMap.end()) - { - if (programObject->second->getRefCount() == 0) - { - mProgramShaderHandleAllocator.release(programObject->first); - delete programObject->second; - mProgramMap.erase(programObject); - } - else - { - programObject->second->flagForDeletion(); - } - } -} - -void ResourceManager::deleteTexture(GLuint texture) -{ - TextureMap::iterator textureObject = mTextureMap.find(texture); - - if (textureObject != mTextureMap.end()) - { - mTextureHandleAllocator.release(textureObject->first); - if (textureObject->second) textureObject->second->release(); - mTextureMap.erase(textureObject); - } -} - -void ResourceManager::deleteRenderbuffer(GLuint renderbuffer) -{ - RenderbufferMap::iterator renderbufferObject = mRenderbufferMap.find(renderbuffer); - - if (renderbufferObject != mRenderbufferMap.end()) - { - mRenderbufferHandleAllocator.release(renderbufferObject->first); - if (renderbufferObject->second) renderbufferObject->second->release(); - mRenderbufferMap.erase(renderbufferObject); - } -} - -void ResourceManager::deleteSampler(GLuint sampler) -{ - auto samplerObject = mSamplerMap.find(sampler); - - if (samplerObject != mSamplerMap.end()) - { - mSamplerHandleAllocator.release(samplerObject->first); - if (samplerObject->second) samplerObject->second->release(); - mSamplerMap.erase(samplerObject); - } -} - -void ResourceManager::deleteFenceSync(GLuint fenceSync) -{ - auto fenceObjectIt = mFenceSyncMap.find(fenceSync); - - if (fenceObjectIt != mFenceSyncMap.end()) - { - mFenceSyncHandleAllocator.release(fenceObjectIt->first); - if (fenceObjectIt->second) fenceObjectIt->second->release(); - mFenceSyncMap.erase(fenceObjectIt); - } -} - -Buffer *ResourceManager::getBuffer(unsigned int handle) -{ - BufferMap::iterator buffer = mBufferMap.find(handle); - - if (buffer == mBufferMap.end()) - { - return NULL; - } - else - { - return buffer->second; - } -} - -Shader *ResourceManager::getShader(unsigned int handle) -{ - ShaderMap::iterator shader = mShaderMap.find(handle); - - if (shader == mShaderMap.end()) - { - return NULL; - } - else - { - return shader->second; - } -} - -Texture *ResourceManager::getTexture(unsigned int handle) -{ - if (handle == 0) return NULL; - - TextureMap::iterator texture = mTextureMap.find(handle); - - if (texture == mTextureMap.end()) - { - return NULL; - } - else - { - return texture->second; - } -} - -Program *ResourceManager::getProgram(unsigned int handle) const -{ - ProgramMap::const_iterator program = mProgramMap.find(handle); - - if (program == mProgramMap.end()) - { - return NULL; - } - else - { - return program->second; - } -} - -Renderbuffer *ResourceManager::getRenderbuffer(unsigned int handle) -{ - RenderbufferMap::iterator renderbuffer = mRenderbufferMap.find(handle); - - if (renderbuffer == mRenderbufferMap.end()) - { - return NULL; - } - else - { - return renderbuffer->second; - } -} - -Sampler *ResourceManager::getSampler(unsigned int handle) -{ - auto sampler = mSamplerMap.find(handle); - - if (sampler == mSamplerMap.end()) - { - return NULL; - } - else - { - return sampler->second; - } -} - -FenceSync *ResourceManager::getFenceSync(unsigned int handle) -{ - auto fenceObjectIt = mFenceSyncMap.find(handle); - - if (fenceObjectIt == mFenceSyncMap.end()) - { - return NULL; - } - else - { - return fenceObjectIt->second; - } -} - -void ResourceManager::setRenderbuffer(GLuint handle, Renderbuffer *buffer) -{ - mRenderbufferMap[handle] = buffer; -} - -void ResourceManager::checkBufferAllocation(unsigned int buffer) -{ - if (buffer != 0 && !getBuffer(buffer)) - { - Buffer *bufferObject = new Buffer(mRenderer->createBuffer(), buffer); - mBufferMap[buffer] = bufferObject; - bufferObject->addRef(); - } -} - -void ResourceManager::checkTextureAllocation(GLuint texture, GLenum type) -{ - if (!getTexture(texture) && texture != 0) - { - Texture *textureObject; - - if (type == GL_TEXTURE_2D) - { - textureObject = new Texture2D(mRenderer->createTexture(GL_TEXTURE_2D), texture); - } - else if (type == GL_TEXTURE_CUBE_MAP) - { - textureObject = new TextureCubeMap(mRenderer->createTexture(GL_TEXTURE_CUBE_MAP), texture); - } - else if (type == GL_TEXTURE_3D) - { - textureObject = new Texture3D(mRenderer->createTexture(GL_TEXTURE_3D), texture); - } - else if (type == GL_TEXTURE_2D_ARRAY) - { - textureObject = new Texture2DArray(mRenderer->createTexture(GL_TEXTURE_2D_ARRAY), texture); - } - else - { - UNREACHABLE(); - return; - } - - mTextureMap[texture] = textureObject; - textureObject->addRef(); - } -} - -void ResourceManager::checkRenderbufferAllocation(GLuint renderbuffer) -{ - if (renderbuffer != 0 && !getRenderbuffer(renderbuffer)) - { - Renderbuffer *renderbufferObject = new Renderbuffer(mRenderer->createRenderbuffer(), renderbuffer); - mRenderbufferMap[renderbuffer] = renderbufferObject; - renderbufferObject->addRef(); - } -} - -void ResourceManager::checkSamplerAllocation(GLuint sampler) -{ - if (sampler != 0 && !getSampler(sampler)) - { - Sampler *samplerObject = new Sampler(sampler); - mSamplerMap[sampler] = samplerObject; - samplerObject->addRef(); - } -} - -bool ResourceManager::isSampler(GLuint sampler) -{ - return mSamplerMap.find(sampler) != mSamplerMap.end(); -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/ResourceManager.h b/src/3rdparty/angle/src/libGLESv2/ResourceManager.h deleted file mode 100644 index acad29b51d..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/ResourceManager.h +++ /dev/null @@ -1,115 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// ResourceManager.h : Defines the ResourceManager class, which tracks objects -// shared by multiple GL contexts. - -#ifndef LIBGLESV2_RESOURCEMANAGER_H_ -#define LIBGLESV2_RESOURCEMANAGER_H_ - -#include "common/angleutils.h" -#include "libGLESv2/angletypes.h" -#include "libGLESv2/HandleAllocator.h" - -#include "angle_gl.h" - -#include - -namespace rx -{ -class Renderer; -} - -namespace gl -{ -class Buffer; -class Shader; -class Program; -class Texture; -class Renderbuffer; -class Sampler; -class FenceSync; -struct Data; - -class ResourceManager -{ - public: - explicit ResourceManager(rx::Renderer *renderer); - ~ResourceManager(); - - void addRef(); - void release(); - - GLuint createBuffer(); - GLuint createShader(const gl::Data &data, GLenum type); - GLuint createProgram(); - GLuint createTexture(); - GLuint createRenderbuffer(); - GLuint createSampler(); - GLuint createFenceSync(); - - void deleteBuffer(GLuint buffer); - void deleteShader(GLuint shader); - void deleteProgram(GLuint program); - void deleteTexture(GLuint texture); - void deleteRenderbuffer(GLuint renderbuffer); - void deleteSampler(GLuint sampler); - void deleteFenceSync(GLuint fenceSync); - - Buffer *getBuffer(GLuint handle); - Shader *getShader(GLuint handle); - Program *getProgram(GLuint handle) const; - Texture *getTexture(GLuint handle); - Renderbuffer *getRenderbuffer(GLuint handle); - Sampler *getSampler(GLuint handle); - FenceSync *getFenceSync(GLuint handle); - - void setRenderbuffer(GLuint handle, Renderbuffer *renderbuffer); - - void checkBufferAllocation(unsigned int buffer); - void checkTextureAllocation(GLuint texture, GLenum type); - void checkRenderbufferAllocation(GLuint renderbuffer); - void checkSamplerAllocation(GLuint sampler); - - bool isSampler(GLuint sampler); - - private: - DISALLOW_COPY_AND_ASSIGN(ResourceManager); - - rx::Renderer *mRenderer; - std::size_t mRefCount; - - typedef std::unordered_map BufferMap; - BufferMap mBufferMap; - HandleAllocator mBufferHandleAllocator; - - typedef std::unordered_map ShaderMap; - ShaderMap mShaderMap; - - typedef std::unordered_map ProgramMap; - ProgramMap mProgramMap; - HandleAllocator mProgramShaderHandleAllocator; - - typedef std::unordered_map TextureMap; - TextureMap mTextureMap; - HandleAllocator mTextureHandleAllocator; - - typedef std::unordered_map RenderbufferMap; - RenderbufferMap mRenderbufferMap; - HandleAllocator mRenderbufferHandleAllocator; - - typedef std::unordered_map SamplerMap; - SamplerMap mSamplerMap; - HandleAllocator mSamplerHandleAllocator; - - typedef std::unordered_map FenceMap; - FenceMap mFenceSyncMap; - HandleAllocator mFenceSyncHandleAllocator; -}; - -} - -#endif // LIBGLESV2_RESOURCEMANAGER_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/Sampler.cpp b/src/3rdparty/angle/src/libGLESv2/Sampler.cpp deleted file mode 100644 index b906e65557..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/Sampler.cpp +++ /dev/null @@ -1,43 +0,0 @@ -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Sampler.cpp : Implements the Sampler class, which represents a GLES 3 -// sampler object. Sampler objects store some state needed to sample textures. - -#include "libGLESv2/Sampler.h" -#include "libGLESv2/angletypes.h" - -namespace gl -{ - -Sampler::Sampler(GLuint id) - : RefCountObject(id), - mMinFilter(GL_NEAREST_MIPMAP_LINEAR), - mMagFilter(GL_LINEAR), - mWrapS(GL_REPEAT), - mWrapT(GL_REPEAT), - mWrapR(GL_REPEAT), - mMinLod(-1000.0f), - mMaxLod(1000.0f), - mComparisonMode(GL_NONE), - mComparisonFunc(GL_LEQUAL) -{ -} - -void Sampler::getState(SamplerState *samplerState) const -{ - samplerState->minFilter = mMinFilter; - samplerState->magFilter = mMagFilter; - samplerState->wrapS = mWrapS; - samplerState->wrapT = mWrapT; - samplerState->wrapR = mWrapR; - samplerState->minLod = mMinLod; - samplerState->maxLod = mMaxLod; - samplerState->compareMode = mComparisonMode; - samplerState->compareFunc = mComparisonFunc; -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/Sampler.h b/src/3rdparty/angle/src/libGLESv2/Sampler.h deleted file mode 100644 index 257bc25d22..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/Sampler.h +++ /dev/null @@ -1,60 +0,0 @@ -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Sampler.h : Defines the Sampler class, which represents a GLES 3 -// sampler object. Sampler objects store some state needed to sample textures. - -#ifndef LIBGLESV2_SAMPLER_H_ -#define LIBGLESV2_SAMPLER_H_ - -#include "common/RefCountObject.h" - -namespace gl -{ -struct SamplerState; - -class Sampler : public RefCountObject -{ - public: - Sampler(GLuint id); - - void setMinFilter(GLenum minFilter) { mMinFilter = minFilter; } - void setMagFilter(GLenum magFilter) { mMagFilter = magFilter; } - void setWrapS(GLenum wrapS) { mWrapS = wrapS; } - void setWrapT(GLenum wrapT) { mWrapT = wrapT; } - void setWrapR(GLenum wrapR) { mWrapR = wrapR; } - void setMinLod(GLfloat minLod) { mMinLod = minLod; } - void setMaxLod(GLfloat maxLod) { mMaxLod = maxLod; } - void setComparisonMode(GLenum comparisonMode) { mComparisonMode = comparisonMode; } - void setComparisonFunc(GLenum comparisonFunc) { mComparisonFunc = comparisonFunc; } - - GLenum getMinFilter() const { return mMinFilter; } - GLenum getMagFilter() const { return mMagFilter; } - GLenum getWrapS() const { return mWrapS; } - GLenum getWrapT() const { return mWrapT; } - GLenum getWrapR() const { return mWrapR; } - GLfloat getMinLod() const { return mMinLod; } - GLfloat getMaxLod() const { return mMaxLod; } - GLenum getComparisonMode() const { return mComparisonMode; } - GLenum getComparisonFunc() const { return mComparisonFunc; } - - void getState(SamplerState *samplerState) const; - - private: - GLenum mMinFilter; - GLenum mMagFilter; - GLenum mWrapS; - GLenum mWrapT; - GLenum mWrapR; - GLfloat mMinLod; - GLfloat mMaxLod; - GLenum mComparisonMode; - GLenum mComparisonFunc; -}; - -} - -#endif // LIBGLESV2_SAMPLER_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/Shader.cpp b/src/3rdparty/angle/src/libGLESv2/Shader.cpp deleted file mode 100644 index 024ef8fb7c..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/Shader.cpp +++ /dev/null @@ -1,219 +0,0 @@ -// -// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Shader.cpp: Implements the gl::Shader class and its derived classes -// VertexShader and FragmentShader. Implements GL shader objects and related -// functionality. [OpenGL ES 2.0.24] section 2.10 page 24 and section 3.8 page 84. - -#include "libGLESv2/Shader.h" -#include "libGLESv2/renderer/Renderer.h" -#include "libGLESv2/renderer/ShaderImpl.h" -#include "libGLESv2/Constants.h" -#include "libGLESv2/ResourceManager.h" - -#include "common/utilities.h" - -#include "GLSLANG/ShaderLang.h" - -#include - -namespace gl -{ - -Shader::Shader(ResourceManager *manager, rx::ShaderImpl *impl, GLenum type, GLuint handle) - : mShader(impl), - mType(type), - mHandle(handle), - mResourceManager(manager), - mRefCount(0), - mDeleteStatus(false), - mCompiled(false) -{ - ASSERT(impl); -} - -Shader::~Shader() -{ - SafeDelete(mShader); -} - -GLuint Shader::getHandle() const -{ - return mHandle; -} - -void Shader::setSource(GLsizei count, const char *const *string, const GLint *length) -{ - std::ostringstream stream; - - for (int i = 0; i < count; i++) - { - if (length == nullptr || length[i] < 0) - { - stream.write(string[i], strlen(string[i])); - } - else - { - stream.write(string[i], length[i]); - } - } - - mSource = stream.str(); -} - -int Shader::getInfoLogLength() const -{ - return mShader->getInfoLog().empty() ? 0 : (mShader->getInfoLog().length() + 1); -} - -void Shader::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) const -{ - int index = 0; - - if (bufSize > 0) - { - index = std::min(bufSize - 1, static_cast(mShader->getInfoLog().length())); - memcpy(infoLog, mShader->getInfoLog().c_str(), index); - - infoLog[index] = '\0'; - } - - if (length) - { - *length = index; - } -} - -int Shader::getSourceLength() const -{ - return mSource.empty() ? 0 : (mSource.length() + 1); -} - -int Shader::getTranslatedSourceLength() const -{ - return mShader->getTranslatedSource().empty() ? 0 : (mShader->getTranslatedSource().length() + 1); -} - -void Shader::getSourceImpl(const std::string &source, GLsizei bufSize, GLsizei *length, char *buffer) -{ - int index = 0; - - if (bufSize > 0) - { - index = std::min(bufSize - 1, static_cast(source.length())); - memcpy(buffer, source.c_str(), index); - - buffer[index] = '\0'; - } - - if (length) - { - *length = index; - } -} - -void Shader::getSource(GLsizei bufSize, GLsizei *length, char *buffer) const -{ - getSourceImpl(mSource, bufSize, length, buffer); -} - -void Shader::getTranslatedSource(GLsizei bufSize, GLsizei *length, char *buffer) const -{ - getSourceImpl(mShader->getTranslatedSource(), bufSize, length, buffer); -} - -void Shader::getTranslatedSourceWithDebugInfo(GLsizei bufSize, GLsizei *length, char *buffer) const -{ - std::string debugInfo(mShader->getDebugInfo()); - getSourceImpl(debugInfo, bufSize, length, buffer); -} - -void Shader::compile(const gl::Data &data) -{ - mCompiled = mShader->compile(data, mSource); -} - -void Shader::addRef() -{ - mRefCount++; -} - -void Shader::release() -{ - mRefCount--; - - if (mRefCount == 0 && mDeleteStatus) - { - mResourceManager->deleteShader(mHandle); - } -} - -unsigned int Shader::getRefCount() const -{ - return mRefCount; -} - -bool Shader::isFlaggedForDeletion() const -{ - return mDeleteStatus; -} - -void Shader::flagForDeletion() -{ - mDeleteStatus = true; -} - -const std::vector &Shader::getVaryings() const -{ - return mShader->getVaryings(); -} - -const std::vector &Shader::getUniforms() const -{ - return mShader->getUniforms(); -} - -const std::vector &Shader::getInterfaceBlocks() const -{ - return mShader->getInterfaceBlocks(); -} - -const std::vector &Shader::getActiveAttributes() const -{ - return mShader->getActiveAttributes(); -} - -const std::vector &Shader::getActiveOutputVariables() const -{ - return mShader->getActiveOutputVariables(); -} - -std::vector &Shader::getVaryings() -{ - return mShader->getVaryings(); -} - -std::vector &Shader::getUniforms() -{ - return mShader->getUniforms(); -} - -std::vector &Shader::getInterfaceBlocks() -{ - return mShader->getInterfaceBlocks(); -} - -std::vector &Shader::getActiveAttributes() -{ - return mShader->getActiveAttributes(); -} - -std::vector &Shader::getActiveOutputVariables() -{ - return mShader->getActiveOutputVariables(); -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/Shader.h b/src/3rdparty/angle/src/libGLESv2/Shader.h deleted file mode 100644 index 904217dab8..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/Shader.h +++ /dev/null @@ -1,118 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Shader.h: Defines the abstract gl::Shader class and its concrete derived -// classes VertexShader and FragmentShader. Implements GL shader objects and -// related functionality. [OpenGL ES 2.0.24] section 2.10 page 24 and section -// 3.8 page 84. - -#ifndef LIBGLESV2_SHADER_H_ -#define LIBGLESV2_SHADER_H_ - - -#include -#include -#include - -#include "angle_gl.h" -#include - -#include "common/angleutils.h" -#include "libGLESv2/angletypes.h" - -namespace rx -{ -class ShaderImpl; -} - -namespace gl -{ -class ResourceManager; -struct Data; - -struct PackedVarying : public sh::Varying -{ - unsigned int registerIndex; // Assigned during link - unsigned int columnIndex; // Assigned during link, defaults to 0 - - PackedVarying(const sh::Varying &varying) - : sh::Varying(varying), - registerIndex(GL_INVALID_INDEX), - columnIndex(0) - {} - - bool registerAssigned() const { return registerIndex != GL_INVALID_INDEX; } - bool isBuiltIn() const { return name.compare(0, 3, "gl_") == 0; } - - void resetRegisterAssignment() - { - registerIndex = GL_INVALID_INDEX; - } -}; - -class Shader -{ - public: - Shader(ResourceManager *manager, rx::ShaderImpl *impl, GLenum type, GLuint handle); - - virtual ~Shader(); - - GLenum getType() const { return mType; } - GLuint getHandle() const; - - rx::ShaderImpl *getImplementation() { return mShader; } - const rx::ShaderImpl *getImplementation() const { return mShader; } - - void deleteSource(); - void setSource(GLsizei count, const char *const *string, const GLint *length); - int getInfoLogLength() const; - void getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) const; - int getSourceLength() const; - void getSource(GLsizei bufSize, GLsizei *length, char *buffer) const; - int getTranslatedSourceLength() const; - void getTranslatedSource(GLsizei bufSize, GLsizei *length, char *buffer) const; - void getTranslatedSourceWithDebugInfo(GLsizei bufSize, GLsizei *length, char *buffer) const; - - void compile(const gl::Data &data); - bool isCompiled() const { return mCompiled; } - - void addRef(); - void release(); - unsigned int getRefCount() const; - bool isFlaggedForDeletion() const; - void flagForDeletion(); - - const std::vector &getVaryings() const; - const std::vector &getUniforms() const; - const std::vector &getInterfaceBlocks() const; - const std::vector &getActiveAttributes() const; - const std::vector &getActiveOutputVariables() const; - - std::vector &getVaryings(); - std::vector &getUniforms(); - std::vector &getInterfaceBlocks(); - std::vector &getActiveAttributes(); - std::vector &getActiveOutputVariables(); - - private: - DISALLOW_COPY_AND_ASSIGN(Shader); - - static void getSourceImpl(const std::string &source, GLsizei bufSize, GLsizei *length, char *buffer); - - rx::ShaderImpl *mShader; - const GLuint mHandle; - const GLenum mType; - std::string mSource; - unsigned int mRefCount; // Number of program objects this shader is attached to - bool mDeleteStatus; // Flag to indicate that the shader can be deleted when no longer in use - bool mCompiled; // Indicates if this shader has been successfully compiled - - ResourceManager *mResourceManager; -}; - -} - -#endif // LIBGLESV2_SHADER_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/State.cpp b/src/3rdparty/angle/src/libGLESv2/State.cpp deleted file mode 100644 index b5b62f5848..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/State.cpp +++ /dev/null @@ -1,1464 +0,0 @@ -// -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// State.cpp: Implements the State class, encapsulating raw GL state. - -#include "libGLESv2/State.h" - -#include "libGLESv2/Context.h" -#include "libGLESv2/Caps.h" -#include "libGLESv2/Framebuffer.h" -#include "libGLESv2/FramebufferAttachment.h" -#include "libGLESv2/Query.h" -#include "libGLESv2/VertexArray.h" -#include "libGLESv2/formatutils.h" -#include "libGLESv2/renderer/RenderTarget.h" - -namespace gl -{ - -State::State() -{ - mMaxDrawBuffers = 0; - mMaxCombinedTextureImageUnits = 0; -} - -State::~State() -{ - reset(); -} - -void State::initialize(const Caps& caps, GLuint clientVersion) -{ - mMaxDrawBuffers = caps.maxDrawBuffers; - mMaxCombinedTextureImageUnits = caps.maxCombinedTextureImageUnits; - - setClearColor(0.0f, 0.0f, 0.0f, 0.0f); - - mDepthClearValue = 1.0f; - mStencilClearValue = 0; - - mRasterizer.rasterizerDiscard = false; - mRasterizer.cullFace = false; - mRasterizer.cullMode = GL_BACK; - mRasterizer.frontFace = GL_CCW; - mRasterizer.polygonOffsetFill = false; - mRasterizer.polygonOffsetFactor = 0.0f; - mRasterizer.polygonOffsetUnits = 0.0f; - mRasterizer.pointDrawMode = false; - mRasterizer.multiSample = false; - mScissorTest = false; - mScissor.x = 0; - mScissor.y = 0; - mScissor.width = 0; - mScissor.height = 0; - - mBlend.blend = false; - mBlend.sourceBlendRGB = GL_ONE; - mBlend.sourceBlendAlpha = GL_ONE; - mBlend.destBlendRGB = GL_ZERO; - mBlend.destBlendAlpha = GL_ZERO; - mBlend.blendEquationRGB = GL_FUNC_ADD; - mBlend.blendEquationAlpha = GL_FUNC_ADD; - mBlend.sampleAlphaToCoverage = false; - mBlend.dither = true; - - mBlendColor.red = 0; - mBlendColor.green = 0; - mBlendColor.blue = 0; - mBlendColor.alpha = 0; - - mDepthStencil.depthTest = false; - mDepthStencil.depthFunc = GL_LESS; - mDepthStencil.depthMask = true; - mDepthStencil.stencilTest = false; - mDepthStencil.stencilFunc = GL_ALWAYS; - mDepthStencil.stencilMask = -1; - mDepthStencil.stencilWritemask = -1; - mDepthStencil.stencilBackFunc = GL_ALWAYS; - mDepthStencil.stencilBackMask = -1; - mDepthStencil.stencilBackWritemask = -1; - mDepthStencil.stencilFail = GL_KEEP; - mDepthStencil.stencilPassDepthFail = GL_KEEP; - mDepthStencil.stencilPassDepthPass = GL_KEEP; - mDepthStencil.stencilBackFail = GL_KEEP; - mDepthStencil.stencilBackPassDepthFail = GL_KEEP; - mDepthStencil.stencilBackPassDepthPass = GL_KEEP; - - mStencilRef = 0; - mStencilBackRef = 0; - - mSampleCoverage = false; - mSampleCoverageValue = 1.0f; - mSampleCoverageInvert = false; - mGenerateMipmapHint = GL_DONT_CARE; - mFragmentShaderDerivativeHint = GL_DONT_CARE; - - mLineWidth = 1.0f; - - mViewport.x = 0; - mViewport.y = 0; - mViewport.width = 0; - mViewport.height = 0; - mNearZ = 0.0f; - mFarZ = 1.0f; - - mBlend.colorMaskRed = true; - mBlend.colorMaskGreen = true; - mBlend.colorMaskBlue = true; - mBlend.colorMaskAlpha = true; - - mActiveSampler = 0; - - const GLfloat defaultFloatValues[] = { 0.0f, 0.0f, 0.0f, 1.0f }; - mVertexAttribCurrentValues.resize(caps.maxVertexAttributes); - for (size_t attribIndex = 0; attribIndex < mVertexAttribCurrentValues.size(); ++attribIndex) - { - mVertexAttribCurrentValues[attribIndex].setFloatValues(defaultFloatValues); - } - - mUniformBuffers.resize(caps.maxCombinedUniformBlocks); - mTransformFeedbackBuffers.resize(caps.maxTransformFeedbackSeparateAttributes); - - mSamplerTextures[GL_TEXTURE_2D].resize(caps.maxCombinedTextureImageUnits); - mSamplerTextures[GL_TEXTURE_CUBE_MAP].resize(caps.maxCombinedTextureImageUnits); - if (clientVersion >= 3) - { - // TODO: These could also be enabled via extension - mSamplerTextures[GL_TEXTURE_2D_ARRAY].resize(caps.maxCombinedTextureImageUnits); - mSamplerTextures[GL_TEXTURE_3D].resize(caps.maxCombinedTextureImageUnits); - } - - mSamplers.resize(caps.maxCombinedTextureImageUnits); - - mActiveQueries[GL_ANY_SAMPLES_PASSED].set(NULL); - mActiveQueries[GL_ANY_SAMPLES_PASSED_CONSERVATIVE].set(NULL); - mActiveQueries[GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN].set(NULL); - - mCurrentProgramId = 0; - mCurrentProgramBinary.set(NULL); - - mReadFramebuffer = NULL; - mDrawFramebuffer = NULL; -} - -void State::reset() -{ - for (TextureBindingMap::iterator bindingVec = mSamplerTextures.begin(); bindingVec != mSamplerTextures.end(); bindingVec++) - { - TextureBindingVector &textureVector = bindingVec->second; - for (size_t textureIdx = 0; textureIdx < textureVector.size(); textureIdx++) - { - textureVector[textureIdx].set(NULL); - } - } - for (size_t samplerIdx = 0; samplerIdx < mSamplers.size(); samplerIdx++) - { - mSamplers[samplerIdx].set(NULL); - } - - mArrayBuffer.set(NULL); - mRenderbuffer.set(NULL); - - mTransformFeedback.set(NULL); - - for (State::ActiveQueryMap::iterator i = mActiveQueries.begin(); i != mActiveQueries.end(); i++) - { - i->second.set(NULL); - } - - mGenericUniformBuffer.set(NULL); - mGenericTransformFeedbackBuffer.set(NULL); - for (BufferVector::iterator bufItr = mUniformBuffers.begin(); bufItr != mUniformBuffers.end(); ++bufItr) - { - bufItr->set(NULL); - } - - for (BufferVector::iterator bufItr = mTransformFeedbackBuffers.begin(); bufItr != mTransformFeedbackBuffers.end(); ++bufItr) - { - bufItr->set(NULL); - } - - mCopyReadBuffer.set(NULL); - mCopyWriteBuffer.set(NULL); - - mPack.pixelBuffer.set(NULL); - mUnpack.pixelBuffer.set(NULL); -} - -const RasterizerState &State::getRasterizerState() const -{ - return mRasterizer; -} - -const BlendState &State::getBlendState() const -{ - return mBlend; -} - -const DepthStencilState &State::getDepthStencilState() const -{ - return mDepthStencil; -} - -void State::setClearColor(float red, float green, float blue, float alpha) -{ - mColorClearValue.red = red; - mColorClearValue.green = green; - mColorClearValue.blue = blue; - mColorClearValue.alpha = alpha; -} - -void State::setClearDepth(float depth) -{ - mDepthClearValue = depth; -} - -void State::setClearStencil(int stencil) -{ - mStencilClearValue = stencil; -} - -ClearParameters State::getClearParameters(GLbitfield mask) const -{ - ClearParameters clearParams = { 0 }; - for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++) - { - clearParams.clearColor[i] = false; - } - clearParams.colorFClearValue = mColorClearValue; - clearParams.colorClearType = GL_FLOAT; - clearParams.colorMaskRed = mBlend.colorMaskRed; - clearParams.colorMaskGreen = mBlend.colorMaskGreen; - clearParams.colorMaskBlue = mBlend.colorMaskBlue; - clearParams.colorMaskAlpha = mBlend.colorMaskAlpha; - clearParams.clearDepth = false; - clearParams.depthClearValue = mDepthClearValue; - clearParams.clearStencil = false; - clearParams.stencilClearValue = mStencilClearValue; - clearParams.stencilWriteMask = mDepthStencil.stencilWritemask; - clearParams.scissorEnabled = mScissorTest; - clearParams.scissor = mScissor; - - const Framebuffer *framebufferObject = getDrawFramebuffer(); - if (mask & GL_COLOR_BUFFER_BIT) - { - if (framebufferObject->hasEnabledColorAttachment()) - { - for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++) - { - clearParams.clearColor[i] = true; - } - } - } - - if (mask & GL_DEPTH_BUFFER_BIT) - { - if (mDepthStencil.depthMask && framebufferObject->getDepthbuffer() != NULL) - { - clearParams.clearDepth = true; - } - } - - if (mask & GL_STENCIL_BUFFER_BIT) - { - if (framebufferObject->getStencilbuffer() != NULL) - { - GLenum stencilActualFormat = framebufferObject->getStencilbuffer()->getActualFormat(); - if (GetInternalFormatInfo(stencilActualFormat).stencilBits > 0) - { - clearParams.clearStencil = true; - } - } - } - - return clearParams; -} - -void State::setColorMask(bool red, bool green, bool blue, bool alpha) -{ - mBlend.colorMaskRed = red; - mBlend.colorMaskGreen = green; - mBlend.colorMaskBlue = blue; - mBlend.colorMaskAlpha = alpha; -} - -void State::setDepthMask(bool mask) -{ - mDepthStencil.depthMask = mask; -} - -bool State::isRasterizerDiscardEnabled() const -{ - return mRasterizer.rasterizerDiscard; -} - -void State::setRasterizerDiscard(bool enabled) -{ - mRasterizer.rasterizerDiscard = enabled; -} - -bool State::isCullFaceEnabled() const -{ - return mRasterizer.cullFace; -} - -void State::setCullFace(bool enabled) -{ - mRasterizer.cullFace = enabled; -} - -void State::setCullMode(GLenum mode) -{ - mRasterizer.cullMode = mode; -} - -void State::setFrontFace(GLenum front) -{ - mRasterizer.frontFace = front; -} - -bool State::isDepthTestEnabled() const -{ - return mDepthStencil.depthTest; -} - -void State::setDepthTest(bool enabled) -{ - mDepthStencil.depthTest = enabled; -} - -void State::setDepthFunc(GLenum depthFunc) -{ - mDepthStencil.depthFunc = depthFunc; -} - -void State::setDepthRange(float zNear, float zFar) -{ - mNearZ = zNear; - mFarZ = zFar; -} - -void State::getDepthRange(float *zNear, float *zFar) const -{ - *zNear = mNearZ; - *zFar = mFarZ; -} - -bool State::isBlendEnabled() const -{ - return mBlend.blend; -} - -void State::setBlend(bool enabled) -{ - mBlend.blend = enabled; -} - -void State::setBlendFactors(GLenum sourceRGB, GLenum destRGB, GLenum sourceAlpha, GLenum destAlpha) -{ - mBlend.sourceBlendRGB = sourceRGB; - mBlend.destBlendRGB = destRGB; - mBlend.sourceBlendAlpha = sourceAlpha; - mBlend.destBlendAlpha = destAlpha; -} - -void State::setBlendColor(float red, float green, float blue, float alpha) -{ - mBlendColor.red = red; - mBlendColor.green = green; - mBlendColor.blue = blue; - mBlendColor.alpha = alpha; -} - -void State::setBlendEquation(GLenum rgbEquation, GLenum alphaEquation) -{ - mBlend.blendEquationRGB = rgbEquation; - mBlend.blendEquationAlpha = alphaEquation; -} - -const ColorF &State::getBlendColor() const -{ - return mBlendColor; -} - -bool State::isStencilTestEnabled() const -{ - return mDepthStencil.stencilTest; -} - -void State::setStencilTest(bool enabled) -{ - mDepthStencil.stencilTest = enabled; -} - -void State::setStencilParams(GLenum stencilFunc, GLint stencilRef, GLuint stencilMask) -{ - mDepthStencil.stencilFunc = stencilFunc; - mStencilRef = (stencilRef > 0) ? stencilRef : 0; - mDepthStencil.stencilMask = stencilMask; -} - -void State::setStencilBackParams(GLenum stencilBackFunc, GLint stencilBackRef, GLuint stencilBackMask) -{ - mDepthStencil.stencilBackFunc = stencilBackFunc; - mStencilBackRef = (stencilBackRef > 0) ? stencilBackRef : 0; - mDepthStencil.stencilBackMask = stencilBackMask; -} - -void State::setStencilWritemask(GLuint stencilWritemask) -{ - mDepthStencil.stencilWritemask = stencilWritemask; -} - -void State::setStencilBackWritemask(GLuint stencilBackWritemask) -{ - mDepthStencil.stencilBackWritemask = stencilBackWritemask; -} - -void State::setStencilOperations(GLenum stencilFail, GLenum stencilPassDepthFail, GLenum stencilPassDepthPass) -{ - mDepthStencil.stencilFail = stencilFail; - mDepthStencil.stencilPassDepthFail = stencilPassDepthFail; - mDepthStencil.stencilPassDepthPass = stencilPassDepthPass; -} - -void State::setStencilBackOperations(GLenum stencilBackFail, GLenum stencilBackPassDepthFail, GLenum stencilBackPassDepthPass) -{ - mDepthStencil.stencilBackFail = stencilBackFail; - mDepthStencil.stencilBackPassDepthFail = stencilBackPassDepthFail; - mDepthStencil.stencilBackPassDepthPass = stencilBackPassDepthPass; -} - -GLint State::getStencilRef() const -{ - return mStencilRef; -} - -GLint State::getStencilBackRef() const -{ - return mStencilBackRef; -} - -bool State::isPolygonOffsetFillEnabled() const -{ - return mRasterizer.polygonOffsetFill; -} - -void State::setPolygonOffsetFill(bool enabled) -{ - mRasterizer.polygonOffsetFill = enabled; -} - -void State::setPolygonOffsetParams(GLfloat factor, GLfloat units) -{ - // An application can pass NaN values here, so handle this gracefully - mRasterizer.polygonOffsetFactor = factor != factor ? 0.0f : factor; - mRasterizer.polygonOffsetUnits = units != units ? 0.0f : units; -} - -bool State::isSampleAlphaToCoverageEnabled() const -{ - return mBlend.sampleAlphaToCoverage; -} - -void State::setSampleAlphaToCoverage(bool enabled) -{ - mBlend.sampleAlphaToCoverage = enabled; -} - -bool State::isSampleCoverageEnabled() const -{ - return mSampleCoverage; -} - -void State::setSampleCoverage(bool enabled) -{ - mSampleCoverage = enabled; -} - -void State::setSampleCoverageParams(GLclampf value, bool invert) -{ - mSampleCoverageValue = value; - mSampleCoverageInvert = invert; -} - -void State::getSampleCoverageParams(GLclampf *value, bool *invert) const -{ - ASSERT(value != NULL && invert != NULL); - - *value = mSampleCoverageValue; - *invert = mSampleCoverageInvert; -} - -bool State::isScissorTestEnabled() const -{ - return mScissorTest; -} - -void State::setScissorTest(bool enabled) -{ - mScissorTest = enabled; -} - -void State::setScissorParams(GLint x, GLint y, GLsizei width, GLsizei height) -{ - mScissor.x = x; - mScissor.y = y; - mScissor.width = width; - mScissor.height = height; -} - -const Rectangle &State::getScissor() const -{ - return mScissor; -} - -bool State::isDitherEnabled() const -{ - return mBlend.dither; -} - -void State::setDither(bool enabled) -{ - mBlend.dither = enabled; -} - -void State::setEnableFeature(GLenum feature, bool enabled) -{ - switch (feature) - { - case GL_CULL_FACE: setCullFace(enabled); break; - case GL_POLYGON_OFFSET_FILL: setPolygonOffsetFill(enabled); break; - case GL_SAMPLE_ALPHA_TO_COVERAGE: setSampleAlphaToCoverage(enabled); break; - case GL_SAMPLE_COVERAGE: setSampleCoverage(enabled); break; - case GL_SCISSOR_TEST: setScissorTest(enabled); break; - case GL_STENCIL_TEST: setStencilTest(enabled); break; - case GL_DEPTH_TEST: setDepthTest(enabled); break; - case GL_BLEND: setBlend(enabled); break; - case GL_DITHER: setDither(enabled); break; - case GL_PRIMITIVE_RESTART_FIXED_INDEX: UNIMPLEMENTED(); break; - case GL_RASTERIZER_DISCARD: setRasterizerDiscard(enabled); break; - default: UNREACHABLE(); - } -} - -bool State::getEnableFeature(GLenum feature) -{ - switch (feature) - { - case GL_CULL_FACE: return isCullFaceEnabled(); - case GL_POLYGON_OFFSET_FILL: return isPolygonOffsetFillEnabled(); - case GL_SAMPLE_ALPHA_TO_COVERAGE: return isSampleAlphaToCoverageEnabled(); - case GL_SAMPLE_COVERAGE: return isSampleCoverageEnabled(); - case GL_SCISSOR_TEST: return isScissorTestEnabled(); - case GL_STENCIL_TEST: return isStencilTestEnabled(); - case GL_DEPTH_TEST: return isDepthTestEnabled(); - case GL_BLEND: return isBlendEnabled(); - case GL_DITHER: return isDitherEnabled(); - case GL_PRIMITIVE_RESTART_FIXED_INDEX: UNIMPLEMENTED(); return false; - case GL_RASTERIZER_DISCARD: return isRasterizerDiscardEnabled(); - default: UNREACHABLE(); return false; - } -} - -void State::setLineWidth(GLfloat width) -{ - mLineWidth = width; -} - -void State::setGenerateMipmapHint(GLenum hint) -{ - mGenerateMipmapHint = hint; -} - -void State::setFragmentShaderDerivativeHint(GLenum hint) -{ - mFragmentShaderDerivativeHint = hint; - // TODO: Propagate the hint to shader translator so we can write - // ddx, ddx_coarse, or ddx_fine depending on the hint. - // Ignore for now. It is valid for implementations to ignore hint. -} - -void State::setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height) -{ - mViewport.x = x; - mViewport.y = y; - mViewport.width = width; - mViewport.height = height; -} - -const Rectangle &State::getViewport() const -{ - return mViewport; -} - -void State::setActiveSampler(unsigned int active) -{ - mActiveSampler = active; -} - -unsigned int State::getActiveSampler() const -{ - return mActiveSampler; -} - -void State::setSamplerTexture(GLenum type, Texture *texture) -{ - mSamplerTextures[type][mActiveSampler].set(texture); -} - -Texture *State::getSamplerTexture(unsigned int sampler, GLenum type) const -{ - return mSamplerTextures.at(type)[sampler].get(); -} - -GLuint State::getSamplerTextureId(unsigned int sampler, GLenum type) const -{ - return mSamplerTextures.at(type)[sampler].id(); -} - -void State::detachTexture(const TextureMap &zeroTextures, GLuint texture) -{ - // Textures have a detach method on State rather than a simple - // removeBinding, because the zero/null texture objects are managed - // separately, and don't have to go through the Context's maps or - // the ResourceManager. - - // [OpenGL ES 2.0.24] section 3.8 page 84: - // If a texture object is deleted, it is as if all texture units which are bound to that texture object are - // rebound to texture object zero - - for (TextureBindingMap::iterator bindingVec = mSamplerTextures.begin(); bindingVec != mSamplerTextures.end(); bindingVec++) - { - GLenum textureType = bindingVec->first; - TextureBindingVector &textureVector = bindingVec->second; - for (size_t textureIdx = 0; textureIdx < textureVector.size(); textureIdx++) - { - BindingPointer &binding = textureVector[textureIdx]; - if (binding.id() == texture) - { - // Zero textures are the "default" textures instead of NULL - binding.set(zeroTextures.at(textureType).get()); - } - } - } - - // [OpenGL ES 2.0.24] section 4.4 page 112: - // If a texture object is deleted while its image is attached to the currently bound framebuffer, then it is - // as if Texture2DAttachment had been called, with a texture of 0, for each attachment point to which this - // image was attached in the currently bound framebuffer. - - if (mReadFramebuffer) - { - mReadFramebuffer->detachTexture(texture); - } - - if (mDrawFramebuffer) - { - mDrawFramebuffer->detachTexture(texture); - } -} - -void State::initializeZeroTextures(const TextureMap &zeroTextures) -{ - for (TextureMap::const_iterator i = zeroTextures.begin(); i != zeroTextures.end(); i++) - { - TextureBindingVector &samplerTextureArray = mSamplerTextures[i->first]; - - for (size_t textureUnit = 0; textureUnit < samplerTextureArray.size(); ++textureUnit) - { - samplerTextureArray[textureUnit].set(i->second.get()); - } - } -} - -void State::setSamplerBinding(GLuint textureUnit, Sampler *sampler) -{ - mSamplers[textureUnit].set(sampler); -} - -GLuint State::getSamplerId(GLuint textureUnit) const -{ - ASSERT(textureUnit < mSamplers.size()); - return mSamplers[textureUnit].id(); -} - -Sampler *State::getSampler(GLuint textureUnit) const -{ - return mSamplers[textureUnit].get(); -} - -void State::detachSampler(GLuint sampler) -{ - // [OpenGL ES 3.0.2] section 3.8.2 pages 123-124: - // If a sampler object that is currently bound to one or more texture units is - // deleted, it is as though BindSampler is called once for each texture unit to - // which the sampler is bound, with unit set to the texture unit and sampler set to zero. - for (size_t textureUnit = 0; textureUnit < mSamplers.size(); textureUnit++) - { - BindingPointer &samplerBinding = mSamplers[textureUnit]; - if (samplerBinding.id() == sampler) - { - samplerBinding.set(NULL); - } - } -} - -void State::setRenderbufferBinding(Renderbuffer *renderbuffer) -{ - mRenderbuffer.set(renderbuffer); -} - -GLuint State::getRenderbufferId() const -{ - return mRenderbuffer.id(); -} - -Renderbuffer *State::getCurrentRenderbuffer() -{ - return mRenderbuffer.get(); -} - -void State::detachRenderbuffer(GLuint renderbuffer) -{ - // [OpenGL ES 2.0.24] section 4.4 page 109: - // If a renderbuffer that is currently bound to RENDERBUFFER is deleted, it is as though BindRenderbuffer - // had been executed with the target RENDERBUFFER and name of zero. - - if (mRenderbuffer.id() == renderbuffer) - { - mRenderbuffer.set(NULL); - } - - // [OpenGL ES 2.0.24] section 4.4 page 111: - // If a renderbuffer object is deleted while its image is attached to the currently bound framebuffer, - // then it is as if FramebufferRenderbuffer had been called, with a renderbuffer of 0, for each attachment - // point to which this image was attached in the currently bound framebuffer. - - Framebuffer *readFramebuffer = mReadFramebuffer; - Framebuffer *drawFramebuffer = mDrawFramebuffer; - - if (readFramebuffer) - { - readFramebuffer->detachRenderbuffer(renderbuffer); - } - - if (drawFramebuffer && drawFramebuffer != readFramebuffer) - { - drawFramebuffer->detachRenderbuffer(renderbuffer); - } - -} - -void State::setReadFramebufferBinding(Framebuffer *framebuffer) -{ - mReadFramebuffer = framebuffer; -} - -void State::setDrawFramebufferBinding(Framebuffer *framebuffer) -{ - mDrawFramebuffer = framebuffer; -} - -Framebuffer *State::getTargetFramebuffer(GLenum target) const -{ - switch (target) - { - case GL_READ_FRAMEBUFFER_ANGLE: return mReadFramebuffer; - case GL_DRAW_FRAMEBUFFER_ANGLE: - case GL_FRAMEBUFFER: return mDrawFramebuffer; - default: UNREACHABLE(); return NULL; - } -} - -Framebuffer *State::getReadFramebuffer() -{ - return mReadFramebuffer; -} - -Framebuffer *State::getDrawFramebuffer() -{ - return mDrawFramebuffer; -} - -const Framebuffer *State::getReadFramebuffer() const -{ - return mReadFramebuffer; -} - -const Framebuffer *State::getDrawFramebuffer() const -{ - return mDrawFramebuffer; -} - -bool State::removeReadFramebufferBinding(GLuint framebuffer) -{ - if (mReadFramebuffer->id() == framebuffer) - { - mReadFramebuffer = NULL; - return true; - } - - return false; -} - -bool State::removeDrawFramebufferBinding(GLuint framebuffer) -{ - if (mDrawFramebuffer->id() == framebuffer) - { - mDrawFramebuffer = NULL; - return true; - } - - return false; -} - -void State::setVertexArrayBinding(VertexArray *vertexArray) -{ - mVertexArray = vertexArray; -} - -GLuint State::getVertexArrayId() const -{ - ASSERT(mVertexArray != NULL); - return mVertexArray->id(); -} - -VertexArray *State::getVertexArray() const -{ - ASSERT(mVertexArray != NULL); - return mVertexArray; -} - -bool State::removeVertexArrayBinding(GLuint vertexArray) -{ - if (mVertexArray->id() == vertexArray) - { - mVertexArray = NULL; - return true; - } - - return false; -} - -void State::setCurrentProgram(GLuint programId, Program *newProgram) -{ - mCurrentProgramId = programId; // set new ID before trying to delete program binary; otherwise it will only be flagged for deletion - mCurrentProgramBinary.set(NULL); - - if (newProgram) - { - newProgram->addRef(); - mCurrentProgramBinary.set(newProgram->getProgramBinary()); - } -} - -void State::setCurrentProgramBinary(ProgramBinary *binary) -{ - mCurrentProgramBinary.set(binary); -} - -GLuint State::getCurrentProgramId() const -{ - return mCurrentProgramId; -} - -ProgramBinary *State::getCurrentProgramBinary() const -{ - return mCurrentProgramBinary.get(); -} - -void State::setTransformFeedbackBinding(TransformFeedback *transformFeedback) -{ - mTransformFeedback.set(transformFeedback); -} - -TransformFeedback *State::getCurrentTransformFeedback() const -{ - return mTransformFeedback.get(); -} - -void State::detachTransformFeedback(GLuint transformFeedback) -{ - if (mTransformFeedback.id() == transformFeedback) - { - mTransformFeedback.set(NULL); - } -} - -bool State::isQueryActive() const -{ - for (State::ActiveQueryMap::const_iterator i = mActiveQueries.begin(); - i != mActiveQueries.end(); i++) - { - if (i->second.get() != NULL) - { - return true; - } - } - - return false; -} - -void State::setActiveQuery(GLenum target, Query *query) -{ - mActiveQueries[target].set(query); -} - -GLuint State::getActiveQueryId(GLenum target) const -{ - const Query *query = getActiveQuery(target); - return (query ? query->id() : 0u); -} - -Query *State::getActiveQuery(GLenum target) const -{ - // All query types should already exist in the activeQueries map - ASSERT(mActiveQueries.find(target) != mActiveQueries.end()); - - return mActiveQueries.at(target).get(); -} - -void State::setArrayBufferBinding(Buffer *buffer) -{ - mArrayBuffer.set(buffer); -} - -GLuint State::getArrayBufferId() const -{ - return mArrayBuffer.id(); -} - -bool State::removeArrayBufferBinding(GLuint buffer) -{ - if (mArrayBuffer.id() == buffer) - { - mArrayBuffer.set(NULL); - return true; - } - - return false; -} - -void State::setGenericUniformBufferBinding(Buffer *buffer) -{ - mGenericUniformBuffer.set(buffer); -} - -void State::setIndexedUniformBufferBinding(GLuint index, Buffer *buffer, GLintptr offset, GLsizeiptr size) -{ - mUniformBuffers[index].set(buffer, offset, size); -} - -GLuint State::getIndexedUniformBufferId(GLuint index) const -{ - ASSERT(static_cast(index) < mUniformBuffers.size()); - - return mUniformBuffers[index].id(); -} - -Buffer *State::getIndexedUniformBuffer(GLuint index) const -{ - ASSERT(static_cast(index) < mUniformBuffers.size()); - - return mUniformBuffers[index].get(); -} - -void State::setGenericTransformFeedbackBufferBinding(Buffer *buffer) -{ - mGenericTransformFeedbackBuffer.set(buffer); -} - -void State::setIndexedTransformFeedbackBufferBinding(GLuint index, Buffer *buffer, GLintptr offset, GLsizeiptr size) -{ - mTransformFeedbackBuffers[index].set(buffer, offset, size); -} - -GLuint State::getIndexedTransformFeedbackBufferId(GLuint index) const -{ - ASSERT(static_cast(index) < mTransformFeedbackBuffers.size()); - - return mTransformFeedbackBuffers[index].id(); -} - -Buffer *State::getIndexedTransformFeedbackBuffer(GLuint index) const -{ - ASSERT(static_cast(index) < mTransformFeedbackBuffers.size()); - - return mTransformFeedbackBuffers[index].get(); -} - -GLuint State::getIndexedTransformFeedbackBufferOffset(GLuint index) const -{ - ASSERT(static_cast(index) < mTransformFeedbackBuffers.size()); - - return mTransformFeedbackBuffers[index].getOffset(); -} - -size_t State::getTransformFeedbackBufferIndexRange() const -{ - return mTransformFeedbackBuffers.size(); -} - -void State::setCopyReadBufferBinding(Buffer *buffer) -{ - mCopyReadBuffer.set(buffer); -} - -void State::setCopyWriteBufferBinding(Buffer *buffer) -{ - mCopyWriteBuffer.set(buffer); -} - -void State::setPixelPackBufferBinding(Buffer *buffer) -{ - mPack.pixelBuffer.set(buffer); -} - -void State::setPixelUnpackBufferBinding(Buffer *buffer) -{ - mUnpack.pixelBuffer.set(buffer); -} - -Buffer *State::getTargetBuffer(GLenum target) const -{ - switch (target) - { - case GL_ARRAY_BUFFER: return mArrayBuffer.get(); - case GL_COPY_READ_BUFFER: return mCopyReadBuffer.get(); - case GL_COPY_WRITE_BUFFER: return mCopyWriteBuffer.get(); - case GL_ELEMENT_ARRAY_BUFFER: return getVertexArray()->getElementArrayBuffer(); - case GL_PIXEL_PACK_BUFFER: return mPack.pixelBuffer.get(); - case GL_PIXEL_UNPACK_BUFFER: return mUnpack.pixelBuffer.get(); - case GL_TRANSFORM_FEEDBACK_BUFFER: return mGenericTransformFeedbackBuffer.get(); - case GL_UNIFORM_BUFFER: return mGenericUniformBuffer.get(); - default: UNREACHABLE(); return NULL; - } -} - -void State::setEnableVertexAttribArray(unsigned int attribNum, bool enabled) -{ - getVertexArray()->enableAttribute(attribNum, enabled); -} - -void State::setVertexAttribf(GLuint index, const GLfloat values[4]) -{ - ASSERT(static_cast(index) < mVertexAttribCurrentValues.size()); - mVertexAttribCurrentValues[index].setFloatValues(values); -} - -void State::setVertexAttribu(GLuint index, const GLuint values[4]) -{ - ASSERT(static_cast(index) < mVertexAttribCurrentValues.size()); - mVertexAttribCurrentValues[index].setUnsignedIntValues(values); -} - -void State::setVertexAttribi(GLuint index, const GLint values[4]) -{ - ASSERT(static_cast(index) < mVertexAttribCurrentValues.size()); - mVertexAttribCurrentValues[index].setIntValues(values); -} - -void State::setVertexAttribState(unsigned int attribNum, Buffer *boundBuffer, GLint size, GLenum type, bool normalized, - bool pureInteger, GLsizei stride, const void *pointer) -{ - getVertexArray()->setAttributeState(attribNum, boundBuffer, size, type, normalized, pureInteger, stride, pointer); -} - -const VertexAttribute &State::getVertexAttribState(unsigned int attribNum) const -{ - return getVertexArray()->getVertexAttribute(attribNum); -} - -const VertexAttribCurrentValueData &State::getVertexAttribCurrentValue(unsigned int attribNum) const -{ - ASSERT(static_cast(attribNum) < mVertexAttribCurrentValues.size()); - return mVertexAttribCurrentValues[attribNum]; -} - -const void *State::getVertexAttribPointer(unsigned int attribNum) const -{ - return getVertexArray()->getVertexAttribute(attribNum).pointer; -} - -void State::setPackAlignment(GLint alignment) -{ - mPack.alignment = alignment; -} - -GLint State::getPackAlignment() const -{ - return mPack.alignment; -} - -void State::setPackReverseRowOrder(bool reverseRowOrder) -{ - mPack.reverseRowOrder = reverseRowOrder; -} - -bool State::getPackReverseRowOrder() const -{ - return mPack.reverseRowOrder; -} - -const PixelPackState &State::getPackState() const -{ - return mPack; -} - -void State::setUnpackAlignment(GLint alignment) -{ - mUnpack.alignment = alignment; -} - -GLint State::getUnpackAlignment() const -{ - return mUnpack.alignment; -} - -const PixelUnpackState &State::getUnpackState() const -{ - return mUnpack; -} - -void State::getBooleanv(GLenum pname, GLboolean *params) -{ - switch (pname) - { - case GL_SAMPLE_COVERAGE_INVERT: *params = mSampleCoverageInvert; break; - case GL_DEPTH_WRITEMASK: *params = mDepthStencil.depthMask; break; - case GL_COLOR_WRITEMASK: - params[0] = mBlend.colorMaskRed; - params[1] = mBlend.colorMaskGreen; - params[2] = mBlend.colorMaskBlue; - params[3] = mBlend.colorMaskAlpha; - break; - case GL_CULL_FACE: *params = mRasterizer.cullFace; break; - case GL_POLYGON_OFFSET_FILL: *params = mRasterizer.polygonOffsetFill; break; - case GL_SAMPLE_ALPHA_TO_COVERAGE: *params = mBlend.sampleAlphaToCoverage; break; - case GL_SAMPLE_COVERAGE: *params = mSampleCoverage; break; - case GL_SCISSOR_TEST: *params = mScissorTest; break; - case GL_STENCIL_TEST: *params = mDepthStencil.stencilTest; break; - case GL_DEPTH_TEST: *params = mDepthStencil.depthTest; break; - case GL_BLEND: *params = mBlend.blend; break; - case GL_DITHER: *params = mBlend.dither; break; - case GL_TRANSFORM_FEEDBACK_ACTIVE: *params = getCurrentTransformFeedback()->isStarted(); break; - case GL_TRANSFORM_FEEDBACK_PAUSED: *params = getCurrentTransformFeedback()->isPaused(); break; - default: - UNREACHABLE(); - break; - } -} - -void State::getFloatv(GLenum pname, GLfloat *params) -{ - // Please note: DEPTH_CLEAR_VALUE is included in our internal getFloatv implementation - // because it is stored as a float, despite the fact that the GL ES 2.0 spec names - // GetIntegerv as its native query function. As it would require conversion in any - // case, this should make no difference to the calling application. - switch (pname) - { - case GL_LINE_WIDTH: *params = mLineWidth; break; - case GL_SAMPLE_COVERAGE_VALUE: *params = mSampleCoverageValue; break; - case GL_DEPTH_CLEAR_VALUE: *params = mDepthClearValue; break; - case GL_POLYGON_OFFSET_FACTOR: *params = mRasterizer.polygonOffsetFactor; break; - case GL_POLYGON_OFFSET_UNITS: *params = mRasterizer.polygonOffsetUnits; break; - case GL_DEPTH_RANGE: - params[0] = mNearZ; - params[1] = mFarZ; - break; - case GL_COLOR_CLEAR_VALUE: - params[0] = mColorClearValue.red; - params[1] = mColorClearValue.green; - params[2] = mColorClearValue.blue; - params[3] = mColorClearValue.alpha; - break; - case GL_BLEND_COLOR: - params[0] = mBlendColor.red; - params[1] = mBlendColor.green; - params[2] = mBlendColor.blue; - params[3] = mBlendColor.alpha; - break; - default: - UNREACHABLE(); - break; - } -} - -void State::getIntegerv(const gl::Data &data, GLenum pname, GLint *params) -{ - if (pname >= GL_DRAW_BUFFER0_EXT && pname <= GL_DRAW_BUFFER15_EXT) - { - unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0_EXT); - ASSERT(colorAttachment < mMaxDrawBuffers); - Framebuffer *framebuffer = mDrawFramebuffer; - *params = framebuffer->getDrawBufferState(colorAttachment); - return; - } - - // Please note: DEPTH_CLEAR_VALUE is not included in our internal getIntegerv implementation - // because it is stored as a float, despite the fact that the GL ES 2.0 spec names - // GetIntegerv as its native query function. As it would require conversion in any - // case, this should make no difference to the calling application. You may find it in - // State::getFloatv. - switch (pname) - { - case GL_ARRAY_BUFFER_BINDING: *params = mArrayBuffer.id(); break; - case GL_ELEMENT_ARRAY_BUFFER_BINDING: *params = getVertexArray()->getElementArrayBufferId(); break; - //case GL_FRAMEBUFFER_BINDING: // now equivalent to GL_DRAW_FRAMEBUFFER_BINDING_ANGLE - case GL_DRAW_FRAMEBUFFER_BINDING_ANGLE: *params = mDrawFramebuffer->id(); break; - case GL_READ_FRAMEBUFFER_BINDING_ANGLE: *params = mReadFramebuffer->id(); break; - case GL_RENDERBUFFER_BINDING: *params = mRenderbuffer.id(); break; - case GL_VERTEX_ARRAY_BINDING: *params = mVertexArray->id(); break; - case GL_CURRENT_PROGRAM: *params = mCurrentProgramId; break; - case GL_PACK_ALIGNMENT: *params = mPack.alignment; break; - case GL_PACK_REVERSE_ROW_ORDER_ANGLE: *params = mPack.reverseRowOrder; break; - case GL_UNPACK_ALIGNMENT: *params = mUnpack.alignment; break; - case GL_GENERATE_MIPMAP_HINT: *params = mGenerateMipmapHint; break; - case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES: *params = mFragmentShaderDerivativeHint; break; - case GL_ACTIVE_TEXTURE: *params = (mActiveSampler + GL_TEXTURE0); break; - case GL_STENCIL_FUNC: *params = mDepthStencil.stencilFunc; break; - case GL_STENCIL_REF: *params = mStencilRef; break; - case GL_STENCIL_VALUE_MASK: *params = clampToInt(mDepthStencil.stencilMask); break; - case GL_STENCIL_BACK_FUNC: *params = mDepthStencil.stencilBackFunc; break; - case GL_STENCIL_BACK_REF: *params = mStencilBackRef; break; - case GL_STENCIL_BACK_VALUE_MASK: *params = clampToInt(mDepthStencil.stencilBackMask); break; - case GL_STENCIL_FAIL: *params = mDepthStencil.stencilFail; break; - case GL_STENCIL_PASS_DEPTH_FAIL: *params = mDepthStencil.stencilPassDepthFail; break; - case GL_STENCIL_PASS_DEPTH_PASS: *params = mDepthStencil.stencilPassDepthPass; break; - case GL_STENCIL_BACK_FAIL: *params = mDepthStencil.stencilBackFail; break; - case GL_STENCIL_BACK_PASS_DEPTH_FAIL: *params = mDepthStencil.stencilBackPassDepthFail; break; - case GL_STENCIL_BACK_PASS_DEPTH_PASS: *params = mDepthStencil.stencilBackPassDepthPass; break; - case GL_DEPTH_FUNC: *params = mDepthStencil.depthFunc; break; - case GL_BLEND_SRC_RGB: *params = mBlend.sourceBlendRGB; break; - case GL_BLEND_SRC_ALPHA: *params = mBlend.sourceBlendAlpha; break; - case GL_BLEND_DST_RGB: *params = mBlend.destBlendRGB; break; - case GL_BLEND_DST_ALPHA: *params = mBlend.destBlendAlpha; break; - case GL_BLEND_EQUATION_RGB: *params = mBlend.blendEquationRGB; break; - case GL_BLEND_EQUATION_ALPHA: *params = mBlend.blendEquationAlpha; break; - case GL_STENCIL_WRITEMASK: *params = clampToInt(mDepthStencil.stencilWritemask); break; - case GL_STENCIL_BACK_WRITEMASK: *params = clampToInt(mDepthStencil.stencilBackWritemask); break; - case GL_STENCIL_CLEAR_VALUE: *params = mStencilClearValue; break; - case GL_SAMPLE_BUFFERS: - case GL_SAMPLES: - { - gl::Framebuffer *framebuffer = mDrawFramebuffer; - if (framebuffer->completeness(data) == GL_FRAMEBUFFER_COMPLETE) - { - switch (pname) - { - case GL_SAMPLE_BUFFERS: - if (framebuffer->getSamples(data) != 0) - { - *params = 1; - } - else - { - *params = 0; - } - break; - case GL_SAMPLES: - *params = framebuffer->getSamples(data); - break; - } - } - else - { - *params = 0; - } - } - break; - case GL_VIEWPORT: - params[0] = mViewport.x; - params[1] = mViewport.y; - params[2] = mViewport.width; - params[3] = mViewport.height; - break; - case GL_SCISSOR_BOX: - params[0] = mScissor.x; - params[1] = mScissor.y; - params[2] = mScissor.width; - params[3] = mScissor.height; - break; - case GL_CULL_FACE_MODE: *params = mRasterizer.cullMode; break; - case GL_FRONT_FACE: *params = mRasterizer.frontFace; break; - case GL_RED_BITS: - case GL_GREEN_BITS: - case GL_BLUE_BITS: - case GL_ALPHA_BITS: - { - gl::Framebuffer *framebuffer = getDrawFramebuffer(); - gl::FramebufferAttachment *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; - } - } - else - { - *params = 0; - } - } - break; - case GL_DEPTH_BITS: - { - gl::Framebuffer *framebuffer = getDrawFramebuffer(); - gl::FramebufferAttachment *depthbuffer = framebuffer->getDepthbuffer(); - - if (depthbuffer) - { - *params = depthbuffer->getDepthSize(); - } - else - { - *params = 0; - } - } - break; - case GL_STENCIL_BITS: - { - gl::Framebuffer *framebuffer = getDrawFramebuffer(); - gl::FramebufferAttachment *stencilbuffer = framebuffer->getStencilbuffer(); - - if (stencilbuffer) - { - *params = stencilbuffer->getStencilSize(); - } - else - { - *params = 0; - } - } - break; - case GL_TEXTURE_BINDING_2D: - ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits); - *params = mSamplerTextures.at(GL_TEXTURE_2D)[mActiveSampler].id(); - break; - case GL_TEXTURE_BINDING_CUBE_MAP: - ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits); - *params = mSamplerTextures.at(GL_TEXTURE_CUBE_MAP)[mActiveSampler].id(); - break; - case GL_TEXTURE_BINDING_3D: - ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits); - *params = mSamplerTextures.at(GL_TEXTURE_3D)[mActiveSampler].id(); - break; - case GL_TEXTURE_BINDING_2D_ARRAY: - ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits); - *params = mSamplerTextures.at(GL_TEXTURE_2D_ARRAY)[mActiveSampler].id(); - break; - case GL_UNIFORM_BUFFER_BINDING: - *params = mGenericUniformBuffer.id(); - break; - case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: - *params = mGenericTransformFeedbackBuffer.id(); - break; - case GL_COPY_READ_BUFFER_BINDING: - *params = mCopyReadBuffer.id(); - break; - case GL_COPY_WRITE_BUFFER_BINDING: - *params = mCopyWriteBuffer.id(); - break; - case GL_PIXEL_PACK_BUFFER_BINDING: - *params = mPack.pixelBuffer.id(); - break; - case GL_PIXEL_UNPACK_BUFFER_BINDING: - *params = mUnpack.pixelBuffer.id(); - break; - default: - UNREACHABLE(); - break; - } -} - -bool State::getIndexedIntegerv(GLenum target, GLuint index, GLint *data) -{ - switch (target) - { - case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: - if (static_cast(index) < mTransformFeedbackBuffers.size()) - { - *data = mTransformFeedbackBuffers[index].id(); - } - break; - case GL_UNIFORM_BUFFER_BINDING: - if (static_cast(index) < mUniformBuffers.size()) - { - *data = mUniformBuffers[index].id(); - } - break; - default: - return false; - } - - return true; -} - -bool State::getIndexedInteger64v(GLenum target, GLuint index, GLint64 *data) -{ - switch (target) - { - case GL_TRANSFORM_FEEDBACK_BUFFER_START: - if (static_cast(index) < mTransformFeedbackBuffers.size()) - { - *data = mTransformFeedbackBuffers[index].getOffset(); - } - break; - case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE: - if (static_cast(index) < mTransformFeedbackBuffers.size()) - { - *data = mTransformFeedbackBuffers[index].getSize(); - } - break; - case GL_UNIFORM_BUFFER_START: - if (static_cast(index) < mUniformBuffers.size()) - { - *data = mUniformBuffers[index].getOffset(); - } - break; - case GL_UNIFORM_BUFFER_SIZE: - if (static_cast(index) < mUniformBuffers.size()) - { - *data = mUniformBuffers[index].getSize(); - } - break; - default: - return false; - } - - return true; -} - -bool State::hasMappedBuffer(GLenum target) const -{ - if (target == GL_ARRAY_BUFFER) - { - for (size_t attribIndex = 0; attribIndex < mVertexAttribCurrentValues.size(); attribIndex++) - { - const gl::VertexAttribute &vertexAttrib = getVertexAttribState(static_cast(attribIndex)); - gl::Buffer *boundBuffer = vertexAttrib.buffer.get(); - if (vertexAttrib.enabled && boundBuffer && boundBuffer->isMapped()) - { - return true; - } - } - - return false; - } - else - { - Buffer *buffer = getTargetBuffer(target); - return (buffer && buffer->isMapped()); - } -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/State.h b/src/3rdparty/angle/src/libGLESv2/State.h deleted file mode 100644 index c3e6106bd8..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/State.h +++ /dev/null @@ -1,325 +0,0 @@ -// -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// State.h: Defines the State class, encapsulating raw GL state - -#ifndef LIBGLESV2_STATE_H_ -#define LIBGLESV2_STATE_H_ - -#include "common/angleutils.h" -#include "common/RefCountObject.h" -#include "libGLESv2/angletypes.h" -#include "libGLESv2/VertexAttribute.h" -#include "libGLESv2/Renderbuffer.h" -#include "libGLESv2/Texture.h" -#include "libGLESv2/TransformFeedback.h" -#include "libGLESv2/Program.h" -#include "libGLESv2/Sampler.h" - -namespace gl -{ -class Query; -class VertexArray; -class Context; -struct Caps; -struct Data; - -typedef std::map< GLenum, BindingPointer > TextureMap; - -class State -{ - public: - State(); - ~State(); - - void initialize(const Caps& caps, GLuint clientVersion); - void reset(); - - // State chunk getters - const RasterizerState &getRasterizerState() const; - const BlendState &getBlendState() const; - const DepthStencilState &getDepthStencilState() const; - - // Clear behavior setters & state parameter block generation function - void setClearColor(float red, float green, float blue, float alpha); - void setClearDepth(float depth); - void setClearStencil(int stencil); - ClearParameters getClearParameters(GLbitfield mask) const; - - // Write mask manipulation - void setColorMask(bool red, bool green, bool blue, bool alpha); - void setDepthMask(bool mask); - - // Discard toggle & query - bool isRasterizerDiscardEnabled() const; - void setRasterizerDiscard(bool enabled); - - // Face culling state manipulation - bool isCullFaceEnabled() const; - void setCullFace(bool enabled); - void setCullMode(GLenum mode); - void setFrontFace(GLenum front); - - // Depth test state manipulation - bool isDepthTestEnabled() const; - void setDepthTest(bool enabled); - void setDepthFunc(GLenum depthFunc); - void setDepthRange(float zNear, float zFar); - void getDepthRange(float *zNear, float *zFar) const; - - // Blend state manipulation - bool isBlendEnabled() const; - void setBlend(bool enabled); - void setBlendFactors(GLenum sourceRGB, GLenum destRGB, GLenum sourceAlpha, GLenum destAlpha); - void setBlendColor(float red, float green, float blue, float alpha); - void setBlendEquation(GLenum rgbEquation, GLenum alphaEquation); - const ColorF &getBlendColor() const; - - // Stencil state maniupulation - bool isStencilTestEnabled() const; - void setStencilTest(bool enabled); - void setStencilParams(GLenum stencilFunc, GLint stencilRef, GLuint stencilMask); - void setStencilBackParams(GLenum stencilBackFunc, GLint stencilBackRef, GLuint stencilBackMask); - void setStencilWritemask(GLuint stencilWritemask); - void setStencilBackWritemask(GLuint stencilBackWritemask); - void setStencilOperations(GLenum stencilFail, GLenum stencilPassDepthFail, GLenum stencilPassDepthPass); - void setStencilBackOperations(GLenum stencilBackFail, GLenum stencilBackPassDepthFail, GLenum stencilBackPassDepthPass); - GLint getStencilRef() const; - GLint getStencilBackRef() const; - - // Depth bias/polygon offset state manipulation - bool isPolygonOffsetFillEnabled() const; - void setPolygonOffsetFill(bool enabled); - void setPolygonOffsetParams(GLfloat factor, GLfloat units); - - // Multisample coverage state manipulation - bool isSampleAlphaToCoverageEnabled() const; - void setSampleAlphaToCoverage(bool enabled); - bool isSampleCoverageEnabled() const; - void setSampleCoverage(bool enabled); - void setSampleCoverageParams(GLclampf value, bool invert); - void getSampleCoverageParams(GLclampf *value, bool *invert) const; - - // Scissor test state toggle & query - bool isScissorTestEnabled() const; - void setScissorTest(bool enabled); - void setScissorParams(GLint x, GLint y, GLsizei width, GLsizei height); - const Rectangle &getScissor() const; - - // Dither state toggle & query - bool isDitherEnabled() const; - void setDither(bool enabled); - - // Generic state toggle & query - void setEnableFeature(GLenum feature, bool enabled); - bool getEnableFeature(GLenum feature); - - // Line width state setter - void setLineWidth(GLfloat width); - - // Hint setters - void setGenerateMipmapHint(GLenum hint); - void setFragmentShaderDerivativeHint(GLenum hint); - - // Viewport state setter/getter - void setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height); - const Rectangle &getViewport() const; - - // Texture binding & active texture unit manipulation - void setActiveSampler(unsigned int active); - unsigned int getActiveSampler() const; - void setSamplerTexture(GLenum type, Texture *texture); - Texture *getSamplerTexture(unsigned int sampler, GLenum type) const; - GLuint getSamplerTextureId(unsigned int sampler, GLenum type) const; - void detachTexture(const TextureMap &zeroTextures, GLuint texture); - void initializeZeroTextures(const TextureMap &zeroTextures); - - // Sampler object binding manipulation - void setSamplerBinding(GLuint textureUnit, Sampler *sampler); - GLuint getSamplerId(GLuint textureUnit) const; - Sampler *getSampler(GLuint textureUnit) const; - void detachSampler(GLuint sampler); - - // Renderbuffer binding manipulation - void setRenderbufferBinding(Renderbuffer *renderbuffer); - GLuint getRenderbufferId() const; - Renderbuffer *getCurrentRenderbuffer(); - void detachRenderbuffer(GLuint renderbuffer); - - // Framebuffer binding manipulation - void setReadFramebufferBinding(Framebuffer *framebuffer); - void setDrawFramebufferBinding(Framebuffer *framebuffer); - Framebuffer *getTargetFramebuffer(GLenum target) const; - Framebuffer *getReadFramebuffer(); - Framebuffer *getDrawFramebuffer(); - const Framebuffer *getReadFramebuffer() const; - const Framebuffer *getDrawFramebuffer() const; - bool removeReadFramebufferBinding(GLuint framebuffer); - bool removeDrawFramebufferBinding(GLuint framebuffer); - - // Vertex array object binding manipulation - void setVertexArrayBinding(VertexArray *vertexArray); - GLuint getVertexArrayId() const; - VertexArray *getVertexArray() const; - bool removeVertexArrayBinding(GLuint vertexArray); - - // Program binding manipulation - void setCurrentProgram(GLuint programId, Program *newProgram); - void setCurrentProgramBinary(ProgramBinary *binary); - GLuint getCurrentProgramId() const; - ProgramBinary *getCurrentProgramBinary() const; - - // Transform feedback object (not buffer) binding manipulation - void setTransformFeedbackBinding(TransformFeedback *transformFeedback); - TransformFeedback *getCurrentTransformFeedback() const; - void detachTransformFeedback(GLuint transformFeedback); - - // Query binding manipulation - bool isQueryActive() const; - void setActiveQuery(GLenum target, Query *query); - GLuint getActiveQueryId(GLenum target) const; - Query *getActiveQuery(GLenum target) const; - - //// Typed buffer binding point manipulation //// - // GL_ARRAY_BUFFER - void setArrayBufferBinding(Buffer *buffer); - GLuint getArrayBufferId() const; - bool removeArrayBufferBinding(GLuint buffer); - - // GL_UNIFORM_BUFFER - Both indexed and generic targets - void setGenericUniformBufferBinding(Buffer *buffer); - void setIndexedUniformBufferBinding(GLuint index, Buffer *buffer, GLintptr offset, GLsizeiptr size); - GLuint getIndexedUniformBufferId(GLuint index) const; - Buffer *getIndexedUniformBuffer(GLuint index) const; - - // GL_TRANSFORM_FEEDBACK_BUFFER - Both indexed and generic targets - void setGenericTransformFeedbackBufferBinding(Buffer *buffer); - void setIndexedTransformFeedbackBufferBinding(GLuint index, Buffer *buffer, GLintptr offset, GLsizeiptr size); - GLuint getIndexedTransformFeedbackBufferId(GLuint index) const; - Buffer *getIndexedTransformFeedbackBuffer(GLuint index) const; - GLuint getIndexedTransformFeedbackBufferOffset(GLuint index) const; - size_t getTransformFeedbackBufferIndexRange() const; - - // GL_COPY_[READ/WRITE]_BUFFER - void setCopyReadBufferBinding(Buffer *buffer); - void setCopyWriteBufferBinding(Buffer *buffer); - - // GL_PIXEL[PACK/UNPACK]_BUFFER - void setPixelPackBufferBinding(Buffer *buffer); - void setPixelUnpackBufferBinding(Buffer *buffer); - - // Retrieve typed buffer by target (non-indexed) - Buffer *getTargetBuffer(GLenum target) const; - - // Vertex attrib manipulation - void setEnableVertexAttribArray(unsigned int attribNum, bool enabled); - void setVertexAttribf(GLuint index, const GLfloat values[4]); - void setVertexAttribu(GLuint index, const GLuint values[4]); - void setVertexAttribi(GLuint index, const GLint values[4]); - void setVertexAttribState(unsigned int attribNum, Buffer *boundBuffer, GLint size, GLenum type, - bool normalized, bool pureInteger, GLsizei stride, const void *pointer); - const VertexAttribute &getVertexAttribState(unsigned int attribNum) const; - const VertexAttribCurrentValueData &getVertexAttribCurrentValue(unsigned int attribNum) const; - const void *getVertexAttribPointer(unsigned int attribNum) const; - - // Pixel pack state manipulation - void setPackAlignment(GLint alignment); - GLint getPackAlignment() const; - void setPackReverseRowOrder(bool reverseRowOrder); - bool getPackReverseRowOrder() const; - const PixelPackState &getPackState() const; - - // Pixel unpack state manipulation - void setUnpackAlignment(GLint alignment); - GLint getUnpackAlignment() const; - const PixelUnpackState &getUnpackState() const; - - // State query functions - void getBooleanv(GLenum pname, GLboolean *params); - void getFloatv(GLenum pname, GLfloat *params); - void getIntegerv(const gl::Data &data, GLenum pname, GLint *params); - bool getIndexedIntegerv(GLenum target, GLuint index, GLint *data); - bool getIndexedInteger64v(GLenum target, GLuint index, GLint64 *data); - - bool hasMappedBuffer(GLenum target) const; - - private: - DISALLOW_COPY_AND_ASSIGN(State); - - // Cached values from Context's caps - GLuint mMaxDrawBuffers; - GLuint mMaxCombinedTextureImageUnits; - - ColorF mColorClearValue; - GLclampf mDepthClearValue; - int mStencilClearValue; - - RasterizerState mRasterizer; - bool mScissorTest; - Rectangle mScissor; - - BlendState mBlend; - ColorF mBlendColor; - bool mSampleCoverage; - GLclampf mSampleCoverageValue; - bool mSampleCoverageInvert; - - DepthStencilState mDepthStencil; - GLint mStencilRef; - GLint mStencilBackRef; - - GLfloat mLineWidth; - - GLenum mGenerateMipmapHint; - GLenum mFragmentShaderDerivativeHint; - - Rectangle mViewport; - float mNearZ; - float mFarZ; - - BindingPointer mArrayBuffer; - Framebuffer *mReadFramebuffer; - Framebuffer *mDrawFramebuffer; - BindingPointer mRenderbuffer; - GLuint mCurrentProgramId; - BindingPointer mCurrentProgramBinary; - - typedef std::vector VertexAttribVector; - VertexAttribVector mVertexAttribCurrentValues; // From glVertexAttrib - VertexArray *mVertexArray; - - // Texture and sampler bindings - size_t mActiveSampler; // Active texture unit selector - GL_TEXTURE0 - - typedef std::vector< BindingPointer > TextureBindingVector; - typedef std::map TextureBindingMap; - TextureBindingMap mSamplerTextures; - - typedef std::vector< BindingPointer > SamplerBindingVector; - SamplerBindingVector mSamplers; - - typedef std::map< GLenum, BindingPointer > ActiveQueryMap; - ActiveQueryMap mActiveQueries; - - BindingPointer mGenericUniformBuffer; - typedef std::vector< OffsetBindingPointer > BufferVector; - BufferVector mUniformBuffers; - - BindingPointer mTransformFeedback; - BindingPointer mGenericTransformFeedbackBuffer; - BufferVector mTransformFeedbackBuffers; - - BindingPointer mCopyReadBuffer; - BindingPointer mCopyWriteBuffer; - - PixelUnpackState mUnpack; - PixelPackState mPack; -}; - -} - -#endif // LIBGLESV2_STATE_H_ - diff --git a/src/3rdparty/angle/src/libGLESv2/Texture.cpp b/src/3rdparty/angle/src/libGLESv2/Texture.cpp deleted file mode 100644 index cd4fc4e32a..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/Texture.cpp +++ /dev/null @@ -1,1012 +0,0 @@ -// -// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Texture.cpp: Implements the gl::Texture class and its derived classes -// Texture2D and TextureCubeMap. Implements GL texture objects and related -// functionality. [OpenGL ES 2.0.24] section 3.7 page 63. - -#include "libGLESv2/Texture.h" -#include "libGLESv2/main.h" -#include "libGLESv2/Context.h" -#include "libGLESv2/formatutils.h" -#include "libGLESv2/ImageIndex.h" -#include "libGLESv2/Renderbuffer.h" -#include "libGLESv2/renderer/Image.h" -#include "libGLESv2/renderer/d3d/TextureStorage.h" - -#include "libEGL/Surface.h" - -#include "common/mathutil.h" -#include "common/utilities.h" - -namespace gl -{ - -bool IsMipmapFiltered(const gl::SamplerState &samplerState) -{ - switch (samplerState.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; - } -} - -bool IsPointSampled(const gl::SamplerState &samplerState) -{ - return (samplerState.magFilter == GL_NEAREST && (samplerState.minFilter == GL_NEAREST || samplerState.minFilter == GL_NEAREST_MIPMAP_NEAREST)); -} - -unsigned int Texture::mCurrentTextureSerial = 1; - -Texture::Texture(rx::TextureImpl *impl, GLuint id, GLenum target) - : RefCountObject(id), - mTexture(impl), - mTextureSerial(issueTextureSerial()), - mUsage(GL_NONE), - mImmutableLevelCount(0), - mTarget(target) -{ -} - -Texture::~Texture() -{ - SafeDelete(mTexture); -} - -GLenum Texture::getTarget() const -{ - return mTarget; -} - -void Texture::setUsage(GLenum usage) -{ - mUsage = usage; - getImplementation()->setUsage(usage); -} - -GLenum Texture::getUsage() const -{ - return mUsage; -} - -GLint Texture::getBaseLevelWidth() const -{ - const rx::Image *baseImage = getBaseLevelImage(); - return (baseImage ? baseImage->getWidth() : 0); -} - -GLint Texture::getBaseLevelHeight() const -{ - const rx::Image *baseImage = getBaseLevelImage(); - return (baseImage ? baseImage->getHeight() : 0); -} - -GLint Texture::getBaseLevelDepth() const -{ - const rx::Image *baseImage = getBaseLevelImage(); - return (baseImage ? baseImage->getDepth() : 0); -} - -// Note: "base level image" is loosely defined to be any image from the base level, -// where in the base of 2D array textures and cube maps there are several. Don't use -// the base level image for anything except querying texture format and size. -GLenum Texture::getBaseLevelInternalFormat() const -{ - const rx::Image *baseImage = getBaseLevelImage(); - return (baseImage ? baseImage->getInternalFormat() : GL_NONE); -} - -GLsizei Texture::getWidth(const ImageIndex &index) const -{ - rx::Image *image = mTexture->getImage(index); - return image->getWidth(); -} - -GLsizei Texture::getHeight(const ImageIndex &index) const -{ - rx::Image *image = mTexture->getImage(index); - return image->getHeight(); -} - -GLenum Texture::getInternalFormat(const ImageIndex &index) const -{ - rx::Image *image = mTexture->getImage(index); - return image->getInternalFormat(); -} - -GLenum Texture::getActualFormat(const ImageIndex &index) const -{ - rx::Image *image = mTexture->getImage(index); - return image->getActualFormat(); -} - -Error Texture::generateMipmaps() -{ - return getImplementation()->generateMipmaps(); -} - -Error Texture::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, - GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source) -{ - return mTexture->copySubImage(target, level, xoffset, yoffset, zoffset, x, y, width, height, source); -} - -unsigned int Texture::getTextureSerial() const -{ - return mTextureSerial; -} - -unsigned int Texture::issueTextureSerial() -{ - return mCurrentTextureSerial++; -} - -bool Texture::isImmutable() const -{ - return (mImmutableLevelCount > 0); -} - -int Texture::immutableLevelCount() -{ - return mImmutableLevelCount; -} - -int Texture::mipLevels() const -{ - return log2(std::max(std::max(getBaseLevelWidth(), getBaseLevelHeight()), getBaseLevelDepth())) + 1; -} - -const rx::Image *Texture::getBaseLevelImage() const -{ - return (getImplementation()->getLayerCount(0) > 0 ? getImplementation()->getImage(0, 0) : NULL); -} - -Texture2D::Texture2D(rx::TextureImpl *impl, GLuint id) - : Texture(impl, id, GL_TEXTURE_2D) -{ - mSurface = NULL; -} - -Texture2D::~Texture2D() -{ - if (mSurface) - { - mSurface->setBoundTexture(NULL); - mSurface = NULL; - } -} - -GLsizei Texture2D::getWidth(GLint level) const -{ - if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) - return mTexture->getImage(level, 0)->getWidth(); - else - return 0; -} - -GLsizei Texture2D::getHeight(GLint level) const -{ - if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) - return mTexture->getImage(level, 0)->getHeight(); - else - return 0; -} - -GLenum Texture2D::getInternalFormat(GLint level) const -{ - if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) - return mTexture->getImage(level, 0)->getInternalFormat(); - else - return GL_NONE; -} - -GLenum Texture2D::getActualFormat(GLint level) const -{ - if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) - return mTexture->getImage(level, 0)->getActualFormat(); - else - return GL_NONE; -} - -Error Texture2D::setImage(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) -{ - releaseTexImage(); - - return mTexture->setImage(GL_TEXTURE_2D, level, width, height, 1, internalFormat, format, type, unpack, pixels); -} - -void Texture2D::bindTexImage(egl::Surface *surface) -{ - releaseTexImage(); - - mTexture->bindTexImage(surface); - - mSurface = surface; - mSurface->setBoundTexture(this); -} - -void Texture2D::releaseTexImage() -{ - if (mSurface) - { - mSurface->setBoundTexture(NULL); - mSurface = NULL; - - mTexture->releaseTexImage(); - } -} - -Error Texture2D::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, - const PixelUnpackState &unpack, const void *pixels) -{ - releaseTexImage(); - - return mTexture->setCompressedImage(GL_TEXTURE_2D, level, format, width, height, 1, imageSize, unpack, pixels); -} - -Error Texture2D::subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) -{ - return mTexture->subImage(GL_TEXTURE_2D, level, xoffset, yoffset, 0, width, height, 1, format, type, unpack, pixels); -} - -Error Texture2D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, - GLenum format, GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels) -{ - return mTexture->subImageCompressed(GL_TEXTURE_2D, level, xoffset, yoffset, 0, width, height, 1, format, imageSize, unpack, pixels); -} - -Error Texture2D::copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, - Framebuffer *source) -{ - releaseTexImage(); - - return mTexture->copyImage(GL_TEXTURE_2D, level, format, x, y, width, height, source); -} - -Error Texture2D::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) -{ - Error error = mTexture->storage(GL_TEXTURE_2D, levels, internalformat, width, height, 1); - if (error.isError()) - { - return error; - } - - mImmutableLevelCount = levels; - - return Error(GL_NO_ERROR); -} - -// Tests for 2D texture sampling completeness. [OpenGL ES 2.0.24] section 3.8.2 page 85. -bool Texture2D::isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const -{ - GLsizei width = getBaseLevelWidth(); - GLsizei height = getBaseLevelHeight(); - - if (width <= 0 || height <= 0) - { - return false; - } - - if (!textureCaps.get(getInternalFormat(0)).filterable && !IsPointSampled(samplerState)) - { - return false; - } - - bool npotSupport = extensions.textureNPOT; - - if (!npotSupport) - { - if ((samplerState.wrapS != GL_CLAMP_TO_EDGE && !gl::isPow2(width)) || - (samplerState.wrapT != GL_CLAMP_TO_EDGE && !gl::isPow2(height))) - { - return false; - } - } - - if (IsMipmapFiltered(samplerState)) - { - if (!npotSupport) - { - if (!gl::isPow2(width) || !gl::isPow2(height)) - { - return false; - } - } - - if (!isMipmapComplete()) - { - return false; - } - } - - // OpenGLES 3.0.2 spec section 3.8.13 states that a texture is not mipmap complete if: - // The internalformat specified for the texture arrays is a sized internal depth or - // depth and stencil format (see table 3.13), the value of TEXTURE_COMPARE_- - // MODE is NONE, and either the magnification filter is not NEAREST or the mini- - // fication filter is neither NEAREST nor NEAREST_MIPMAP_NEAREST. - const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(getInternalFormat(0)); - if (formatInfo.depthBits > 0 && clientVersion > 2) - { - if (samplerState.compareMode == GL_NONE) - { - if ((samplerState.minFilter != GL_NEAREST && samplerState.minFilter != GL_NEAREST_MIPMAP_NEAREST) || - samplerState.magFilter != GL_NEAREST) - { - return false; - } - } - } - - return true; -} - -bool Texture2D::isCompressed(GLint level) const -{ - return GetInternalFormatInfo(getInternalFormat(level)).compressed; -} - -bool Texture2D::isDepth(GLint level) const -{ - return GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0; -} - -Error Texture2D::generateMipmaps() -{ - releaseTexImage(); - - return mTexture->generateMipmaps(); -} - -// Tests for 2D texture (mipmap) completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81. -bool Texture2D::isMipmapComplete() const -{ - int levelCount = mipLevels(); - - for (int level = 0; level < levelCount; level++) - { - if (!isLevelComplete(level)) - { - return false; - } - } - - return true; -} - -bool Texture2D::isLevelComplete(int level) const -{ - if (isImmutable()) - { - return true; - } - - const rx::Image *baseImage = getBaseLevelImage(); - - GLsizei width = baseImage->getWidth(); - GLsizei height = baseImage->getHeight(); - - if (width <= 0 || height <= 0) - { - return false; - } - - // The base image level is complete if the width and height are positive - if (level == 0) - { - return true; - } - - ASSERT(level >= 1 && level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mTexture->getImage(level, 0) != NULL); - rx::Image *image = mTexture->getImage(level, 0); - - if (image->getInternalFormat() != baseImage->getInternalFormat()) - { - return false; - } - - if (image->getWidth() != std::max(1, width >> level)) - { - return false; - } - - if (image->getHeight() != std::max(1, height >> level)) - { - return false; - } - - return true; -} - -TextureCubeMap::TextureCubeMap(rx::TextureImpl *impl, GLuint id) - : Texture(impl, id, GL_TEXTURE_CUBE_MAP) -{ -} - -TextureCubeMap::~TextureCubeMap() -{ -} - -GLsizei TextureCubeMap::getWidth(GLenum target, GLint level) const -{ - if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) - return mTexture->getImage(level, targetToLayerIndex(target))->getWidth(); - else - return 0; -} - -GLsizei TextureCubeMap::getHeight(GLenum target, GLint level) const -{ - if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) - return mTexture->getImage(level, targetToLayerIndex(target))->getHeight(); - else - return 0; -} - -GLenum TextureCubeMap::getInternalFormat(GLenum target, GLint level) const -{ - if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) - return mTexture->getImage(level, targetToLayerIndex(target))->getInternalFormat(); - else - return GL_NONE; -} - -GLenum TextureCubeMap::getActualFormat(GLenum target, GLint level) const -{ - if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) - return mTexture->getImage(level, targetToLayerIndex(target))->getActualFormat(); - else - return GL_NONE; -} - -Error TextureCubeMap::setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) -{ - return mTexture->setImage(target, level, width, height, 1, internalFormat, format, type, unpack, pixels); -} - -Error TextureCubeMap::setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, - GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels) -{ - return mTexture->setCompressedImage(target, level, format, width, height, 1, imageSize, unpack, pixels); -} - -Error TextureCubeMap::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) -{ - return mTexture->subImage(target, level, xoffset, yoffset, 0, width, height, 1, format, type, unpack, pixels); -} - -Error TextureCubeMap::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, - GLsizei width, GLsizei height, GLenum format, - GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels) -{ - return mTexture->subImageCompressed(target, level, xoffset, yoffset, 0, width, height, 1, format, imageSize, unpack, pixels); -} - -// Tests for cube texture completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81. -bool TextureCubeMap::isCubeComplete() const -{ - int baseWidth = getBaseLevelWidth(); - int baseHeight = getBaseLevelHeight(); - GLenum baseFormat = getBaseLevelInternalFormat(); - - if (baseWidth <= 0 || baseWidth != baseHeight) - { - return false; - } - - for (int faceIndex = 1; faceIndex < 6; faceIndex++) - { - const rx::Image *faceBaseImage = mTexture->getImage(0, faceIndex); - - if (faceBaseImage->getWidth() != baseWidth || - faceBaseImage->getHeight() != baseHeight || - faceBaseImage->getInternalFormat() != baseFormat ) - { - return false; - } - } - - return true; -} - -bool TextureCubeMap::isCompressed(GLenum target, GLint level) const -{ - return GetInternalFormatInfo(getInternalFormat(target, level)).compressed; -} - -bool TextureCubeMap::isDepth(GLenum target, GLint level) const -{ - return GetInternalFormatInfo(getInternalFormat(target, level)).depthBits > 0; -} - -Error TextureCubeMap::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, - GLsizei width, GLsizei height, Framebuffer *source) -{ - return mTexture->copyImage(target, level, format, x, y, width, height, source); -} - -Error TextureCubeMap::storage(GLsizei levels, GLenum internalformat, GLsizei size) -{ - Error error = mTexture->storage(GL_TEXTURE_CUBE_MAP, levels, internalformat, size, size, 1); - if (error.isError()) - { - return error; - } - - mImmutableLevelCount = levels; - - return Error(GL_NO_ERROR); -} - -// Tests for texture sampling completeness -bool TextureCubeMap::isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const -{ - int size = getBaseLevelWidth(); - - bool mipmapping = IsMipmapFiltered(samplerState); - - if (!textureCaps.get(getInternalFormat(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0)).filterable && !IsPointSampled(samplerState)) - { - return false; - } - - if (!gl::isPow2(size) && !extensions.textureNPOT) - { - if (samplerState.wrapS != GL_CLAMP_TO_EDGE || samplerState.wrapT != GL_CLAMP_TO_EDGE || mipmapping) - { - return false; - } - } - - if (!mipmapping) - { - if (!isCubeComplete()) - { - return false; - } - } - else - { - if (!isMipmapComplete()) // Also tests for isCubeComplete() - { - return false; - } - } - - return true; -} - -int TextureCubeMap::targetToLayerIndex(GLenum target) -{ - META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_X - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 1); - META_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 2); - META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 3); - META_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 4); - META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 5); - - return target - GL_TEXTURE_CUBE_MAP_POSITIVE_X; -} - -GLenum TextureCubeMap::layerIndexToTarget(GLint layer) -{ - META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_X - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 1); - META_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 2); - META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 3); - META_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 4); - META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 5); - - return GL_TEXTURE_CUBE_MAP_POSITIVE_X + layer; -} - -bool TextureCubeMap::isMipmapComplete() const -{ - if (isImmutable()) - { - return true; - } - - if (!isCubeComplete()) - { - return false; - } - - int levelCount = mipLevels(); - - for (int face = 0; face < 6; face++) - { - for (int level = 1; level < levelCount; level++) - { - if (!isFaceLevelComplete(face, level)) - { - return false; - } - } - } - - return true; -} - -bool TextureCubeMap::isFaceLevelComplete(int faceIndex, int level) const -{ - ASSERT(level >= 0 && faceIndex < 6 && level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mTexture->getImage(level, faceIndex) != NULL); - - if (isImmutable()) - { - return true; - } - - int baseSize = getBaseLevelWidth(); - - if (baseSize <= 0) - { - return false; - } - - // "isCubeComplete" checks for base level completeness and we must call that - // to determine if any face at level 0 is complete. We omit that check here - // to avoid re-checking cube-completeness for every face at level 0. - if (level == 0) - { - return true; - } - - // Check that non-zero levels are consistent with the base level. - const rx::Image *faceLevelImage = mTexture->getImage(level, faceIndex); - - if (faceLevelImage->getInternalFormat() != getBaseLevelInternalFormat()) - { - return false; - } - - if (faceLevelImage->getWidth() != std::max(1, baseSize >> level)) - { - return false; - } - - return true; -} - - -Texture3D::Texture3D(rx::TextureImpl *impl, GLuint id) - : Texture(impl, id, GL_TEXTURE_3D) -{ -} - -Texture3D::~Texture3D() -{ -} - -GLsizei Texture3D::getWidth(GLint level) const -{ - return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getImage(level, 0)->getWidth() : 0; -} - -GLsizei Texture3D::getHeight(GLint level) const -{ - return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getImage(level, 0)->getHeight() : 0; -} - -GLsizei Texture3D::getDepth(GLint level) const -{ - return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getImage(level, 0)->getDepth() : 0; -} - -GLenum Texture3D::getInternalFormat(GLint level) const -{ - return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getImage(level, 0)->getInternalFormat() : GL_NONE; -} - -GLenum Texture3D::getActualFormat(GLint level) const -{ - return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getImage(level, 0)->getActualFormat() : GL_NONE; -} - -bool Texture3D::isCompressed(GLint level) const -{ - return GetInternalFormatInfo(getInternalFormat(level)).compressed; -} - -bool Texture3D::isDepth(GLint level) const -{ - return GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0; -} - -Error Texture3D::setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) -{ - return mTexture->setImage(GL_TEXTURE_3D, level, width, height, depth, internalFormat, format, type, unpack, pixels); -} - -Error Texture3D::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, - GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels) -{ - return mTexture->setCompressedImage(GL_TEXTURE_3D, level, format, width, height, depth, imageSize, unpack, pixels); -} - -Error Texture3D::subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) -{ - return mTexture->subImage(GL_TEXTURE_3D, level, xoffset, yoffset, zoffset, width, height, depth, format, type, unpack, pixels); -} - -Error Texture3D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, - GLsizei width, GLsizei height, GLsizei depth, GLenum format, - GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels) -{ - return mTexture->subImageCompressed(GL_TEXTURE_3D, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, unpack, pixels); -} - -Error Texture3D::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) -{ - Error error = mTexture->storage(GL_TEXTURE_3D, levels, internalformat, width, height, depth); - if (error.isError()) - { - return error; - } - - mImmutableLevelCount = levels; - - return Error(GL_NO_ERROR); -} - -bool Texture3D::isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const -{ - GLsizei width = getBaseLevelWidth(); - GLsizei height = getBaseLevelHeight(); - GLsizei depth = getBaseLevelDepth(); - - if (width <= 0 || height <= 0 || depth <= 0) - { - return false; - } - - if (!textureCaps.get(getInternalFormat(0)).filterable && !IsPointSampled(samplerState)) - { - return false; - } - - if (IsMipmapFiltered(samplerState) && !isMipmapComplete()) - { - return false; - } - - return true; -} - -bool Texture3D::isMipmapComplete() const -{ - int levelCount = mipLevels(); - - for (int level = 0; level < levelCount; level++) - { - if (!isLevelComplete(level)) - { - return false; - } - } - - return true; -} - -bool Texture3D::isLevelComplete(int level) const -{ - ASSERT(level >= 0 && level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mTexture->getImage(level, 0) != NULL); - - if (isImmutable()) - { - return true; - } - - GLsizei width = getBaseLevelWidth(); - GLsizei height = getBaseLevelHeight(); - GLsizei depth = getBaseLevelDepth(); - - if (width <= 0 || height <= 0 || depth <= 0) - { - return false; - } - - if (level == 0) - { - return true; - } - - rx::Image *levelImage = mTexture->getImage(level, 0); - - if (levelImage->getInternalFormat() != getBaseLevelInternalFormat()) - { - return false; - } - - if (levelImage->getWidth() != std::max(1, width >> level)) - { - return false; - } - - if (levelImage->getHeight() != std::max(1, height >> level)) - { - return false; - } - - if (levelImage->getDepth() != std::max(1, depth >> level)) - { - return false; - } - - return true; -} - -Texture2DArray::Texture2DArray(rx::TextureImpl *impl, GLuint id) - : Texture(impl, id, GL_TEXTURE_2D_ARRAY) -{ -} - -Texture2DArray::~Texture2DArray() -{ -} - -GLsizei Texture2DArray::getWidth(GLint level) const -{ - return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mTexture->getLayerCount(level) > 0) ? mTexture->getImage(level, 0)->getWidth() : 0; -} - -GLsizei Texture2DArray::getHeight(GLint level) const -{ - return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mTexture->getLayerCount(level) > 0) ? mTexture->getImage(level, 0)->getHeight() : 0; -} - -GLsizei Texture2DArray::getLayers(GLint level) const -{ - return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getLayerCount(level) : 0; -} - -GLenum Texture2DArray::getInternalFormat(GLint level) const -{ - return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mTexture->getLayerCount(level) > 0) ? mTexture->getImage(level, 0)->getInternalFormat() : GL_NONE; -} - -GLenum Texture2DArray::getActualFormat(GLint level) const -{ - return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mTexture->getLayerCount(level) > 0) ? mTexture->getImage(level, 0)->getActualFormat() : GL_NONE; -} - -bool Texture2DArray::isCompressed(GLint level) const -{ - return GetInternalFormatInfo(getInternalFormat(level)).compressed; -} - -bool Texture2DArray::isDepth(GLint level) const -{ - return GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0; -} - -Error Texture2DArray::setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) -{ - return mTexture->setImage(GL_TEXTURE_2D_ARRAY, level, width, height, depth, internalFormat, format, type, unpack, pixels); -} - -Error Texture2DArray::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, - GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels) -{ - return mTexture->setCompressedImage(GL_TEXTURE_2D_ARRAY, level, format, width, height, depth, imageSize, unpack, pixels); -} - -Error Texture2DArray::subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) -{ - return mTexture->subImage(GL_TEXTURE_2D_ARRAY, level, xoffset, yoffset, zoffset, width, height, depth, format, type, unpack, pixels); -} - -Error Texture2DArray::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, - GLsizei width, GLsizei height, GLsizei depth, GLenum format, - GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels) -{ - return mTexture->subImageCompressed(GL_TEXTURE_2D_ARRAY, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, unpack, pixels); -} - -Error Texture2DArray::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) -{ - Error error = mTexture->storage(GL_TEXTURE_2D_ARRAY, levels, internalformat, width, height, depth); - if (error.isError()) - { - return error; - } - - mImmutableLevelCount = levels; - - return Error(GL_NO_ERROR); -} - -bool Texture2DArray::isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const -{ - GLsizei width = getBaseLevelWidth(); - GLsizei height = getBaseLevelHeight(); - GLsizei depth = getLayers(0); - - if (width <= 0 || height <= 0 || depth <= 0) - { - return false; - } - - if (!textureCaps.get(getBaseLevelInternalFormat()).filterable && !IsPointSampled(samplerState)) - { - return false; - } - - if (IsMipmapFiltered(samplerState) && !isMipmapComplete()) - { - return false; - } - - return true; -} - -bool Texture2DArray::isMipmapComplete() const -{ - int levelCount = mipLevels(); - - for (int level = 1; level < levelCount; level++) - { - if (!isLevelComplete(level)) - { - return false; - } - } - - return true; -} - -bool Texture2DArray::isLevelComplete(int level) const -{ - ASSERT(level >= 0 && level < IMPLEMENTATION_MAX_TEXTURE_LEVELS); - - if (isImmutable()) - { - return true; - } - - GLsizei width = getBaseLevelWidth(); - GLsizei height = getBaseLevelHeight(); - GLsizei layers = getLayers(0); - - if (width <= 0 || height <= 0 || layers <= 0) - { - return false; - } - - if (level == 0) - { - return true; - } - - if (getInternalFormat(level) != getInternalFormat(0)) - { - return false; - } - - if (getWidth(level) != std::max(1, width >> level)) - { - return false; - } - - if (getHeight(level) != std::max(1, height >> level)) - { - return false; - } - - if (getLayers(level) != layers) - { - return false; - } - - return true; -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/Texture.h b/src/3rdparty/angle/src/libGLESv2/Texture.h deleted file mode 100644 index 66d4df8015..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/Texture.h +++ /dev/null @@ -1,241 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Texture.h: Defines the abstract gl::Texture class and its concrete derived -// classes Texture2D and TextureCubeMap. Implements GL texture objects and -// related functionality. [OpenGL ES 2.0.24] section 3.7 page 63. - -#ifndef LIBGLESV2_TEXTURE_H_ -#define LIBGLESV2_TEXTURE_H_ - -#include "common/debug.h" -#include "common/RefCountObject.h" -#include "libGLESv2/angletypes.h" -#include "libGLESv2/Constants.h" -#include "libGLESv2/renderer/TextureImpl.h" -#include "libGLESv2/Caps.h" - -#include "angle_gl.h" - -#include - -namespace egl -{ -class Surface; -} - -namespace rx -{ -class TextureStorageInterface; -class Image; -} - -namespace gl -{ -class Framebuffer; -class FramebufferAttachment; -struct ImageIndex; - -bool IsMipmapFiltered(const gl::SamplerState &samplerState); - -class Texture : public RefCountObject -{ - public: - Texture(rx::TextureImpl *impl, GLuint id, GLenum target); - - virtual ~Texture(); - - GLenum getTarget() const; - - const SamplerState &getSamplerState() const { return mSamplerState; } - SamplerState &getSamplerState() { return mSamplerState; } - - void setUsage(GLenum usage); - GLenum getUsage() const; - - GLint getBaseLevelWidth() const; - GLint getBaseLevelHeight() const; - GLint getBaseLevelDepth() const; - GLenum getBaseLevelInternalFormat() const; - - GLsizei getWidth(const ImageIndex &index) const; - GLsizei getHeight(const ImageIndex &index) const; - GLenum getInternalFormat(const ImageIndex &index) const; - GLenum getActualFormat(const ImageIndex &index) const; - - virtual bool isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const = 0; - - virtual Error generateMipmaps(); - - virtual Error copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source); - - // Texture serials provide a unique way of identifying a Texture that isn't a raw pointer. - // "id" is not good enough, as Textures can be deleted, then re-allocated with the same id. - unsigned int getTextureSerial() const; - - bool isImmutable() const; - GLsizei immutableLevelCount(); - - rx::TextureImpl *getImplementation() { return mTexture; } - const rx::TextureImpl *getImplementation() const { return mTexture; } - - 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: - int mipLevels() const; - const rx::Image *getBaseLevelImage() const; - static unsigned int issueTextureSerial(); - - rx::TextureImpl *mTexture; - - SamplerState mSamplerState; - GLenum mUsage; - - GLsizei mImmutableLevelCount; - - GLenum mTarget; - - const unsigned int mTextureSerial; - static unsigned int mCurrentTextureSerial; - - private: - DISALLOW_COPY_AND_ASSIGN(Texture); -}; - -class Texture2D : public Texture -{ - public: - Texture2D(rx::TextureImpl *impl, GLuint id); - - virtual ~Texture2D(); - - GLsizei getWidth(GLint level) const; - GLsizei getHeight(GLint level) const; - GLenum getInternalFormat(GLint level) const; - GLenum getActualFormat(GLint level) const; - bool isCompressed(GLint level) const; - bool isDepth(GLint level) const; - - Error setImage(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels); - Error setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels); - Error subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels); - Error subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels); - Error copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source); - Error storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); - - virtual bool isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const; - virtual void bindTexImage(egl::Surface *surface); - virtual void releaseTexImage(); - - virtual Error generateMipmaps(); - - private: - DISALLOW_COPY_AND_ASSIGN(Texture2D); - - bool isMipmapComplete() const; - bool isLevelComplete(int level) const; - - egl::Surface *mSurface; -}; - -class TextureCubeMap : public Texture -{ - public: - TextureCubeMap(rx::TextureImpl *impl, GLuint id); - - virtual ~TextureCubeMap(); - - GLsizei getWidth(GLenum target, GLint level) const; - GLsizei getHeight(GLenum target, GLint level) const; - GLenum getInternalFormat(GLenum target, GLint level) const; - GLenum getActualFormat(GLenum target, GLint level) const; - bool isCompressed(GLenum target, GLint level) const; - bool isDepth(GLenum target, GLint level) const; - - Error setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels); - Error setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels); - Error subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels); - Error subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels); - Error copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source); - Error storage(GLsizei levels, GLenum internalformat, GLsizei size); - - virtual bool isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const; - - bool isCubeComplete() const; - - static int targetToLayerIndex(GLenum target); - static GLenum layerIndexToTarget(GLint layer); - - private: - DISALLOW_COPY_AND_ASSIGN(TextureCubeMap); - - bool isMipmapComplete() const; - bool isFaceLevelComplete(int faceIndex, int level) const; -}; - -class Texture3D : public Texture -{ - public: - Texture3D(rx::TextureImpl *impl, GLuint id); - - virtual ~Texture3D(); - - GLsizei getWidth(GLint level) const; - GLsizei getHeight(GLint level) const; - GLsizei getDepth(GLint level) const; - GLenum getInternalFormat(GLint level) const; - GLenum getActualFormat(GLint level) const; - bool isCompressed(GLint level) const; - bool isDepth(GLint level) const; - - Error setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels); - Error setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels); - Error subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels); - Error subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels); - Error storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); - - virtual bool isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const; - - private: - DISALLOW_COPY_AND_ASSIGN(Texture3D); - - bool isMipmapComplete() const; - bool isLevelComplete(int level) const; -}; - -class Texture2DArray : public Texture -{ - public: - Texture2DArray(rx::TextureImpl *impl, GLuint id); - - virtual ~Texture2DArray(); - - GLsizei getWidth(GLint level) const; - GLsizei getHeight(GLint level) const; - GLsizei getLayers(GLint level) const; - GLenum getInternalFormat(GLint level) const; - GLenum getActualFormat(GLint level) const; - bool isCompressed(GLint level) const; - bool isDepth(GLint level) const; - - Error setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels); - Error setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels); - Error subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels); - Error subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels); - Error storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); - - virtual bool isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const; - - private: - DISALLOW_COPY_AND_ASSIGN(Texture2DArray); - - bool isMipmapComplete() const; - bool isLevelComplete(int level) const; -}; - -} - -#endif // LIBGLESV2_TEXTURE_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/TransformFeedback.cpp b/src/3rdparty/angle/src/libGLESv2/TransformFeedback.cpp deleted file mode 100644 index bfa7072326..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/TransformFeedback.cpp +++ /dev/null @@ -1,71 +0,0 @@ -// -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "libGLESv2/TransformFeedback.h" -#include "libGLESv2/renderer/TransformFeedbackImpl.h" - -namespace gl -{ - -TransformFeedback::TransformFeedback(rx::TransformFeedbackImpl* impl, GLuint id) - : RefCountObject(id), - mTransformFeedback(impl), - mStarted(GL_FALSE), - mPrimitiveMode(GL_NONE), - mPaused(GL_FALSE) -{ - ASSERT(impl != NULL); -} - -TransformFeedback::~TransformFeedback() -{ - SafeDelete(mTransformFeedback); -} - -void TransformFeedback::start(GLenum primitiveMode) -{ - mStarted = GL_TRUE; - mPrimitiveMode = primitiveMode; - mPaused = GL_FALSE; - mTransformFeedback->begin(primitiveMode); -} - -void TransformFeedback::stop() -{ - mStarted = GL_FALSE; - mPrimitiveMode = GL_NONE; - mPaused = GL_FALSE; - mTransformFeedback->end(); -} - -GLboolean TransformFeedback::isStarted() const -{ - return mStarted; -} - -GLenum TransformFeedback::getDrawMode() const -{ - return mPrimitiveMode; -} - -void TransformFeedback::pause() -{ - mPaused = GL_TRUE; - mTransformFeedback->pause(); -} - -void TransformFeedback::resume() -{ - mPaused = GL_FALSE; - mTransformFeedback->resume(); -} - -GLboolean TransformFeedback::isPaused() const -{ - return mPaused; -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/TransformFeedback.h b/src/3rdparty/angle/src/libGLESv2/TransformFeedback.h deleted file mode 100644 index 885a4fe172..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/TransformFeedback.h +++ /dev/null @@ -1,51 +0,0 @@ -// -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef LIBGLESV2_TRANSFORM_FEEDBACK_H_ -#define LIBGLESV2_TRANSFORM_FEEDBACK_H_ - -#include "common/angleutils.h" -#include "common/RefCountObject.h" - -#include "angle_gl.h" - -namespace rx -{ -class TransformFeedbackImpl; -} - -namespace gl -{ - -class TransformFeedback : public RefCountObject -{ - public: - TransformFeedback(rx::TransformFeedbackImpl* impl, GLuint id); - virtual ~TransformFeedback(); - - void start(GLenum primitiveMode); - void stop(); - GLboolean isStarted() const; - - GLenum getDrawMode() const; - - void pause(); - void resume(); - GLboolean isPaused() const; - - private: - DISALLOW_COPY_AND_ASSIGN(TransformFeedback); - - rx::TransformFeedbackImpl* mTransformFeedback; - - GLboolean mStarted; - GLenum mPrimitiveMode; - GLboolean mPaused; -}; - -} - -#endif // LIBGLESV2_TRANSFORM_FEEDBACK_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/Uniform.cpp b/src/3rdparty/angle/src/libGLESv2/Uniform.cpp deleted file mode 100644 index bd0cd2eeec..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/Uniform.cpp +++ /dev/null @@ -1,105 +0,0 @@ -// -// 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 "common/utilities.h" - -namespace gl -{ - -LinkedUniform::LinkedUniform(GLenum type, GLenum precision, const std::string &name, unsigned int arraySize, - const int blockIndex, const sh::BlockMemberInfo &blockInfo) - : type(type), - precision(precision), - name(name), - arraySize(arraySize), - blockIndex(blockIndex), - blockInfo(blockInfo), - data(NULL), - dirty(true), - psRegisterIndex(GL_INVALID_INDEX), - vsRegisterIndex(GL_INVALID_INDEX), - registerCount(0), - registerElement(0) -{ - // We use data storage for default block uniforms to cache values that are sent to D3D during rendering - // Uniform blocks/buffers are treated separately by the Renderer (ES3 path only) - if (isInDefaultBlock()) - { - size_t bytes = dataSize(); - data = new unsigned char[bytes]; - memset(data, 0, bytes); - registerCount = VariableRowCount(type) * elementCount(); - } -} - -LinkedUniform::~LinkedUniform() -{ - delete[] data; -} - -bool LinkedUniform::isArray() const -{ - return arraySize > 0; -} - -unsigned int LinkedUniform::elementCount() const -{ - return arraySize > 0 ? arraySize : 1; -} - -bool LinkedUniform::isReferencedByVertexShader() const -{ - return vsRegisterIndex != GL_INVALID_INDEX; -} - -bool LinkedUniform::isReferencedByFragmentShader() const -{ - return psRegisterIndex != GL_INVALID_INDEX; -} - -bool LinkedUniform::isInDefaultBlock() const -{ - return blockIndex == -1; -} - -size_t LinkedUniform::dataSize() const -{ - ASSERT(type != GL_STRUCT_ANGLEX); - return VariableInternalSize(type) * elementCount(); -} - -bool LinkedUniform::isSampler() const -{ - return IsSampler(type); -} - -UniformBlock::UniformBlock(const std::string &name, unsigned int elementIndex, unsigned int dataSize) - : name(name), - elementIndex(elementIndex), - dataSize(dataSize), - psRegisterIndex(GL_INVALID_INDEX), - vsRegisterIndex(GL_INVALID_INDEX) -{ -} - -bool UniformBlock::isArrayElement() const -{ - return elementIndex != GL_INVALID_INDEX; -} - -bool UniformBlock::isReferencedByVertexShader() const -{ - return vsRegisterIndex != GL_INVALID_INDEX; -} - -bool UniformBlock::isReferencedByFragmentShader() const -{ - return psRegisterIndex != GL_INVALID_INDEX; -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/Uniform.h b/src/3rdparty/angle/src/libGLESv2/Uniform.h deleted file mode 100644 index 633d70bb19..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/Uniform.h +++ /dev/null @@ -1,79 +0,0 @@ -// -// 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 "common/debug.h" -#include "common/blocklayout.h" - -#include "libGLESv2/angletypes.h" - -#include "angle_gl.h" - -#include -#include - -namespace gl -{ - -// Helper struct representing a single shader uniform -struct LinkedUniform -{ - LinkedUniform(GLenum type, GLenum precision, const std::string &name, unsigned int arraySize, const int blockIndex, const sh::BlockMemberInfo &blockInfo); - - ~LinkedUniform(); - - bool isArray() const; - unsigned int elementCount() const; - bool isReferencedByVertexShader() const; - bool isReferencedByFragmentShader() const; - bool isInDefaultBlock() const; - size_t dataSize() const; - bool isSampler() const; - - const GLenum type; - const GLenum precision; - const std::string name; - const unsigned int arraySize; - const int blockIndex; - const sh::BlockMemberInfo blockInfo; - - unsigned char *data; - bool dirty; - - unsigned int psRegisterIndex; - unsigned int vsRegisterIndex; - unsigned int registerCount; - - // Register "elements" are used for uniform structs in ES3, to appropriately identify single uniforms - // inside aggregate types, which are packed according C-like structure rules. - unsigned int registerElement; -}; - -// Helper struct representing a single shader uniform block -struct UniformBlock -{ - // use GL_INVALID_INDEX for non-array elements - UniformBlock(const std::string &name, unsigned int elementIndex, unsigned int dataSize); - - bool isArrayElement() const; - bool isReferencedByVertexShader() const; - bool isReferencedByFragmentShader() const; - - const std::string name; - const unsigned int elementIndex; - const unsigned int dataSize; - - std::vector memberUniformIndexes; - - unsigned int psRegisterIndex; - unsigned int vsRegisterIndex; -}; - -} - -#endif // LIBGLESV2_UNIFORM_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/VertexArray.cpp b/src/3rdparty/angle/src/libGLESv2/VertexArray.cpp deleted file mode 100644 index f8ca661062..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/VertexArray.cpp +++ /dev/null @@ -1,96 +0,0 @@ -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// Implementation of the state class for mananging GLES 3 Vertex Array Objects. -// - -#include "libGLESv2/VertexArray.h" -#include "libGLESv2/Buffer.h" -#include "libGLESv2/renderer/VertexArrayImpl.h" - -namespace gl -{ - -VertexArray::VertexArray(rx::VertexArrayImpl *impl, GLuint id, size_t maxAttribs) - : mId(id), - mVertexArray(impl), - mVertexAttributes(maxAttribs) -{ - ASSERT(impl != NULL); -} - -VertexArray::~VertexArray() -{ - SafeDelete(mVertexArray); - - for (size_t i = 0; i < getMaxAttribs(); i++) - { - mVertexAttributes[i].buffer.set(NULL); - } - mElementArrayBuffer.set(NULL); -} - -GLuint VertexArray::id() const -{ - return mId; -} - -void VertexArray::detachBuffer(GLuint bufferName) -{ - for (size_t attribute = 0; attribute < getMaxAttribs(); attribute++) - { - if (mVertexAttributes[attribute].buffer.id() == bufferName) - { - mVertexAttributes[attribute].buffer.set(NULL); - } - } - - if (mElementArrayBuffer.id() == bufferName) - { - mElementArrayBuffer.set(NULL); - } -} - -const VertexAttribute& VertexArray::getVertexAttribute(size_t attributeIndex) const -{ - ASSERT(attributeIndex < getMaxAttribs()); - return mVertexAttributes[attributeIndex]; -} - -void VertexArray::setVertexAttribDivisor(GLuint index, GLuint divisor) -{ - ASSERT(index < getMaxAttribs()); - mVertexAttributes[index].divisor = divisor; - mVertexArray->setAttributeDivisor(index, divisor); -} - -void VertexArray::enableAttribute(unsigned int attributeIndex, bool enabledState) -{ - ASSERT(attributeIndex < getMaxAttribs()); - mVertexAttributes[attributeIndex].enabled = enabledState; - mVertexArray->enableAttribute(attributeIndex, enabledState); -} - -void VertexArray::setAttributeState(unsigned int attributeIndex, gl::Buffer *boundBuffer, GLint size, GLenum type, - bool normalized, bool pureInteger, GLsizei stride, const void *pointer) -{ - ASSERT(attributeIndex < getMaxAttribs()); - mVertexAttributes[attributeIndex].buffer.set(boundBuffer); - mVertexAttributes[attributeIndex].size = size; - mVertexAttributes[attributeIndex].type = type; - mVertexAttributes[attributeIndex].normalized = normalized; - mVertexAttributes[attributeIndex].pureInteger = pureInteger; - mVertexAttributes[attributeIndex].stride = stride; - mVertexAttributes[attributeIndex].pointer = pointer; - mVertexArray->setAttribute(attributeIndex, mVertexAttributes[attributeIndex]); -} - -void VertexArray::setElementArrayBuffer(Buffer *buffer) -{ - mElementArrayBuffer.set(buffer); - mVertexArray->setElementArrayBuffer(buffer); -} - -} \ No newline at end of file diff --git a/src/3rdparty/angle/src/libGLESv2/VertexArray.h b/src/3rdparty/angle/src/libGLESv2/VertexArray.h deleted file mode 100644 index a724c0be1c..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/VertexArray.h +++ /dev/null @@ -1,62 +0,0 @@ -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// This class contains prototypes for representing GLES 3 Vertex Array Objects: -// -// The buffer objects that are to be used by the vertex stage of the GL are collected -// together to form a vertex array object. All state related to the definition of data used -// by the vertex processor is encapsulated in a vertex array object. -// - -#ifndef LIBGLESV2_VERTEXARRAY_H_ -#define LIBGLESV2_VERTEXARRAY_H_ - -#include "common/RefCountObject.h" -#include "libGLESv2/Constants.h" -#include "libGLESv2/VertexAttribute.h" - -#include - -namespace rx -{ -class VertexArrayImpl; -} - -namespace gl -{ -class Buffer; - -class VertexArray -{ - public: - VertexArray(rx::VertexArrayImpl *impl, GLuint id, size_t maxAttribs); - ~VertexArray(); - - GLuint id() const; - - const VertexAttribute& getVertexAttribute(size_t attributeIndex) const; - void detachBuffer(GLuint bufferName); - void setVertexAttribDivisor(GLuint index, GLuint divisor); - void enableAttribute(unsigned int attributeIndex, bool enabledState); - void setAttributeState(unsigned int attributeIndex, gl::Buffer *boundBuffer, GLint size, GLenum type, - bool normalized, bool pureInteger, GLsizei stride, const void *pointer); - - const VertexAttribute* getVertexAttributes() const { return &mVertexAttributes[0]; } - Buffer *getElementArrayBuffer() const { return mElementArrayBuffer.get(); } - void setElementArrayBuffer(Buffer *buffer); - GLuint getElementArrayBufferId() const { return mElementArrayBuffer.id(); } - size_t getMaxAttribs() const { return mVertexAttributes.size(); } - - private: - GLuint mId; - - rx::VertexArrayImpl *mVertexArray; - std::vector mVertexAttributes; - BindingPointer mElementArrayBuffer; -}; - -} - -#endif // LIBGLESV2_VERTEXARRAY_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/VertexAttribute.cpp b/src/3rdparty/angle/src/libGLESv2/VertexAttribute.cpp deleted file mode 100644 index 1096856b8a..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/VertexAttribute.cpp +++ /dev/null @@ -1,55 +0,0 @@ -// -// Copyright 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// Implementation of the state class for mananging GLES 3 Vertex Array Objects. -// - -#include "libGLESv2/VertexAttribute.h" - -namespace gl -{ - -VertexAttribute::VertexAttribute() - : enabled(false), - type(GL_FLOAT), - size(4), - normalized(false), - pureInteger(false), - stride(0), - pointer(NULL), - divisor(0) -{ -} - -size_t ComputeVertexAttributeTypeSize(const VertexAttribute& attrib) -{ - GLuint size = attrib.size; - switch (attrib.type) - { - case GL_BYTE: return size * sizeof(GLbyte); - case GL_UNSIGNED_BYTE: return size * sizeof(GLubyte); - case GL_SHORT: return size * sizeof(GLshort); - case GL_UNSIGNED_SHORT: return size * sizeof(GLushort); - case GL_INT: return size * sizeof(GLint); - case GL_UNSIGNED_INT: return size * sizeof(GLuint); - case GL_INT_2_10_10_10_REV: return 4; - case GL_UNSIGNED_INT_2_10_10_10_REV: return 4; - case GL_FIXED: return size * sizeof(GLfixed); - case GL_HALF_FLOAT: return size * sizeof(GLhalf); - case GL_FLOAT: return size * sizeof(GLfloat); - default: UNREACHABLE(); return size * sizeof(GLfloat); - } -} - -size_t ComputeVertexAttributeStride(const VertexAttribute& attrib) -{ - if (!attrib.enabled) - { - return 16; - } - return attrib.stride ? attrib.stride : ComputeVertexAttributeTypeSize(attrib); -} - -} \ No newline at end of file diff --git a/src/3rdparty/angle/src/libGLESv2/VertexAttribute.h b/src/3rdparty/angle/src/libGLESv2/VertexAttribute.h deleted file mode 100644 index e9757b618b..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/VertexAttribute.h +++ /dev/null @@ -1,119 +0,0 @@ -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// Helper structure describing a single vertex attribute -// - -#ifndef LIBGLESV2_VERTEXATTRIBUTE_H_ -#define LIBGLESV2_VERTEXATTRIBUTE_H_ - -#include "libGLESv2/Buffer.h" - -namespace gl -{ - -struct VertexAttribute -{ - bool enabled; // From glEnable/DisableVertexAttribArray - - GLenum type; - GLuint size; - bool normalized; - bool pureInteger; - GLuint stride; // 0 means natural stride - - union - { - const GLvoid *pointer; - GLintptr offset; - }; - BindingPointer buffer; // Captured when glVertexAttribPointer is called. - - GLuint divisor; - - VertexAttribute(); -}; - -template -T QuerySingleVertexAttributeParameter(const VertexAttribute& attrib, GLenum pname) -{ - switch (pname) - { - case GL_VERTEX_ATTRIB_ARRAY_ENABLED: - return static_cast(attrib.enabled ? GL_TRUE : GL_FALSE); - case GL_VERTEX_ATTRIB_ARRAY_SIZE: - return static_cast(attrib.size); - case GL_VERTEX_ATTRIB_ARRAY_STRIDE: - return static_cast(attrib.stride); - case GL_VERTEX_ATTRIB_ARRAY_TYPE: - return static_cast(attrib.type); - case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED: - return static_cast(attrib.normalized ? GL_TRUE : GL_FALSE); - case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: - return static_cast(attrib.buffer.id()); - case GL_VERTEX_ATTRIB_ARRAY_DIVISOR: - return static_cast(attrib.divisor); - case GL_VERTEX_ATTRIB_ARRAY_INTEGER: - return static_cast(attrib.pureInteger ? GL_TRUE : GL_FALSE); - default: - UNREACHABLE(); - return static_cast(0); - } -} - -size_t ComputeVertexAttributeTypeSize(const VertexAttribute& attrib); -size_t ComputeVertexAttributeStride(const VertexAttribute& attrib); - -struct VertexAttribCurrentValueData -{ - union - { - GLfloat FloatValues[4]; - GLint IntValues[4]; - GLuint UnsignedIntValues[4]; - }; - GLenum Type; - - void setFloatValues(const GLfloat floatValues[4]) - { - for (unsigned int valueIndex = 0; valueIndex < 4; valueIndex++) - { - FloatValues[valueIndex] = floatValues[valueIndex]; - } - Type = GL_FLOAT; - } - - void setIntValues(const GLint intValues[4]) - { - for (unsigned int valueIndex = 0; valueIndex < 4; valueIndex++) - { - IntValues[valueIndex] = intValues[valueIndex]; - } - Type = GL_INT; - } - - void setUnsignedIntValues(const GLuint unsignedIntValues[4]) - { - for (unsigned int valueIndex = 0; valueIndex < 4; valueIndex++) - { - UnsignedIntValues[valueIndex] = unsignedIntValues[valueIndex]; - } - Type = GL_UNSIGNED_INT; - } - - bool operator==(const VertexAttribCurrentValueData &other) - { - return (Type == other.Type && memcmp(FloatValues, other.FloatValues, sizeof(float) * 4) == 0); - } - - bool operator!=(const VertexAttribCurrentValueData &other) - { - return !(*this == other); - } -}; - -} - -#endif // LIBGLESV2_VERTEXATTRIBUTE_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/angletypes.cpp b/src/3rdparty/angle/src/libGLESv2/angletypes.cpp deleted file mode 100644 index 5a0cfc5ad9..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/angletypes.cpp +++ /dev/null @@ -1,210 +0,0 @@ -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// angletypes.h : Defines a variety of structures and enum types that are used throughout libGLESv2 - -#include "libGLESv2/angletypes.h" -#include "libGLESv2/ProgramBinary.h" -#include "libGLESv2/VertexAttribute.h" -#include "libGLESv2/State.h" -#include "libGLESv2/VertexArray.h" - -#include - -namespace gl -{ - -SamplerState::SamplerState() - : minFilter(GL_NEAREST_MIPMAP_LINEAR), - magFilter(GL_LINEAR), - wrapS(GL_REPEAT), - wrapT(GL_REPEAT), - wrapR(GL_REPEAT), - maxAnisotropy(1.0f), - baseLevel(0), - maxLevel(1000), - minLod(-FLT_MAX), - maxLod(FLT_MAX), - compareMode(GL_NONE), - compareFunc(GL_LEQUAL), - swizzleRed(GL_RED), - swizzleGreen(GL_GREEN), - swizzleBlue(GL_BLUE), - swizzleAlpha(GL_ALPHA) -{} - -bool SamplerState::swizzleRequired() const -{ - return swizzleRed != GL_RED || swizzleGreen != GL_GREEN || - swizzleBlue != GL_BLUE || swizzleAlpha != GL_ALPHA; -} - -static void MinMax(int a, int b, int *minimum, int *maximum) -{ - if (a < b) - { - *minimum = a; - *maximum = b; - } - else - { - *minimum = b; - *maximum = a; - } -} - -bool ClipRectangle(const Rectangle &source, const Rectangle &clip, Rectangle *intersection) -{ - int minSourceX, maxSourceX, minSourceY, maxSourceY; - MinMax(source.x, source.x + source.width, &minSourceX, &maxSourceX); - MinMax(source.y, source.y + source.height, &minSourceY, &maxSourceY); - - int minClipX, maxClipX, minClipY, maxClipY; - MinMax(clip.x, clip.x + clip.width, &minClipX, &maxClipX); - MinMax(clip.y, clip.y + clip.height, &minClipY, &maxClipY); - - if (minSourceX >= maxClipX || maxSourceX <= minClipX || minSourceY >= maxClipY || maxSourceY <= minClipY) - { - if (intersection) - { - intersection->x = minSourceX; - intersection->y = maxSourceY; - intersection->width = maxSourceX - minSourceX; - intersection->height = maxSourceY - minSourceY; - } - - return false; - } - else - { - if (intersection) - { - intersection->x = std::max(minSourceX, minClipX); - intersection->y = std::max(minSourceY, minClipY); - intersection->width = std::min(maxSourceX, maxClipX) - std::max(minSourceX, minClipX); - intersection->height = std::min(maxSourceY, maxClipY) - std::max(minSourceY, minClipY); - } - - return true; - } -} - -VertexFormat::VertexFormat() - : mType(GL_NONE), - mNormalized(GL_FALSE), - mComponents(0), - mPureInteger(false) -{} - -VertexFormat::VertexFormat(GLenum type, GLboolean normalized, GLuint components, bool pureInteger) - : mType(type), - mNormalized(normalized), - mComponents(components), - mPureInteger(pureInteger) -{ - // Float data can not be normalized, so ignore the user setting - if (mType == GL_FLOAT || mType == GL_HALF_FLOAT || mType == GL_FIXED) - { - mNormalized = GL_FALSE; - } -} - -VertexFormat::VertexFormat(const VertexAttribute &attrib) - : mType(attrib.type), - mNormalized(attrib.normalized ? GL_TRUE : GL_FALSE), - mComponents(attrib.size), - mPureInteger(attrib.pureInteger) -{ - // Ensure we aren't initializing a vertex format which should be using - // the current-value type - ASSERT(attrib.enabled); - - // Float data can not be normalized, so ignore the user setting - if (mType == GL_FLOAT || mType == GL_HALF_FLOAT || mType == GL_FIXED) - { - mNormalized = GL_FALSE; - } -} - -VertexFormat::VertexFormat(const VertexAttribute &attrib, GLenum currentValueType) - : mType(attrib.type), - mNormalized(attrib.normalized ? GL_TRUE : GL_FALSE), - mComponents(attrib.size), - mPureInteger(attrib.pureInteger) -{ - if (!attrib.enabled) - { - mType = currentValueType; - mNormalized = GL_FALSE; - mComponents = 4; - mPureInteger = (currentValueType != GL_FLOAT); - } - - // Float data can not be normalized, so ignore the user setting - if (mType == GL_FLOAT || mType == GL_HALF_FLOAT || mType == GL_FIXED) - { - mNormalized = GL_FALSE; - } -} - -void VertexFormat::GetInputLayout(VertexFormat *inputLayout, - ProgramBinary *programBinary, - const State &state) -{ - const VertexAttribute *vertexAttributes = state.getVertexArray()->getVertexAttributes(); - for (unsigned int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++) - { - int semanticIndex = programBinary->getSemanticIndex(attributeIndex); - - if (semanticIndex != -1) - { - inputLayout[semanticIndex] = VertexFormat(vertexAttributes[attributeIndex], state.getVertexAttribCurrentValue(attributeIndex).Type); - } - } -} - -bool VertexFormat::operator==(const VertexFormat &other) const -{ - return (mType == other.mType && - mComponents == other.mComponents && - mNormalized == other.mNormalized && - mPureInteger == other.mPureInteger ); -} - -bool VertexFormat::operator!=(const VertexFormat &other) const -{ - return !(*this == other); -} - -bool VertexFormat::operator<(const VertexFormat& other) const -{ - if (mType != other.mType) - { - return mType < other.mType; - } - if (mNormalized != other.mNormalized) - { - return mNormalized < other.mNormalized; - } - if (mComponents != other.mComponents) - { - return mComponents < other.mComponents; - } - return mPureInteger < other.mPureInteger; -} - -bool Box::operator==(const Box &other) const -{ - return (x == other.x && y == other.y && z == other.z && - width == other.width && height == other.height && depth == other.depth); -} - -bool Box::operator!=(const Box &other) const -{ - return !(*this == other); -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/angletypes.h b/src/3rdparty/angle/src/libGLESv2/angletypes.h deleted file mode 100644 index 78fe6b0e26..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/angletypes.h +++ /dev/null @@ -1,257 +0,0 @@ -// -// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// angletypes.h : Defines a variety of structures and enum types that are used throughout libGLESv2 - -#ifndef LIBGLESV2_ANGLETYPES_H_ -#define LIBGLESV2_ANGLETYPES_H_ - -#include "libGLESv2/Constants.h" -#include "common/RefCountObject.h" - -namespace gl -{ -class Buffer; -class State; -class ProgramBinary; -struct VertexAttribute; -struct VertexAttribCurrentValueData; - -enum SamplerType -{ - SAMPLER_PIXEL, - SAMPLER_VERTEX -}; - -template -struct Color -{ - T red; - T green; - T blue; - T alpha; - - Color() : red(0), green(0), blue(0), alpha(0) { } - Color(T r, T g, T b, T a) : red(r), green(g), blue(b), alpha(a) { } -}; - -typedef Color ColorF; -typedef Color ColorI; -typedef Color ColorUI; - -struct Rectangle -{ - int x; - int y; - int width; - int height; - - Rectangle() : x(0), y(0), width(0), height(0) { } - Rectangle(int x_in, int y_in, int width_in, int height_in) : x(x_in), y(y_in), width(width_in), height(height_in) { } -}; - -bool ClipRectangle(const Rectangle &source, const Rectangle &clip, Rectangle *intersection); - -struct Box -{ - int x; - int y; - int z; - int width; - int height; - int depth; - - Box() : x(0), y(0), z(0), width(0), height(0), depth(0) { } - Box(int x_in, int y_in, int z_in, int width_in, int height_in, int depth_in) : x(x_in), y(y_in), z(z_in), width(width_in), height(height_in), depth(depth_in) { } - bool operator==(const Box &other) const; - bool operator!=(const Box &other) const; -}; - -struct Extents -{ - int width; - int height; - int depth; - - Extents() : width(0), height(0), depth(0) { } - Extents(int width_, int height_, int depth_) : width(width_), height(height_), depth(depth_) { } -}; - -struct RasterizerState -{ - bool cullFace; - GLenum cullMode; - GLenum frontFace; - - bool polygonOffsetFill; - GLfloat polygonOffsetFactor; - GLfloat polygonOffsetUnits; - - bool pointDrawMode; - bool multiSample; - - bool rasterizerDiscard; -}; - -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 -{ - SamplerState(); - - GLenum minFilter; - GLenum magFilter; - GLenum wrapS; - GLenum wrapT; - GLenum wrapR; - float maxAnisotropy; - - GLint baseLevel; - GLint maxLevel; - GLfloat minLod; - GLfloat maxLod; - - GLenum compareMode; - GLenum compareFunc; - - GLenum swizzleRed; - GLenum swizzleGreen; - GLenum swizzleBlue; - GLenum swizzleAlpha; - - bool swizzleRequired() const; -}; - -struct ClearParameters -{ - bool clearColor[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS]; - ColorF colorFClearValue; - ColorI colorIClearValue; - ColorUI colorUIClearValue; - GLenum colorClearType; - bool colorMaskRed; - bool colorMaskGreen; - bool colorMaskBlue; - bool colorMaskAlpha; - - bool clearDepth; - float depthClearValue; - - bool clearStencil; - GLint stencilClearValue; - GLuint stencilWriteMask; - - bool scissorEnabled; - Rectangle scissor; -}; - -struct PixelUnpackState -{ - BindingPointer pixelBuffer; - GLint alignment; - - PixelUnpackState() - : alignment(4) - {} - - explicit PixelUnpackState(GLint alignmentIn) - : alignment(alignmentIn) - {} -}; - -struct PixelPackState -{ - BindingPointer pixelBuffer; - GLint alignment; - bool reverseRowOrder; - - PixelPackState() - : alignment(4), - reverseRowOrder(false) - {} - - explicit PixelPackState(GLint alignmentIn, bool reverseRowOrderIn) - : alignment(alignmentIn), - reverseRowOrder(reverseRowOrderIn) - {} -}; - -struct VertexFormat -{ - GLenum mType; - GLboolean mNormalized; - GLuint mComponents; - bool mPureInteger; - - VertexFormat(); - VertexFormat(GLenum type, GLboolean normalized, GLuint components, bool pureInteger); - explicit VertexFormat(const VertexAttribute &attribute); - VertexFormat(const VertexAttribute &attribute, GLenum currentValueType); - - static void GetInputLayout(VertexFormat *inputLayout, - ProgramBinary *programBinary, - const State& currentValues); - - bool operator==(const VertexFormat &other) const; - bool operator!=(const VertexFormat &other) const; - bool operator<(const VertexFormat& other) const; -}; - -} - -namespace rx -{ - -enum VertexConversionType -{ - VERTEX_CONVERT_NONE = 0, - VERTEX_CONVERT_CPU = 1, - VERTEX_CONVERT_GPU = 2, - VERTEX_CONVERT_BOTH = 3 -}; - -} - -#endif // LIBGLESV2_ANGLETYPES_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/constants.h b/src/3rdparty/angle/src/libGLESv2/constants.h deleted file mode 100644 index 69c4823fb2..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/constants.h +++ /dev/null @@ -1,44 +0,0 @@ -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Contants.h: Defines some implementation specific and gl constants - -#ifndef LIBGLESV2_CONSTANTS_H_ -#define LIBGLESV2_CONSTANTS_H_ - -namespace gl -{ - -enum -{ - MAX_VERTEX_ATTRIBS = 16, - - // Implementation upper limits, real maximums depend on the hardware - IMPLEMENTATION_MAX_VARYING_VECTORS = 32, - IMPLEMENTATION_MAX_DRAW_BUFFERS = 8, - IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS = IMPLEMENTATION_MAX_DRAW_BUFFERS + 2, // 2 extra for depth and/or stencil buffers - - IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS = 16, - IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS = 16, - IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS = IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS + - IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS, - - IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS = 4, - - // These are the maximums the implementation can support - // The actual GL caps are limited by the device caps - // and should be queried from the Context - IMPLEMENTATION_MAX_2D_TEXTURE_SIZE = 16384, - IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE = 16384, - IMPLEMENTATION_MAX_3D_TEXTURE_SIZE = 2048, - IMPLEMENTATION_MAX_2D_ARRAY_TEXTURE_LAYERS = 2048, - - IMPLEMENTATION_MAX_TEXTURE_LEVELS = 15 // 1+log2 of MAX_TEXTURE_SIZE -}; - -} - -#endif // LIBGLESV2_CONSTANTS_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/entry_points_egl.cpp b/src/3rdparty/angle/src/libGLESv2/entry_points_egl.cpp new file mode 100644 index 0000000000..a6db1585e7 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/entry_points_egl.cpp @@ -0,0 +1,1127 @@ +// +// Copyright(c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// entry_points_egl.cpp : Implements the EGL entry points. + +#include "libGLESv2/entry_points_egl.h" +#include "libGLESv2/entry_points_egl_ext.h" +#include "libGLESv2/entry_points_gles_2_0_ext.h" +#include "libGLESv2/entry_points_gles_3_0_ext.h" +#include "libGLESv2/global_state.h" + +#include "libANGLE/Context.h" +#include "libANGLE/Display.h" +#include "libANGLE/Texture.h" +#include "libANGLE/Surface.h" +#include "libANGLE/validationEGL.h" + +#include "common/debug.h" +#include "common/version.h" + +#include + +namespace egl +{ + +// EGL 1.0 +EGLint EGLAPIENTRY GetError(void) +{ + EVENT("()"); + + EGLint error = GetGlobalError(); + SetGlobalError(Error(EGL_SUCCESS)); + return error; +} + +EGLDisplay EGLAPIENTRY GetDisplay(EGLNativeDisplayType display_id) +{ + EVENT("(EGLNativeDisplayType display_id = 0x%0.8p)", display_id); + + return Display::getDisplay(display_id, AttributeMap()); +} + +EGLBoolean EGLAPIENTRY Initialize(EGLDisplay dpy, EGLint *major, EGLint *minor) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLint *major = 0x%0.8p, EGLint *minor = 0x%0.8p)", + dpy, major, minor); + + if (dpy == EGL_NO_DISPLAY) + { + SetGlobalError(Error(EGL_BAD_DISPLAY)); + return EGL_FALSE; + } + + Display *display = static_cast(dpy); + + Error error = display->initialize(); + if (error.isError()) + { + SetGlobalError(error); + return EGL_FALSE; + } + + if (major) *major = 1; + if (minor) *minor = 4; + + SetGlobalError(Error(EGL_SUCCESS)); + return EGL_TRUE; +} + +EGLBoolean EGLAPIENTRY Terminate(EGLDisplay dpy) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p)", dpy); + + if (dpy == EGL_NO_DISPLAY) + { + SetGlobalError(Error(EGL_BAD_DISPLAY)); + return EGL_FALSE; + } + + Display *display = static_cast(dpy); + gl::Context *context = GetGlobalContext(); + + if (display->isValidContext(context)) + { + SetGlobalContext(NULL); + SetGlobalDisplay(NULL); + } + + display->terminate(); + + SetGlobalError(Error(EGL_SUCCESS)); + return EGL_TRUE; +} + +const char *EGLAPIENTRY QueryString(EGLDisplay dpy, EGLint name) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLint name = %d)", dpy, name); + + Display *display = static_cast(dpy); + if (!(display == EGL_NO_DISPLAY && name == EGL_EXTENSIONS)) + { + Error error = ValidateDisplay(display); + if (error.isError()) + { + SetGlobalError(error); + return NULL; + } + } + + const char *result; + switch (name) + { + case EGL_CLIENT_APIS: + result = "OpenGL_ES"; + break; + case EGL_EXTENSIONS: + if (display == EGL_NO_DISPLAY) + { + result = Display::getClientExtensionString().c_str(); + } + else + { + result = display->getExtensionString().c_str(); + } + break; + case EGL_VENDOR: + result = display->getVendorString().c_str(); + break; + case EGL_VERSION: + result = "1.4 (ANGLE " ANGLE_VERSION_STRING ")"; + break; + default: + SetGlobalError(Error(EGL_BAD_PARAMETER)); + return NULL; + } + + SetGlobalError(Error(EGL_SUCCESS)); + return result; +} + +EGLBoolean EGLAPIENTRY GetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig *configs = 0x%0.8p, " + "EGLint config_size = %d, EGLint *num_config = 0x%0.8p)", + dpy, configs, config_size, num_config); + + Display *display = static_cast(dpy); + + Error error = ValidateDisplay(display); + if (error.isError()) + { + SetGlobalError(error); + return EGL_FALSE; + } + + if (!num_config) + { + SetGlobalError(Error(EGL_BAD_PARAMETER)); + return EGL_FALSE; + } + + std::vector filteredConfigs = display->getConfigs(AttributeMap()); + if (configs) + { + filteredConfigs.resize(std::min(filteredConfigs.size(), config_size)); + for (size_t i = 0; i < filteredConfigs.size(); i++) + { + configs[i] = const_cast(filteredConfigs[i]); + } + } + *num_config = filteredConfigs.size(); + + SetGlobalError(Error(EGL_SUCCESS)); + return EGL_TRUE; +} + +EGLBoolean EGLAPIENTRY ChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, const EGLint *attrib_list = 0x%0.8p, " + "EGLConfig *configs = 0x%0.8p, EGLint config_size = %d, EGLint *num_config = 0x%0.8p)", + dpy, attrib_list, configs, config_size, num_config); + + Display *display = static_cast(dpy); + + Error error = ValidateDisplay(display); + if (error.isError()) + { + SetGlobalError(error); + return EGL_FALSE; + } + + if (!num_config) + { + SetGlobalError(Error(EGL_BAD_PARAMETER)); + return EGL_FALSE; + } + + std::vector filteredConfigs = display->getConfigs(AttributeMap(attrib_list)); + if (configs) + { + filteredConfigs.resize(std::min(filteredConfigs.size(), config_size)); + for (size_t i = 0; i < filteredConfigs.size(); i++) + { + configs[i] = const_cast(filteredConfigs[i]); + } + } + *num_config = filteredConfigs.size(); + + SetGlobalError(Error(EGL_SUCCESS)); + return EGL_TRUE; +} + +EGLBoolean EGLAPIENTRY GetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLint attribute = %d, EGLint *value = 0x%0.8p)", + dpy, config, attribute, value); + + Display *display = static_cast(dpy); + Config *configuration = static_cast(config); + + Error error = ValidateConfig(display, configuration); + if (error.isError()) + { + SetGlobalError(error); + return EGL_FALSE; + } + + if (!display->getConfigAttrib(configuration, attribute, value)) + { + SetGlobalError(Error(EGL_BAD_ATTRIBUTE)); + return EGL_FALSE; + } + + SetGlobalError(Error(EGL_SUCCESS)); + return EGL_TRUE; +} + +EGLSurface EGLAPIENTRY CreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLNativeWindowType win = 0x%0.8p, " + "const EGLint *attrib_list = 0x%0.8p)", dpy, config, win, attrib_list); + + Display *display = static_cast(dpy); + Config *configuration = static_cast(config); + AttributeMap attributes(attrib_list); + + Error error = ValidateCreateWindowSurface(display, configuration, win, attributes); + if (error.isError()) + { + SetGlobalError(error); + return EGL_NO_SURFACE; + } + + egl::Surface *surface = nullptr; + error = display->createWindowSurface(configuration, win, attributes, &surface); + if (error.isError()) + { + SetGlobalError(error); + return EGL_NO_SURFACE; + } + + return static_cast(surface); +} + +EGLSurface EGLAPIENTRY CreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, const EGLint *attrib_list = 0x%0.8p)", + dpy, config, attrib_list); + + Display *display = static_cast(dpy); + Config *configuration = static_cast(config); + AttributeMap attributes(attrib_list); + + Error error = ValidateCreatePbufferSurface(display, configuration, attributes); + if (error.isError()) + { + SetGlobalError(error); + return EGL_NO_SURFACE; + } + + egl::Surface *surface = nullptr; + error = display->createPbufferSurface(configuration, attributes, &surface); + if (error.isError()) + { + SetGlobalError(error); + return EGL_NO_SURFACE; + } + + return static_cast(surface); +} + +EGLSurface EGLAPIENTRY CreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLNativePixmapType pixmap = 0x%0.8p, " + "const EGLint *attrib_list = 0x%0.8p)", dpy, config, pixmap, attrib_list); + + Display *display = static_cast(dpy); + Config *configuration = static_cast(config); + + Error error = ValidateConfig(display, configuration); + if (error.isError()) + { + SetGlobalError(error); + return EGL_NO_SURFACE; + } + + UNIMPLEMENTED(); // FIXME + + SetGlobalError(Error(EGL_SUCCESS)); + return EGL_NO_SURFACE; +} + +EGLBoolean EGLAPIENTRY DestroySurface(EGLDisplay dpy, EGLSurface surface) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p)", dpy, surface); + + Display *display = static_cast(dpy); + Surface *eglSurface = static_cast(surface); + + Error error = ValidateSurface(display, eglSurface); + if (error.isError()) + { + SetGlobalError(error); + return EGL_FALSE; + } + + if (surface == EGL_NO_SURFACE) + { + SetGlobalError(Error(EGL_BAD_SURFACE)); + return EGL_FALSE; + } + + display->destroySurface((Surface*)surface); + + SetGlobalError(Error(EGL_SUCCESS)); + return EGL_TRUE; +} + +EGLBoolean EGLAPIENTRY QuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint attribute = %d, EGLint *value = 0x%0.8p)", + dpy, surface, attribute, value); + + Display *display = static_cast(dpy); + Surface *eglSurface = (Surface*)surface; + + Error error = ValidateSurface(display, eglSurface); + if (error.isError()) + { + SetGlobalError(error); + return EGL_FALSE; + } + + if (surface == EGL_NO_SURFACE) + { + SetGlobalError(Error(EGL_BAD_SURFACE)); + return EGL_FALSE; + } + + switch (attribute) + { + case EGL_VG_ALPHA_FORMAT: + UNIMPLEMENTED(); // FIXME + break; + case EGL_VG_COLORSPACE: + UNIMPLEMENTED(); // FIXME + break; + case EGL_CONFIG_ID: + *value = eglSurface->getConfig()->configID; + break; + case EGL_HEIGHT: + *value = eglSurface->getHeight(); + break; + case EGL_HORIZONTAL_RESOLUTION: + UNIMPLEMENTED(); // FIXME + break; + case EGL_LARGEST_PBUFFER: + UNIMPLEMENTED(); // FIXME + break; + case EGL_MIPMAP_TEXTURE: + UNIMPLEMENTED(); // FIXME + break; + case EGL_MIPMAP_LEVEL: + UNIMPLEMENTED(); // FIXME + break; + case EGL_MULTISAMPLE_RESOLVE: + UNIMPLEMENTED(); // FIXME + break; + case EGL_PIXEL_ASPECT_RATIO: + *value = eglSurface->getPixelAspectRatio(); + break; + case EGL_RENDER_BUFFER: + *value = eglSurface->getRenderBuffer(); + break; + case EGL_SWAP_BEHAVIOR: + *value = eglSurface->getSwapBehavior(); + break; + case EGL_TEXTURE_FORMAT: + *value = eglSurface->getTextureFormat(); + break; + case EGL_TEXTURE_TARGET: + *value = eglSurface->getTextureTarget(); + break; + case EGL_VERTICAL_RESOLUTION: + UNIMPLEMENTED(); // FIXME + break; + case EGL_WIDTH: + *value = eglSurface->getWidth(); + break; + case EGL_POST_SUB_BUFFER_SUPPORTED_NV: + if (!display->getExtensions().postSubBuffer) + { + SetGlobalError(Error(EGL_BAD_ATTRIBUTE)); + return EGL_FALSE; + } + *value = eglSurface->isPostSubBufferSupported(); + break; + case EGL_FIXED_SIZE_ANGLE: + if (!display->getExtensions().windowFixedSize) + { + SetGlobalError(Error(EGL_BAD_ATTRIBUTE)); + return EGL_FALSE; + } + *value = eglSurface->isFixedSize(); + break; + default: + SetGlobalError(Error(EGL_BAD_ATTRIBUTE)); + return EGL_FALSE; + } + + SetGlobalError(Error(EGL_SUCCESS)); + return EGL_TRUE; +} + +EGLContext EGLAPIENTRY CreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLContext share_context = 0x%0.8p, " + "const EGLint *attrib_list = 0x%0.8p)", dpy, config, share_context, attrib_list); + + Display *display = static_cast(dpy); + Config *configuration = static_cast(config); + gl::Context* sharedGLContext = static_cast(share_context); + AttributeMap attributes(attrib_list); + + Error error = ValidateCreateContext(display, configuration, sharedGLContext, attributes); + if (error.isError()) + { + SetGlobalError(error); + return EGL_NO_CONTEXT; + } + + gl::Context *context = nullptr; + error = display->createContext(configuration, sharedGLContext, attributes, &context); + if (error.isError()) + { + SetGlobalError(error); + return EGL_NO_CONTEXT; + } + + SetGlobalError(Error(EGL_SUCCESS)); + return static_cast(context); +} + +EGLBoolean EGLAPIENTRY DestroyContext(EGLDisplay dpy, EGLContext ctx) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLContext ctx = 0x%0.8p)", dpy, ctx); + + Display *display = static_cast(dpy); + gl::Context *context = static_cast(ctx); + + Error error = ValidateContext(display, context); + if (error.isError()) + { + SetGlobalError(error); + return EGL_FALSE; + } + + if (ctx == EGL_NO_CONTEXT) + { + SetGlobalError(Error(EGL_BAD_CONTEXT)); + return EGL_FALSE; + } + + if (context == GetGlobalContext()) + { + SetGlobalDisplay(NULL); + SetGlobalContext(NULL); + } + + display->destroyContext(context); + + SetGlobalError(Error(EGL_SUCCESS)); + return EGL_TRUE; +} + +EGLBoolean EGLAPIENTRY MakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface draw = 0x%0.8p, EGLSurface read = 0x%0.8p, EGLContext ctx = 0x%0.8p)", + dpy, draw, read, ctx); + + Display *display = static_cast(dpy); + gl::Context *context = static_cast(ctx); + + bool noContext = (ctx == EGL_NO_CONTEXT); + bool noSurface = (draw == EGL_NO_SURFACE || read == EGL_NO_SURFACE); + if (noContext != noSurface) + { + SetGlobalError(Error(EGL_BAD_MATCH)); + return EGL_FALSE; + } + + if (ctx != EGL_NO_CONTEXT) + { + Error error = ValidateContext(display, context); + if (error.isError()) + { + SetGlobalError(error); + return EGL_FALSE; + } + } + + if (dpy != EGL_NO_DISPLAY && display->isInitialized()) + { + if (display->testDeviceLost()) + { + display->notifyDeviceLost(); + return EGL_FALSE; + } + + if (display->isDeviceLost()) + { + SetGlobalError(Error(EGL_CONTEXT_LOST)); + return EGL_FALSE; + } + } + + Surface *drawSurface = static_cast(draw); + if (draw != EGL_NO_SURFACE) + { + Error error = ValidateSurface(display, drawSurface); + if (error.isError()) + { + SetGlobalError(error); + return EGL_FALSE; + } + } + + Surface *readSurface = static_cast(read); + if (read != EGL_NO_SURFACE) + { + Error error = ValidateSurface(display, readSurface); + if (error.isError()) + { + SetGlobalError(error); + return EGL_FALSE; + } + } + + if (draw != read) + { + UNIMPLEMENTED(); // FIXME + } + + SetGlobalDisplay(display); + SetGlobalDrawSurface(drawSurface); + SetGlobalReadSurface(readSurface); + SetGlobalContext(context); + + if (context != nullptr && display != nullptr && drawSurface != nullptr) + { + display->makeCurrent(drawSurface, readSurface, context); + } + + SetGlobalError(Error(EGL_SUCCESS)); + return EGL_TRUE; +} + +EGLSurface EGLAPIENTRY GetCurrentSurface(EGLint readdraw) +{ + EVENT("(EGLint readdraw = %d)", readdraw); + + if (readdraw == EGL_READ) + { + SetGlobalError(Error(EGL_SUCCESS)); + return GetGlobalReadSurface(); + } + else if (readdraw == EGL_DRAW) + { + SetGlobalError(Error(EGL_SUCCESS)); + return GetGlobalDrawSurface(); + } + else + { + SetGlobalError(Error(EGL_BAD_PARAMETER)); + return EGL_NO_SURFACE; + } +} + +EGLDisplay EGLAPIENTRY GetCurrentDisplay(void) +{ + EVENT("()"); + + EGLDisplay dpy = GetGlobalDisplay(); + + SetGlobalError(Error(EGL_SUCCESS)); + return dpy; +} + +EGLBoolean EGLAPIENTRY QueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLContext ctx = 0x%0.8p, EGLint attribute = %d, EGLint *value = 0x%0.8p)", + dpy, ctx, attribute, value); + + Display *display = static_cast(dpy); + gl::Context *context = static_cast(ctx); + + Error error = ValidateContext(display, context); + if (error.isError()) + { + SetGlobalError(error); + return EGL_FALSE; + } + + switch (attribute) + { + case EGL_CONFIG_ID: + *value = context->getConfigID(); + break; + case EGL_CONTEXT_CLIENT_TYPE: + *value = context->getClientType(); + break; + case EGL_CONTEXT_CLIENT_VERSION: + *value = context->getClientVersion(); + break; + case EGL_RENDER_BUFFER: + *value = context->getRenderBuffer(); + break; + default: + SetGlobalError(Error(EGL_BAD_ATTRIBUTE)); + return EGL_FALSE; + } + + SetGlobalError(Error(EGL_SUCCESS)); + return EGL_TRUE; +} + +EGLBoolean EGLAPIENTRY WaitGL(void) +{ + EVENT("()"); + + UNIMPLEMENTED(); // FIXME + + SetGlobalError(Error(EGL_SUCCESS)); + return 0; +} + +EGLBoolean EGLAPIENTRY WaitNative(EGLint engine) +{ + EVENT("(EGLint engine = %d)", engine); + + UNIMPLEMENTED(); // FIXME + + SetGlobalError(Error(EGL_SUCCESS)); + return 0; +} + +EGLBoolean EGLAPIENTRY SwapBuffers(EGLDisplay dpy, EGLSurface surface) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p)", dpy, surface); + + Display *display = static_cast(dpy); + Surface *eglSurface = (Surface*)surface; + + Error error = ValidateSurface(display, eglSurface); + if (error.isError()) + { + SetGlobalError(error); + return EGL_FALSE; + } + + if (display->isDeviceLost()) + { + SetGlobalError(Error(EGL_CONTEXT_LOST)); + return EGL_FALSE; + } + + if (surface == EGL_NO_SURFACE) + { + SetGlobalError(Error(EGL_BAD_SURFACE)); + return EGL_FALSE; + } + + error = eglSurface->swap(); + if (error.isError()) + { + SetGlobalError(error); + return EGL_FALSE; + } + + SetGlobalError(Error(EGL_SUCCESS)); + return EGL_TRUE; +} + +EGLBoolean EGLAPIENTRY CopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLNativePixmapType target = 0x%0.8p)", dpy, surface, target); + + Display *display = static_cast(dpy); + Surface *eglSurface = static_cast(surface); + + Error error = ValidateSurface(display, eglSurface); + if (error.isError()) + { + SetGlobalError(error); + return EGL_FALSE; + } + + if (display->isDeviceLost()) + { + SetGlobalError(Error(EGL_CONTEXT_LOST)); + return EGL_FALSE; + } + + UNIMPLEMENTED(); // FIXME + + SetGlobalError(Error(EGL_SUCCESS)); + return 0; +} + +// EGL 1.1 +EGLBoolean EGLAPIENTRY BindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint buffer = %d)", dpy, surface, buffer); + + Display *display = static_cast(dpy); + Surface *eglSurface = static_cast(surface); + + Error error = ValidateSurface(display, eglSurface); + if (error.isError()) + { + SetGlobalError(error); + return EGL_FALSE; + } + + if (buffer != EGL_BACK_BUFFER) + { + SetGlobalError(Error(EGL_BAD_PARAMETER)); + return EGL_FALSE; + } + + if (surface == EGL_NO_SURFACE || eglSurface->getType() == EGL_WINDOW_BIT) + { + SetGlobalError(Error(EGL_BAD_SURFACE)); + return EGL_FALSE; + } + + if (eglSurface->getBoundTexture()) + { + SetGlobalError(Error(EGL_BAD_ACCESS)); + return EGL_FALSE; + } + + if (eglSurface->getTextureFormat() == EGL_NO_TEXTURE) + { + SetGlobalError(Error(EGL_BAD_MATCH)); + return EGL_FALSE; + } + + gl::Context *context = GetGlobalContext(); + if (context) + { + gl::Texture *textureObject = context->getTargetTexture(GL_TEXTURE_2D); + ASSERT(textureObject != NULL); + + if (textureObject->isImmutable()) + { + SetGlobalError(Error(EGL_BAD_MATCH)); + return EGL_FALSE; + } + + eglSurface->bindTexImage(textureObject, buffer); + } + + SetGlobalError(Error(EGL_SUCCESS)); + return EGL_TRUE; +} + +EGLBoolean EGLAPIENTRY SurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint attribute = %d, EGLint value = %d)", + dpy, surface, attribute, value); + + Display *display = static_cast(dpy); + Surface *eglSurface = static_cast(surface); + + Error error = ValidateSurface(display, eglSurface); + if (error.isError()) + { + SetGlobalError(error); + return EGL_FALSE; + } + + UNIMPLEMENTED(); // FIXME + + SetGlobalError(Error(EGL_SUCCESS)); + return EGL_TRUE; +} + +EGLBoolean EGLAPIENTRY ReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint buffer = %d)", dpy, surface, buffer); + + Display *display = static_cast(dpy); + Surface *eglSurface = static_cast(surface); + + Error error = ValidateSurface(display, eglSurface); + if (error.isError()) + { + SetGlobalError(error); + return EGL_FALSE; + } + + if (buffer != EGL_BACK_BUFFER) + { + SetGlobalError(Error(EGL_BAD_PARAMETER)); + return EGL_FALSE; + } + + if (surface == EGL_NO_SURFACE || eglSurface->getType() == EGL_WINDOW_BIT) + { + SetGlobalError(Error(EGL_BAD_SURFACE)); + return EGL_FALSE; + } + + if (eglSurface->getTextureFormat() == EGL_NO_TEXTURE) + { + SetGlobalError(Error(EGL_BAD_MATCH)); + return EGL_FALSE; + } + + gl::Texture *texture = eglSurface->getBoundTexture(); + + if (texture) + { + eglSurface->releaseTexImage(buffer); + } + + SetGlobalError(Error(EGL_SUCCESS)); + return EGL_TRUE; +} + +EGLBoolean EGLAPIENTRY SwapInterval(EGLDisplay dpy, EGLint interval) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLint interval = %d)", dpy, interval); + + Display *display = static_cast(dpy); + + Error error = ValidateDisplay(display); + if (error.isError()) + { + SetGlobalError(error); + return EGL_FALSE; + } + + Surface *draw_surface = static_cast(GetGlobalDrawSurface()); + + if (draw_surface == NULL) + { + SetGlobalError(Error(EGL_BAD_SURFACE)); + return EGL_FALSE; + } + + const egl::Config *surfaceConfig = draw_surface->getConfig(); + EGLint clampedInterval = std::min(std::max(interval, surfaceConfig->minSwapInterval), surfaceConfig->maxSwapInterval); + + draw_surface->setSwapInterval(clampedInterval); + + SetGlobalError(Error(EGL_SUCCESS)); + return EGL_TRUE; +} + + +// EGL 1.2 +EGLBoolean EGLAPIENTRY BindAPI(EGLenum api) +{ + EVENT("(EGLenum api = 0x%X)", api); + + switch (api) + { + case EGL_OPENGL_API: + case EGL_OPENVG_API: + SetGlobalError(Error(EGL_BAD_PARAMETER)); + return EGL_FALSE; // Not supported by this implementation + case EGL_OPENGL_ES_API: + break; + default: + SetGlobalError(Error(EGL_BAD_PARAMETER)); + return EGL_FALSE; + } + + SetGlobalAPI(api); + + SetGlobalError(Error(EGL_SUCCESS)); + return EGL_TRUE; +} + +EGLenum EGLAPIENTRY QueryAPI(void) +{ + EVENT("()"); + + EGLenum API = GetGlobalAPI(); + + SetGlobalError(Error(EGL_SUCCESS)); + return API; +} + +EGLSurface EGLAPIENTRY CreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLenum buftype = 0x%X, EGLClientBuffer buffer = 0x%0.8p, " + "EGLConfig config = 0x%0.8p, const EGLint *attrib_list = 0x%0.8p)", + dpy, buftype, buffer, config, attrib_list); + + Display *display = static_cast(dpy); + Config *configuration = static_cast(config); + AttributeMap attributes(attrib_list); + + Error error = ValidateCreatePbufferFromClientBuffer(display, buftype, buffer, configuration, attributes); + if (error.isError()) + { + SetGlobalError(error); + return EGL_NO_SURFACE; + } + + egl::Surface *surface = nullptr; + error = display->createPbufferFromClientBuffer(configuration, buffer, attributes, &surface); + if (error.isError()) + { + SetGlobalError(error); + return EGL_NO_SURFACE; + } + + return static_cast(surface); +} + +EGLBoolean EGLAPIENTRY ReleaseThread(void) +{ + EVENT("()"); + + MakeCurrent(EGL_NO_DISPLAY, EGL_NO_CONTEXT, EGL_NO_SURFACE, EGL_NO_SURFACE); + + SetGlobalError(Error(EGL_SUCCESS)); + return EGL_TRUE; +} + +EGLBoolean EGLAPIENTRY WaitClient(void) +{ + EVENT("()"); + + UNIMPLEMENTED(); // FIXME + + SetGlobalError(Error(EGL_SUCCESS)); + return 0; +} + +// EGL 1.4 +EGLContext EGLAPIENTRY GetCurrentContext(void) +{ + EVENT("()"); + + gl::Context *context = GetGlobalContext(); + + SetGlobalError(Error(EGL_SUCCESS)); + return static_cast(context); +} + +// EGL 1.5 +EGLSync EGLAPIENTRY CreateSync(EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLenum type = 0x%X, const EGLint* attrib_list = 0x%0.8p)", dpy, type, attrib_list); + + UNIMPLEMENTED(); + return EGL_NO_SYNC; +} + +EGLBoolean EGLAPIENTRY DestroySync(EGLDisplay dpy, EGLSync sync) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSync sync = 0x%0.8p)", dpy, sync); + + UNIMPLEMENTED(); + return EGL_FALSE; +} + +EGLint EGLAPIENTRY ClientWaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSync sync = 0x%0.8p, EGLint flags = 0x%X, EGLTime timeout = %d)", dpy, sync, flags, timeout); + + UNIMPLEMENTED(); + return 0; +} + +EGLBoolean EGLAPIENTRY GetSyncAttrib(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib *value) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSync sync = 0x%0.8p, EGLint attribute = 0x%X, EGLAttrib *value = 0x%0.8p)", dpy, sync, attribute, value); + + UNIMPLEMENTED(); + return EGL_FALSE; +} + +EGLImage EGLAPIENTRY CreateImage(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLAttrib *attrib_list) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLContext ctx = 0x%0.8p, EGLenum target = 0x%X, " + "EGLClientBuffer buffer = 0x%0.8p, const EGLAttrib *attrib_list = 0x%0.8p)", + dpy, ctx, target, buffer, attrib_list); + + UNIMPLEMENTED(); + return EGL_NO_IMAGE; +} + +EGLBoolean EGLAPIENTRY DestroyImage(EGLDisplay dpy, EGLImage image) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLImage image = 0x%0.8p)", dpy, image); + + UNIMPLEMENTED(); + return EGL_FALSE; +} + +EGLDisplay EGLAPIENTRY GetPlatformDisplay(EGLenum platform, void *native_display, const EGLAttrib *attrib_list) +{ + EVENT("(EGLenum platform = %d, void* native_display = 0x%0.8p, const EGLint* attrib_list = 0x%0.8p)", + platform, native_display, attrib_list); + + UNIMPLEMENTED(); + return EGL_NO_DISPLAY; +} + +EGLSurface EGLAPIENTRY CreatePlatformWindowSurface(EGLDisplay dpy, EGLConfig config, void *native_window, const EGLAttrib *attrib_list) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, void* native_window = 0x%0.8p, const EGLint* attrib_list = 0x%0.8p)", + dpy, config, native_window, attrib_list); + + UNIMPLEMENTED(); + return EGL_NO_SURFACE; +} + +EGLSurface EGLAPIENTRY CreatePlatformPixmapSurface(EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLAttrib *attrib_list) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, void* native_pixmap = 0x%0.8p, const EGLint* attrib_list = 0x%0.8p)", + dpy, config, native_pixmap, attrib_list); + + UNIMPLEMENTED(); + return EGL_NO_SURFACE; +} + +EGLBoolean EGLAPIENTRY WaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSync sync = 0x%0.8p, EGLint flags = 0x%X)", dpy, sync, flags); + + UNIMPLEMENTED(); + return EGL_FALSE; +} + +__eglMustCastToProperFunctionPointerType EGLAPIENTRY GetProcAddress(const char *procname) +{ + EVENT("(const char *procname = \"%s\")", procname); + + struct Extension + { + const char *name; + __eglMustCastToProperFunctionPointerType address; + }; + + static const Extension extensions[] = + { + { "eglQuerySurfacePointerANGLE", (__eglMustCastToProperFunctionPointerType)QuerySurfacePointerANGLE }, + { "eglPostSubBufferNV", (__eglMustCastToProperFunctionPointerType)PostSubBufferNV }, + { "eglGetPlatformDisplayEXT", (__eglMustCastToProperFunctionPointerType)GetPlatformDisplayEXT }, + { "glBlitFramebufferANGLE", (__eglMustCastToProperFunctionPointerType)gl::BlitFramebufferANGLE }, + { "glRenderbufferStorageMultisampleANGLE", (__eglMustCastToProperFunctionPointerType)gl::RenderbufferStorageMultisampleANGLE }, + { "glDeleteFencesNV", (__eglMustCastToProperFunctionPointerType)gl::DeleteFencesNV }, + { "glGenFencesNV", (__eglMustCastToProperFunctionPointerType)gl::GenFencesNV }, + { "glIsFenceNV", (__eglMustCastToProperFunctionPointerType)gl::IsFenceNV }, + { "glTestFenceNV", (__eglMustCastToProperFunctionPointerType)gl::TestFenceNV }, + { "glGetFenceivNV", (__eglMustCastToProperFunctionPointerType)gl::GetFenceivNV }, + { "glFinishFenceNV", (__eglMustCastToProperFunctionPointerType)gl::FinishFenceNV }, + { "glSetFenceNV", (__eglMustCastToProperFunctionPointerType)gl::SetFenceNV }, + { "glGetTranslatedShaderSourceANGLE", (__eglMustCastToProperFunctionPointerType)gl::GetTranslatedShaderSourceANGLE }, + { "glTexStorage2DEXT", (__eglMustCastToProperFunctionPointerType)gl::TexStorage2DEXT }, + { "glGetGraphicsResetStatusEXT", (__eglMustCastToProperFunctionPointerType)gl::GetGraphicsResetStatusEXT }, + { "glReadnPixelsEXT", (__eglMustCastToProperFunctionPointerType)gl::ReadnPixelsEXT }, + { "glGetnUniformfvEXT", (__eglMustCastToProperFunctionPointerType)gl::GetnUniformfvEXT }, + { "glGetnUniformivEXT", (__eglMustCastToProperFunctionPointerType)gl::GetnUniformivEXT }, + { "glGenQueriesEXT", (__eglMustCastToProperFunctionPointerType)gl::GenQueriesEXT }, + { "glDeleteQueriesEXT", (__eglMustCastToProperFunctionPointerType)gl::DeleteQueriesEXT }, + { "glIsQueryEXT", (__eglMustCastToProperFunctionPointerType)gl::IsQueryEXT }, + { "glBeginQueryEXT", (__eglMustCastToProperFunctionPointerType)gl::BeginQueryEXT }, + { "glEndQueryEXT", (__eglMustCastToProperFunctionPointerType)gl::EndQueryEXT }, + { "glGetQueryivEXT", (__eglMustCastToProperFunctionPointerType)gl::GetQueryivEXT }, + { "glGetQueryObjectuivEXT", (__eglMustCastToProperFunctionPointerType)gl::GetQueryObjectuivEXT }, + { "glDrawBuffersEXT", (__eglMustCastToProperFunctionPointerType)gl::DrawBuffersEXT }, + { "glVertexAttribDivisorANGLE", (__eglMustCastToProperFunctionPointerType)gl::VertexAttribDivisorANGLE }, + { "glDrawArraysInstancedANGLE", (__eglMustCastToProperFunctionPointerType)gl::DrawArraysInstancedANGLE }, + { "glDrawElementsInstancedANGLE", (__eglMustCastToProperFunctionPointerType)gl::DrawElementsInstancedANGLE }, + { "glGetProgramBinaryOES", (__eglMustCastToProperFunctionPointerType)gl::GetProgramBinaryOES }, + { "glProgramBinaryOES", (__eglMustCastToProperFunctionPointerType)gl::ProgramBinaryOES }, + { "glGetBufferPointervOES", (__eglMustCastToProperFunctionPointerType)gl::GetBufferPointervOES }, + { "glMapBufferOES", (__eglMustCastToProperFunctionPointerType)gl::MapBufferOES }, + { "glUnmapBufferOES", (__eglMustCastToProperFunctionPointerType)gl::UnmapBufferOES }, + { "glMapBufferRangeEXT", (__eglMustCastToProperFunctionPointerType)gl::MapBufferRangeEXT }, + { "glFlushMappedBufferRangeEXT", (__eglMustCastToProperFunctionPointerType)gl::FlushMappedBufferRangeEXT }, + { "", NULL }, + }; + + for (const Extension *extension = &extensions[0]; extension->address != nullptr; extension++) + { + if (strcmp(procname, extension->name) == 0) + { + return reinterpret_cast<__eglMustCastToProperFunctionPointerType>(extension->address); + } + } + + return NULL; +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/entry_points_egl.h b/src/3rdparty/angle/src/libGLESv2/entry_points_egl.h new file mode 100644 index 0000000000..259a209684 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/entry_points_egl.h @@ -0,0 +1,74 @@ +// +// Copyright(c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// entry_points_egl.h : Defines the EGL entry points. + +#ifndef LIBGLESV2_ENTRYPOINTSEGL_H_ +#define LIBGLESV2_ENTRYPOINTSEGL_H_ + +#include +#include + +namespace egl +{ + +// EGL 1.0 +ANGLE_EXPORT EGLBoolean EGLAPIENTRY ChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config); +ANGLE_EXPORT EGLBoolean EGLAPIENTRY CopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target); +ANGLE_EXPORT EGLContext EGLAPIENTRY CreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list); +ANGLE_EXPORT EGLSurface EGLAPIENTRY CreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list); +ANGLE_EXPORT EGLSurface EGLAPIENTRY CreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list); +ANGLE_EXPORT EGLSurface EGLAPIENTRY CreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list); +ANGLE_EXPORT EGLBoolean EGLAPIENTRY DestroyContext(EGLDisplay dpy, EGLContext ctx); +ANGLE_EXPORT EGLBoolean EGLAPIENTRY DestroySurface(EGLDisplay dpy, EGLSurface surface); +ANGLE_EXPORT EGLBoolean EGLAPIENTRY GetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value); +ANGLE_EXPORT EGLBoolean EGLAPIENTRY GetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config); +ANGLE_EXPORT EGLDisplay EGLAPIENTRY GetCurrentDisplay(void); +ANGLE_EXPORT EGLSurface EGLAPIENTRY GetCurrentSurface(EGLint readdraw); +ANGLE_EXPORT EGLDisplay EGLAPIENTRY GetDisplay(EGLNativeDisplayType display_id); +ANGLE_EXPORT EGLint EGLAPIENTRY GetError(void); +ANGLE_EXPORT __eglMustCastToProperFunctionPointerType EGLAPIENTRY GetProcAddress(const char *procname); +ANGLE_EXPORT EGLBoolean EGLAPIENTRY Initialize(EGLDisplay dpy, EGLint *major, EGLint *minor); +ANGLE_EXPORT EGLBoolean EGLAPIENTRY MakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx); +ANGLE_EXPORT EGLBoolean EGLAPIENTRY QueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value); +ANGLE_EXPORT const char *EGLAPIENTRY QueryString(EGLDisplay dpy, EGLint name); +ANGLE_EXPORT EGLBoolean EGLAPIENTRY QuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value); +ANGLE_EXPORT EGLBoolean EGLAPIENTRY SwapBuffers(EGLDisplay dpy, EGLSurface surface); +ANGLE_EXPORT EGLBoolean EGLAPIENTRY Terminate(EGLDisplay dpy); +ANGLE_EXPORT EGLBoolean EGLAPIENTRY WaitGL(void); +ANGLE_EXPORT EGLBoolean EGLAPIENTRY WaitNative(EGLint engine); + +// EGL 1.1 +ANGLE_EXPORT EGLBoolean EGLAPIENTRY BindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer); +ANGLE_EXPORT EGLBoolean EGLAPIENTRY ReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer); +ANGLE_EXPORT EGLBoolean EGLAPIENTRY SurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value); +ANGLE_EXPORT EGLBoolean EGLAPIENTRY SwapInterval(EGLDisplay dpy, EGLint interval); + +// EGL 1.2 +ANGLE_EXPORT EGLBoolean EGLAPIENTRY BindAPI(EGLenum api); +ANGLE_EXPORT EGLenum EGLAPIENTRY QueryAPI(void); +ANGLE_EXPORT EGLSurface EGLAPIENTRY CreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list); +ANGLE_EXPORT EGLBoolean EGLAPIENTRY ReleaseThread(void); +ANGLE_EXPORT EGLBoolean EGLAPIENTRY WaitClient(void); + +// EGL 1.4 +ANGLE_EXPORT EGLContext EGLAPIENTRY GetCurrentContext(void); + +// EGL 1.5 +ANGLE_EXPORT EGLSync EGLAPIENTRY CreateSync(EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list); +ANGLE_EXPORT EGLBoolean EGLAPIENTRY DestroySync(EGLDisplay dpy, EGLSync sync); +ANGLE_EXPORT EGLint EGLAPIENTRY ClientWaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout); +ANGLE_EXPORT EGLBoolean EGLAPIENTRY GetSyncAttrib(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib *value); +ANGLE_EXPORT EGLImage EGLAPIENTRY CreateImage(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLAttrib *attrib_list); +ANGLE_EXPORT EGLBoolean EGLAPIENTRY DestroyImage(EGLDisplay dpy, EGLImage image); +ANGLE_EXPORT EGLDisplay EGLAPIENTRY GetPlatformDisplay(EGLenum platform, void *native_display, const EGLAttrib *attrib_list); +ANGLE_EXPORT EGLSurface EGLAPIENTRY CreatePlatformWindowSurface(EGLDisplay dpy, EGLConfig config, void *native_window, const EGLAttrib *attrib_list); +ANGLE_EXPORT EGLSurface EGLAPIENTRY CreatePlatformPixmapSurface(EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLAttrib *attrib_list); +ANGLE_EXPORT EGLBoolean EGLAPIENTRY WaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags); + +} + +#endif // LIBGLESV2_ENTRYPOINTSEGL_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/entry_points_egl_ext.cpp b/src/3rdparty/angle/src/libGLESv2/entry_points_egl_ext.cpp new file mode 100644 index 0000000000..ded73dbb48 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/entry_points_egl_ext.cpp @@ -0,0 +1,271 @@ +// +// Copyright(c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// entry_points_ext.cpp : Implements the EGL extension entry points. + +#include "libGLESv2/entry_points_egl_ext.h" +#include "libGLESv2/global_state.h" + +#include "libANGLE/Display.h" +#include "libANGLE/Surface.h" +#include "libANGLE/validationEGL.h" + +#include "common/debug.h" + +namespace egl +{ + +// EGL_ANGLE_query_surface_pointer +EGLBoolean EGLAPIENTRY QuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint attribute = %d, void **value = 0x%0.8p)", + dpy, surface, attribute, value); + + Display *display = static_cast(dpy); + Surface *eglSurface = static_cast(surface); + + Error error = ValidateSurface(display, eglSurface); + if (error.isError()) + { + SetGlobalError(error); + return EGL_FALSE; + } + + if (!display->getExtensions().querySurfacePointer) + { + SetGlobalError(Error(EGL_SUCCESS)); + return EGL_FALSE; + } + + if (surface == EGL_NO_SURFACE) + { + SetGlobalError(Error(EGL_BAD_SURFACE)); + return EGL_FALSE; + } + + // validate the attribute parameter + switch (attribute) + { + case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE: + if (!display->getExtensions().surfaceD3DTexture2DShareHandle) + { + SetGlobalError(Error(EGL_BAD_ATTRIBUTE)); + return EGL_FALSE; + } + break; + + default: + SetGlobalError(Error(EGL_BAD_ATTRIBUTE)); + return EGL_FALSE; + } + + error = eglSurface->querySurfacePointerANGLE(attribute, value); + SetGlobalError(error); + return (error.isError() ? EGL_FALSE : EGL_TRUE); +} + + +// EGL_NV_post_sub_buffer +EGLBoolean EGLAPIENTRY PostSubBufferNV(EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint x = %d, EGLint y = %d, EGLint width = %d, EGLint height = %d)", dpy, surface, x, y, width, height); + + if (x < 0 || y < 0 || width < 0 || height < 0) + { + SetGlobalError(Error(EGL_BAD_PARAMETER)); + return EGL_FALSE; + } + + Display *display = static_cast(dpy); + Surface *eglSurface = static_cast(surface); + + Error error = ValidateSurface(display, eglSurface); + if (error.isError()) + { + SetGlobalError(error); + return EGL_FALSE; + } + + if (display->isDeviceLost()) + { + SetGlobalError(Error(EGL_CONTEXT_LOST)); + return EGL_FALSE; + } + + if (surface == EGL_NO_SURFACE) + { + SetGlobalError(Error(EGL_BAD_SURFACE)); + return EGL_FALSE; + } + + if (!display->getExtensions().postSubBuffer) + { + // Spec is not clear about how this should be handled. + SetGlobalError(Error(EGL_SUCCESS)); + return EGL_TRUE; + } + + error = eglSurface->postSubBuffer(x, y, width, height); + if (error.isError()) + { + SetGlobalError(error); + return EGL_FALSE; + } + + SetGlobalError(Error(EGL_SUCCESS)); + return EGL_TRUE; +} + +// EGL_EXT_platform_base +EGLDisplay EGLAPIENTRY GetPlatformDisplayEXT(EGLenum platform, void *native_display, const EGLint *attrib_list) +{ + EVENT("(EGLenum platform = %d, void* native_display = 0x%0.8p, const EGLint* attrib_list = 0x%0.8p)", + platform, native_display, attrib_list); + + const ClientExtensions &clientExtensions = Display::getClientExtensions(); + + switch (platform) + { + case EGL_PLATFORM_ANGLE_ANGLE: + if (!clientExtensions.platformANGLE) + { + SetGlobalError(Error(EGL_BAD_PARAMETER)); + return EGL_NO_DISPLAY; + } + break; + + default: + SetGlobalError(Error(EGL_BAD_CONFIG)); + return EGL_NO_DISPLAY; + } + + EGLint platformType = EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE; + EGLint deviceType = EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE; + bool majorVersionSpecified = false; + bool minorVersionSpecified = false; + bool enableAutoTrimSpecified = false; + + if (attrib_list) + { + for (const EGLint *curAttrib = attrib_list; curAttrib[0] != EGL_NONE; curAttrib += 2) + { + switch (curAttrib[0]) + { + case EGL_PLATFORM_ANGLE_TYPE_ANGLE: + switch (curAttrib[1]) + { + case EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE: + break; + + case EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE: + case EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE: + if (!clientExtensions.platformANGLED3D) + { + SetGlobalError(Error(EGL_BAD_ATTRIBUTE)); + return EGL_NO_DISPLAY; + } + break; + + case EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE: + case EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE: + if (!clientExtensions.platformANGLEOpenGL) + { + SetGlobalError(Error(EGL_BAD_ATTRIBUTE)); + return EGL_NO_DISPLAY; + } + break; + + default: + SetGlobalError(Error(EGL_BAD_ATTRIBUTE)); + return EGL_NO_DISPLAY; + } + platformType = curAttrib[1]; + break; + + case EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE: + if (curAttrib[1] != EGL_DONT_CARE) + { + majorVersionSpecified = true; + } + break; + + case EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE: + if (curAttrib[1] != EGL_DONT_CARE) + { + minorVersionSpecified = true; + } + break; + + case EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE: + switch (curAttrib[1]) + { + case EGL_TRUE: + case EGL_FALSE: + break; + default: + SetGlobalError(Error(EGL_BAD_ATTRIBUTE)); + return EGL_NO_DISPLAY; + } + enableAutoTrimSpecified = true; + break; + + case EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE: + if (!clientExtensions.platformANGLED3D) + { + SetGlobalError(Error(EGL_BAD_ATTRIBUTE)); + return EGL_NO_DISPLAY; + } + + switch (curAttrib[1]) + { + case EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE: + case EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE: + case EGL_PLATFORM_ANGLE_DEVICE_TYPE_REFERENCE_ANGLE: + case EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE: + break; + + default: + SetGlobalError(Error(EGL_BAD_ATTRIBUTE)); + return EGL_NO_DISPLAY; + } + deviceType = curAttrib[1]; + break; + + default: + break; + } + } + } + + if (!majorVersionSpecified && minorVersionSpecified) + { + SetGlobalError(Error(EGL_BAD_ATTRIBUTE)); + return EGL_NO_DISPLAY; + } + + if (deviceType == EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE && + platformType != EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE) + { + SetGlobalError(Error(EGL_BAD_ATTRIBUTE, "EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE requires a device type of " + "EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE.")); + return EGL_NO_DISPLAY; + } + + if (enableAutoTrimSpecified && + platformType != EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE) + { + SetGlobalError(Error(EGL_BAD_ATTRIBUTE, "EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE requires a device type of " + "EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE.")); + return EGL_NO_DISPLAY; + } + + SetGlobalError(Error(EGL_SUCCESS)); + + EGLNativeDisplayType displayId = static_cast(native_display); + return Display::getDisplay(displayId, AttributeMap(attrib_list)); +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/entry_points_egl_ext.h b/src/3rdparty/angle/src/libGLESv2/entry_points_egl_ext.h new file mode 100644 index 0000000000..9de1027082 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/entry_points_egl_ext.h @@ -0,0 +1,30 @@ +// +// Copyright(c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// entry_points_egl_ext.h : Defines the EGL extension entry points. + +#ifndef LIBGLESV2_ENTRYPOINTSEGLEXT_H_ +#define LIBGLESV2_ENTRYPOINTSEGLEXT_H_ + +#include +#include +#include + +namespace egl +{ + +// EGL_ANGLE_query_surface_pointer +ANGLE_EXPORT EGLBoolean EGLAPIENTRY QuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value); + +// EGL_NV_post_sub_buffer +ANGLE_EXPORT EGLBoolean EGLAPIENTRY PostSubBufferNV(EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height); + +// EGL_EXT_platform_base +ANGLE_EXPORT EGLDisplay EGLAPIENTRY GetPlatformDisplayEXT(EGLenum platform, void *native_display, const EGLint *attrib_list); + +} + +#endif // LIBGLESV2_ENTRYPOINTSEGLEXT_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/entry_points_gles_2_0.cpp b/src/3rdparty/angle/src/libGLESv2/entry_points_gles_2_0.cpp new file mode 100644 index 0000000000..6d3089ba4f --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/entry_points_gles_2_0.cpp @@ -0,0 +1,4318 @@ +// +// Copyright(c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// entry_points_gles_2_0.cpp : Implements the GLES 2.0 entry points. + +#include "libGLESv2/entry_points_gles_2_0.h" +#include "libGLESv2/global_state.h" + +#include "libANGLE/formatutils.h" +#include "libANGLE/Buffer.h" +#include "libANGLE/Compiler.h" +#include "libANGLE/Context.h" +#include "libANGLE/Error.h" +#include "libANGLE/Framebuffer.h" +#include "libANGLE/Renderbuffer.h" +#include "libANGLE/Shader.h" +#include "libANGLE/Program.h" +#include "libANGLE/Texture.h" +#include "libANGLE/VertexArray.h" +#include "libANGLE/VertexAttribute.h" +#include "libANGLE/FramebufferAttachment.h" + +#include "libANGLE/validationES.h" +#include "libANGLE/validationES2.h" +#include "libANGLE/validationES3.h" +#include "libANGLE/queryconversions.h" + +#include "common/debug.h" +#include "common/utilities.h" +#include "common/version.h" + +namespace gl +{ + +void GL_APIENTRY ActiveTexture(GLenum texture) +{ + EVENT("(GLenum texture = 0x%X)", texture); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (texture < GL_TEXTURE0 || texture > GL_TEXTURE0 + context->getCaps().maxCombinedTextureImageUnits - 1) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + context->getState().setActiveSampler(texture - GL_TEXTURE0); + } +} + +void GL_APIENTRY AttachShader(GLuint program, GLuint shader) +{ + EVENT("(GLuint program = %d, GLuint shader = %d)", program, shader); + + Context *context = GetValidGlobalContext(); + if (context) + { + Program *programObject = context->getProgram(program); + Shader *shaderObject = context->getShader(shader); + + if (!programObject) + { + if (context->getShader(program)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + else + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + } + + if (!shaderObject) + { + if (context->getProgram(shader)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + else + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + } + + if (!programObject->attachShader(shaderObject)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + } +} + +void GL_APIENTRY BindAttribLocation(GLuint program, GLuint index, const GLchar* name) +{ + EVENT("(GLuint program = %d, GLuint index = %d, const GLchar* name = 0x%0.8p)", program, index, name); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (index >= MAX_VERTEX_ATTRIBS) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + Program *programObject = context->getProgram(program); + + if (!programObject) + { + if (context->getShader(program)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + else + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + } + + if (strncmp(name, "gl_", 3) == 0) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + programObject->bindAttributeLocation(index, name); + } +} + +void GL_APIENTRY BindBuffer(GLenum target, GLuint buffer) +{ + EVENT("(GLenum target = 0x%X, GLuint buffer = %d)", target, buffer); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidBufferTarget(context, target)) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + switch (target) + { + case GL_ARRAY_BUFFER: + context->bindArrayBuffer(buffer); + return; + case GL_ELEMENT_ARRAY_BUFFER: + context->bindElementArrayBuffer(buffer); + return; + case GL_COPY_READ_BUFFER: + context->bindCopyReadBuffer(buffer); + return; + case GL_COPY_WRITE_BUFFER: + context->bindCopyWriteBuffer(buffer); + return; + case GL_PIXEL_PACK_BUFFER: + context->bindPixelPackBuffer(buffer); + return; + case GL_PIXEL_UNPACK_BUFFER: + context->bindPixelUnpackBuffer(buffer); + return; + case GL_UNIFORM_BUFFER: + context->bindGenericUniformBuffer(buffer); + return; + case GL_TRANSFORM_FEEDBACK_BUFFER: + context->bindGenericTransformFeedbackBuffer(buffer); + return; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + } +} + +void GL_APIENTRY BindFramebuffer(GLenum target, GLuint framebuffer) +{ + EVENT("(GLenum target = 0x%X, GLuint framebuffer = %d)", target, framebuffer); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidFramebufferTarget(target)) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + if (target == GL_READ_FRAMEBUFFER_ANGLE || target == GL_FRAMEBUFFER) + { + context->bindReadFramebuffer(framebuffer); + } + + if (target == GL_DRAW_FRAMEBUFFER_ANGLE || target == GL_FRAMEBUFFER) + { + context->bindDrawFramebuffer(framebuffer); + } + } +} + +void GL_APIENTRY BindRenderbuffer(GLenum target, GLuint renderbuffer) +{ + EVENT("(GLenum target = 0x%X, GLuint renderbuffer = %d)", target, renderbuffer); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (target != GL_RENDERBUFFER) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + context->bindRenderbuffer(renderbuffer); + } +} + +void GL_APIENTRY BindTexture(GLenum target, GLuint texture) +{ + EVENT("(GLenum target = 0x%X, GLuint texture = %d)", target, texture); + + Context *context = GetValidGlobalContext(); + if (context) + { + Texture *textureObject = context->getTexture(texture); + + if (textureObject && textureObject->getTarget() != target && texture != 0) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + switch (target) + { + case GL_TEXTURE_2D: + case GL_TEXTURE_CUBE_MAP: + break; + + case GL_TEXTURE_3D: + case GL_TEXTURE_2D_ARRAY: + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + context->bindTexture(target, texture); + } +} + +void GL_APIENTRY BlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) +{ + EVENT("(GLclampf red = %f, GLclampf green = %f, GLclampf blue = %f, GLclampf alpha = %f)", + red, green, blue, alpha); + + Context *context = GetValidGlobalContext(); + if (context) + { + context->getState().setBlendColor(clamp01(red), clamp01(green), clamp01(blue), clamp01(alpha)); + } +} + +void GL_APIENTRY BlendEquation(GLenum mode) +{ + BlendEquationSeparate(mode, mode); +} + +void GL_APIENTRY BlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha) +{ + EVENT("(GLenum modeRGB = 0x%X, GLenum modeAlpha = 0x%X)", modeRGB, modeAlpha); + + Context *context = GetValidGlobalContext(); + if (context) + { + switch (modeRGB) + { + case GL_FUNC_ADD: + case GL_FUNC_SUBTRACT: + case GL_FUNC_REVERSE_SUBTRACT: + case GL_MIN: + case GL_MAX: + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + switch (modeAlpha) + { + case GL_FUNC_ADD: + case GL_FUNC_SUBTRACT: + case GL_FUNC_REVERSE_SUBTRACT: + case GL_MIN: + case GL_MAX: + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + context->getState().setBlendEquation(modeRGB, modeAlpha); + } +} + +void GL_APIENTRY BlendFunc(GLenum sfactor, GLenum dfactor) +{ + BlendFuncSeparate(sfactor, dfactor, sfactor, dfactor); +} + +void GL_APIENTRY BlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) +{ + EVENT("(GLenum srcRGB = 0x%X, GLenum dstRGB = 0x%X, GLenum srcAlpha = 0x%X, GLenum dstAlpha = 0x%X)", + srcRGB, dstRGB, srcAlpha, dstAlpha); + + Context *context = GetValidGlobalContext(); + if (context) + { + switch (srcRGB) + { + case GL_ZERO: + case GL_ONE: + case GL_SRC_COLOR: + case GL_ONE_MINUS_SRC_COLOR: + case GL_DST_COLOR: + case GL_ONE_MINUS_DST_COLOR: + case GL_SRC_ALPHA: + case GL_ONE_MINUS_SRC_ALPHA: + case GL_DST_ALPHA: + case GL_ONE_MINUS_DST_ALPHA: + case GL_CONSTANT_COLOR: + case GL_ONE_MINUS_CONSTANT_COLOR: + case GL_CONSTANT_ALPHA: + case GL_ONE_MINUS_CONSTANT_ALPHA: + case GL_SRC_ALPHA_SATURATE: + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + switch (dstRGB) + { + case GL_ZERO: + case GL_ONE: + case GL_SRC_COLOR: + case GL_ONE_MINUS_SRC_COLOR: + case GL_DST_COLOR: + case GL_ONE_MINUS_DST_COLOR: + case GL_SRC_ALPHA: + case GL_ONE_MINUS_SRC_ALPHA: + case GL_DST_ALPHA: + case GL_ONE_MINUS_DST_ALPHA: + case GL_CONSTANT_COLOR: + case GL_ONE_MINUS_CONSTANT_COLOR: + case GL_CONSTANT_ALPHA: + case GL_ONE_MINUS_CONSTANT_ALPHA: + break; + + case GL_SRC_ALPHA_SATURATE: + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + switch (srcAlpha) + { + case GL_ZERO: + case GL_ONE: + case GL_SRC_COLOR: + case GL_ONE_MINUS_SRC_COLOR: + case GL_DST_COLOR: + case GL_ONE_MINUS_DST_COLOR: + case GL_SRC_ALPHA: + case GL_ONE_MINUS_SRC_ALPHA: + case GL_DST_ALPHA: + case GL_ONE_MINUS_DST_ALPHA: + case GL_CONSTANT_COLOR: + case GL_ONE_MINUS_CONSTANT_COLOR: + case GL_CONSTANT_ALPHA: + case GL_ONE_MINUS_CONSTANT_ALPHA: + case GL_SRC_ALPHA_SATURATE: + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + switch (dstAlpha) + { + case GL_ZERO: + case GL_ONE: + case GL_SRC_COLOR: + case GL_ONE_MINUS_SRC_COLOR: + case GL_DST_COLOR: + case GL_ONE_MINUS_DST_COLOR: + case GL_SRC_ALPHA: + case GL_ONE_MINUS_SRC_ALPHA: + case GL_DST_ALPHA: + case GL_ONE_MINUS_DST_ALPHA: + case GL_CONSTANT_COLOR: + case GL_ONE_MINUS_CONSTANT_COLOR: + case GL_CONSTANT_ALPHA: + case GL_ONE_MINUS_CONSTANT_ALPHA: + break; + + case GL_SRC_ALPHA_SATURATE: + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + bool constantColorUsed = (srcRGB == GL_CONSTANT_COLOR || srcRGB == GL_ONE_MINUS_CONSTANT_COLOR || + dstRGB == GL_CONSTANT_COLOR || dstRGB == GL_ONE_MINUS_CONSTANT_COLOR); + + bool constantAlphaUsed = (srcRGB == GL_CONSTANT_ALPHA || srcRGB == GL_ONE_MINUS_CONSTANT_ALPHA || + dstRGB == GL_CONSTANT_ALPHA || dstRGB == GL_ONE_MINUS_CONSTANT_ALPHA); + + if (constantColorUsed && constantAlphaUsed) + { + ERR("Simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR invalid under WebGL"); + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + context->getState().setBlendFactors(srcRGB, dstRGB, srcAlpha, dstAlpha); + } +} + +void GL_APIENTRY BufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage) +{ + EVENT("(GLenum target = 0x%X, GLsizeiptr size = %d, const GLvoid* data = 0x%0.8p, GLenum usage = %d)", + target, size, data, usage); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (size < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + switch (usage) + { + case GL_STREAM_DRAW: + case GL_STATIC_DRAW: + case GL_DYNAMIC_DRAW: + break; + + case GL_STREAM_READ: + case GL_STREAM_COPY: + case GL_STATIC_READ: + case GL_STATIC_COPY: + case GL_DYNAMIC_READ: + case GL_DYNAMIC_COPY: + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + if (!ValidBufferTarget(context, target)) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + Buffer *buffer = context->getState().getTargetBuffer(target); + + if (!buffer) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + Error error = buffer->bufferData(data, size, usage); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY BufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data) +{ + EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr size = %d, const GLvoid* data = 0x%0.8p)", + target, offset, size, data); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (size < 0 || offset < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + if (data == NULL) + { + return; + } + + if (!ValidBufferTarget(context, target)) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + Buffer *buffer = context->getState().getTargetBuffer(target); + + if (!buffer) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (buffer->isMapped()) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + // Check for possible overflow of size + offset + if (!rx::IsUnsignedAdditionSafe(size, offset)) + { + context->recordError(Error(GL_OUT_OF_MEMORY)); + return; + } + + if (size + offset > buffer->getSize()) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + Error error = buffer->bufferSubData(data, size, offset); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +GLenum GL_APIENTRY CheckFramebufferStatus(GLenum target) +{ + EVENT("(GLenum target = 0x%X)", target); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidFramebufferTarget(target)) + { + context->recordError(Error(GL_INVALID_ENUM)); + return 0; + } + + Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target); + ASSERT(framebuffer); + + return framebuffer->checkStatus(context->getData()); + } + + return 0; +} + +void GL_APIENTRY Clear(GLbitfield mask) +{ + EVENT("(GLbitfield mask = 0x%X)", mask); + + Context *context = GetValidGlobalContext(); + if (context) + { + Framebuffer *framebufferObject = context->getState().getDrawFramebuffer(); + ASSERT(framebufferObject); + + if (framebufferObject->checkStatus(context->getData()) != GL_FRAMEBUFFER_COMPLETE) + { + context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION)); + return; + } + + if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + Error error = framebufferObject->clear(context->getData(), mask); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY ClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) +{ + EVENT("(GLclampf red = %f, GLclampf green = %f, GLclampf blue = %f, GLclampf alpha = %f)", + red, green, blue, alpha); + + Context *context = GetValidGlobalContext(); + if (context) + { + context->getState().setColorClearValue(red, green, blue, alpha); + } +} + +void GL_APIENTRY ClearDepthf(GLclampf depth) +{ + EVENT("(GLclampf depth = %f)", depth); + + Context *context = GetValidGlobalContext(); + if (context) + { + context->getState().setDepthClearValue(depth); + } +} + +void GL_APIENTRY ClearStencil(GLint s) +{ + EVENT("(GLint s = %d)", s); + + Context *context = GetValidGlobalContext(); + if (context) + { + context->getState().setStencilClearValue(s); + } +} + +void GL_APIENTRY ColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) +{ + EVENT("(GLboolean red = %d, GLboolean green = %u, GLboolean blue = %u, GLboolean alpha = %u)", + red, green, blue, alpha); + + Context *context = GetValidGlobalContext(); + if (context) + { + context->getState().setColorMask(red == GL_TRUE, green == GL_TRUE, blue == GL_TRUE, alpha == GL_TRUE); + } +} + +void GL_APIENTRY CompileShader(GLuint shader) +{ + EVENT("(GLuint shader = %d)", shader); + + Context *context = GetValidGlobalContext(); + if (context) + { + Shader *shaderObject = context->getShader(shader); + + if (!shaderObject) + { + if (context->getProgram(shader)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + else + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + } + + shaderObject->compile(context->getCompiler()); + } +} + +void GL_APIENTRY CompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, + GLint border, GLsizei imageSize, const GLvoid* data) +{ + EVENT("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, " + "GLsizei height = %d, GLint border = %d, GLsizei imageSize = %d, const GLvoid* data = 0x%0.8p)", + target, level, internalformat, width, height, border, imageSize, data); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3 && + !ValidateES2TexImageParameters(context, target, level, internalformat, true, false, + 0, 0, width, height, border, GL_NONE, GL_NONE, data)) + { + return; + } + + if (context->getClientVersion() >= 3 && + !ValidateES3TexImageParameters(context, target, level, internalformat, true, false, + 0, 0, 0, width, height, 1, border, GL_NONE, GL_NONE, data)) + { + return; + } + + const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat); + if (imageSize < 0 || static_cast(imageSize) != formatInfo.computeBlockSize(GL_UNSIGNED_BYTE, width, height)) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + Extents size(width, height, 1); + Texture *texture = context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target); + Error error = texture->setCompressedImage(target, level, internalformat, size, context->getState().getUnpackState(), + reinterpret_cast(data)); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY CompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + GLenum format, GLsizei imageSize, const GLvoid* data) +{ + EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, " + "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, " + "GLsizei imageSize = %d, const GLvoid* data = 0x%0.8p)", + target, level, xoffset, yoffset, width, height, format, imageSize, data); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3 && + !ValidateES2TexImageParameters(context, target, level, GL_NONE, true, true, + xoffset, yoffset, width, height, 0, GL_NONE, GL_NONE, data)) + { + return; + } + + if (context->getClientVersion() >= 3 && + !ValidateES3TexImageParameters(context, target, level, GL_NONE, true, true, + xoffset, yoffset, 0, width, height, 1, 0, GL_NONE, GL_NONE, data)) + { + return; + } + + const InternalFormat &formatInfo = GetInternalFormatInfo(format); + if (imageSize < 0 || static_cast(imageSize) != formatInfo.computeBlockSize(GL_UNSIGNED_BYTE, width, height)) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + + Box area(xoffset, yoffset, 0, width, height, 1); + Texture *texture = context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target); + Error error = texture->setCompressedSubImage(target, level, area, format, context->getState().getUnpackState(), + reinterpret_cast(data)); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY CopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) +{ + EVENT("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, " + "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, GLint border = %d)", + target, level, internalformat, x, y, width, height, border); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3 && + !ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, + 0, 0, x, y, width, height, border)) + { + return; + } + + if (context->getClientVersion() >= 3 && + !ValidateES3CopyTexImageParameters(context, target, level, internalformat, false, + 0, 0, 0, x, y, width, height, border)) + { + return; + } + + Rectangle sourceArea(x, y, width, height); + + const Framebuffer *framebuffer = context->getState().getReadFramebuffer(); + Texture *texture = context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target); + Error error = texture->copyImage(target, level, sourceArea, internalformat, framebuffer); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY CopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) +{ + EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, " + "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", + target, level, xoffset, yoffset, x, y, width, height); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3 && + !ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, + xoffset, yoffset, x, y, width, height, 0)) + { + return; + } + + if (context->getClientVersion() >= 3 && + !ValidateES3CopyTexImageParameters(context, target, level, GL_NONE, true, + xoffset, yoffset, 0, x, y, width, height, 0)) + { + return; + } + + Offset destOffset(xoffset, yoffset, 0); + Rectangle sourceArea(x, y, width, height); + + const Framebuffer *framebuffer = context->getState().getReadFramebuffer(); + Texture *texture = context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target); + Error error = texture->copySubImage(target, level, destOffset, sourceArea, framebuffer); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +GLuint GL_APIENTRY CreateProgram(void) +{ + EVENT("()"); + + Context *context = GetValidGlobalContext(); + if (context) + { + return context->createProgram(); + } + + return 0; +} + +GLuint GL_APIENTRY CreateShader(GLenum type) +{ + EVENT("(GLenum type = 0x%X)", type); + + Context *context = GetValidGlobalContext(); + if (context) + { + switch (type) + { + case GL_FRAGMENT_SHADER: + case GL_VERTEX_SHADER: + return context->createShader(type); + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return 0; + } + } + + return 0; +} + +void GL_APIENTRY CullFace(GLenum mode) +{ + EVENT("(GLenum mode = 0x%X)", mode); + + Context *context = GetValidGlobalContext(); + if (context) + { + switch (mode) + { + case GL_FRONT: + case GL_BACK: + case GL_FRONT_AND_BACK: + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + context->getState().setCullMode(mode); + } +} + +void GL_APIENTRY DeleteBuffers(GLsizei n, const GLuint* buffers) +{ + EVENT("(GLsizei n = %d, const GLuint* buffers = 0x%0.8p)", n, buffers); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (n < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + for (int i = 0; i < n; i++) + { + context->deleteBuffer(buffers[i]); + } + } +} + +void GL_APIENTRY DeleteFramebuffers(GLsizei n, const GLuint* framebuffers) +{ + EVENT("(GLsizei n = %d, const GLuint* framebuffers = 0x%0.8p)", n, framebuffers); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (n < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + for (int i = 0; i < n; i++) + { + if (framebuffers[i] != 0) + { + context->deleteFramebuffer(framebuffers[i]); + } + } + } +} + +void GL_APIENTRY DeleteProgram(GLuint program) +{ + EVENT("(GLuint program = %d)", program); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (program == 0) + { + return; + } + + if (!context->getProgram(program)) + { + if(context->getShader(program)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + else + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + } + + context->deleteProgram(program); + } +} + +void GL_APIENTRY DeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers) +{ + EVENT("(GLsizei n = %d, const GLuint* renderbuffers = 0x%0.8p)", n, renderbuffers); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (n < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + for (int i = 0; i < n; i++) + { + context->deleteRenderbuffer(renderbuffers[i]); + } + } +} + +void GL_APIENTRY DeleteShader(GLuint shader) +{ + EVENT("(GLuint shader = %d)", shader); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (shader == 0) + { + return; + } + + if (!context->getShader(shader)) + { + if(context->getProgram(shader)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + else + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + } + + context->deleteShader(shader); + } +} + +void GL_APIENTRY DeleteTextures(GLsizei n, const GLuint* textures) +{ + EVENT("(GLsizei n = %d, const GLuint* textures = 0x%0.8p)", n, textures); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (n < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + for (int i = 0; i < n; i++) + { + if (textures[i] != 0) + { + context->deleteTexture(textures[i]); + } + } + } +} + +void GL_APIENTRY DepthFunc(GLenum func) +{ + EVENT("(GLenum func = 0x%X)", func); + + Context *context = GetValidGlobalContext(); + if (context) + { + switch (func) + { + case GL_NEVER: + case GL_ALWAYS: + case GL_LESS: + case GL_LEQUAL: + case GL_EQUAL: + case GL_GREATER: + case GL_GEQUAL: + case GL_NOTEQUAL: + context->getState().setDepthFunc(func); + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + } +} + +void GL_APIENTRY DepthMask(GLboolean flag) +{ + EVENT("(GLboolean flag = %u)", flag); + + Context *context = GetValidGlobalContext(); + if (context) + { + context->getState().setDepthMask(flag != GL_FALSE); + } +} + +void GL_APIENTRY DepthRangef(GLclampf zNear, GLclampf zFar) +{ + EVENT("(GLclampf zNear = %f, GLclampf zFar = %f)", zNear, zFar); + + Context *context = GetValidGlobalContext(); + if (context) + { + context->getState().setDepthRange(zNear, zFar); + } +} + +void GL_APIENTRY DetachShader(GLuint program, GLuint shader) +{ + EVENT("(GLuint program = %d, GLuint shader = %d)", program, shader); + + Context *context = GetValidGlobalContext(); + if (context) + { + Program *programObject = context->getProgram(program); + Shader *shaderObject = context->getShader(shader); + + if (!programObject) + { + Shader *shaderByProgramHandle; + shaderByProgramHandle = context->getShader(program); + if (!shaderByProgramHandle) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + else + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + } + + if (!shaderObject) + { + Program *programByShaderHandle = context->getProgram(shader); + if (!programByShaderHandle) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + else + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + } + + if (!programObject->detachShader(shaderObject)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + } +} + +void GL_APIENTRY Disable(GLenum cap) +{ + EVENT("(GLenum cap = 0x%X)", cap); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidCap(context, cap)) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + context->getState().setEnableFeature(cap, false); + } +} + +void GL_APIENTRY DisableVertexAttribArray(GLuint index) +{ + EVENT("(GLuint index = %d)", index); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (index >= MAX_VERTEX_ATTRIBS) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + context->getState().setEnableVertexAttribArray(index, false); + } +} + +void GL_APIENTRY DrawArrays(GLenum mode, GLint first, GLsizei count) +{ + EVENT("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d)", mode, first, count); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateDrawArrays(context, mode, first, count, 0)) + { + return; + } + + Error error = context->drawArrays(mode, first, count, 0); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY DrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices) +{ + EVENT("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = 0x%0.8p)", + mode, count, type, indices); + + Context *context = GetValidGlobalContext(); + if (context) + { + rx::RangeUI indexRange; + if (!ValidateDrawElements(context, mode, count, type, indices, 0, &indexRange)) + { + return; + } + + Error error = context->drawElements(mode, count, type, indices, 0, indexRange); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY Enable(GLenum cap) +{ + EVENT("(GLenum cap = 0x%X)", cap); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidCap(context, cap)) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + context->getState().setEnableFeature(cap, true); + } +} + +void GL_APIENTRY EnableVertexAttribArray(GLuint index) +{ + EVENT("(GLuint index = %d)", index); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (index >= MAX_VERTEX_ATTRIBS) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + context->getState().setEnableVertexAttribArray(index, true); + } +} + +void GL_APIENTRY Finish(void) +{ + EVENT("()"); + + Context *context = GetValidGlobalContext(); + if (context) + { + Error error = context->finish(); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY Flush(void) +{ + EVENT("()"); + + Context *context = GetValidGlobalContext(); + if (context) + { + Error error = context->flush(); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY FramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) +{ + EVENT("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum renderbuffertarget = 0x%X, " + "GLuint renderbuffer = %d)", target, attachment, renderbuffertarget, renderbuffer); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidFramebufferTarget(target) || (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0)) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + if (!ValidateFramebufferRenderbufferParameters(context, target, attachment, renderbuffertarget, renderbuffer)) + { + return; + } + + Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target); + ASSERT(framebuffer); + + if (renderbuffer != 0) + { + Renderbuffer *renderbufferObject = context->getRenderbuffer(renderbuffer); + framebuffer->setRenderbufferAttachment(attachment, renderbufferObject); + } + else + { + framebuffer->setNULLAttachment(attachment); + } + } +} + +void GL_APIENTRY FramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) +{ + EVENT("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum textarget = 0x%X, " + "GLuint texture = %d, GLint level = %d)", target, attachment, textarget, texture, level); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateFramebufferTexture2D(context, target, attachment, textarget, texture, level)) + { + return; + } + + Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target); + ASSERT(framebuffer); + + if (texture != 0) + { + Texture *textureObj = context->getTexture(texture); + + ImageIndex index = ImageIndex::MakeInvalid(); + + if (textarget == GL_TEXTURE_2D) + { + index = ImageIndex::Make2D(level); + } + else + { + ASSERT(IsCubeMapTextureTarget(textarget)); + index = ImageIndex::MakeCube(textarget, level); + } + + framebuffer->setTextureAttachment(attachment, textureObj, index); + } + else + { + framebuffer->setNULLAttachment(attachment); + } + } +} + +void GL_APIENTRY FrontFace(GLenum mode) +{ + EVENT("(GLenum mode = 0x%X)", mode); + + Context *context = GetValidGlobalContext(); + if (context) + { + switch (mode) + { + case GL_CW: + case GL_CCW: + context->getState().setFrontFace(mode); + break; + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + } +} + +void GL_APIENTRY GenBuffers(GLsizei n, GLuint* buffers) +{ + EVENT("(GLsizei n = %d, GLuint* buffers = 0x%0.8p)", n, buffers); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (n < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + for (int i = 0; i < n; i++) + { + buffers[i] = context->createBuffer(); + } + } +} + +void GL_APIENTRY GenerateMipmap(GLenum target) +{ + EVENT("(GLenum target = 0x%X)", target); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidTextureTarget(context, target)) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + Texture *texture = context->getTargetTexture(target); + + if (texture == NULL) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target; + GLenum internalFormat = texture->getInternalFormat(baseTarget, 0); + const TextureCaps &formatCaps = context->getTextureCaps().get(internalFormat); + const InternalFormat &formatInfo = GetInternalFormatInfo(internalFormat); + + // GenerateMipmap should not generate an INVALID_OPERATION for textures created with + // unsized formats or that are color renderable and filterable. Since we do not track if + // the texture was created with sized or unsized format (only sized formats are stored), + // it is not possible to make sure the the LUMA formats can generate mipmaps (they should + // be able to) because they aren't color renderable. Simply do a special case for LUMA + // textures since they're the only texture format that can be created with unsized formats + // that is not color renderable. New unsized formats are unlikely to be added, since ES2 + // was the last version to use add them. + bool isLUMA = internalFormat == GL_LUMINANCE8_EXT || + internalFormat == GL_LUMINANCE8_ALPHA8_EXT || + internalFormat == GL_ALPHA8_EXT; + + if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0 || !formatCaps.filterable || + (!formatCaps.renderable && !isLUMA) || formatInfo.compressed) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + // GL_EXT_sRGB does not support mipmap generation on sRGB textures + if (context->getClientVersion() == 2 && formatInfo.colorEncoding == GL_SRGB) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + // Non-power of 2 ES2 check + if (!context->getExtensions().textureNPOT && (!isPow2(texture->getWidth(baseTarget, 0)) || !isPow2(texture->getHeight(baseTarget, 0)))) + { + ASSERT(context->getClientVersion() <= 2 && (target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP)); + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + // Cube completeness check + if (target == GL_TEXTURE_CUBE_MAP && !texture->isCubeComplete()) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + Error error = texture->generateMipmaps(); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY GenFramebuffers(GLsizei n, GLuint* framebuffers) +{ + EVENT("(GLsizei n = %d, GLuint* framebuffers = 0x%0.8p)", n, framebuffers); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (n < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + for (int i = 0; i < n; i++) + { + framebuffers[i] = context->createFramebuffer(); + } + } +} + +void GL_APIENTRY GenRenderbuffers(GLsizei n, GLuint* renderbuffers) +{ + EVENT("(GLsizei n = %d, GLuint* renderbuffers = 0x%0.8p)", n, renderbuffers); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (n < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + for (int i = 0; i < n; i++) + { + renderbuffers[i] = context->createRenderbuffer(); + } + } +} + +void GL_APIENTRY GenTextures(GLsizei n, GLuint* textures) +{ + EVENT("(GLsizei n = %d, GLuint* textures = 0x%0.8p)", n, textures); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (n < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + for (int i = 0; i < n; i++) + { + textures[i] = context->createTexture(); + } + } +} + +void GL_APIENTRY GetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) +{ + EVENT("(GLuint program = %d, GLuint index = %d, GLsizei bufsize = %d, GLsizei *length = 0x%0.8p, " + "GLint *size = 0x%0.8p, GLenum *type = %0.8p, GLchar *name = %0.8p)", + program, index, bufsize, length, size, type, name); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (bufsize < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + Program *programObject = context->getProgram(program); + + if (!programObject) + { + if (context->getShader(program)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + else + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + } + + if (index >= (GLuint)programObject->getActiveAttributeCount()) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + programObject->getActiveAttribute(index, bufsize, length, size, type, name); + } +} + +void GL_APIENTRY GetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name) +{ + EVENT("(GLuint program = %d, GLuint index = %d, GLsizei bufsize = %d, " + "GLsizei* length = 0x%0.8p, GLint* size = 0x%0.8p, GLenum* type = 0x%0.8p, GLchar* name = 0x%0.8p)", + program, index, bufsize, length, size, type, name); + + + Context *context = GetValidGlobalContext(); + if (context) + { + if (bufsize < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + Program *programObject = context->getProgram(program); + + if (!programObject) + { + if (context->getShader(program)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + else + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + } + + if (index >= (GLuint)programObject->getActiveUniformCount()) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + programObject->getActiveUniform(index, bufsize, length, size, type, name); + } +} + +void GL_APIENTRY GetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders) +{ + EVENT("(GLuint program = %d, GLsizei maxcount = %d, GLsizei* count = 0x%0.8p, GLuint* shaders = 0x%0.8p)", + program, maxcount, count, shaders); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (maxcount < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + Program *programObject = context->getProgram(program); + + if (!programObject) + { + if (context->getShader(program)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + else + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + } + + return programObject->getAttachedShaders(maxcount, count, shaders); + } +} + +GLint GL_APIENTRY GetAttribLocation(GLuint program, const GLchar* name) +{ + EVENT("(GLuint program = %d, const GLchar* name = %s)", program, name); + + Context *context = GetValidGlobalContext(); + if (context) + { + Program *programObject = context->getProgram(program); + + if (!programObject) + { + if (context->getShader(program)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return -1; + } + else + { + context->recordError(Error(GL_INVALID_VALUE)); + return -1; + } + } + + if (!programObject->isLinked()) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return -1; + } + + return programObject->getAttributeLocation(name); + } + + return -1; +} + +void GL_APIENTRY GetBooleanv(GLenum pname, GLboolean* params) +{ + EVENT("(GLenum pname = 0x%X, GLboolean* params = 0x%0.8p)", pname, params); + + Context *context = GetValidGlobalContext(); + if (context) + { + GLenum nativeType; + unsigned int numParams = 0; + if (!ValidateStateQuery(context, pname, &nativeType, &numParams)) + { + return; + } + + if (nativeType == GL_BOOL) + { + context->getBooleanv(pname, params); + } + else + { + CastStateValues(context, nativeType, pname, numParams, params); + } + } +} + +void GL_APIENTRY GetBufferParameteriv(GLenum target, GLenum pname, GLint* params) +{ + EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidBufferTarget(context, target)) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + if (!ValidBufferParameter(context, pname)) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + Buffer *buffer = context->getState().getTargetBuffer(target); + + if (!buffer) + { + // A null buffer means that "0" is bound to the requested buffer target + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + switch (pname) + { + case GL_BUFFER_USAGE: + *params = static_cast(buffer->getUsage()); + break; + case GL_BUFFER_SIZE: + *params = clampCast(buffer->getSize()); + break; + case GL_BUFFER_ACCESS_FLAGS: + *params = buffer->getAccessFlags(); + break; + case GL_BUFFER_MAPPED: + *params = static_cast(buffer->isMapped()); + break; + case GL_BUFFER_MAP_OFFSET: + *params = clampCast(buffer->getMapOffset()); + break; + case GL_BUFFER_MAP_LENGTH: + *params = clampCast(buffer->getMapLength()); + break; + default: UNREACHABLE(); break; + } + } +} + +GLenum GL_APIENTRY GetError(void) +{ + EVENT("()"); + + Context *context = GetGlobalContext(); + + if (context) + { + return context->getError(); + } + + return GL_NO_ERROR; +} + +void GL_APIENTRY GetFloatv(GLenum pname, GLfloat* params) +{ + EVENT("(GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", pname, params); + + Context *context = GetValidGlobalContext(); + if (context) + { + GLenum nativeType; + unsigned int numParams = 0; + if (!ValidateStateQuery(context, pname, &nativeType, &numParams)) + { + return; + } + + if (nativeType == GL_FLOAT) + { + context->getFloatv(pname, params); + } + else + { + CastStateValues(context, nativeType, pname, numParams, params); + } + } +} + +void GL_APIENTRY GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params) +{ + EVENT("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", + target, attachment, pname, params); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidFramebufferTarget(target)) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + int clientVersion = context->getClientVersion(); + + switch (pname) + { + case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE: + case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME: + case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL: + case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE: + break; + + case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING: + if (clientVersion < 3 && !context->getExtensions().sRGB) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + break; + + case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE: + case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE: + case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE: + case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE: + case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE: + case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE: + case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE: + case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER: + if (clientVersion < 3) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + // Determine if the attachment is a valid enum + switch (attachment) + { + case GL_BACK: + case GL_FRONT: + case GL_DEPTH: + case GL_STENCIL: + case GL_DEPTH_STENCIL_ATTACHMENT: + if (clientVersion < 3) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + break; + + case GL_DEPTH_ATTACHMENT: + case GL_STENCIL_ATTACHMENT: + break; + + default: + if (attachment < GL_COLOR_ATTACHMENT0_EXT || + (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + break; + } + + Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target); + ASSERT(framebuffer); + + if (framebuffer->id() == 0) + { + if (clientVersion < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + switch (attachment) + { + case GL_BACK: + case GL_DEPTH: + case GL_STENCIL: + break; + + default: + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + } + else + { + if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT) + { + // Valid attachment query + } + else + { + switch (attachment) + { + case GL_DEPTH_ATTACHMENT: + case GL_STENCIL_ATTACHMENT: + break; + + case GL_DEPTH_STENCIL_ATTACHMENT: + if (framebuffer->hasValidDepthStencil()) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + break; + + default: + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + } + } + + const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment); + if (attachmentObject) + { + ASSERT(attachmentObject->type() == GL_RENDERBUFFER || + attachmentObject->type() == GL_TEXTURE || + attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT); + + switch (pname) + { + case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE: + *params = attachmentObject->type(); + break; + + case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME: + if (attachmentObject->type() != GL_RENDERBUFFER && attachmentObject->type() != GL_TEXTURE) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + *params = attachmentObject->id(); + break; + + case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL: + if (attachmentObject->type() != GL_TEXTURE) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + *params = attachmentObject->mipLevel(); + break; + + case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE: + if (attachmentObject->type() != GL_TEXTURE) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + *params = attachmentObject->cubeMapFace(); + break; + + case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE: + *params = attachmentObject->getRedSize(); + break; + + case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE: + *params = attachmentObject->getGreenSize(); + break; + + case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE: + *params = attachmentObject->getBlueSize(); + break; + + case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE: + *params = attachmentObject->getAlphaSize(); + break; + + case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE: + *params = attachmentObject->getDepthSize(); + break; + + case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE: + *params = attachmentObject->getStencilSize(); + break; + + case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE: + if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + *params = attachmentObject->getComponentType(); + break; + + case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING: + *params = attachmentObject->getColorEncoding(); + break; + + case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER: + if (attachmentObject->type() != GL_TEXTURE) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + *params = attachmentObject->layer(); + break; + + default: + UNREACHABLE(); + break; + } + } + else + { + // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE + // is NONE, then querying any other pname will generate INVALID_ENUM. + + // ES 3.0.2 spec pg 235 states that if the attachment type is none, + // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an + // INVALID_OPERATION for all other pnames + + switch (pname) + { + case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE: + *params = GL_NONE; + break; + + case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME: + if (clientVersion < 3) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + *params = 0; + break; + + default: + if (clientVersion < 3) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + else + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + } + } + } +} + +void GL_APIENTRY GetIntegerv(GLenum pname, GLint* params) +{ + EVENT("(GLenum pname = 0x%X, GLint* params = 0x%0.8p)", pname, params); + + Context *context = GetValidGlobalContext(); + if (context) + { + GLenum nativeType; + unsigned int numParams = 0; + + if (!ValidateStateQuery(context, pname, &nativeType, &numParams)) + { + return; + } + + if (nativeType == GL_INT) + { + context->getIntegerv(pname, params); + } + else + { + CastStateValues(context, nativeType, pname, numParams, params); + } + } +} + +void GL_APIENTRY GetProgramiv(GLuint program, GLenum pname, GLint* params) +{ + EVENT("(GLuint program = %d, GLenum pname = %d, GLint* params = 0x%0.8p)", program, pname, params); + + Context *context = GetValidGlobalContext(); + if (context) + { + Program *programObject = context->getProgram(program); + + if (!programObject) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + if (context->getClientVersion() < 3) + { + switch (pname) + { + case GL_ACTIVE_UNIFORM_BLOCKS: + case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH: + case GL_TRANSFORM_FEEDBACK_BUFFER_MODE: + case GL_TRANSFORM_FEEDBACK_VARYINGS: + case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + } + + switch (pname) + { + case GL_DELETE_STATUS: + *params = programObject->isFlaggedForDeletion(); + return; + case GL_LINK_STATUS: + *params = programObject->isLinked(); + return; + case GL_VALIDATE_STATUS: + *params = programObject->isValidated(); + return; + case GL_INFO_LOG_LENGTH: + *params = programObject->getInfoLogLength(); + return; + case GL_ATTACHED_SHADERS: + *params = programObject->getAttachedShadersCount(); + return; + case GL_ACTIVE_ATTRIBUTES: + *params = programObject->getActiveAttributeCount(); + return; + case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH: + *params = programObject->getActiveAttributeMaxLength(); + return; + case GL_ACTIVE_UNIFORMS: + *params = programObject->getActiveUniformCount(); + return; + case GL_ACTIVE_UNIFORM_MAX_LENGTH: + *params = programObject->getActiveUniformMaxLength(); + return; + case GL_PROGRAM_BINARY_LENGTH_OES: + *params = programObject->getBinaryLength(); + return; + case GL_ACTIVE_UNIFORM_BLOCKS: + *params = programObject->getActiveUniformBlockCount(); + return; + case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH: + *params = programObject->getActiveUniformBlockMaxLength(); + break; + case GL_TRANSFORM_FEEDBACK_BUFFER_MODE: + *params = programObject->getTransformFeedbackBufferMode(); + break; + case GL_TRANSFORM_FEEDBACK_VARYINGS: + *params = programObject->getTransformFeedbackVaryingCount(); + break; + case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH: + *params = programObject->getTransformFeedbackVaryingMaxLength(); + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + } +} + +void GL_APIENTRY GetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog) +{ + EVENT("(GLuint program = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* infolog = 0x%0.8p)", + program, bufsize, length, infolog); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (bufsize < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + Program *programObject = context->getProgram(program); + + if (!programObject) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + programObject->getInfoLog(bufsize, length, infolog); + } +} + +void GL_APIENTRY GetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params) +{ + EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (target != GL_RENDERBUFFER) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + if (context->getState().getRenderbufferId() == 0) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + Renderbuffer *renderbuffer = context->getRenderbuffer(context->getState().getRenderbufferId()); + + switch (pname) + { + case GL_RENDERBUFFER_WIDTH: *params = renderbuffer->getWidth(); break; + case GL_RENDERBUFFER_HEIGHT: *params = renderbuffer->getHeight(); break; + case GL_RENDERBUFFER_INTERNAL_FORMAT: *params = renderbuffer->getInternalFormat(); break; + case GL_RENDERBUFFER_RED_SIZE: *params = renderbuffer->getRedSize(); break; + case GL_RENDERBUFFER_GREEN_SIZE: *params = renderbuffer->getGreenSize(); break; + case GL_RENDERBUFFER_BLUE_SIZE: *params = renderbuffer->getBlueSize(); break; + case GL_RENDERBUFFER_ALPHA_SIZE: *params = renderbuffer->getAlphaSize(); break; + case GL_RENDERBUFFER_DEPTH_SIZE: *params = renderbuffer->getDepthSize(); break; + case GL_RENDERBUFFER_STENCIL_SIZE: *params = renderbuffer->getStencilSize(); break; + + case GL_RENDERBUFFER_SAMPLES_ANGLE: + if (!context->getExtensions().framebufferMultisample) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + *params = renderbuffer->getSamples(); + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + } +} + +void GL_APIENTRY GetShaderiv(GLuint shader, GLenum pname, GLint* params) +{ + EVENT("(GLuint shader = %d, GLenum pname = %d, GLint* params = 0x%0.8p)", shader, pname, params); + + Context *context = GetValidGlobalContext(); + if (context) + { + Shader *shaderObject = context->getShader(shader); + + if (!shaderObject) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + switch (pname) + { + case GL_SHADER_TYPE: + *params = shaderObject->getType(); + return; + case GL_DELETE_STATUS: + *params = shaderObject->isFlaggedForDeletion(); + return; + case GL_COMPILE_STATUS: + *params = shaderObject->isCompiled() ? GL_TRUE : GL_FALSE; + return; + case GL_INFO_LOG_LENGTH: + *params = shaderObject->getInfoLogLength(); + return; + case GL_SHADER_SOURCE_LENGTH: + *params = shaderObject->getSourceLength(); + return; + case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE: + *params = shaderObject->getTranslatedSourceLength(); + return; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + } +} + +void GL_APIENTRY GetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog) +{ + EVENT("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* infolog = 0x%0.8p)", + shader, bufsize, length, infolog); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (bufsize < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + Shader *shaderObject = context->getShader(shader); + + if (!shaderObject) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + shaderObject->getInfoLog(bufsize, length, infolog); + } +} + +void GL_APIENTRY GetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision) +{ + EVENT("(GLenum shadertype = 0x%X, GLenum precisiontype = 0x%X, GLint* range = 0x%0.8p, GLint* precision = 0x%0.8p)", + shadertype, precisiontype, range, precision); + + Context *context = GetValidGlobalContext(); + if (context) + { + switch (shadertype) + { + case GL_VERTEX_SHADER: + switch (precisiontype) + { + case GL_LOW_FLOAT: + context->getCaps().vertexLowpFloat.get(range, precision); + break; + case GL_MEDIUM_FLOAT: + context->getCaps().vertexMediumpFloat.get(range, precision); + break; + case GL_HIGH_FLOAT: + context->getCaps().vertexHighpFloat.get(range, precision); + break; + + case GL_LOW_INT: + context->getCaps().vertexLowpInt.get(range, precision); + break; + case GL_MEDIUM_INT: + context->getCaps().vertexMediumpInt.get(range, precision); + break; + case GL_HIGH_INT: + context->getCaps().vertexHighpInt.get(range, precision); + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + break; + case GL_FRAGMENT_SHADER: + switch (precisiontype) + { + case GL_LOW_FLOAT: + context->getCaps().fragmentLowpFloat.get(range, precision); + break; + case GL_MEDIUM_FLOAT: + context->getCaps().fragmentMediumpFloat.get(range, precision); + break; + case GL_HIGH_FLOAT: + context->getCaps().fragmentHighpFloat.get(range, precision); + break; + + case GL_LOW_INT: + context->getCaps().fragmentLowpInt.get(range, precision); + break; + case GL_MEDIUM_INT: + context->getCaps().fragmentMediumpInt.get(range, precision); + break; + case GL_HIGH_INT: + context->getCaps().fragmentHighpInt.get(range, precision); + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + break; + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + } +} + +void GL_APIENTRY GetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source) +{ + EVENT("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* source = 0x%0.8p)", + shader, bufsize, length, source); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (bufsize < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + Shader *shaderObject = context->getShader(shader); + + if (!shaderObject) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + shaderObject->getSource(bufsize, length, source); + } +} + +const GLubyte *GL_APIENTRY GetString(GLenum name) +{ + EVENT("(GLenum name = 0x%X)", name); + + Context *context = GetValidGlobalContext(); + + switch (name) + { + case GL_VENDOR: + return (GLubyte*)"Google Inc."; + + case GL_RENDERER: + return (GLubyte*)((context != NULL) ? context->getRendererString().c_str() : "ANGLE"); + + case GL_VERSION: + if (context->getClientVersion() == 2) + { + return (GLubyte*)"OpenGL ES 2.0 (ANGLE " ANGLE_VERSION_STRING ")"; + } + else + { + return (GLubyte*)"OpenGL ES 3.0 (ANGLE " ANGLE_VERSION_STRING ")"; + } + + case GL_SHADING_LANGUAGE_VERSION: + if (context->getClientVersion() == 2) + { + return (GLubyte*)"OpenGL ES GLSL ES 1.00 (ANGLE " ANGLE_VERSION_STRING ")"; + } + else + { + return (GLubyte*)"OpenGL ES GLSL ES 3.00 (ANGLE " ANGLE_VERSION_STRING ")"; + } + + case GL_EXTENSIONS: + return (GLubyte*)((context != NULL) ? context->getExtensionString().c_str() : ""); + + default: + if (context) + { + context->recordError(Error(GL_INVALID_ENUM)); + } + return NULL; + } +} + +void GL_APIENTRY GetTexParameterfv(GLenum target, GLenum pname, GLfloat* params) +{ + EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", target, pname, params); + + Context *context = GetValidGlobalContext(); + if (context) + { + Texture *texture = context->getTargetTexture(target); + + if (!texture) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + switch (pname) + { + case GL_TEXTURE_MAG_FILTER: + *params = (GLfloat)texture->getSamplerState().magFilter; + break; + case GL_TEXTURE_MIN_FILTER: + *params = (GLfloat)texture->getSamplerState().minFilter; + break; + case GL_TEXTURE_WRAP_S: + *params = (GLfloat)texture->getSamplerState().wrapS; + break; + case GL_TEXTURE_WRAP_T: + *params = (GLfloat)texture->getSamplerState().wrapT; + break; + case GL_TEXTURE_WRAP_R: + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + *params = (GLfloat)texture->getSamplerState().wrapR; + break; + case GL_TEXTURE_IMMUTABLE_FORMAT: + // Exposed to ES2.0 through EXT_texture_storage, no client version validation. + *params = (GLfloat)(texture->isImmutable() ? GL_TRUE : GL_FALSE); + break; + case GL_TEXTURE_IMMUTABLE_LEVELS: + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + *params = (GLfloat)texture->immutableLevelCount(); + break; + case GL_TEXTURE_USAGE_ANGLE: + *params = (GLfloat)texture->getUsage(); + break; + case GL_TEXTURE_MAX_ANISOTROPY_EXT: + if (!context->getExtensions().textureFilterAnisotropic) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + *params = (GLfloat)texture->getSamplerState().maxAnisotropy; + break; + case GL_TEXTURE_SWIZZLE_R: + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + *params = (GLfloat)texture->getSamplerState().swizzleRed; + break; + case GL_TEXTURE_SWIZZLE_G: + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + *params = (GLfloat)texture->getSamplerState().swizzleGreen; + break; + case GL_TEXTURE_SWIZZLE_B: + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + *params = (GLfloat)texture->getSamplerState().swizzleBlue; + break; + case GL_TEXTURE_SWIZZLE_A: + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + *params = (GLfloat)texture->getSamplerState().swizzleAlpha; + break; + case GL_TEXTURE_BASE_LEVEL: + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + *params = (GLfloat)texture->getSamplerState().baseLevel; + break; + case GL_TEXTURE_MAX_LEVEL: + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + *params = (GLfloat)texture->getSamplerState().maxLevel; + break; + case GL_TEXTURE_MIN_LOD: + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + *params = texture->getSamplerState().minLod; + break; + case GL_TEXTURE_MAX_LOD: + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + *params = texture->getSamplerState().maxLod; + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + } +} + +void GL_APIENTRY GetTexParameteriv(GLenum target, GLenum pname, GLint* params) +{ + EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params); + + Context *context = GetValidGlobalContext(); + if (context) + { + Texture *texture = context->getTargetTexture(target); + + if (!texture) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + switch (pname) + { + case GL_TEXTURE_MAG_FILTER: + *params = texture->getSamplerState().magFilter; + break; + case GL_TEXTURE_MIN_FILTER: + *params = texture->getSamplerState().minFilter; + break; + case GL_TEXTURE_WRAP_S: + *params = texture->getSamplerState().wrapS; + break; + case GL_TEXTURE_WRAP_T: + *params = texture->getSamplerState().wrapT; + break; + case GL_TEXTURE_WRAP_R: + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + *params = texture->getSamplerState().wrapR; + break; + case GL_TEXTURE_IMMUTABLE_FORMAT: + // Exposed to ES2.0 through EXT_texture_storage, no client version validation. + *params = texture->isImmutable() ? GL_TRUE : GL_FALSE; + break; + case GL_TEXTURE_IMMUTABLE_LEVELS: + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + *params = static_cast(texture->immutableLevelCount()); + break; + case GL_TEXTURE_USAGE_ANGLE: + *params = texture->getUsage(); + break; + case GL_TEXTURE_MAX_ANISOTROPY_EXT: + if (!context->getExtensions().textureFilterAnisotropic) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + *params = (GLint)texture->getSamplerState().maxAnisotropy; + break; + case GL_TEXTURE_SWIZZLE_R: + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + *params = texture->getSamplerState().swizzleRed; + break; + case GL_TEXTURE_SWIZZLE_G: + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + *params = texture->getSamplerState().swizzleGreen; + break; + case GL_TEXTURE_SWIZZLE_B: + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + *params = texture->getSamplerState().swizzleBlue; + break; + case GL_TEXTURE_SWIZZLE_A: + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + *params = texture->getSamplerState().swizzleAlpha; + break; + case GL_TEXTURE_BASE_LEVEL: + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + *params = texture->getSamplerState().baseLevel; + break; + case GL_TEXTURE_MAX_LEVEL: + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + *params = texture->getSamplerState().maxLevel; + break; + case GL_TEXTURE_MIN_LOD: + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + *params = (GLint)texture->getSamplerState().minLod; + break; + case GL_TEXTURE_MAX_LOD: + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + *params = (GLint)texture->getSamplerState().maxLod; + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + } +} + +void GL_APIENTRY GetUniformfv(GLuint program, GLint location, GLfloat* params) +{ + EVENT("(GLuint program = %d, GLint location = %d, GLfloat* params = 0x%0.8p)", program, location, params); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateGetUniformfv(context, program, location, params)) + { + return; + } + + Program *programObject = context->getProgram(program); + ASSERT(programObject); + + programObject->getUniformfv(location, params); + } +} + +void GL_APIENTRY GetUniformiv(GLuint program, GLint location, GLint* params) +{ + EVENT("(GLuint program = %d, GLint location = %d, GLint* params = 0x%0.8p)", program, location, params); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateGetUniformiv(context, program, location, params)) + { + return; + } + + Program *programObject = context->getProgram(program); + ASSERT(programObject); + + programObject->getUniformiv(location, params); + } +} + +GLint GL_APIENTRY GetUniformLocation(GLuint program, const GLchar* name) +{ + EVENT("(GLuint program = %d, const GLchar* name = 0x%0.8p)", program, name); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (strstr(name, "gl_") == name) + { + return -1; + } + + Program *programObject = context->getProgram(program); + + if (!programObject) + { + if (context->getShader(program)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return -1; + } + else + { + context->recordError(Error(GL_INVALID_VALUE)); + return -1; + } + } + + if (!programObject->isLinked()) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return -1; + } + + return programObject->getUniformLocation(name); + } + + return -1; +} + +void GL_APIENTRY GetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params) +{ + EVENT("(GLuint index = %d, GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", index, pname, params); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (index >= MAX_VERTEX_ATTRIBS) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + if (!ValidateGetVertexAttribParameters(context, pname)) + { + return; + } + + if (pname == GL_CURRENT_VERTEX_ATTRIB) + { + const VertexAttribCurrentValueData ¤tValueData = context->getState().getVertexAttribCurrentValue(index); + for (int i = 0; i < 4; ++i) + { + params[i] = currentValueData.FloatValues[i]; + } + } + else + { + const VertexAttribute &attribState = context->getState().getVertexArray()->getVertexAttribute(index); + *params = QuerySingleVertexAttributeParameter(attribState, pname); + } + } +} + +void GL_APIENTRY GetVertexAttribiv(GLuint index, GLenum pname, GLint* params) +{ + EVENT("(GLuint index = %d, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", index, pname, params); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (index >= MAX_VERTEX_ATTRIBS) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + if (!ValidateGetVertexAttribParameters(context, pname)) + { + return; + } + + if (pname == GL_CURRENT_VERTEX_ATTRIB) + { + const VertexAttribCurrentValueData ¤tValueData = context->getState().getVertexAttribCurrentValue(index); + for (int i = 0; i < 4; ++i) + { + float currentValue = currentValueData.FloatValues[i]; + params[i] = iround(currentValue); + } + } + else + { + const VertexAttribute &attribState = context->getState().getVertexArray()->getVertexAttribute(index); + *params = QuerySingleVertexAttributeParameter(attribState, pname); + } + } +} + +void GL_APIENTRY GetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid** pointer) +{ + EVENT("(GLuint index = %d, GLenum pname = 0x%X, GLvoid** pointer = 0x%0.8p)", index, pname, pointer); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (index >= MAX_VERTEX_ATTRIBS) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + *pointer = const_cast(context->getState().getVertexAttribPointer(index)); + } +} + +void GL_APIENTRY Hint(GLenum target, GLenum mode) +{ + EVENT("(GLenum target = 0x%X, GLenum mode = 0x%X)", target, mode); + + Context *context = GetValidGlobalContext(); + if (context) + { + switch (mode) + { + case GL_FASTEST: + case GL_NICEST: + case GL_DONT_CARE: + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + switch (target) + { + case GL_GENERATE_MIPMAP_HINT: + context->getState().setGenerateMipmapHint(mode); + break; + + case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES: + context->getState().setFragmentShaderDerivativeHint(mode); + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + } +} + +GLboolean GL_APIENTRY IsBuffer(GLuint buffer) +{ + EVENT("(GLuint buffer = %d)", buffer); + + Context *context = GetValidGlobalContext(); + if (context && buffer) + { + Buffer *bufferObject = context->getBuffer(buffer); + + if (bufferObject) + { + return GL_TRUE; + } + } + + return GL_FALSE; +} + +GLboolean GL_APIENTRY IsEnabled(GLenum cap) +{ + EVENT("(GLenum cap = 0x%X)", cap); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidCap(context, cap)) + { + context->recordError(Error(GL_INVALID_ENUM)); + return GL_FALSE; + } + + return context->getState().getEnableFeature(cap); + } + + return false; +} + +GLboolean GL_APIENTRY IsFramebuffer(GLuint framebuffer) +{ + EVENT("(GLuint framebuffer = %d)", framebuffer); + + Context *context = GetValidGlobalContext(); + if (context && framebuffer) + { + Framebuffer *framebufferObject = context->getFramebuffer(framebuffer); + + if (framebufferObject) + { + return GL_TRUE; + } + } + + return GL_FALSE; +} + +GLboolean GL_APIENTRY IsProgram(GLuint program) +{ + EVENT("(GLuint program = %d)", program); + + Context *context = GetValidGlobalContext(); + if (context && program) + { + Program *programObject = context->getProgram(program); + + if (programObject) + { + return GL_TRUE; + } + } + + return GL_FALSE; +} + +GLboolean GL_APIENTRY IsRenderbuffer(GLuint renderbuffer) +{ + EVENT("(GLuint renderbuffer = %d)", renderbuffer); + + Context *context = GetValidGlobalContext(); + if (context && renderbuffer) + { + Renderbuffer *renderbufferObject = context->getRenderbuffer(renderbuffer); + + if (renderbufferObject) + { + return GL_TRUE; + } + } + + return GL_FALSE; +} + +GLboolean GL_APIENTRY IsShader(GLuint shader) +{ + EVENT("(GLuint shader = %d)", shader); + + Context *context = GetValidGlobalContext(); + if (context && shader) + { + Shader *shaderObject = context->getShader(shader); + + if (shaderObject) + { + return GL_TRUE; + } + } + + return GL_FALSE; +} + +GLboolean GL_APIENTRY IsTexture(GLuint texture) +{ + EVENT("(GLuint texture = %d)", texture); + + Context *context = GetValidGlobalContext(); + if (context && texture) + { + Texture *textureObject = context->getTexture(texture); + + if (textureObject) + { + return GL_TRUE; + } + } + + return GL_FALSE; +} + +void GL_APIENTRY LineWidth(GLfloat width) +{ + EVENT("(GLfloat width = %f)", width); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (width <= 0.0f) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + context->getState().setLineWidth(width); + } +} + +void GL_APIENTRY LinkProgram(GLuint program) +{ + EVENT("(GLuint program = %d)", program); + + Context *context = GetValidGlobalContext(); + if (context) + { + Program *programObject = context->getProgram(program); + + if (!programObject) + { + if (context->getShader(program)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + else + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + } + + Error error = programObject->link(context->getData()); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY PixelStorei(GLenum pname, GLint param) +{ + EVENT("(GLenum pname = 0x%X, GLint param = %d)", pname, param); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + switch (pname) + { + case GL_UNPACK_IMAGE_HEIGHT: + case GL_UNPACK_SKIP_IMAGES: + case GL_UNPACK_ROW_LENGTH: + case GL_UNPACK_SKIP_ROWS: + case GL_UNPACK_SKIP_PIXELS: + case GL_PACK_ROW_LENGTH: + case GL_PACK_SKIP_ROWS: + case GL_PACK_SKIP_PIXELS: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + } + + if (param < 0) + { + context->recordError(Error(GL_INVALID_VALUE, "Cannot use negative values in PixelStorei")); + return; + } + + State &state = context->getState(); + + switch (pname) + { + case GL_UNPACK_ALIGNMENT: + if (param != 1 && param != 2 && param != 4 && param != 8) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + state.setUnpackAlignment(param); + break; + + case GL_PACK_ALIGNMENT: + if (param != 1 && param != 2 && param != 4 && param != 8) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + state.setPackAlignment(param); + break; + + case GL_PACK_REVERSE_ROW_ORDER_ANGLE: + state.setPackReverseRowOrder(param != 0); + break; + + case GL_UNPACK_ROW_LENGTH: + ASSERT(context->getClientVersion() >= 3); + state.setUnpackRowLength(param); + break; + + case GL_UNPACK_IMAGE_HEIGHT: + ASSERT(context->getClientVersion() >= 3); + state.getUnpackState().imageHeight = param; + break; + + case GL_UNPACK_SKIP_IMAGES: + ASSERT(context->getClientVersion() >= 3); + state.getUnpackState().skipImages = param; + break; + + case GL_UNPACK_SKIP_ROWS: + ASSERT(context->getClientVersion() >= 3); + state.getUnpackState().skipRows = param; + break; + + case GL_UNPACK_SKIP_PIXELS: + ASSERT(context->getClientVersion() >= 3); + state.getUnpackState().skipPixels = param; + break; + + case GL_PACK_ROW_LENGTH: + ASSERT(context->getClientVersion() >= 3); + state.getPackState().rowLength = param; + break; + + case GL_PACK_SKIP_ROWS: + ASSERT(context->getClientVersion() >= 3); + state.getPackState().skipRows = param; + break; + + case GL_PACK_SKIP_PIXELS: + ASSERT(context->getClientVersion() >= 3); + state.getPackState().skipPixels = param; + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + } +} + +void GL_APIENTRY PolygonOffset(GLfloat factor, GLfloat units) +{ + EVENT("(GLfloat factor = %f, GLfloat units = %f)", factor, units); + + Context *context = GetValidGlobalContext(); + if (context) + { + context->getState().setPolygonOffsetParams(factor, units); + } +} + +void GL_APIENTRY ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, + GLenum format, GLenum type, GLvoid* pixels) +{ + EVENT("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, " + "GLenum format = 0x%X, GLenum type = 0x%X, GLvoid* pixels = 0x%0.8p)", + x, y, width, height, format, type, pixels); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (width < 0 || height < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + if (!ValidateReadPixelsParameters(context, x, y, width, height, + format, type, NULL, pixels)) + { + return; + } + + Framebuffer *framebufferObject = context->getState().getReadFramebuffer(); + ASSERT(framebufferObject); + + Rectangle area(x, y, width, height); + Error error = framebufferObject->readPixels(context->getState(), area, format, type, pixels); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY ReleaseShaderCompiler(void) +{ + EVENT("()"); + + Context *context = GetValidGlobalContext(); + + if (context) + { + Compiler *compiler = context->getCompiler(); + Error error = compiler->release(); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY RenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height) +{ + EVENT("(GLenum target = 0x%X, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)", + target, internalformat, width, height); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateRenderbufferStorageParametersANGLE(context, target, 0, internalformat, + width, height)) + { + return; + } + + Renderbuffer *renderbuffer = context->getState().getCurrentRenderbuffer(); + Error error = renderbuffer->setStorage(internalformat, width, height); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY SampleCoverage(GLclampf value, GLboolean invert) +{ + EVENT("(GLclampf value = %f, GLboolean invert = %u)", value, invert); + + Context* context = GetValidGlobalContext(); + + if (context) + { + context->getState().setSampleCoverageParams(clamp01(value), invert == GL_TRUE); + } +} + +void GL_APIENTRY Scissor(GLint x, GLint y, GLsizei width, GLsizei height) +{ + EVENT("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height); + + Context* context = GetValidGlobalContext(); + if (context) + { + if (width < 0 || height < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + context->getState().setScissorParams(x, y, width, height); + } +} + +void GL_APIENTRY ShaderBinary(GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length) +{ + EVENT("(GLsizei n = %d, const GLuint* shaders = 0x%0.8p, GLenum binaryformat = 0x%X, " + "const GLvoid* binary = 0x%0.8p, GLsizei length = %d)", + n, shaders, binaryformat, binary, length); + + Context* context = GetValidGlobalContext(); + if (context) + { + const std::vector &shaderBinaryFormats = context->getCaps().shaderBinaryFormats; + if (std::find(shaderBinaryFormats.begin(), shaderBinaryFormats.end(), binaryformat) == shaderBinaryFormats.end()) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + // No binary shader formats are supported. + UNIMPLEMENTED(); + } +} + +void GL_APIENTRY ShaderSource(GLuint shader, GLsizei count, const GLchar* const* string, const GLint* length) +{ + EVENT("(GLuint shader = %d, GLsizei count = %d, const GLchar** string = 0x%0.8p, const GLint* length = 0x%0.8p)", + shader, count, string, length); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (count < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + Shader *shaderObject = context->getShader(shader); + + if (!shaderObject) + { + if (context->getProgram(shader)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + else + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + } + + shaderObject->setSource(count, string, length); + } +} + +void GL_APIENTRY StencilFunc(GLenum func, GLint ref, GLuint mask) +{ + StencilFuncSeparate(GL_FRONT_AND_BACK, func, ref, mask); +} + +void GL_APIENTRY StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask) +{ + EVENT("(GLenum face = 0x%X, GLenum func = 0x%X, GLint ref = %d, GLuint mask = %d)", face, func, ref, mask); + + Context *context = GetValidGlobalContext(); + if (context) + { + switch (face) + { + case GL_FRONT: + case GL_BACK: + case GL_FRONT_AND_BACK: + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + switch (func) + { + case GL_NEVER: + case GL_ALWAYS: + case GL_LESS: + case GL_LEQUAL: + case GL_EQUAL: + case GL_GEQUAL: + case GL_GREATER: + case GL_NOTEQUAL: + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + if (face == GL_FRONT || face == GL_FRONT_AND_BACK) + { + context->getState().setStencilParams(func, ref, mask); + } + + if (face == GL_BACK || face == GL_FRONT_AND_BACK) + { + context->getState().setStencilBackParams(func, ref, mask); + } + } +} + +void GL_APIENTRY StencilMask(GLuint mask) +{ + StencilMaskSeparate(GL_FRONT_AND_BACK, mask); +} + +void GL_APIENTRY StencilMaskSeparate(GLenum face, GLuint mask) +{ + EVENT("(GLenum face = 0x%X, GLuint mask = %d)", face, mask); + + Context *context = GetValidGlobalContext(); + if (context) + { + switch (face) + { + case GL_FRONT: + case GL_BACK: + case GL_FRONT_AND_BACK: + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + if (face == GL_FRONT || face == GL_FRONT_AND_BACK) + { + context->getState().setStencilWritemask(mask); + } + + if (face == GL_BACK || face == GL_FRONT_AND_BACK) + { + context->getState().setStencilBackWritemask(mask); + } + } +} + +void GL_APIENTRY StencilOp(GLenum fail, GLenum zfail, GLenum zpass) +{ + StencilOpSeparate(GL_FRONT_AND_BACK, fail, zfail, zpass); +} + +void GL_APIENTRY StencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass) +{ + EVENT("(GLenum face = 0x%X, GLenum fail = 0x%X, GLenum zfail = 0x%X, GLenum zpas = 0x%Xs)", + face, fail, zfail, zpass); + + Context *context = GetValidGlobalContext(); + if (context) + { + switch (face) + { + case GL_FRONT: + case GL_BACK: + case GL_FRONT_AND_BACK: + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + switch (fail) + { + case GL_ZERO: + case GL_KEEP: + case GL_REPLACE: + case GL_INCR: + case GL_DECR: + case GL_INVERT: + case GL_INCR_WRAP: + case GL_DECR_WRAP: + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + switch (zfail) + { + case GL_ZERO: + case GL_KEEP: + case GL_REPLACE: + case GL_INCR: + case GL_DECR: + case GL_INVERT: + case GL_INCR_WRAP: + case GL_DECR_WRAP: + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + switch (zpass) + { + case GL_ZERO: + case GL_KEEP: + case GL_REPLACE: + case GL_INCR: + case GL_DECR: + case GL_INVERT: + case GL_INCR_WRAP: + case GL_DECR_WRAP: + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + if (face == GL_FRONT || face == GL_FRONT_AND_BACK) + { + context->getState().setStencilOperations(fail, zfail, zpass); + } + + if (face == GL_BACK || face == GL_FRONT_AND_BACK) + { + context->getState().setStencilBackOperations(fail, zfail, zpass); + } + } +} + +void GL_APIENTRY TexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, + GLint border, GLenum format, GLenum type, const GLvoid* pixels) +{ + EVENT("(GLenum target = 0x%X, GLint level = %d, GLint internalformat = %d, GLsizei width = %d, GLsizei height = %d, " + "GLint border = %d, GLenum format = 0x%X, GLenum type = 0x%X, const GLvoid* pixels = 0x%0.8p)", + target, level, internalformat, width, height, border, format, type, pixels); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3 && + !ValidateES2TexImageParameters(context, target, level, internalformat, false, false, + 0, 0, width, height, border, format, type, pixels)) + { + return; + } + + if (context->getClientVersion() >= 3 && + !ValidateES3TexImageParameters(context, target, level, internalformat, false, false, + 0, 0, 0, width, height, 1, border, format, type, pixels)) + { + return; + } + + Extents size(width, height, 1); + Texture *texture = context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target); + Error error = texture->setImage(target, level, internalformat, size, format, type, context->getState().getUnpackState(), + reinterpret_cast(pixels)); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY TexParameterf(GLenum target, GLenum pname, GLfloat param) +{ + EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %f)", target, pname, param); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateTexParamParameters(context, pname, static_cast(param))) + { + return; + } + + Texture *texture = context->getTargetTexture(target); + + if (!texture) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + switch (pname) + { + case GL_TEXTURE_WRAP_S: texture->getSamplerState().wrapS = uiround(param); break; + case GL_TEXTURE_WRAP_T: texture->getSamplerState().wrapT = uiround(param); break; + case GL_TEXTURE_WRAP_R: texture->getSamplerState().wrapR = uiround(param); break; + case GL_TEXTURE_MIN_FILTER: texture->getSamplerState().minFilter = uiround(param); break; + case GL_TEXTURE_MAG_FILTER: texture->getSamplerState().magFilter = uiround(param); break; + case GL_TEXTURE_USAGE_ANGLE: texture->setUsage(uiround(param)); break; + case GL_TEXTURE_MAX_ANISOTROPY_EXT: texture->getSamplerState().maxAnisotropy = std::min(param, context->getExtensions().maxTextureAnisotropy); break; + case GL_TEXTURE_COMPARE_MODE: texture->getSamplerState().compareMode = uiround(param); break; + case GL_TEXTURE_COMPARE_FUNC: texture->getSamplerState().compareFunc = uiround(param); break; + case GL_TEXTURE_SWIZZLE_R: texture->getSamplerState().swizzleRed = uiround(param); break; + case GL_TEXTURE_SWIZZLE_G: texture->getSamplerState().swizzleGreen = uiround(param); break; + case GL_TEXTURE_SWIZZLE_B: texture->getSamplerState().swizzleBlue = uiround(param); break; + case GL_TEXTURE_SWIZZLE_A: texture->getSamplerState().swizzleAlpha = uiround(param); break; + case GL_TEXTURE_BASE_LEVEL: texture->getSamplerState().baseLevel = iround(param); break; + case GL_TEXTURE_MAX_LEVEL: texture->getSamplerState().maxLevel = iround(param); break; + case GL_TEXTURE_MIN_LOD: texture->getSamplerState().minLod = param; break; + case GL_TEXTURE_MAX_LOD: texture->getSamplerState().maxLod = param; break; + default: UNREACHABLE(); break; + } + } +} + +void GL_APIENTRY TexParameterfv(GLenum target, GLenum pname, const GLfloat* params) +{ + TexParameterf(target, pname, (GLfloat)*params); +} + +void GL_APIENTRY TexParameteri(GLenum target, GLenum pname, GLint param) +{ + EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %d)", target, pname, param); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateTexParamParameters(context, pname, param)) + { + return; + } + + Texture *texture = context->getTargetTexture(target); + + if (!texture) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + switch (pname) + { + case GL_TEXTURE_WRAP_S: texture->getSamplerState().wrapS = (GLenum)param; break; + case GL_TEXTURE_WRAP_T: texture->getSamplerState().wrapT = (GLenum)param; break; + case GL_TEXTURE_WRAP_R: texture->getSamplerState().wrapR = (GLenum)param; break; + case GL_TEXTURE_MIN_FILTER: texture->getSamplerState().minFilter = (GLenum)param; break; + case GL_TEXTURE_MAG_FILTER: texture->getSamplerState().magFilter = (GLenum)param; break; + case GL_TEXTURE_USAGE_ANGLE: texture->setUsage((GLenum)param); break; + case GL_TEXTURE_MAX_ANISOTROPY_EXT: texture->getSamplerState().maxAnisotropy = std::min((float)param, context->getExtensions().maxTextureAnisotropy); break; + case GL_TEXTURE_COMPARE_MODE: texture->getSamplerState().compareMode = (GLenum)param; break; + case GL_TEXTURE_COMPARE_FUNC: texture->getSamplerState().compareFunc = (GLenum)param; break; + case GL_TEXTURE_SWIZZLE_R: texture->getSamplerState().swizzleRed = (GLenum)param; break; + case GL_TEXTURE_SWIZZLE_G: texture->getSamplerState().swizzleGreen = (GLenum)param; break; + case GL_TEXTURE_SWIZZLE_B: texture->getSamplerState().swizzleBlue = (GLenum)param; break; + case GL_TEXTURE_SWIZZLE_A: texture->getSamplerState().swizzleAlpha = (GLenum)param; break; + case GL_TEXTURE_BASE_LEVEL: texture->getSamplerState().baseLevel = param; break; + case GL_TEXTURE_MAX_LEVEL: texture->getSamplerState().maxLevel = param; break; + case GL_TEXTURE_MIN_LOD: texture->getSamplerState().minLod = (GLfloat)param; break; + case GL_TEXTURE_MAX_LOD: texture->getSamplerState().maxLod = (GLfloat)param; break; + default: UNREACHABLE(); break; + } + } +} + +void GL_APIENTRY TexParameteriv(GLenum target, GLenum pname, const GLint* params) +{ + TexParameteri(target, pname, *params); +} + +void GL_APIENTRY TexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + GLenum format, GLenum type, const GLvoid* pixels) +{ + EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, " + "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, GLenum type = 0x%X, " + "const GLvoid* pixels = 0x%0.8p)", + target, level, xoffset, yoffset, width, height, format, type, pixels); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3 && + !ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, + xoffset, yoffset, width, height, 0, format, type, pixels)) + { + return; + } + + if (context->getClientVersion() >= 3 && + !ValidateES3TexImageParameters(context, target, level, GL_NONE, false, true, + xoffset, yoffset, 0, width, height, 1, 0, format, type, pixels)) + { + return; + } + + // Zero sized uploads are valid but no-ops + if (width == 0 || height == 0) + { + return; + } + + Box area(xoffset, yoffset, 0, width, height, 1); + Texture *texture = context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target); + Error error = texture->setSubImage(target, level, area, format, type, context->getState().getUnpackState(), + reinterpret_cast(pixels)); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY Uniform1f(GLint location, GLfloat x) +{ + Uniform1fv(location, 1, &x); +} + +void GL_APIENTRY Uniform1fv(GLint location, GLsizei count, const GLfloat* v) +{ + EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateUniform(context, GL_FLOAT, location, count)) + { + return; + } + + Program *program = context->getState().getProgram(); + program->setUniform1fv(location, count, v); + } +} + +void GL_APIENTRY Uniform1i(GLint location, GLint x) +{ + Uniform1iv(location, 1, &x); +} + +void GL_APIENTRY Uniform1iv(GLint location, GLsizei count, const GLint* v) +{ + EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateUniform(context, GL_INT, location, count)) + { + return; + } + + Program *program = context->getState().getProgram(); + program->setUniform1iv(location, count, v); + } +} + +void GL_APIENTRY Uniform2f(GLint location, GLfloat x, GLfloat y) +{ + GLfloat xy[2] = {x, y}; + + Uniform2fv(location, 1, xy); +} + +void GL_APIENTRY Uniform2fv(GLint location, GLsizei count, const GLfloat* v) +{ + EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateUniform(context, GL_FLOAT_VEC2, location, count)) + { + return; + } + + Program *program = context->getState().getProgram(); + program->setUniform2fv(location, count, v); + } +} + +void GL_APIENTRY Uniform2i(GLint location, GLint x, GLint y) +{ + GLint xy[2] = {x, y}; + + Uniform2iv(location, 1, xy); +} + +void GL_APIENTRY Uniform2iv(GLint location, GLsizei count, const GLint* v) +{ + EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateUniform(context, GL_INT_VEC2, location, count)) + { + return; + } + + Program *program = context->getState().getProgram(); + program->setUniform2iv(location, count, v); + } +} + +void GL_APIENTRY Uniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z) +{ + GLfloat xyz[3] = {x, y, z}; + + Uniform3fv(location, 1, xyz); +} + +void GL_APIENTRY Uniform3fv(GLint location, GLsizei count, const GLfloat* v) +{ + EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateUniform(context, GL_FLOAT_VEC3, location, count)) + { + return; + } + + Program *program = context->getState().getProgram(); + program->setUniform3fv(location, count, v); + } +} + +void GL_APIENTRY Uniform3i(GLint location, GLint x, GLint y, GLint z) +{ + GLint xyz[3] = {x, y, z}; + + Uniform3iv(location, 1, xyz); +} + +void GL_APIENTRY Uniform3iv(GLint location, GLsizei count, const GLint* v) +{ + EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateUniform(context, GL_INT_VEC3, location, count)) + { + return; + } + + Program *program = context->getState().getProgram(); + program->setUniform3iv(location, count, v); + } +} + +void GL_APIENTRY Uniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + GLfloat xyzw[4] = {x, y, z, w}; + + Uniform4fv(location, 1, xyzw); +} + +void GL_APIENTRY Uniform4fv(GLint location, GLsizei count, const GLfloat* v) +{ + EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateUniform(context, GL_FLOAT_VEC4, location, count)) + { + return; + } + + Program *program = context->getState().getProgram(); + program->setUniform4fv(location, count, v); + } +} + +void GL_APIENTRY Uniform4i(GLint location, GLint x, GLint y, GLint z, GLint w) +{ + GLint xyzw[4] = {x, y, z, w}; + + Uniform4iv(location, 1, xyzw); +} + +void GL_APIENTRY Uniform4iv(GLint location, GLsizei count, const GLint* v) +{ + EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateUniform(context, GL_INT_VEC4, location, count)) + { + return; + } + + Program *program = context->getState().getProgram(); + program->setUniform4iv(location, count, v); + } +} + +void GL_APIENTRY UniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +{ + EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)", + location, count, transpose, value); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateUniformMatrix(context, GL_FLOAT_MAT2, location, count, transpose)) + { + return; + } + + Program *program = context->getState().getProgram(); + program->setUniformMatrix2fv(location, count, transpose, value); + } +} + +void GL_APIENTRY UniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +{ + EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)", + location, count, transpose, value); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateUniformMatrix(context, GL_FLOAT_MAT3, location, count, transpose)) + { + return; + } + + Program *program = context->getState().getProgram(); + program->setUniformMatrix3fv(location, count, transpose, value); + } +} + +void GL_APIENTRY UniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +{ + EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)", + location, count, transpose, value); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateUniformMatrix(context, GL_FLOAT_MAT4, location, count, transpose)) + { + return; + } + + Program *program = context->getState().getProgram(); + program->setUniformMatrix4fv(location, count, transpose, value); + } +} + +void GL_APIENTRY UseProgram(GLuint program) +{ + EVENT("(GLuint program = %d)", program); + + Context *context = GetValidGlobalContext(); + if (context) + { + Program *programObject = context->getProgram(program); + + if (!programObject && program != 0) + { + if (context->getShader(program)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + else + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + } + + if (program != 0 && !programObject->isLinked()) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + context->useProgram(program); + } +} + +void GL_APIENTRY ValidateProgram(GLuint program) +{ + EVENT("(GLuint program = %d)", program); + + Context *context = GetValidGlobalContext(); + if (context) + { + Program *programObject = context->getProgram(program); + + if (!programObject) + { + if (context->getShader(program)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + else + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + } + + programObject->validate(context->getCaps()); + } +} + +void GL_APIENTRY VertexAttrib1f(GLuint index, GLfloat x) +{ + EVENT("(GLuint index = %d, GLfloat x = %f)", index, x); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (index >= MAX_VERTEX_ATTRIBS) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + GLfloat vals[4] = { x, 0, 0, 1 }; + context->getState().setVertexAttribf(index, vals); + } +} + +void GL_APIENTRY VertexAttrib1fv(GLuint index, const GLfloat* values) +{ + EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (index >= MAX_VERTEX_ATTRIBS) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + GLfloat vals[4] = { values[0], 0, 0, 1 }; + context->getState().setVertexAttribf(index, vals); + } +} + +void GL_APIENTRY VertexAttrib2f(GLuint index, GLfloat x, GLfloat y) +{ + EVENT("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f)", index, x, y); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (index >= MAX_VERTEX_ATTRIBS) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + GLfloat vals[4] = { x, y, 0, 1 }; + context->getState().setVertexAttribf(index, vals); + } +} + +void GL_APIENTRY VertexAttrib2fv(GLuint index, const GLfloat* values) +{ + EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (index >= MAX_VERTEX_ATTRIBS) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + GLfloat vals[4] = { values[0], values[1], 0, 1 }; + context->getState().setVertexAttribf(index, vals); + } +} + +void GL_APIENTRY VertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z) +{ + EVENT("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f)", index, x, y, z); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (index >= MAX_VERTEX_ATTRIBS) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + GLfloat vals[4] = { x, y, z, 1 }; + context->getState().setVertexAttribf(index, vals); + } +} + +void GL_APIENTRY VertexAttrib3fv(GLuint index, const GLfloat* values) +{ + EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (index >= MAX_VERTEX_ATTRIBS) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + GLfloat vals[4] = { values[0], values[1], values[2], 1 }; + context->getState().setVertexAttribf(index, vals); + } +} + +void GL_APIENTRY VertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + EVENT("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f, GLfloat w = %f)", index, x, y, z, w); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (index >= MAX_VERTEX_ATTRIBS) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + GLfloat vals[4] = { x, y, z, w }; + context->getState().setVertexAttribf(index, vals); + } +} + +void GL_APIENTRY VertexAttrib4fv(GLuint index, const GLfloat* values) +{ + EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (index >= MAX_VERTEX_ATTRIBS) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + context->getState().setVertexAttribf(index, values); + } +} + +void GL_APIENTRY VertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr) +{ + EVENT("(GLuint index = %d, GLint size = %d, GLenum type = 0x%X, " + "GLboolean normalized = %u, GLsizei stride = %d, const GLvoid* ptr = 0x%0.8p)", + index, size, type, normalized, stride, ptr); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (index >= MAX_VERTEX_ATTRIBS) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + if (size < 1 || size > 4) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + switch (type) + { + case GL_BYTE: + case GL_UNSIGNED_BYTE: + case GL_SHORT: + case GL_UNSIGNED_SHORT: + case GL_FIXED: + case GL_FLOAT: + break; + + case GL_HALF_FLOAT: + case GL_INT: + case GL_UNSIGNED_INT: + case GL_INT_2_10_10_10_REV: + case GL_UNSIGNED_INT_2_10_10_10_REV: + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + if (stride < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + if ((type == GL_INT_2_10_10_10_REV || type == GL_UNSIGNED_INT_2_10_10_10_REV) && size != 4) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + // [OpenGL ES 3.0.2] Section 2.8 page 24: + // An INVALID_OPERATION error is generated when a non-zero vertex array object + // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point, + // and the pointer argument is not NULL. + if (context->getState().getVertexArray()->id() != 0 && context->getState().getArrayBufferId() == 0 && ptr != NULL) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + context->getState().setVertexAttribState(index, context->getState().getTargetBuffer(GL_ARRAY_BUFFER), size, type, + normalized == GL_TRUE, false, stride, ptr); + } +} + +void GL_APIENTRY Viewport(GLint x, GLint y, GLsizei width, GLsizei height) +{ + EVENT("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (width < 0 || height < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + context->getState().setViewportParams(x, y, width, height); + } +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/entry_points_gles_2_0.h b/src/3rdparty/angle/src/libGLESv2/entry_points_gles_2_0.h new file mode 100644 index 0000000000..eee5fb5468 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/entry_points_gles_2_0.h @@ -0,0 +1,163 @@ +// +// Copyright(c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// entry_points_gles_2_0.h : Defines the GLES 2.0 entry points. + +#ifndef LIBGLESV2_ENTRYPOINTGLES20_H_ +#define LIBGLESV2_ENTRYPOINTGLES20_H_ + +#include +#include + +namespace gl +{ + +ANGLE_EXPORT void GL_APIENTRY ActiveTexture(GLenum texture); +ANGLE_EXPORT void GL_APIENTRY AttachShader(GLuint program, GLuint shader); +ANGLE_EXPORT void GL_APIENTRY BindAttribLocation(GLuint program, GLuint index, const GLchar* name); +ANGLE_EXPORT void GL_APIENTRY BindBuffer(GLenum target, GLuint buffer); +ANGLE_EXPORT void GL_APIENTRY BindFramebuffer(GLenum target, GLuint framebuffer); +ANGLE_EXPORT void GL_APIENTRY BindRenderbuffer(GLenum target, GLuint renderbuffer); +ANGLE_EXPORT void GL_APIENTRY BindTexture(GLenum target, GLuint texture); +ANGLE_EXPORT void GL_APIENTRY BlendColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +ANGLE_EXPORT void GL_APIENTRY BlendEquation(GLenum mode); +ANGLE_EXPORT void GL_APIENTRY BlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha); +ANGLE_EXPORT void GL_APIENTRY BlendFunc(GLenum sfactor, GLenum dfactor); +ANGLE_EXPORT void GL_APIENTRY BlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); +ANGLE_EXPORT void GL_APIENTRY BufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage); +ANGLE_EXPORT void GL_APIENTRY BufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data); +ANGLE_EXPORT GLenum GL_APIENTRY CheckFramebufferStatus(GLenum target); +ANGLE_EXPORT void GL_APIENTRY Clear(GLbitfield mask); +ANGLE_EXPORT void GL_APIENTRY ClearColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +ANGLE_EXPORT void GL_APIENTRY ClearDepthf(GLfloat depth); +ANGLE_EXPORT void GL_APIENTRY ClearStencil(GLint s); +ANGLE_EXPORT void GL_APIENTRY ColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); +ANGLE_EXPORT void GL_APIENTRY CompileShader(GLuint shader); +ANGLE_EXPORT void GL_APIENTRY CompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data); +ANGLE_EXPORT void GL_APIENTRY CompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data); +ANGLE_EXPORT void GL_APIENTRY CopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +ANGLE_EXPORT void GL_APIENTRY CopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +ANGLE_EXPORT GLuint GL_APIENTRY CreateProgram(void); +ANGLE_EXPORT GLuint GL_APIENTRY CreateShader(GLenum type); +ANGLE_EXPORT void GL_APIENTRY CullFace(GLenum mode); +ANGLE_EXPORT void GL_APIENTRY DeleteBuffers(GLsizei n, const GLuint* buffers); +ANGLE_EXPORT void GL_APIENTRY DeleteFramebuffers(GLsizei n, const GLuint* framebuffers); +ANGLE_EXPORT void GL_APIENTRY DeleteProgram(GLuint program); +ANGLE_EXPORT void GL_APIENTRY DeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers); +ANGLE_EXPORT void GL_APIENTRY DeleteShader(GLuint shader); +ANGLE_EXPORT void GL_APIENTRY DeleteTextures(GLsizei n, const GLuint* textures); +ANGLE_EXPORT void GL_APIENTRY DepthFunc(GLenum func); +ANGLE_EXPORT void GL_APIENTRY DepthMask(GLboolean flag); +ANGLE_EXPORT void GL_APIENTRY DepthRangef(GLfloat n, GLfloat f); +ANGLE_EXPORT void GL_APIENTRY DetachShader(GLuint program, GLuint shader); +ANGLE_EXPORT void GL_APIENTRY Disable(GLenum cap); +ANGLE_EXPORT void GL_APIENTRY DisableVertexAttribArray(GLuint index); +ANGLE_EXPORT void GL_APIENTRY DrawArrays(GLenum mode, GLint first, GLsizei count); +ANGLE_EXPORT void GL_APIENTRY DrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices); +ANGLE_EXPORT void GL_APIENTRY Enable(GLenum cap); +ANGLE_EXPORT void GL_APIENTRY EnableVertexAttribArray(GLuint index); +ANGLE_EXPORT void GL_APIENTRY Finish(void); +ANGLE_EXPORT void GL_APIENTRY Flush(void); +ANGLE_EXPORT void GL_APIENTRY FramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); +ANGLE_EXPORT void GL_APIENTRY FramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +ANGLE_EXPORT void GL_APIENTRY FrontFace(GLenum mode); +ANGLE_EXPORT void GL_APIENTRY GenBuffers(GLsizei n, GLuint* buffers); +ANGLE_EXPORT void GL_APIENTRY GenerateMipmap(GLenum target); +ANGLE_EXPORT void GL_APIENTRY GenFramebuffers(GLsizei n, GLuint* framebuffers); +ANGLE_EXPORT void GL_APIENTRY GenRenderbuffers(GLsizei n, GLuint* renderbuffers); +ANGLE_EXPORT void GL_APIENTRY GenTextures(GLsizei n, GLuint* textures); +ANGLE_EXPORT void GL_APIENTRY GetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name); +ANGLE_EXPORT void GL_APIENTRY GetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name); +ANGLE_EXPORT void GL_APIENTRY GetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders); +ANGLE_EXPORT GLint GL_APIENTRY GetAttribLocation(GLuint program, const GLchar* name); +ANGLE_EXPORT void GL_APIENTRY GetBooleanv(GLenum pname, GLboolean* params); +ANGLE_EXPORT void GL_APIENTRY GetBufferParameteriv(GLenum target, GLenum pname, GLint* params); +ANGLE_EXPORT GLenum GL_APIENTRY GetError(void); +ANGLE_EXPORT void GL_APIENTRY GetFloatv(GLenum pname, GLfloat* params); +ANGLE_EXPORT void GL_APIENTRY GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params); +ANGLE_EXPORT void GL_APIENTRY GetIntegerv(GLenum pname, GLint* params); +ANGLE_EXPORT void GL_APIENTRY GetProgramiv(GLuint program, GLenum pname, GLint* params); +ANGLE_EXPORT void GL_APIENTRY GetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog); +ANGLE_EXPORT void GL_APIENTRY GetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params); +ANGLE_EXPORT void GL_APIENTRY GetShaderiv(GLuint shader, GLenum pname, GLint* params); +ANGLE_EXPORT void GL_APIENTRY GetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog); +ANGLE_EXPORT void GL_APIENTRY GetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision); +ANGLE_EXPORT void GL_APIENTRY GetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source); +ANGLE_EXPORT const GLubyte *GL_APIENTRY GetString(GLenum name); +ANGLE_EXPORT void GL_APIENTRY GetTexParameterfv(GLenum target, GLenum pname, GLfloat* params); +ANGLE_EXPORT void GL_APIENTRY GetTexParameteriv(GLenum target, GLenum pname, GLint* params); +ANGLE_EXPORT void GL_APIENTRY GetUniformfv(GLuint program, GLint location, GLfloat* params); +ANGLE_EXPORT void GL_APIENTRY GetUniformiv(GLuint program, GLint location, GLint* params); +ANGLE_EXPORT GLint GL_APIENTRY GetUniformLocation(GLuint program, const GLchar* name); +ANGLE_EXPORT void GL_APIENTRY GetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params); +ANGLE_EXPORT void GL_APIENTRY GetVertexAttribiv(GLuint index, GLenum pname, GLint* params); +ANGLE_EXPORT void GL_APIENTRY GetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid** pointer); +ANGLE_EXPORT void GL_APIENTRY Hint(GLenum target, GLenum mode); +ANGLE_EXPORT GLboolean GL_APIENTRY IsBuffer(GLuint buffer); +ANGLE_EXPORT GLboolean GL_APIENTRY IsEnabled(GLenum cap); +ANGLE_EXPORT GLboolean GL_APIENTRY IsFramebuffer(GLuint framebuffer); +ANGLE_EXPORT GLboolean GL_APIENTRY IsProgram(GLuint program); +ANGLE_EXPORT GLboolean GL_APIENTRY IsRenderbuffer(GLuint renderbuffer); +ANGLE_EXPORT GLboolean GL_APIENTRY IsShader(GLuint shader); +ANGLE_EXPORT GLboolean GL_APIENTRY IsTexture(GLuint texture); +ANGLE_EXPORT void GL_APIENTRY LineWidth(GLfloat width); +ANGLE_EXPORT void GL_APIENTRY LinkProgram(GLuint program); +ANGLE_EXPORT void GL_APIENTRY PixelStorei(GLenum pname, GLint param); +ANGLE_EXPORT void GL_APIENTRY PolygonOffset(GLfloat factor, GLfloat units); +ANGLE_EXPORT void GL_APIENTRY ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels); +ANGLE_EXPORT void GL_APIENTRY ReleaseShaderCompiler(void); +ANGLE_EXPORT void GL_APIENTRY RenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height); +ANGLE_EXPORT void GL_APIENTRY SampleCoverage(GLfloat value, GLboolean invert); +ANGLE_EXPORT void GL_APIENTRY Scissor(GLint x, GLint y, GLsizei width, GLsizei height); +ANGLE_EXPORT void GL_APIENTRY ShaderBinary(GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length); +ANGLE_EXPORT void GL_APIENTRY ShaderSource(GLuint shader, GLsizei count, const GLchar* const* string, const GLint* length); +ANGLE_EXPORT void GL_APIENTRY StencilFunc(GLenum func, GLint ref, GLuint mask); +ANGLE_EXPORT void GL_APIENTRY StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask); +ANGLE_EXPORT void GL_APIENTRY StencilMask(GLuint mask); +ANGLE_EXPORT void GL_APIENTRY StencilMaskSeparate(GLenum face, GLuint mask); +ANGLE_EXPORT void GL_APIENTRY StencilOp(GLenum fail, GLenum zfail, GLenum zpass); +ANGLE_EXPORT void GL_APIENTRY StencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass); +ANGLE_EXPORT void GL_APIENTRY TexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels); +ANGLE_EXPORT void GL_APIENTRY TexParameterf(GLenum target, GLenum pname, GLfloat param); +ANGLE_EXPORT void GL_APIENTRY TexParameterfv(GLenum target, GLenum pname, const GLfloat* params); +ANGLE_EXPORT void GL_APIENTRY TexParameteri(GLenum target, GLenum pname, GLint param); +ANGLE_EXPORT void GL_APIENTRY TexParameteriv(GLenum target, GLenum pname, const GLint* params); +ANGLE_EXPORT void GL_APIENTRY TexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels); +ANGLE_EXPORT void GL_APIENTRY Uniform1f(GLint location, GLfloat x); +ANGLE_EXPORT void GL_APIENTRY Uniform1fv(GLint location, GLsizei count, const GLfloat* v); +ANGLE_EXPORT void GL_APIENTRY Uniform1i(GLint location, GLint x); +ANGLE_EXPORT void GL_APIENTRY Uniform1iv(GLint location, GLsizei count, const GLint* v); +ANGLE_EXPORT void GL_APIENTRY Uniform2f(GLint location, GLfloat x, GLfloat y); +ANGLE_EXPORT void GL_APIENTRY Uniform2fv(GLint location, GLsizei count, const GLfloat* v); +ANGLE_EXPORT void GL_APIENTRY Uniform2i(GLint location, GLint x, GLint y); +ANGLE_EXPORT void GL_APIENTRY Uniform2iv(GLint location, GLsizei count, const GLint* v); +ANGLE_EXPORT void GL_APIENTRY Uniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z); +ANGLE_EXPORT void GL_APIENTRY Uniform3fv(GLint location, GLsizei count, const GLfloat* v); +ANGLE_EXPORT void GL_APIENTRY Uniform3i(GLint location, GLint x, GLint y, GLint z); +ANGLE_EXPORT void GL_APIENTRY Uniform3iv(GLint location, GLsizei count, const GLint* v); +ANGLE_EXPORT void GL_APIENTRY Uniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +ANGLE_EXPORT void GL_APIENTRY Uniform4fv(GLint location, GLsizei count, const GLfloat* v); +ANGLE_EXPORT void GL_APIENTRY Uniform4i(GLint location, GLint x, GLint y, GLint z, GLint w); +ANGLE_EXPORT void GL_APIENTRY Uniform4iv(GLint location, GLsizei count, const GLint* v); +ANGLE_EXPORT void GL_APIENTRY UniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +ANGLE_EXPORT void GL_APIENTRY UniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +ANGLE_EXPORT void GL_APIENTRY UniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +ANGLE_EXPORT void GL_APIENTRY UseProgram(GLuint program); +ANGLE_EXPORT void GL_APIENTRY ValidateProgram(GLuint program); +ANGLE_EXPORT void GL_APIENTRY VertexAttrib1f(GLuint indx, GLfloat x); +ANGLE_EXPORT void GL_APIENTRY VertexAttrib1fv(GLuint indx, const GLfloat* values); +ANGLE_EXPORT void GL_APIENTRY VertexAttrib2f(GLuint indx, GLfloat x, GLfloat y); +ANGLE_EXPORT void GL_APIENTRY VertexAttrib2fv(GLuint indx, const GLfloat* values); +ANGLE_EXPORT void GL_APIENTRY VertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z); +ANGLE_EXPORT void GL_APIENTRY VertexAttrib3fv(GLuint indx, const GLfloat* values); +ANGLE_EXPORT void GL_APIENTRY VertexAttrib4f(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +ANGLE_EXPORT void GL_APIENTRY VertexAttrib4fv(GLuint indx, const GLfloat* values); +ANGLE_EXPORT void GL_APIENTRY VertexAttribPointer(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr); +ANGLE_EXPORT void GL_APIENTRY Viewport(GLint x, GLint y, GLsizei width, GLsizei height); + +} + +#endif // LIBGLESV2_ENTRYPOINTGLES20_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/entry_points_gles_2_0_ext.cpp b/src/3rdparty/angle/src/libGLESv2/entry_points_gles_2_0_ext.cpp new file mode 100644 index 0000000000..8be6ae7d2f --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/entry_points_gles_2_0_ext.cpp @@ -0,0 +1,1058 @@ +// +// Copyright(c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// entry_points_gles_2_0_ext.cpp : Implements the GLES 2.0 extension entry points. + +#include "libGLESv2/entry_points_gles_2_0_ext.h" +#include "libGLESv2/global_state.h" + +#include "libANGLE/Buffer.h" +#include "libANGLE/Context.h" +#include "libANGLE/Error.h" +#include "libANGLE/Fence.h" +#include "libANGLE/Framebuffer.h" +#include "libANGLE/Shader.h" +#include "libANGLE/Query.h" + +#include "libANGLE/validationES.h" +#include "libANGLE/validationES2.h" +#include "libANGLE/validationES3.h" + +#include "common/debug.h" +#include "common/utilities.h" + +namespace gl +{ + +void GL_APIENTRY BeginQueryEXT(GLenum target, GLuint id) +{ + EVENT("(GLenum target = 0x%X, GLuint %d)", target, id); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateBeginQuery(context, target, id)) + { + return; + } + + Error error = context->beginQuery(target, id); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY DeleteFencesNV(GLsizei n, const GLuint* fences) +{ + EVENT("(GLsizei n = %d, const GLuint* fences = 0x%0.8p)", n, fences); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (n < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + for (int i = 0; i < n; i++) + { + context->deleteFenceNV(fences[i]); + } + } +} + +void GL_APIENTRY DeleteQueriesEXT(GLsizei n, const GLuint *ids) +{ + EVENT("(GLsizei n = %d, const GLuint *ids = 0x%0.8p)", n, ids); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (n < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + for (int i = 0; i < n; i++) + { + context->deleteQuery(ids[i]); + } + } +} + +void GL_APIENTRY DrawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei count, GLsizei primcount) +{ + EVENT("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d, GLsizei primcount = %d)", mode, first, count, primcount); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateDrawArraysInstancedANGLE(context, mode, first, count, primcount)) + { + return; + } + + Error error = context->drawArrays(mode, first, count, primcount); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY DrawElementsInstancedANGLE(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount) +{ + EVENT("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = 0x%0.8p, GLsizei primcount = %d)", + mode, count, type, indices, primcount); + + Context *context = GetValidGlobalContext(); + if (context) + { + rx::RangeUI indexRange; + if (!ValidateDrawElementsInstancedANGLE(context, mode, count, type, indices, primcount, &indexRange)) + { + return; + } + + Error error = context->drawElements(mode, count, type, indices, primcount, indexRange); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY EndQueryEXT(GLenum target) +{ + EVENT("GLenum target = 0x%X)", target); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateEndQuery(context, target)) + { + return; + } + + Error error = context->endQuery(target); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY FinishFenceNV(GLuint fence) +{ + EVENT("(GLuint fence = %d)", fence); + + Context *context = GetValidGlobalContext(); + if (context) + { + FenceNV *fenceObject = context->getFenceNV(fence); + + if (fenceObject == NULL) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (fenceObject->isFence() != GL_TRUE) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + fenceObject->finishFence(); + } +} + +void GL_APIENTRY GenFencesNV(GLsizei n, GLuint* fences) +{ + EVENT("(GLsizei n = %d, GLuint* fences = 0x%0.8p)", n, fences); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (n < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + for (int i = 0; i < n; i++) + { + fences[i] = context->createFenceNV(); + } + } +} + +void GL_APIENTRY GenQueriesEXT(GLsizei n, GLuint* ids) +{ + EVENT("(GLsizei n = %d, GLuint* ids = 0x%0.8p)", n, ids); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (n < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + for (GLsizei i = 0; i < n; i++) + { + ids[i] = context->createQuery(); + } + } +} + +void GL_APIENTRY GetFenceivNV(GLuint fence, GLenum pname, GLint *params) +{ + EVENT("(GLuint fence = %d, GLenum pname = 0x%X, GLint *params = 0x%0.8p)", fence, pname, params); + + Context *context = GetValidGlobalContext(); + if (context) + { + FenceNV *fenceObject = context->getFenceNV(fence); + + if (fenceObject == NULL) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (fenceObject->isFence() != GL_TRUE) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + 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. + GLboolean status = GL_TRUE; + if (fenceObject->getStatus() != GL_TRUE) + { + Error error = fenceObject->testFence(&status); + if (error.isError()) + { + context->recordError(error); + return; + } + } + *params = status; + break; + } + + case GL_FENCE_CONDITION_NV: + { + *params = static_cast(fenceObject->getCondition()); + break; + } + + default: + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + } + } +} + +GLenum GL_APIENTRY GetGraphicsResetStatusEXT(void) +{ + EVENT("()"); + + Context *context = GetGlobalContext(); + + if (context) + { + return context->getResetStatus(); + } + + return GL_NO_ERROR; +} + +void GL_APIENTRY GetQueryivEXT(GLenum target, GLenum pname, GLint *params) +{ + EVENT("GLenum target = 0x%X, GLenum pname = 0x%X, GLint *params = 0x%0.8p)", target, pname, params); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidQueryType(context, target)) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + switch (pname) + { + case GL_CURRENT_QUERY_EXT: + params[0] = context->getState().getActiveQueryId(target); + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + } +} + +void GL_APIENTRY GetQueryObjectuivEXT(GLuint id, GLenum pname, GLuint *params) +{ + EVENT("(GLuint id = %d, GLenum pname = 0x%X, GLuint *params = 0x%0.8p)", id, pname, params); + + Context *context = GetValidGlobalContext(); + if (context) + { + Query *queryObject = context->getQuery(id, false, GL_NONE); + + if (!queryObject) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (context->getState().getActiveQueryId(queryObject->getType()) == id) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + switch(pname) + { + case GL_QUERY_RESULT_EXT: + { + Error error = queryObject->getResult(params); + if (error.isError()) + { + context->recordError(error); + return; + } + } + break; + + case GL_QUERY_RESULT_AVAILABLE_EXT: + { + Error error = queryObject->isResultAvailable(params); + if (error.isError()) + { + context->recordError(error); + return; + } + } + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + } +} + +void GL_APIENTRY GetTranslatedShaderSourceANGLE(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source) +{ + EVENT("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* source = 0x%0.8p)", + shader, bufsize, length, source); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (bufsize < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + Shader *shaderObject = context->getShader(shader); + + if (!shaderObject) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + // Only returns extra info if ANGLE_GENERATE_SHADER_DEBUG_INFO is defined + shaderObject->getTranslatedSourceWithDebugInfo(bufsize, length, source); + } +} + +void GL_APIENTRY GetnUniformfvEXT(GLuint program, GLint location, GLsizei bufSize, GLfloat* params) +{ + EVENT("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLfloat* params = 0x%0.8p)", + program, location, bufSize, params); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateGetnUniformfvEXT(context, program, location, bufSize, params)) + { + return; + } + + Program *programObject = context->getProgram(program); + ASSERT(programObject); + + programObject->getUniformfv(location, params); + } +} + +void GL_APIENTRY GetnUniformivEXT(GLuint program, GLint location, GLsizei bufSize, GLint* params) +{ + EVENT("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLint* params = 0x%0.8p)", + program, location, bufSize, params); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateGetnUniformivEXT(context, program, location, bufSize, params)) + { + return; + } + + Program *programObject = context->getProgram(program); + ASSERT(programObject); + + programObject->getUniformiv(location, params); + } +} + +GLboolean GL_APIENTRY IsFenceNV(GLuint fence) +{ + EVENT("(GLuint fence = %d)", fence); + + Context *context = GetValidGlobalContext(); + if (context) + { + FenceNV *fenceObject = context->getFenceNV(fence); + + if (fenceObject == NULL) + { + return GL_FALSE; + } + + return fenceObject->isFence(); + } + + return GL_FALSE; +} + +GLboolean GL_APIENTRY IsQueryEXT(GLuint id) +{ + EVENT("(GLuint id = %d)", id); + + Context *context = GetValidGlobalContext(); + if (context) + { + return (context->getQuery(id, false, GL_NONE) != NULL) ? GL_TRUE : GL_FALSE; + } + + return GL_FALSE; +} + +void GL_APIENTRY ReadnPixelsEXT(GLint x, GLint y, GLsizei width, GLsizei height, + GLenum format, GLenum type, GLsizei bufSize, + GLvoid *data) +{ + EVENT("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, " + "GLenum format = 0x%X, GLenum type = 0x%X, GLsizei bufSize = 0x%d, GLvoid *data = 0x%0.8p)", + x, y, width, height, format, type, bufSize, data); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (width < 0 || height < 0 || bufSize < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + if (!ValidateReadPixelsParameters(context, x, y, width, height, + format, type, &bufSize, data)) + { + return; + } + + Framebuffer *framebufferObject = context->getState().getReadFramebuffer(); + ASSERT(framebufferObject); + + Rectangle area(x, y, width, height); + Error error = framebufferObject->readPixels(context->getState(), area, format, type, data); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY RenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height) +{ + EVENT("(GLenum target = 0x%X, GLsizei samples = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)", + target, samples, internalformat, width, height); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateRenderbufferStorageParametersANGLE(context, target, samples, internalformat, + width, height)) + { + return; + } + + Renderbuffer *renderbuffer = context->getState().getCurrentRenderbuffer(); + Error error = renderbuffer->setStorageMultisample(samples, internalformat, width, height); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY SetFenceNV(GLuint fence, GLenum condition) +{ + EVENT("(GLuint fence = %d, GLenum condition = 0x%X)", fence, condition); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (condition != GL_ALL_COMPLETED_NV) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + FenceNV *fenceObject = context->getFenceNV(fence); + + if (fenceObject == NULL) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + Error error = fenceObject->setFence(condition); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +GLboolean GL_APIENTRY TestFenceNV(GLuint fence) +{ + EVENT("(GLuint fence = %d)", fence); + + Context *context = GetValidGlobalContext(); + if (context) + { + FenceNV *fenceObject = context->getFenceNV(fence); + + if (fenceObject == NULL) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return GL_TRUE; + } + + if (fenceObject->isFence() != GL_TRUE) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return GL_TRUE; + } + + GLboolean result; + Error error = fenceObject->testFence(&result); + if (error.isError()) + { + context->recordError(error); + return GL_TRUE; + } + + return result; + } + + return GL_TRUE; +} + +void GL_APIENTRY TexStorage2DEXT(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) +{ + EVENT("(GLenum target = 0x%X, GLsizei levels = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)", + target, levels, internalformat, width, height); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!context->getExtensions().textureStorage) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (context->getClientVersion() < 3 && + !ValidateES2TexStorageParameters(context, target, levels, internalformat, width, height)) + { + return; + } + + if (context->getClientVersion() >= 3 && + !ValidateES3TexStorageParameters(context, target, levels, internalformat, width, height, 1)) + { + return; + } + + Extents size(width, height, 1); + Texture *texture = context->getTargetTexture(target); + Error error = texture->setStorage(target, levels, internalformat, size); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY VertexAttribDivisorANGLE(GLuint index, GLuint divisor) +{ + EVENT("(GLuint index = %d, GLuint divisor = %d)", index, divisor); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (index >= MAX_VERTEX_ATTRIBS) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + context->setVertexAttribDivisor(index, divisor); + } +} + +void GL_APIENTRY BlitFramebufferANGLE(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, + GLbitfield mask, GLenum filter) +{ + EVENT("(GLint srcX0 = %d, GLint srcY0 = %d, GLint srcX1 = %d, GLint srcY1 = %d, " + "GLint dstX0 = %d, GLint dstY0 = %d, GLint dstX1 = %d, GLint dstY1 = %d, " + "GLbitfield mask = 0x%X, GLenum filter = 0x%X)", + srcX0, srcY0, srcX1, srcX1, dstX0, dstY0, dstX1, dstY1, mask, filter); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, + dstX0, dstY0, dstX1, dstY1, mask, filter, + true)) + { + return; + } + + Framebuffer *readFramebuffer = context->getState().getReadFramebuffer(); + ASSERT(readFramebuffer); + + Framebuffer *drawFramebuffer = context->getState().getDrawFramebuffer(); + ASSERT(drawFramebuffer); + + Rectangle srcArea(srcX0, srcY0, srcX1 - srcX0, srcY1 - srcY0); + Rectangle dstArea(dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0); + + Error error = drawFramebuffer->blit(context->getState(), srcArea, dstArea, mask, filter, readFramebuffer); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY TexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, + GLint border, GLenum format, GLenum type, const GLvoid* pixels) +{ + EVENT("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, " + "GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, GLint border = %d, " + "GLenum format = 0x%X, GLenum type = 0x%x, const GLvoid* pixels = 0x%0.8p)", + target, level, internalformat, width, height, depth, border, format, type, pixels); + + UNIMPLEMENTED(); // FIXME +} + +void GL_APIENTRY GetProgramBinaryOES(GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary) +{ + EVENT("(GLenum program = 0x%X, bufSize = %d, length = 0x%0.8p, binaryFormat = 0x%0.8p, binary = 0x%0.8p)", + program, bufSize, length, binaryFormat, binary); + + Context *context = GetValidGlobalContext(); + if (context) + { + Program *programObject = context->getProgram(program); + + if (!programObject || !programObject->isLinked()) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + Error error = programObject->saveBinary(binaryFormat, binary, bufSize, length); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY ProgramBinaryOES(GLuint program, GLenum binaryFormat, const void *binary, GLint length) +{ + EVENT("(GLenum program = 0x%X, binaryFormat = 0x%x, binary = 0x%0.8p, length = %d)", + program, binaryFormat, binary, length); + + Context *context = GetValidGlobalContext(); + if (context) + { + const std::vector &programBinaryFormats = context->getCaps().programBinaryFormats; + if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) == programBinaryFormats.end()) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + Program *programObject = context->getProgram(program); + if (!programObject) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + Error error = programObject->loadBinary(binaryFormat, binary, length); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY DrawBuffersEXT(GLsizei n, const GLenum *bufs) +{ + EVENT("(GLenum n = %d, bufs = 0x%0.8p)", n, bufs); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (n < 0 || static_cast(n) > context->getCaps().maxDrawBuffers) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + ASSERT(context->getState().getDrawFramebuffer()); + + if (context->getState().getDrawFramebuffer()->id() == 0) + { + if (n != 1) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (bufs[0] != GL_NONE && bufs[0] != GL_BACK) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + } + else + { + for (int colorAttachment = 0; colorAttachment < n; colorAttachment++) + { + const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment; + if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + } + } + + Framebuffer *framebuffer = context->getState().getDrawFramebuffer(); + ASSERT(framebuffer); + + framebuffer->setDrawBuffers(n, bufs); + } +} + +void GL_APIENTRY GetBufferPointervOES(GLenum target, GLenum pname, void** params) +{ + EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLvoid** params = 0x%0.8p)", target, pname, params); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidBufferTarget(context, target)) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + if (pname != GL_BUFFER_MAP_POINTER) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + Buffer *buffer = context->getState().getTargetBuffer(target); + + if (!buffer || !buffer->isMapped()) + { + *params = NULL; + } + else + { + *params = buffer->getMapPointer(); + } + } +} + +void *GL_APIENTRY MapBufferOES(GLenum target, GLenum access) +{ + EVENT("(GLenum target = 0x%X, GLbitfield access = 0x%X)", target, access); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidBufferTarget(context, target)) + { + context->recordError(Error(GL_INVALID_ENUM)); + return NULL; + } + + Buffer *buffer = context->getState().getTargetBuffer(target); + + if (buffer == NULL) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return NULL; + } + + if (access != GL_WRITE_ONLY_OES) + { + context->recordError(Error(GL_INVALID_ENUM)); + return NULL; + } + + if (buffer->isMapped()) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return NULL; + } + + Error error = buffer->mapRange(0, buffer->getSize(), GL_MAP_WRITE_BIT); + if (error.isError()) + { + context->recordError(error); + return NULL; + } + + return buffer->getMapPointer(); + } + + return NULL; +} + +GLboolean GL_APIENTRY UnmapBufferOES(GLenum target) +{ + EVENT("(GLenum target = 0x%X)", target); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidBufferTarget(context, target)) + { + context->recordError(Error(GL_INVALID_ENUM)); + return GL_FALSE; + } + + Buffer *buffer = context->getState().getTargetBuffer(target); + + if (buffer == NULL || !buffer->isMapped()) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return GL_FALSE; + } + + // TODO: detect if we had corruption. if so, throw an error and return false. + + Error error = buffer->unmap(); + if (error.isError()) + { + context->recordError(error); + return GL_FALSE; + } + + return GL_TRUE; + } + + return GL_FALSE; +} + +void *GL_APIENTRY MapBufferRangeEXT(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access) +{ + EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d, GLbitfield access = 0x%X)", + target, offset, length, access); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidBufferTarget(context, target)) + { + context->recordError(Error(GL_INVALID_ENUM)); + return NULL; + } + + if (offset < 0 || length < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return NULL; + } + + Buffer *buffer = context->getState().getTargetBuffer(target); + + if (buffer == NULL) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return NULL; + } + + // Check for buffer overflow + size_t offsetSize = static_cast(offset); + size_t lengthSize = static_cast(length); + + if (!rx::IsUnsignedAdditionSafe(offsetSize, lengthSize) || + offsetSize + lengthSize > static_cast(buffer->getSize())) + { + context->recordError(Error(GL_INVALID_VALUE)); + return NULL; + } + + // Check for invalid bits in the mask + GLbitfield allAccessBits = GL_MAP_READ_BIT | + GL_MAP_WRITE_BIT | + GL_MAP_INVALIDATE_RANGE_BIT | + GL_MAP_INVALIDATE_BUFFER_BIT | + GL_MAP_FLUSH_EXPLICIT_BIT | + GL_MAP_UNSYNCHRONIZED_BIT; + + if (access & ~(allAccessBits)) + { + context->recordError(Error(GL_INVALID_VALUE)); + return NULL; + } + + if (length == 0 || buffer->isMapped()) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return NULL; + } + + // Check for invalid bit combinations + if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return NULL; + } + + GLbitfield writeOnlyBits = GL_MAP_INVALIDATE_RANGE_BIT | + GL_MAP_INVALIDATE_BUFFER_BIT | + GL_MAP_UNSYNCHRONIZED_BIT; + + if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return NULL; + } + + if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return NULL; + } + + Error error = buffer->mapRange(offset, length, access); + if (error.isError()) + { + context->recordError(error); + return NULL; + } + + return buffer->getMapPointer(); + } + + return NULL; +} + +void GL_APIENTRY FlushMappedBufferRangeEXT(GLenum target, GLintptr offset, GLsizeiptr length) +{ + EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d)", target, offset, length); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (offset < 0 || length < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + if (!ValidBufferTarget(context, target)) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + Buffer *buffer = context->getState().getTargetBuffer(target); + + if (buffer == NULL) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + // Check for buffer overflow + size_t offsetSize = static_cast(offset); + size_t lengthSize = static_cast(length); + + if (!rx::IsUnsignedAdditionSafe(offsetSize, lengthSize) || + offsetSize + lengthSize > static_cast(buffer->getMapLength())) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + // We do not currently support a non-trivial implementation of FlushMappedBufferRange + } +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/entry_points_gles_2_0_ext.h b/src/3rdparty/angle/src/libGLESv2/entry_points_gles_2_0_ext.h new file mode 100644 index 0000000000..816519fe1f --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/entry_points_gles_2_0_ext.h @@ -0,0 +1,78 @@ +// +// Copyright(c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// entry_points_gles_2_0_ext.h : Defines the GLES 2.0 extension entry points. + +#ifndef LIBGLESV2_ENTRYPOINTGLES20EXT_H_ +#define LIBGLESV2_ENTRYPOINTGLES20EXT_H_ + +#include +#include +#include + +namespace gl +{ + +// GL_ANGLE_framebuffer_blit +ANGLE_EXPORT void GL_APIENTRY BlitFramebufferANGLE(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); + +// GL_ANGLE_framebuffer_multisample +ANGLE_EXPORT void GL_APIENTRY RenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); + +// GL_NV_fence +ANGLE_EXPORT void GL_APIENTRY DeleteFencesNV(GLsizei n, const GLuint* fences); +ANGLE_EXPORT void GL_APIENTRY GenFencesNV(GLsizei n, GLuint* fences); +ANGLE_EXPORT GLboolean GL_APIENTRY IsFenceNV(GLuint fence); +ANGLE_EXPORT GLboolean GL_APIENTRY TestFenceNV(GLuint fence); +ANGLE_EXPORT void GL_APIENTRY GetFenceivNV(GLuint fence, GLenum pname, GLint *params); +ANGLE_EXPORT void GL_APIENTRY FinishFenceNV(GLuint fence); +ANGLE_EXPORT void GL_APIENTRY SetFenceNV(GLuint fence, GLenum condition); + +// GL_ANGLE_translated_shader_source +ANGLE_EXPORT void GL_APIENTRY GetTranslatedShaderSourceANGLE(GLuint shader, GLsizei bufsize, GLsizei *length, GLchar *source); + +// GL_EXT_texture_storage +ANGLE_EXPORT void GL_APIENTRY TexStorage2DEXT(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); + +// GL_EXT_robustness +ANGLE_EXPORT GLenum GL_APIENTRY GetGraphicsResetStatusEXT(void); +ANGLE_EXPORT void GL_APIENTRY ReadnPixelsEXT(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data); +ANGLE_EXPORT void GL_APIENTRY GetnUniformfvEXT(GLuint program, GLint location, GLsizei bufSize, float *params); +ANGLE_EXPORT void GL_APIENTRY GetnUniformivEXT(GLuint program, GLint location, GLsizei bufSize, GLint *params); + +// GL_EXT_occlusion_query_boolean +ANGLE_EXPORT void GL_APIENTRY GenQueriesEXT(GLsizei n, GLuint *ids); +ANGLE_EXPORT void GL_APIENTRY DeleteQueriesEXT(GLsizei n, const GLuint *ids); +ANGLE_EXPORT GLboolean GL_APIENTRY IsQueryEXT(GLuint id); +ANGLE_EXPORT void GL_APIENTRY BeginQueryEXT(GLenum target, GLuint id); +ANGLE_EXPORT void GL_APIENTRY EndQueryEXT(GLenum target); +ANGLE_EXPORT void GL_APIENTRY GetQueryivEXT(GLenum target, GLenum pname, GLint *params); +ANGLE_EXPORT void GL_APIENTRY GetQueryObjectuivEXT(GLuint id, GLenum pname, GLuint *params); + +// GL_EXT_draw_buffers +ANGLE_EXPORT void GL_APIENTRY DrawBuffersEXT(GLsizei n, const GLenum *bufs); + +// GL_ANGLE_instanced_arrays +ANGLE_EXPORT void GL_APIENTRY DrawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei count, GLsizei primcount); +ANGLE_EXPORT void GL_APIENTRY DrawElementsInstancedANGLE(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount); +ANGLE_EXPORT void GL_APIENTRY VertexAttribDivisorANGLE(GLuint index, GLuint divisor); + +// GL_OES_get_program_binary +ANGLE_EXPORT void GL_APIENTRY GetProgramBinaryOES(GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, GLvoid *binary); +ANGLE_EXPORT void GL_APIENTRY ProgramBinaryOES(GLuint program, GLenum binaryFormat, const GLvoid *binary, GLint length); + +// GL_OES_mapbuffer +ANGLE_EXPORT void *GL_APIENTRY MapBufferOES(GLenum target, GLenum access); +ANGLE_EXPORT GLboolean GL_APIENTRY UnmapBufferOES(GLenum target); +ANGLE_EXPORT void GL_APIENTRY GetBufferPointervOES(GLenum target, GLenum pname, GLvoid **params); + +// GL_EXT_map_buffer_range +ANGLE_EXPORT void *GL_APIENTRY MapBufferRangeEXT(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access); +ANGLE_EXPORT void GL_APIENTRY FlushMappedBufferRangeEXT(GLenum target, GLintptr offset, GLsizeiptr length); + +} + +#endif // LIBGLESV2_ENTRYPOINTGLES20EXT_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_0.cpp b/src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_0.cpp new file mode 100644 index 0000000000..d8bdcd2e50 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_0.cpp @@ -0,0 +1,3394 @@ +// +// Copyright(c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// entry_points_gles_3_0.cpp : Implements the GLES 3.0 entry points. + +#include "libGLESv2/entry_points_gles_3_0.h" +#include "libGLESv2/entry_points_gles_2_0_ext.h" +#include "libGLESv2/global_state.h" + +#include "libANGLE/formatutils.h" +#include "libANGLE/Buffer.h" +#include "libANGLE/Context.h" +#include "libANGLE/Error.h" +#include "libANGLE/Fence.h" +#include "libANGLE/Framebuffer.h" +#include "libANGLE/Query.h" +#include "libANGLE/VertexArray.h" + +#include "libANGLE/validationES.h" +#include "libANGLE/validationES3.h" +#include "libANGLE/queryconversions.h" + +#include "common/debug.h" + +namespace gl +{ + +void GL_APIENTRY ReadBuffer(GLenum mode) +{ + EVENT("(GLenum mode = 0x%X)", mode); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateReadBuffer(context, mode)) + { + return; + } + + Framebuffer *readFBO = context->getState().getReadFramebuffer(); + readFBO->setReadBuffer(mode); + } +} + +void GL_APIENTRY DrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid* indices) +{ + EVENT("(GLenum mode = 0x%X, GLuint start = %u, GLuint end = %u, GLsizei count = %d, GLenum type = 0x%X, " + "const GLvoid* indices = 0x%0.8p)", mode, start, end, count, type, indices); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + rx::RangeUI indexRange; + if (!ValidateDrawElements(context, mode, count, type, indices, 0, &indexRange)) + { + return; + } + if (indexRange.end > end || indexRange.start < start) + { + // GL spec says that behavior in this case is undefined - generating an error is fine. + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + // As long as index validation is done, it doesn't matter whether the context receives a drawElements or + // a drawRangeElements call - the GL back-end is free to choose to call drawRangeElements based on the + // validated index range. If index validation is removed, adding drawRangeElements to the context interface + // should be reconsidered. + Error error = context->drawElements(mode, count, type, indices, 0, indexRange); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY TexImage3D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* pixels) +{ + EVENT("(GLenum target = 0x%X, GLint level = %d, GLint internalformat = %d, GLsizei width = %d, " + "GLsizei height = %d, GLsizei depth = %d, GLint border = %d, GLenum format = 0x%X, " + "GLenum type = 0x%X, const GLvoid* pixels = 0x%0.8p)", + target, level, internalformat, width, height, depth, border, format, type, pixels); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + // validateES3TexImageFormat sets the error code if there is an error + if (!ValidateES3TexImageParameters(context, target, level, internalformat, false, false, + 0, 0, 0, width, height, depth, border, format, type, pixels)) + { + return; + } + + Extents size(width, height, depth); + Texture *texture = context->getTargetTexture(target); + Error error = texture->setImage(target, level, internalformat, size, format, type, context->getState().getUnpackState(), + reinterpret_cast(pixels)); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY TexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* pixels) +{ + EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, " + "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, " + "GLenum format = 0x%X, GLenum type = 0x%X, const GLvoid* pixels = 0x%0.8p)", + target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + // validateES3TexImageFormat sets the error code if there is an error + if (!ValidateES3TexImageParameters(context, target, level, GL_NONE, false, true, + xoffset, yoffset, zoffset, width, height, depth, 0, + format, type, pixels)) + { + return; + } + + // Zero sized uploads are valid but no-ops + if (width == 0 || height == 0 || depth == 0) + { + return; + } + + Box area(xoffset, yoffset, zoffset, width, height, depth); + Texture *texture = context->getTargetTexture(target); + Error error = texture->setSubImage(target, level, area, format, type, context->getState().getUnpackState(), + reinterpret_cast(pixels)); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY CopyTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height) +{ + EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, " + "GLint zoffset = %d, GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", + target, level, xoffset, yoffset, zoffset, x, y, width, height); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (!ValidateES3CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset, yoffset, zoffset, + x, y, width, height, 0)) + { + return; + } + + Offset destOffset(xoffset, yoffset, zoffset); + Rectangle sourceArea(x, y, width, height); + + const Framebuffer *framebuffer = context->getState().getReadFramebuffer(); + Texture *texture = context->getTargetTexture(target); + Error error = texture->copySubImage(target, level, destOffset, sourceArea, framebuffer); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY CompressedTexImage3D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data) +{ + EVENT("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, " + "GLsizei height = %d, GLsizei depth = %d, GLint border = %d, GLsizei imageSize = %d, " + "const GLvoid* data = 0x%0.8p)", + target, level, internalformat, width, height, depth, border, imageSize, data); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat); + if (imageSize < 0 || static_cast(imageSize) != formatInfo.computeBlockSize(GL_UNSIGNED_BYTE, width, height)) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + // validateES3TexImageFormat sets the error code if there is an error + if (!ValidateES3TexImageParameters(context, target, level, internalformat, true, false, + 0, 0, 0, width, height, depth, border, GL_NONE, GL_NONE, data)) + { + return; + } + + Extents size(width, height, depth); + Texture *texture = context->getTargetTexture(target); + Error error = texture->setCompressedImage(target, level, internalformat, size, context->getState().getUnpackState(), + reinterpret_cast(data)); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY CompressedTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid* data) +{ + EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, " + "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, " + "GLenum format = 0x%X, GLsizei imageSize = %d, const GLvoid* data = 0x%0.8p)", + target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + const InternalFormat &formatInfo = GetInternalFormatInfo(format); + if (imageSize < 0 || static_cast(imageSize) != formatInfo.computeBlockSize(GL_UNSIGNED_BYTE, width, height)) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + if (!data) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + // validateES3TexImageFormat sets the error code if there is an error + if (!ValidateES3TexImageParameters(context, target, level, GL_NONE, true, true, + 0, 0, 0, width, height, depth, 0, GL_NONE, GL_NONE, data)) + { + return; + } + + // Zero sized uploads are valid but no-ops + if (width == 0 || height == 0) + { + return; + } + + Box area(xoffset, yoffset, zoffset, width, height, depth); + Texture *texture = context->getTargetTexture(target); + Error error = texture->setCompressedSubImage(target, level, area, format, context->getState().getUnpackState(), + reinterpret_cast(data)); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY GenQueries(GLsizei n, GLuint* ids) +{ + EVENT("(GLsizei n = %d, GLuint* ids = 0x%0.8p)", n, ids); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (n < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + for (GLsizei i = 0; i < n; i++) + { + ids[i] = context->createQuery(); + } + } +} + +void GL_APIENTRY DeleteQueries(GLsizei n, const GLuint* ids) +{ + EVENT("(GLsizei n = %d, GLuint* ids = 0x%0.8p)", n, ids); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (n < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + for (GLsizei i = 0; i < n; i++) + { + context->deleteQuery(ids[i]); + } + } +} + +GLboolean GL_APIENTRY IsQuery(GLuint id) +{ + EVENT("(GLuint id = %u)", id); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return GL_FALSE; + } + + return (context->getQuery(id, false, GL_NONE) != NULL) ? GL_TRUE : GL_FALSE; + } + + return GL_FALSE; +} + +void GL_APIENTRY BeginQuery(GLenum target, GLuint id) +{ + EVENT("(GLenum target = 0x%X, GLuint id = %u)", target, id); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (!ValidateBeginQuery(context, target, id)) + { + return; + } + + Error error = context->beginQuery(target, id); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY EndQuery(GLenum target) +{ + EVENT("(GLenum target = 0x%X)", target); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (!ValidateEndQuery(context, target)) + { + return; + } + + Error error = context->endQuery(target); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY GetQueryiv(GLenum target, GLenum pname, GLint* params) +{ + EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (!ValidQueryType(context, target)) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + switch (pname) + { + case GL_CURRENT_QUERY: + params[0] = static_cast(context->getState().getActiveQueryId(target)); + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + } +} + +void GL_APIENTRY GetQueryObjectuiv(GLuint id, GLenum pname, GLuint* params) +{ + EVENT("(GLuint id = %u, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", id, pname, params); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + Query *queryObject = context->getQuery(id, false, GL_NONE); + + if (!queryObject) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (context->getState().getActiveQueryId(queryObject->getType()) == id) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + switch(pname) + { + case GL_QUERY_RESULT_EXT: + { + Error error = queryObject->getResult(params); + if (error.isError()) + { + context->recordError(error); + return; + } + } + break; + + case GL_QUERY_RESULT_AVAILABLE_EXT: + { + Error error = queryObject->isResultAvailable(params); + if (error.isError()) + { + context->recordError(error); + return; + } + } + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + } +} + +GLboolean GL_APIENTRY UnmapBuffer(GLenum target) +{ + EVENT("(GLenum target = 0x%X)", target); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return GL_FALSE; + } + + return UnmapBufferOES(target); + } + + return GL_FALSE; +} + +void GL_APIENTRY GetBufferPointerv(GLenum target, GLenum pname, GLvoid** params) +{ + EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLvoid** params = 0x%0.8p)", target, pname, params); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + GetBufferPointervOES(target, pname, params); + } +} + +void GL_APIENTRY DrawBuffers(GLsizei n, const GLenum* bufs) +{ + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + DrawBuffersEXT(n, bufs); + } +} + +void GL_APIENTRY UniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +{ + EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)", + location, count, transpose, value); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateUniformMatrix(context, GL_FLOAT_MAT2x3, location, count, transpose)) + { + return; + } + + Program *program = context->getState().getProgram(); + program->setUniformMatrix2x3fv(location, count, transpose, value); + } +} + +void GL_APIENTRY UniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +{ + EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)", + location, count, transpose, value); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateUniformMatrix(context, GL_FLOAT_MAT3x2, location, count, transpose)) + { + return; + } + + Program *program = context->getState().getProgram(); + program->setUniformMatrix3x2fv(location, count, transpose, value); + } +} + +void GL_APIENTRY UniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +{ + EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)", + location, count, transpose, value); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateUniformMatrix(context, GL_FLOAT_MAT2x4, location, count, transpose)) + { + return; + } + + Program *program = context->getState().getProgram(); + program->setUniformMatrix2x4fv(location, count, transpose, value); + } +} + +void GL_APIENTRY UniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +{ + EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)", + location, count, transpose, value); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateUniformMatrix(context, GL_FLOAT_MAT4x2, location, count, transpose)) + { + return; + } + + Program *program = context->getState().getProgram(); + program->setUniformMatrix4x2fv(location, count, transpose, value); + } +} + +void GL_APIENTRY UniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +{ + EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)", + location, count, transpose, value); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateUniformMatrix(context, GL_FLOAT_MAT3x4, location, count, transpose)) + { + return; + } + + Program *program = context->getState().getProgram(); + program->setUniformMatrix3x4fv(location, count, transpose, value); + } +} + +void GL_APIENTRY UniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +{ + EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)", + location, count, transpose, value); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateUniformMatrix(context, GL_FLOAT_MAT4x3, location, count, transpose)) + { + return; + } + + Program *program = context->getState().getProgram(); + program->setUniformMatrix4x3fv(location, count, transpose, value); + } +} + +void GL_APIENTRY BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) +{ + EVENT("(GLint srcX0 = %d, GLint srcY0 = %d, GLint srcX1 = %d, GLint srcY1 = %d, GLint dstX0 = %d, " + "GLint dstY0 = %d, GLint dstX1 = %d, GLint dstY1 = %d, GLbitfield mask = 0x%X, GLenum filter = 0x%X)", + srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (!ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, + dstX0, dstY0, dstX1, dstY1, mask, filter, + false)) + { + return; + } + + Framebuffer *readFramebuffer = context->getState().getReadFramebuffer(); + ASSERT(readFramebuffer); + + Framebuffer *drawFramebuffer = context->getState().getDrawFramebuffer(); + ASSERT(drawFramebuffer); + + Rectangle srcArea(srcX0, srcY0, srcX1 - srcX0, srcY1 - srcY0); + Rectangle dstArea(dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0); + + Error error = drawFramebuffer->blit(context->getState(), srcArea, dstArea, mask, filter, readFramebuffer); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY RenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height) +{ + EVENT("(GLenum target = 0x%X, GLsizei samples = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)", + target, samples, internalformat, width, height); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (!ValidateES3RenderbufferStorageParameters(context, target, samples, internalformat, width, height)) + { + return; + } + + Renderbuffer *renderbuffer = context->getState().getCurrentRenderbuffer(); + renderbuffer->setStorageMultisample(samples, internalformat, width, height); + } +} + +void GL_APIENTRY FramebufferTextureLayer(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer) +{ + EVENT("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLuint texture = %u, GLint level = %d, GLint layer = %d)", + target, attachment, texture, level, layer); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateFramebufferTextureLayer(context, target, attachment, texture, + level, layer)) + { + return; + } + + Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target); + ASSERT(framebuffer); + + if (texture != 0) + { + Texture *textureObject = context->getTexture(texture); + + ImageIndex index = ImageIndex::MakeInvalid(); + + if (textureObject->getTarget() == GL_TEXTURE_3D) + { + index = ImageIndex::Make3D(level, layer); + } + else + { + ASSERT(textureObject->getTarget() == GL_TEXTURE_2D_ARRAY); + index = ImageIndex::Make2DArray(level, layer); + } + + framebuffer->setTextureAttachment(attachment, textureObject, index); + } + else + { + framebuffer->setNULLAttachment(attachment); + } + } +} + +GLvoid *GL_APIENTRY MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access) +{ + EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d, GLbitfield access = 0x%X)", + target, offset, length, access); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return NULL; + } + + return MapBufferRangeEXT(target, offset, length, access); + } + + return NULL; +} + +void GL_APIENTRY FlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length) +{ + EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d)", target, offset, length); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + FlushMappedBufferRangeEXT(target, offset, length); + } +} + +void GL_APIENTRY BindVertexArray(GLuint array) +{ + EVENT("(GLuint array = %u)", array); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + VertexArray *vao = context->getVertexArray(array); + + if (!vao) + { + // The default VAO should always exist + ASSERT(array != 0); + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + context->bindVertexArray(array); + } +} + +void GL_APIENTRY DeleteVertexArrays(GLsizei n, const GLuint* arrays) +{ + EVENT("(GLsizei n = %d, const GLuint* arrays = 0x%0.8p)", n, arrays); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (n < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + for (int arrayIndex = 0; arrayIndex < n; arrayIndex++) + { + if (arrays[arrayIndex] != 0) + { + context->deleteVertexArray(arrays[arrayIndex]); + } + } + } +} + +void GL_APIENTRY GenVertexArrays(GLsizei n, GLuint* arrays) +{ + EVENT("(GLsizei n = %d, GLuint* arrays = 0x%0.8p)", n, arrays); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (n < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + for (int arrayIndex = 0; arrayIndex < n; arrayIndex++) + { + arrays[arrayIndex] = context->createVertexArray(); + } + } +} + +GLboolean GL_APIENTRY IsVertexArray(GLuint array) +{ + EVENT("(GLuint array = %u)", array); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return GL_FALSE; + } + + if (array == 0) + { + return GL_FALSE; + } + + VertexArray *vao = context->getVertexArray(array); + + return (vao != NULL ? GL_TRUE : GL_FALSE); + } + + return GL_FALSE; +} + +void GL_APIENTRY GetIntegeri_v(GLenum target, GLuint index, GLint* data) +{ + EVENT("(GLenum target = 0x%X, GLuint index = %u, GLint* data = 0x%0.8p)", + target, index, data); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + const Caps &caps = context->getCaps(); + switch (target) + { + case GL_TRANSFORM_FEEDBACK_BUFFER_START: + case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE: + case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: + if (index >= caps.maxTransformFeedbackSeparateAttributes) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + break; + + case GL_UNIFORM_BUFFER_START: + case GL_UNIFORM_BUFFER_SIZE: + case GL_UNIFORM_BUFFER_BINDING: + if (index >= caps.maxCombinedUniformBlocks) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + if (!(context->getIndexedIntegerv(target, index, data))) + { + GLenum nativeType; + unsigned int numParams = 0; + if (!context->getIndexedQueryParameterInfo(target, &nativeType, &numParams)) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + if (numParams == 0) + { + return; // it is known that pname is valid, but there are no parameters to return + } + + if (nativeType == GL_INT_64_ANGLEX) + { + GLint64 minIntValue = static_cast(std::numeric_limits::min()); + GLint64 maxIntValue = static_cast(std::numeric_limits::max()); + GLint64 *int64Params = new GLint64[numParams]; + + context->getIndexedInteger64v(target, index, int64Params); + + for (unsigned int i = 0; i < numParams; ++i) + { + GLint64 clampedValue = std::max(std::min(int64Params[i], maxIntValue), minIntValue); + data[i] = static_cast(clampedValue); + } + + delete [] int64Params; + } + else + { + UNREACHABLE(); + } + } + } +} + +void GL_APIENTRY BeginTransformFeedback(GLenum primitiveMode) +{ + EVENT("(GLenum primitiveMode = 0x%X)", primitiveMode); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + switch (primitiveMode) + { + case GL_TRIANGLES: + case GL_LINES: + case GL_POINTS: + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback(); + ASSERT(transformFeedback != NULL); + + if (transformFeedback->isStarted()) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (transformFeedback->isPaused()) + { + transformFeedback->resume(); + } + else + { + transformFeedback->start(primitiveMode); + } + } +} + +void GL_APIENTRY EndTransformFeedback(void) +{ + EVENT("(void)"); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback(); + ASSERT(transformFeedback != NULL); + + if (!transformFeedback->isStarted()) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + transformFeedback->stop(); + } +} + +void GL_APIENTRY BindBufferRange(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size) +{ + EVENT("(GLenum target = 0x%X, GLuint index = %u, GLuint buffer = %u, GLintptr offset = %d, GLsizeiptr size = %d)", + target, index, buffer, offset, size); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + const Caps &caps = context->getCaps(); + switch (target) + { + case GL_TRANSFORM_FEEDBACK_BUFFER: + if (index >= caps.maxTransformFeedbackSeparateAttributes) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + break; + + case GL_UNIFORM_BUFFER: + if (index >= caps.maxUniformBufferBindings) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + if (buffer != 0 && size <= 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + switch (target) + { + case GL_TRANSFORM_FEEDBACK_BUFFER: + { + // size and offset must be a multiple of 4 + if (buffer != 0 && ((offset % 4) != 0 || (size % 4) != 0)) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + // Cannot bind a transform feedback buffer if the current transform feedback is active (3.0.4 pg 91 section 2.15.2) + TransformFeedback *curTransformFeedback = context->getState().getCurrentTransformFeedback(); + if (curTransformFeedback && curTransformFeedback->isStarted()) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + context->bindIndexedTransformFeedbackBuffer(buffer, index, offset, size); + context->bindGenericTransformFeedbackBuffer(buffer); + break; + } + + case GL_UNIFORM_BUFFER: + + // it is an error to bind an offset not a multiple of the alignment + if (buffer != 0 && (offset % caps.uniformBufferOffsetAlignment) != 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + context->bindIndexedUniformBuffer(buffer, index, offset, size); + context->bindGenericUniformBuffer(buffer); + break; + + default: + UNREACHABLE(); + } + } +} + +void GL_APIENTRY BindBufferBase(GLenum target, GLuint index, GLuint buffer) +{ + EVENT("(GLenum target = 0x%X, GLuint index = %u, GLuint buffer = %u)", + target, index, buffer); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + const Caps &caps = context->getCaps(); + switch (target) + { + case GL_TRANSFORM_FEEDBACK_BUFFER: + if (index >= caps.maxTransformFeedbackSeparateAttributes) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + break; + + case GL_UNIFORM_BUFFER: + if (index >= caps.maxUniformBufferBindings) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + switch (target) + { + case GL_TRANSFORM_FEEDBACK_BUFFER: + { + // Cannot bind a transform feedback buffer if the current transform feedback is active (3.0.4 pg 91 section 2.15.2) + TransformFeedback *curTransformFeedback = context->getState().getCurrentTransformFeedback(); + if (curTransformFeedback && curTransformFeedback->isStarted()) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + context->bindIndexedTransformFeedbackBuffer(buffer, index, 0, 0); + context->bindGenericTransformFeedbackBuffer(buffer); + break; + } + case GL_UNIFORM_BUFFER: + context->bindIndexedUniformBuffer(buffer, index, 0, 0); + context->bindGenericUniformBuffer(buffer); + break; + + default: + UNREACHABLE(); + } + } +} + +void GL_APIENTRY TransformFeedbackVaryings(GLuint program, GLsizei count, const GLchar* const* varyings, GLenum bufferMode) +{ + EVENT("(GLuint program = %u, GLsizei count = %d, const GLchar* const* varyings = 0x%0.8p, GLenum bufferMode = 0x%X)", + program, count, varyings, bufferMode); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (count < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + const Caps &caps = context->getCaps(); + switch (bufferMode) + { + case GL_INTERLEAVED_ATTRIBS: + break; + case GL_SEPARATE_ATTRIBS: + if (static_cast(count) > caps.maxTransformFeedbackSeparateAttributes) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + break; + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + if (!ValidProgram(context, program)) + { + return; + } + + Program *programObject = context->getProgram(program); + ASSERT(programObject); + + programObject->setTransformFeedbackVaryings(count, varyings, bufferMode); + } +} + +void GL_APIENTRY GetTransformFeedbackVarying(GLuint program, GLuint index, GLsizei bufSize, GLsizei* length, GLsizei* size, GLenum* type, GLchar* name) +{ + EVENT("(GLuint program = %u, GLuint index = %u, GLsizei bufSize = %d, GLsizei* length = 0x%0.8p, " + "GLsizei* size = 0x%0.8p, GLenum* type = 0x%0.8p, GLchar* name = 0x%0.8p)", + program, index, bufSize, length, size, type, name); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (bufSize < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + if (!ValidProgram(context, program)) + { + return; + } + + Program *programObject = context->getProgram(program); + ASSERT(programObject); + + if (index >= static_cast(programObject->getTransformFeedbackVaryingCount())) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + programObject->getTransformFeedbackVarying(index, bufSize, length, size, type, name); + } +} + +void GL_APIENTRY VertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid* pointer) +{ + EVENT("(GLuint index = %u, GLint size = %d, GLenum type = 0x%X, GLsizei stride = %d, const GLvoid* pointer = 0x%0.8p)", + index, size, type, stride, pointer); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (index >= MAX_VERTEX_ATTRIBS) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + if (size < 1 || size > 4) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + switch (type) + { + case GL_BYTE: + case GL_UNSIGNED_BYTE: + case GL_SHORT: + case GL_UNSIGNED_SHORT: + case GL_INT: + case GL_UNSIGNED_INT: + case GL_INT_2_10_10_10_REV: + case GL_UNSIGNED_INT_2_10_10_10_REV: + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + if (stride < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + if ((type == GL_INT_2_10_10_10_REV || type == GL_UNSIGNED_INT_2_10_10_10_REV) && size != 4) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + // [OpenGL ES 3.0.2] Section 2.8 page 24: + // An INVALID_OPERATION error is generated when a non-zero vertex array object + // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point, + // and the pointer argument is not NULL. + if (context->getState().getVertexArray()->id() != 0 && context->getState().getArrayBufferId() == 0 && pointer != NULL) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + context->getState().setVertexAttribState(index, context->getState().getTargetBuffer(GL_ARRAY_BUFFER), size, type, false, true, + stride, pointer); + } +} + +void GL_APIENTRY GetVertexAttribIiv(GLuint index, GLenum pname, GLint* params) +{ + EVENT("(GLuint index = %u, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", + index, pname, params); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (index >= MAX_VERTEX_ATTRIBS) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + if (!ValidateGetVertexAttribParameters(context, pname)) + { + return; + } + + if (pname == GL_CURRENT_VERTEX_ATTRIB) + { + const VertexAttribCurrentValueData ¤tValueData = context->getState().getVertexAttribCurrentValue(index); + for (int i = 0; i < 4; ++i) + { + params[i] = currentValueData.IntValues[i]; + } + } + else + { + const VertexAttribute &attribState = context->getState().getVertexArray()->getVertexAttribute(index); + *params = QuerySingleVertexAttributeParameter(attribState, pname); + } + } +} + +void GL_APIENTRY GetVertexAttribIuiv(GLuint index, GLenum pname, GLuint* params) +{ + EVENT("(GLuint index = %u, GLenum pname = 0x%X, GLuint* params = 0x%0.8p)", + index, pname, params); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (index >= MAX_VERTEX_ATTRIBS) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + if (!ValidateGetVertexAttribParameters(context, pname)) + { + return; + } + + if (pname == GL_CURRENT_VERTEX_ATTRIB) + { + const VertexAttribCurrentValueData ¤tValueData = context->getState().getVertexAttribCurrentValue(index); + for (int i = 0; i < 4; ++i) + { + params[i] = currentValueData.UnsignedIntValues[i]; + } + } + else + { + const VertexAttribute &attribState = context->getState().getVertexArray()->getVertexAttribute(index); + *params = QuerySingleVertexAttributeParameter(attribState, pname); + } + } +} + +void GL_APIENTRY VertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint w) +{ + EVENT("(GLuint index = %u, GLint x = %d, GLint y = %d, GLint z = %d, GLint w = %d)", + index, x, y, z, w); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (index >= MAX_VERTEX_ATTRIBS) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + GLint vals[4] = { x, y, z, w }; + context->getState().setVertexAttribi(index, vals); + } +} + +void GL_APIENTRY VertexAttribI4ui(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w) +{ + EVENT("(GLuint index = %u, GLuint x = %u, GLuint y = %u, GLuint z = %u, GLuint w = %u)", + index, x, y, z, w); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (index >= MAX_VERTEX_ATTRIBS) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + GLuint vals[4] = { x, y, z, w }; + context->getState().setVertexAttribu(index, vals); + } +} + +void GL_APIENTRY VertexAttribI4iv(GLuint index, const GLint* v) +{ + EVENT("(GLuint index = %u, const GLint* v = 0x%0.8p)", index, v); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (index >= MAX_VERTEX_ATTRIBS) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + context->getState().setVertexAttribi(index, v); + } +} + +void GL_APIENTRY VertexAttribI4uiv(GLuint index, const GLuint* v) +{ + EVENT("(GLuint index = %u, const GLuint* v = 0x%0.8p)", index, v); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (index >= MAX_VERTEX_ATTRIBS) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + context->getState().setVertexAttribu(index, v); + } +} + +void GL_APIENTRY GetUniformuiv(GLuint program, GLint location, GLuint* params) +{ + EVENT("(GLuint program = %u, GLint location = %d, GLuint* params = 0x%0.8p)", + program, location, params); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateGetUniformuiv(context, program, location, params)) + { + return; + } + + Program *programObject = context->getProgram(program); + ASSERT(programObject); + + programObject->getUniformuiv(location, params); + } +} + +GLint GL_APIENTRY GetFragDataLocation(GLuint program, const GLchar *name) +{ + EVENT("(GLuint program = %u, const GLchar *name = 0x%0.8p)", + program, name); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return -1; + } + + if (program == 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return -1; + } + + Program *programObject = context->getProgram(program); + + if (!programObject || !programObject->isLinked()) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return -1; + } + + return programObject->getFragDataLocation(name); + } + + return 0; +} + +void GL_APIENTRY Uniform1ui(GLint location, GLuint v0) +{ + Uniform1uiv(location, 1, &v0); +} + +void GL_APIENTRY Uniform2ui(GLint location, GLuint v0, GLuint v1) +{ + const GLuint xy[] = { v0, v1 }; + Uniform2uiv(location, 1, xy); +} + +void GL_APIENTRY Uniform3ui(GLint location, GLuint v0, GLuint v1, GLuint v2) +{ + const GLuint xyz[] = { v0, v1, v2 }; + Uniform3uiv(location, 1, xyz); +} + +void GL_APIENTRY Uniform4ui(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3) +{ + const GLuint xyzw[] = { v0, v1, v2, v3 }; + Uniform4uiv(location, 1, xyzw); +} + +void GL_APIENTRY Uniform1uiv(GLint location, GLsizei count, const GLuint* value) +{ + EVENT("(GLint location = %d, GLsizei count = %d, const GLuint* value = 0x%0.8p)", + location, count, value); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateUniform(context, GL_UNSIGNED_INT, location, count)) + { + return; + } + + Program *program = context->getState().getProgram(); + program->setUniform1uiv(location, count, value); + } +} + +void GL_APIENTRY Uniform2uiv(GLint location, GLsizei count, const GLuint* value) +{ + EVENT("(GLint location = %d, GLsizei count = %d, const GLuint* value = 0x%0.8p)", + location, count, value); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateUniform(context, GL_UNSIGNED_INT_VEC2, location, count)) + { + return; + } + + Program *program = context->getState().getProgram(); + program->setUniform2uiv(location, count, value); + } +} + +void GL_APIENTRY Uniform3uiv(GLint location, GLsizei count, const GLuint* value) +{ + EVENT("(GLint location = %d, GLsizei count = %d, const GLuint* value)", + location, count, value); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateUniform(context, GL_UNSIGNED_INT_VEC3, location, count)) + { + return; + } + + Program *program = context->getState().getProgram(); + program->setUniform3uiv(location, count, value); + } +} + +void GL_APIENTRY Uniform4uiv(GLint location, GLsizei count, const GLuint* value) +{ + EVENT("(GLint location = %d, GLsizei count = %d, const GLuint* value = 0x%0.8p)", + location, count, value); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateUniform(context, GL_UNSIGNED_INT_VEC4, location, count)) + { + return; + } + + Program *program = context->getState().getProgram(); + program->setUniform4uiv(location, count, value); + } +} + +void GL_APIENTRY ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint* value) +{ + EVENT("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLint* value = 0x%0.8p)", + buffer, drawbuffer, value); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateClearBuffer(context)) + { + return; + } + + switch (buffer) + { + case GL_COLOR: + if (drawbuffer < 0 || static_cast(drawbuffer) >= context->getCaps().maxDrawBuffers) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + break; + + case GL_STENCIL: + if (drawbuffer != 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + Framebuffer *framebufferObject = context->getState().getDrawFramebuffer(); + ASSERT(framebufferObject); + + Error error = framebufferObject->clearBufferiv(context->getState(), buffer, drawbuffer, value); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint* value) +{ + EVENT("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLuint* value = 0x%0.8p)", + buffer, drawbuffer, value); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateClearBuffer(context)) + { + return; + } + + switch (buffer) + { + case GL_COLOR: + if (drawbuffer < 0 || static_cast(drawbuffer) >= context->getCaps().maxDrawBuffers) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + Framebuffer *framebufferObject = context->getState().getDrawFramebuffer(); + ASSERT(framebufferObject); + + Error error = framebufferObject->clearBufferuiv(context->getState(), buffer, drawbuffer, value); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat* value) +{ + EVENT("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLfloat* value = 0x%0.8p)", + buffer, drawbuffer, value); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateClearBuffer(context)) + { + return; + } + + switch (buffer) + { + case GL_COLOR: + if (drawbuffer < 0 || static_cast(drawbuffer) >= context->getCaps().maxDrawBuffers) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + break; + + case GL_DEPTH: + if (drawbuffer != 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + Framebuffer *framebufferObject = context->getState().getDrawFramebuffer(); + ASSERT(framebufferObject); + + Error error = framebufferObject->clearBufferfv(context->getState(), buffer, drawbuffer, value); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY ClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) +{ + EVENT("(GLenum buffer = 0x%X, GLint drawbuffer = %d, GLfloat depth, GLint stencil = %d)", + buffer, drawbuffer, depth, stencil); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (!ValidateClearBuffer(context)) + { + return; + } + + switch (buffer) + { + case GL_DEPTH_STENCIL: + if (drawbuffer != 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + Framebuffer *framebufferObject = context->getState().getDrawFramebuffer(); + ASSERT(framebufferObject); + + Error error = framebufferObject->clearBufferfi(context->getState(), buffer, drawbuffer, depth, stencil); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +const GLubyte *GL_APIENTRY GetStringi(GLenum name, GLuint index) +{ + EVENT("(GLenum name = 0x%X, GLuint index = %u)", name, index); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return NULL; + } + + if (name != GL_EXTENSIONS) + { + context->recordError(Error(GL_INVALID_ENUM)); + return NULL; + } + + if (index >= context->getExtensionStringCount()) + { + context->recordError(Error(GL_INVALID_VALUE)); + return NULL; + } + + return reinterpret_cast(context->getExtensionString(index).c_str()); + } + + return NULL; +} + +void GL_APIENTRY CopyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size) +{ + EVENT("(GLenum readTarget = 0x%X, GLenum writeTarget = 0x%X, GLintptr readOffset = %d, GLintptr writeOffset = %d, GLsizeiptr size = %d)", + readTarget, writeTarget, readOffset, writeOffset, size); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (!ValidBufferTarget(context, readTarget) || !ValidBufferTarget(context, writeTarget)) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + Buffer *readBuffer = context->getState().getTargetBuffer(readTarget); + Buffer *writeBuffer = context->getState().getTargetBuffer(writeTarget); + + if (!readBuffer || !writeBuffer) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + // Verify that readBuffer and writeBuffer are not currently mapped + if (readBuffer->isMapped() || writeBuffer->isMapped()) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (readOffset < 0 || writeOffset < 0 || size < 0 || + static_cast(readOffset + size) > readBuffer->getSize() || + static_cast(writeOffset + size) > writeBuffer->getSize()) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + if (readBuffer == writeBuffer && std::abs(readOffset - writeOffset) < size) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + // if size is zero, the copy is a successful no-op + if (size > 0) + { + Error error = writeBuffer->copyBufferSubData(readBuffer, readOffset, writeOffset, size); + if (error.isError()) + { + context->recordError(error); + return; + } + } + } +} + +void GL_APIENTRY GetUniformIndices(GLuint program, GLsizei uniformCount, const GLchar* const* uniformNames, GLuint* uniformIndices) +{ + EVENT("(GLuint program = %u, GLsizei uniformCount = %d, const GLchar* const* uniformNames = 0x%0.8p, GLuint* uniformIndices = 0x%0.8p)", + program, uniformCount, uniformNames, uniformIndices); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (uniformCount < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + Program *programObject = context->getProgram(program); + + if (!programObject) + { + if (context->getShader(program)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + else + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + } + + if (!programObject->isLinked()) + { + for (int uniformId = 0; uniformId < uniformCount; uniformId++) + { + uniformIndices[uniformId] = GL_INVALID_INDEX; + } + } + else + { + for (int uniformId = 0; uniformId < uniformCount; uniformId++) + { + uniformIndices[uniformId] = programObject->getUniformIndex(uniformNames[uniformId]); + } + } + } +} + +void GL_APIENTRY GetActiveUniformsiv(GLuint program, GLsizei uniformCount, const GLuint* uniformIndices, GLenum pname, GLint* params) +{ + EVENT("(GLuint program = %u, GLsizei uniformCount = %d, const GLuint* uniformIndices = 0x%0.8p, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", + program, uniformCount, uniformIndices, pname, params); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (uniformCount < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + Program *programObject = context->getProgram(program); + + if (!programObject) + { + if (context->getShader(program)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + else + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + } + + switch (pname) + { + case GL_UNIFORM_TYPE: + case GL_UNIFORM_SIZE: + case GL_UNIFORM_NAME_LENGTH: + case GL_UNIFORM_BLOCK_INDEX: + case GL_UNIFORM_OFFSET: + case GL_UNIFORM_ARRAY_STRIDE: + case GL_UNIFORM_MATRIX_STRIDE: + case GL_UNIFORM_IS_ROW_MAJOR: + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + if (uniformCount > programObject->getActiveUniformCount()) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + for (int uniformId = 0; uniformId < uniformCount; uniformId++) + { + const GLuint index = uniformIndices[uniformId]; + + if (index >= static_cast(programObject->getActiveUniformCount())) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + } + + for (int uniformId = 0; uniformId < uniformCount; uniformId++) + { + const GLuint index = uniformIndices[uniformId]; + params[uniformId] = programObject->getActiveUniformi(index, pname); + } + } +} + +GLuint GL_APIENTRY GetUniformBlockIndex(GLuint program, const GLchar* uniformBlockName) +{ + EVENT("(GLuint program = %u, const GLchar* uniformBlockName = 0x%0.8p)", program, uniformBlockName); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return GL_INVALID_INDEX; + } + + Program *programObject = context->getProgram(program); + + if (!programObject) + { + if (context->getShader(program)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return GL_INVALID_INDEX; + } + else + { + context->recordError(Error(GL_INVALID_VALUE)); + return GL_INVALID_INDEX; + } + } + + return programObject->getUniformBlockIndex(uniformBlockName); + } + + return 0; +} + +void GL_APIENTRY GetActiveUniformBlockiv(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params) +{ + EVENT("(GLuint program = %u, GLuint uniformBlockIndex = %u, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", + program, uniformBlockIndex, pname, params); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + Program *programObject = context->getProgram(program); + + if (!programObject) + { + if (context->getShader(program)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + else + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + } + + if (uniformBlockIndex >= programObject->getActiveUniformBlockCount()) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + switch (pname) + { + case GL_UNIFORM_BLOCK_BINDING: + *params = static_cast(programObject->getUniformBlockBinding(uniformBlockIndex)); + break; + + case GL_UNIFORM_BLOCK_DATA_SIZE: + case GL_UNIFORM_BLOCK_NAME_LENGTH: + case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS: + case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES: + case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER: + case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER: + programObject->getActiveUniformBlockiv(uniformBlockIndex, pname, params); + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + } +} + +void GL_APIENTRY GetActiveUniformBlockName(GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei* length, GLchar* uniformBlockName) +{ + EVENT("(GLuint program = %u, GLuint uniformBlockIndex = %u, GLsizei bufSize = %d, GLsizei* length = 0x%0.8p, GLchar* uniformBlockName = 0x%0.8p)", + program, uniformBlockIndex, bufSize, length, uniformBlockName); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + Program *programObject = context->getProgram(program); + + if (!programObject) + { + if (context->getShader(program)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + else + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + } + + if (uniformBlockIndex >= programObject->getActiveUniformBlockCount()) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + programObject->getActiveUniformBlockName(uniformBlockIndex, bufSize, length, uniformBlockName); + } +} + +void GL_APIENTRY UniformBlockBinding(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding) +{ + EVENT("(GLuint program = %u, GLuint uniformBlockIndex = %u, GLuint uniformBlockBinding = %u)", + program, uniformBlockIndex, uniformBlockBinding); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (uniformBlockBinding >= context->getCaps().maxUniformBufferBindings) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + Program *programObject = context->getProgram(program); + + if (!programObject) + { + if (context->getShader(program)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + else + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + } + + // if never linked, there won't be any uniform blocks + if (uniformBlockIndex >= programObject->getActiveUniformBlockCount()) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + programObject->bindUniformBlock(uniformBlockIndex, uniformBlockBinding); + } +} + +void GL_APIENTRY DrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount) +{ + EVENT("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d, GLsizei instanceCount = %d)", + mode, first, count, instanceCount); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (!ValidateDrawArraysInstanced(context, mode, first, count, instanceCount)) + { + return; + } + + Error error = context->drawArrays(mode, first, count, instanceCount); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY DrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices, GLsizei instanceCount) +{ + EVENT("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = 0x%0.8p, GLsizei instanceCount = %d)", + mode, count, type, indices, instanceCount); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + rx::RangeUI indexRange; + if (!ValidateDrawElementsInstanced(context, mode, count, type, indices, instanceCount, &indexRange)) + { + return; + } + + Error error = context->drawElements(mode, count, type, indices, instanceCount, indexRange); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +GLsync GL_APIENTRY FenceSync_(GLenum condition, GLbitfield flags) +{ + EVENT("(GLenum condition = 0x%X, GLbitfield flags = 0x%X)", condition, flags); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return 0; + } + + if (condition != GL_SYNC_GPU_COMMANDS_COMPLETE) + { + context->recordError(Error(GL_INVALID_ENUM)); + return 0; + } + + if (flags != 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return 0; + } + + GLsync fenceSync = context->createFenceSync(); + + FenceSync *fenceSyncObject = context->getFenceSync(fenceSync); + Error error = fenceSyncObject->set(condition); + if (error.isError()) + { + context->deleteFenceSync(fenceSync); + context->recordError(error); + return NULL; + } + + return fenceSync; + } + + return NULL; +} + +GLboolean GL_APIENTRY IsSync(GLsync sync) +{ + EVENT("(GLsync sync = 0x%0.8p)", sync); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return GL_FALSE; + } + + return (context->getFenceSync(sync) != NULL); + } + + return GL_FALSE; +} + +void GL_APIENTRY DeleteSync(GLsync sync) +{ + EVENT("(GLsync sync = 0x%0.8p)", sync); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (sync != static_cast(0) && !context->getFenceSync(sync)) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + context->deleteFenceSync(sync); + } +} + +GLenum GL_APIENTRY ClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout) +{ + EVENT("(GLsync sync = 0x%0.8p, GLbitfield flags = 0x%X, GLuint64 timeout = %llu)", + sync, flags, timeout); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return GL_WAIT_FAILED; + } + + if ((flags & ~(GL_SYNC_FLUSH_COMMANDS_BIT)) != 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return GL_WAIT_FAILED; + } + + FenceSync *fenceSync = context->getFenceSync(sync); + + if (!fenceSync) + { + context->recordError(Error(GL_INVALID_VALUE)); + return GL_WAIT_FAILED; + } + + GLenum result = GL_WAIT_FAILED; + Error error = fenceSync->clientWait(flags, timeout, &result); + if (error.isError()) + { + context->recordError(error); + return GL_WAIT_FAILED; + } + + return result; + } + + return GL_FALSE; +} + +void GL_APIENTRY WaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout) +{ + EVENT("(GLsync sync = 0x%0.8p, GLbitfield flags = 0x%X, GLuint64 timeout = %llu)", + sync, flags, timeout); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (flags != 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + if (timeout != GL_TIMEOUT_IGNORED) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + FenceSync *fenceSync = context->getFenceSync(sync); + + if (!fenceSync) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + Error error = fenceSync->serverWait(flags, timeout); + if (error.isError()) + { + context->recordError(error); + } + } +} + +void GL_APIENTRY GetInteger64v(GLenum pname, GLint64* params) +{ + EVENT("(GLenum pname = 0x%X, GLint64* params = 0x%0.8p)", + pname, params); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + GLenum nativeType; + unsigned int numParams = 0; + if (!ValidateStateQuery(context, pname, &nativeType, &numParams)) + { + return; + } + + if (nativeType == GL_INT_64_ANGLEX) + { + context->getInteger64v(pname, params); + } + else + { + CastStateValues(context, nativeType, pname, numParams, params); + } + } +} + +void GL_APIENTRY GetSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei* length, GLint* values) +{ + EVENT("(GLsync sync = 0x%0.8p, GLenum pname = 0x%X, GLsizei bufSize = %d, GLsizei* length = 0x%0.8p, GLint* values = 0x%0.8p)", + sync, pname, bufSize, length, values); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (bufSize < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + FenceSync *fenceSync = context->getFenceSync(sync); + + if (!fenceSync) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + switch (pname) + { + case GL_OBJECT_TYPE: values[0] = static_cast(GL_SYNC_FENCE); break; + case GL_SYNC_CONDITION: values[0] = static_cast(fenceSync->getCondition()); break; + case GL_SYNC_FLAGS: values[0] = 0; break; + + case GL_SYNC_STATUS: + { + Error error = fenceSync->getStatus(values); + if (error.isError()) + { + context->recordError(error); + return; + } + break; + } + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + } +} + +void GL_APIENTRY GetInteger64i_v(GLenum target, GLuint index, GLint64* data) +{ + EVENT("(GLenum target = 0x%X, GLuint index = %u, GLint64* data = 0x%0.8p)", + target, index, data); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + const Caps &caps = context->getCaps(); + switch (target) + { + case GL_TRANSFORM_FEEDBACK_BUFFER_START: + case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE: + case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: + if (index >= caps.maxTransformFeedbackSeparateAttributes) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + break; + + case GL_UNIFORM_BUFFER_START: + case GL_UNIFORM_BUFFER_SIZE: + case GL_UNIFORM_BUFFER_BINDING: + if (index >= caps.maxUniformBufferBindings) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + if (!(context->getIndexedInteger64v(target, index, data))) + { + GLenum nativeType; + unsigned int numParams = 0; + if (!context->getIndexedQueryParameterInfo(target, &nativeType, &numParams)) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + if (numParams == 0) + return; // it is known that pname is valid, but there are no parameters to return + + if (nativeType == GL_INT) + { + GLint *intParams = new GLint[numParams]; + + context->getIndexedIntegerv(target, index, intParams); + + for (unsigned int i = 0; i < numParams; ++i) + { + data[i] = static_cast(intParams[i]); + } + + delete [] intParams; + } + else + { + UNREACHABLE(); + } + } + } +} + +void GL_APIENTRY GetBufferParameteri64v(GLenum target, GLenum pname, GLint64* params) +{ + EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint64* params = 0x%0.8p)", + target, pname, params); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (!ValidBufferTarget(context, target)) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + if (!ValidBufferParameter(context, pname)) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + Buffer *buffer = context->getState().getTargetBuffer(target); + + if (!buffer) + { + // A null buffer means that "0" is bound to the requested buffer target + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + switch (pname) + { + case GL_BUFFER_USAGE: + *params = static_cast(buffer->getUsage()); + break; + case GL_BUFFER_SIZE: + *params = buffer->getSize(); + break; + case GL_BUFFER_ACCESS_FLAGS: + *params = static_cast(buffer->getAccessFlags()); + break; + case GL_BUFFER_MAPPED: + *params = static_cast(buffer->isMapped()); + break; + case GL_BUFFER_MAP_OFFSET: + *params = buffer->getMapOffset(); + break; + case GL_BUFFER_MAP_LENGTH: + *params = buffer->getMapLength(); + break; + default: UNREACHABLE(); break; + } + } +} + +void GL_APIENTRY GenSamplers(GLsizei count, GLuint* samplers) +{ + EVENT("(GLsizei count = %d, GLuint* samplers = 0x%0.8p)", count, samplers); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (count < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + for (int i = 0; i < count; i++) + { + samplers[i] = context->createSampler(); + } + } +} + +void GL_APIENTRY DeleteSamplers(GLsizei count, const GLuint* samplers) +{ + EVENT("(GLsizei count = %d, const GLuint* samplers = 0x%0.8p)", count, samplers); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (count < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + for (int i = 0; i < count; i++) + { + context->deleteSampler(samplers[i]); + } + } +} + +GLboolean GL_APIENTRY IsSampler(GLuint sampler) +{ + EVENT("(GLuint sampler = %u)", sampler); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return GL_FALSE; + } + + return context->isSampler(sampler); + } + + return GL_FALSE; +} + +void GL_APIENTRY BindSampler(GLuint unit, GLuint sampler) +{ + EVENT("(GLuint unit = %u, GLuint sampler = %u)", unit, sampler); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (sampler != 0 && !context->isSampler(sampler)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (unit >= context->getCaps().maxCombinedTextureImageUnits) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + context->bindSampler(unit, sampler); + } +} + +void GL_APIENTRY SamplerParameteri(GLuint sampler, GLenum pname, GLint param) +{ + EVENT("(GLuint sampler = %u, GLenum pname = 0x%X, GLint param = %d)", sampler, pname, param); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (!ValidateSamplerObjectParameter(context, pname)) + { + return; + } + + if (!ValidateTexParamParameters(context, pname, param)) + { + return; + } + + if (!context->isSampler(sampler)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + context->samplerParameteri(sampler, pname, param); + } +} + +void GL_APIENTRY SamplerParameteriv(GLuint sampler, GLenum pname, const GLint* param) +{ + SamplerParameteri(sampler, pname, *param); +} + +void GL_APIENTRY SamplerParameterf(GLuint sampler, GLenum pname, GLfloat param) +{ + EVENT("(GLuint sampler = %u, GLenum pname = 0x%X, GLfloat param = %g)", sampler, pname, param); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (!ValidateSamplerObjectParameter(context, pname)) + { + return; + } + + if (!ValidateTexParamParameters(context, pname, static_cast(param))) + { + return; + } + + if (!context->isSampler(sampler)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + context->samplerParameterf(sampler, pname, param); + } +} + +void GL_APIENTRY SamplerParameterfv(GLuint sampler, GLenum pname, const GLfloat* param) +{ + SamplerParameterf(sampler, pname, *param); +} + +void GL_APIENTRY GetSamplerParameteriv(GLuint sampler, GLenum pname, GLint* params) +{ + EVENT("(GLuint sampler = %u, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", sampler, pname, params); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (!ValidateSamplerObjectParameter(context, pname)) + { + return; + } + + if (!context->isSampler(sampler)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + *params = context->getSamplerParameteri(sampler, pname); + } +} + +void GL_APIENTRY GetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat* params) +{ + EVENT("(GLuint sample = %ur, GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", sampler, pname, params); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (!ValidateSamplerObjectParameter(context, pname)) + { + return; + } + + if (!context->isSampler(sampler)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + *params = context->getSamplerParameterf(sampler, pname); + } +} + +void GL_APIENTRY VertexAttribDivisor(GLuint index, GLuint divisor) +{ + EVENT("(GLuint index = %u, GLuint divisor = %u)", index, divisor); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (index >= MAX_VERTEX_ATTRIBS) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + context->setVertexAttribDivisor(index, divisor); + } +} + +void GL_APIENTRY BindTransformFeedback(GLenum target, GLuint id) +{ + EVENT("(GLenum target = 0x%X, GLuint id = %u)", target, id); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + switch (target) + { + case GL_TRANSFORM_FEEDBACK: + { + // Cannot bind a transform feedback object if the current one is started and not paused (3.0.2 pg 85 section 2.14.1) + TransformFeedback *curTransformFeedback = context->getState().getCurrentTransformFeedback(); + if (curTransformFeedback && curTransformFeedback->isStarted() && !curTransformFeedback->isPaused()) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + // Cannot bind a transform feedback object that does not exist (3.0.2 pg 85 section 2.14.1) + if (context->getTransformFeedback(id) == NULL) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + context->bindTransformFeedback(id); + } + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + } +} + +void GL_APIENTRY DeleteTransformFeedbacks(GLsizei n, const GLuint* ids) +{ + EVENT("(GLsizei n = %d, const GLuint* ids = 0x%0.8p)", n, ids); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + for (int i = 0; i < n; i++) + { + context->deleteTransformFeedback(ids[i]); + } + } +} + +void GL_APIENTRY GenTransformFeedbacks(GLsizei n, GLuint* ids) +{ + EVENT("(GLsizei n = %d, GLuint* ids = 0x%0.8p)", n, ids); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + for (int i = 0; i < n; i++) + { + ids[i] = context->createTransformFeedback(); + } + } +} + +GLboolean GL_APIENTRY IsTransformFeedback(GLuint id) +{ + EVENT("(GLuint id = %u)", id); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return GL_FALSE; + } + + return ((context->getTransformFeedback(id) != NULL) ? GL_TRUE : GL_FALSE); + } + + return GL_FALSE; +} + +void GL_APIENTRY PauseTransformFeedback(void) +{ + EVENT("(void)"); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback(); + ASSERT(transformFeedback != NULL); + + // Current transform feedback must be started and not paused in order to pause (3.0.2 pg 86) + if (!transformFeedback->isStarted() || transformFeedback->isPaused()) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + transformFeedback->pause(); + } +} + +void GL_APIENTRY ResumeTransformFeedback(void) +{ + EVENT("(void)"); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback(); + ASSERT(transformFeedback != NULL); + + // Current transform feedback must be started and paused in order to resume (3.0.2 pg 86) + if (!transformFeedback->isStarted() || !transformFeedback->isPaused()) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + transformFeedback->resume(); + } +} + +void GL_APIENTRY GetProgramBinary(GLuint program, GLsizei bufSize, GLsizei* length, GLenum* binaryFormat, GLvoid* binary) +{ + EVENT("(GLuint program = %u, GLsizei bufSize = %d, GLsizei* length = 0x%0.8p, GLenum* binaryFormat = 0x%0.8p, GLvoid* binary = 0x%0.8p)", + program, bufSize, length, binaryFormat, binary); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + // TODO: Pipe through to the OES extension for now, needs proper validation + return GetProgramBinaryOES(program, bufSize, length, binaryFormat, binary); + } +} + +void GL_APIENTRY ProgramBinary(GLuint program, GLenum binaryFormat, const GLvoid* binary, GLsizei length) +{ + EVENT("(GLuint program = %u, GLenum binaryFormat = 0x%X, const GLvoid* binary = 0x%0.8p, GLsizei length = %d)", + program, binaryFormat, binary, length); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + // TODO: Pipe through to the OES extension for now, needs proper validation + return ProgramBinaryOES(program, binaryFormat, binary, length); + } +} + +void GL_APIENTRY ProgramParameteri(GLuint program, GLenum pname, GLint value) +{ + EVENT("(GLuint program = %u, GLenum pname = 0x%X, GLint value = %d)", + program, pname, value); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + // glProgramParameteri + UNIMPLEMENTED(); + } +} + +void GL_APIENTRY InvalidateFramebuffer(GLenum target, GLsizei numAttachments, const GLenum* attachments) +{ + EVENT("(GLenum target = 0x%X, GLsizei numAttachments = %d, const GLenum* attachments = 0x%0.8p)", + target, numAttachments, attachments); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (!ValidateInvalidateFramebufferParameters(context, target, numAttachments, attachments)) + { + return; + } + + Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target); + ASSERT(framebuffer); + + if (framebuffer->checkStatus(context->getData()) == GL_FRAMEBUFFER_COMPLETE) + { + Error error = framebuffer->invalidate(numAttachments, attachments); + if (error.isError()) + { + context->recordError(error); + return; + } + } + } +} + +void GL_APIENTRY InvalidateSubFramebuffer(GLenum target, GLsizei numAttachments, const GLenum* attachments, GLint x, GLint y, GLsizei width, GLsizei height) +{ + EVENT("(GLenum target = 0x%X, GLsizei numAttachments = %d, const GLenum* attachments = 0x%0.8p, GLint x = %d, " + "GLint y = %d, GLsizei width = %d, GLsizei height = %d)", + target, numAttachments, attachments, x, y, width, height); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (!ValidateInvalidateFramebufferParameters(context, target, numAttachments, attachments)) + { + return; + } + + Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target); + ASSERT(framebuffer); + + if (framebuffer->checkStatus(context->getData()) == GL_FRAMEBUFFER_COMPLETE) + { + Rectangle area(x, y, width, height); + Error error = framebuffer->invalidateSub(numAttachments, attachments, area); + if (error.isError()) + { + context->recordError(error); + return; + } + } + } +} + +void GL_APIENTRY TexStorage2D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) +{ + EVENT("(GLenum target = 0x%X, GLsizei levels = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)", + target, levels, internalformat, width, height); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (!ValidateES3TexStorageParameters(context, target, levels, internalformat, width, height, 1)) + { + return; + } + + Extents size(width, height, 1); + Texture *texture = context->getTargetTexture(target); + Error error = texture->setStorage(target, levels, internalformat, size); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY TexStorage3D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) +{ + EVENT("(GLenum target = 0x%X, GLsizei levels = %d, GLenum internalformat = 0x%X, GLsizei width = %d, " + "GLsizei height = %d, GLsizei depth = %d)", + target, levels, internalformat, width, height, depth); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + if (!ValidateES3TexStorageParameters(context, target, levels, internalformat, width, height, depth)) + { + return; + } + + Extents size(width, height, depth); + Texture *texture = context->getTargetTexture(target); + Error error = texture->setStorage(target, levels, internalformat, size); + if (error.isError()) + { + context->recordError(error); + return; + } + } +} + +void GL_APIENTRY GetInternalformativ(GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint* params) +{ + EVENT("(GLenum target = 0x%X, GLenum internalformat = 0x%X, GLenum pname = 0x%X, GLsizei bufSize = %d, " + "GLint* params = 0x%0.8p)", + target, internalformat, pname, bufSize, params); + + Context *context = GetValidGlobalContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return; + } + + const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat); + if (!formatCaps.renderable) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + if (target != GL_RENDERBUFFER) + { + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + + if (bufSize < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return; + } + + switch (pname) + { + case GL_NUM_SAMPLE_COUNTS: + if (bufSize != 0) + { + *params = formatCaps.sampleCounts.size(); + } + break; + + case GL_SAMPLES: + { + size_t returnCount = std::min(bufSize, formatCaps.sampleCounts.size()); + auto sampleReverseIt = formatCaps.sampleCounts.rbegin(); + for (size_t sampleIndex = 0; sampleIndex < returnCount; ++sampleIndex) + { + params[sampleIndex] = *sampleReverseIt++;; + } + } + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return; + } + } +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_0.h b/src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_0.h new file mode 100644 index 0000000000..09ca0e4641 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_0.h @@ -0,0 +1,125 @@ +// +// Copyright(c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// entry_points_gles_3_0.h : Defines the GLES 3.0 entry points. + +#ifndef LIBGLESV2_ENTRYPOINTGLES30_H_ +#define LIBGLESV2_ENTRYPOINTGLES30_H_ + +#include +#include + +namespace gl +{ + +ANGLE_EXPORT void GL_APIENTRY ReadBuffer(GLenum mode); +ANGLE_EXPORT void GL_APIENTRY DrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid* indices); +ANGLE_EXPORT void GL_APIENTRY TexImage3D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* pixels); +ANGLE_EXPORT void GL_APIENTRY TexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* pixels); +ANGLE_EXPORT void GL_APIENTRY CopyTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); +ANGLE_EXPORT void GL_APIENTRY CompressedTexImage3D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data); +ANGLE_EXPORT void GL_APIENTRY CompressedTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid* data); +ANGLE_EXPORT void GL_APIENTRY GenQueries(GLsizei n, GLuint* ids); +ANGLE_EXPORT void GL_APIENTRY DeleteQueries(GLsizei n, const GLuint* ids); +ANGLE_EXPORT GLboolean GL_APIENTRY IsQuery(GLuint id); +ANGLE_EXPORT void GL_APIENTRY BeginQuery(GLenum target, GLuint id); +ANGLE_EXPORT void GL_APIENTRY EndQuery(GLenum target); +ANGLE_EXPORT void GL_APIENTRY GetQueryiv(GLenum target, GLenum pname, GLint* params); +ANGLE_EXPORT void GL_APIENTRY GetQueryObjectuiv(GLuint id, GLenum pname, GLuint* params); +ANGLE_EXPORT GLboolean GL_APIENTRY UnmapBuffer(GLenum target); +ANGLE_EXPORT void GL_APIENTRY GetBufferPointerv(GLenum target, GLenum pname, GLvoid** params); +ANGLE_EXPORT void GL_APIENTRY DrawBuffers(GLsizei n, const GLenum* bufs); +ANGLE_EXPORT void GL_APIENTRY UniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +ANGLE_EXPORT void GL_APIENTRY UniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +ANGLE_EXPORT void GL_APIENTRY UniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +ANGLE_EXPORT void GL_APIENTRY UniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +ANGLE_EXPORT void GL_APIENTRY UniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +ANGLE_EXPORT void GL_APIENTRY UniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +ANGLE_EXPORT void GL_APIENTRY BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +ANGLE_EXPORT void GL_APIENTRY RenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); +ANGLE_EXPORT void GL_APIENTRY FramebufferTextureLayer(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); +ANGLE_EXPORT GLvoid* GL_APIENTRY MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access); +ANGLE_EXPORT void GL_APIENTRY FlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length); +ANGLE_EXPORT void GL_APIENTRY BindVertexArray(GLuint array); +ANGLE_EXPORT void GL_APIENTRY DeleteVertexArrays(GLsizei n, const GLuint* arrays); +ANGLE_EXPORT void GL_APIENTRY GenVertexArrays(GLsizei n, GLuint* arrays); +ANGLE_EXPORT GLboolean GL_APIENTRY IsVertexArray(GLuint array); +ANGLE_EXPORT void GL_APIENTRY GetIntegeri_v(GLenum target, GLuint index, GLint* data); +ANGLE_EXPORT void GL_APIENTRY BeginTransformFeedback(GLenum primitiveMode); +ANGLE_EXPORT void GL_APIENTRY EndTransformFeedback(void); +ANGLE_EXPORT void GL_APIENTRY BindBufferRange(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); +ANGLE_EXPORT void GL_APIENTRY BindBufferBase(GLenum target, GLuint index, GLuint buffer); +ANGLE_EXPORT void GL_APIENTRY TransformFeedbackVaryings(GLuint program, GLsizei count, const GLchar* const* varyings, GLenum bufferMode); +ANGLE_EXPORT void GL_APIENTRY GetTransformFeedbackVarying(GLuint program, GLuint index, GLsizei bufSize, GLsizei* length, GLsizei* size, GLenum* type, GLchar* name); +ANGLE_EXPORT void GL_APIENTRY VertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid* pointer); +ANGLE_EXPORT void GL_APIENTRY GetVertexAttribIiv(GLuint index, GLenum pname, GLint* params); +ANGLE_EXPORT void GL_APIENTRY GetVertexAttribIuiv(GLuint index, GLenum pname, GLuint* params); +ANGLE_EXPORT void GL_APIENTRY VertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint w); +ANGLE_EXPORT void GL_APIENTRY VertexAttribI4ui(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); +ANGLE_EXPORT void GL_APIENTRY VertexAttribI4iv(GLuint index, const GLint* v); +ANGLE_EXPORT void GL_APIENTRY VertexAttribI4uiv(GLuint index, const GLuint* v); +ANGLE_EXPORT void GL_APIENTRY GetUniformuiv(GLuint program, GLint location, GLuint* params); +ANGLE_EXPORT GLint GL_APIENTRY GetFragDataLocation(GLuint program, const GLchar *name); +ANGLE_EXPORT void GL_APIENTRY Uniform1ui(GLint location, GLuint v0); +ANGLE_EXPORT void GL_APIENTRY Uniform2ui(GLint location, GLuint v0, GLuint v1); +ANGLE_EXPORT void GL_APIENTRY Uniform3ui(GLint location, GLuint v0, GLuint v1, GLuint v2); +ANGLE_EXPORT void GL_APIENTRY Uniform4ui(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +ANGLE_EXPORT void GL_APIENTRY Uniform1uiv(GLint location, GLsizei count, const GLuint* value); +ANGLE_EXPORT void GL_APIENTRY Uniform2uiv(GLint location, GLsizei count, const GLuint* value); +ANGLE_EXPORT void GL_APIENTRY Uniform3uiv(GLint location, GLsizei count, const GLuint* value); +ANGLE_EXPORT void GL_APIENTRY Uniform4uiv(GLint location, GLsizei count, const GLuint* value); +ANGLE_EXPORT void GL_APIENTRY ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint* value); +ANGLE_EXPORT void GL_APIENTRY ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint* value); +ANGLE_EXPORT void GL_APIENTRY ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat* value); +ANGLE_EXPORT void GL_APIENTRY ClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil); +ANGLE_EXPORT const GLubyte *GL_APIENTRY GetStringi(GLenum name, GLuint index); +ANGLE_EXPORT void GL_APIENTRY CopyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); +ANGLE_EXPORT void GL_APIENTRY GetUniformIndices(GLuint program, GLsizei uniformCount, const GLchar* const* uniformNames, GLuint* uniformIndices); +ANGLE_EXPORT void GL_APIENTRY GetActiveUniformsiv(GLuint program, GLsizei uniformCount, const GLuint* uniformIndices, GLenum pname, GLint* params); +ANGLE_EXPORT GLuint GL_APIENTRY GetUniformBlockIndex(GLuint program, const GLchar* uniformBlockName); +ANGLE_EXPORT void GL_APIENTRY GetActiveUniformBlockiv(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params); +ANGLE_EXPORT void GL_APIENTRY GetActiveUniformBlockName(GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei* length, GLchar* uniformBlockName); +ANGLE_EXPORT void GL_APIENTRY UniformBlockBinding(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding); +ANGLE_EXPORT void GL_APIENTRY DrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount); +ANGLE_EXPORT void GL_APIENTRY DrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices, GLsizei instanceCount); +ANGLE_EXPORT GLsync GL_APIENTRY FenceSync_(GLenum condition, GLbitfield flags); +ANGLE_EXPORT GLboolean GL_APIENTRY IsSync(GLsync sync); +ANGLE_EXPORT void GL_APIENTRY DeleteSync(GLsync sync); +ANGLE_EXPORT GLenum GL_APIENTRY ClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout); +ANGLE_EXPORT void GL_APIENTRY WaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout); +ANGLE_EXPORT void GL_APIENTRY GetInteger64v(GLenum pname, GLint64* params); +ANGLE_EXPORT void GL_APIENTRY GetSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei* length, GLint* values); +ANGLE_EXPORT void GL_APIENTRY GetInteger64i_v(GLenum target, GLuint index, GLint64* data); +ANGLE_EXPORT void GL_APIENTRY GetBufferParameteri64v(GLenum target, GLenum pname, GLint64* params); +ANGLE_EXPORT void GL_APIENTRY GenSamplers(GLsizei count, GLuint* samplers); +ANGLE_EXPORT void GL_APIENTRY DeleteSamplers(GLsizei count, const GLuint* samplers); +ANGLE_EXPORT GLboolean GL_APIENTRY IsSampler(GLuint sampler); +ANGLE_EXPORT void GL_APIENTRY BindSampler(GLuint unit, GLuint sampler); +ANGLE_EXPORT void GL_APIENTRY SamplerParameteri(GLuint sampler, GLenum pname, GLint param); +ANGLE_EXPORT void GL_APIENTRY SamplerParameteriv(GLuint sampler, GLenum pname, const GLint* param); +ANGLE_EXPORT void GL_APIENTRY SamplerParameterf(GLuint sampler, GLenum pname, GLfloat param); +ANGLE_EXPORT void GL_APIENTRY SamplerParameterfv(GLuint sampler, GLenum pname, const GLfloat* param); +ANGLE_EXPORT void GL_APIENTRY GetSamplerParameteriv(GLuint sampler, GLenum pname, GLint* params); +ANGLE_EXPORT void GL_APIENTRY GetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat* params); +ANGLE_EXPORT void GL_APIENTRY VertexAttribDivisor(GLuint index, GLuint divisor); +ANGLE_EXPORT void GL_APIENTRY BindTransformFeedback(GLenum target, GLuint id); +ANGLE_EXPORT void GL_APIENTRY DeleteTransformFeedbacks(GLsizei n, const GLuint* ids); +ANGLE_EXPORT void GL_APIENTRY GenTransformFeedbacks(GLsizei n, GLuint* ids); +ANGLE_EXPORT GLboolean GL_APIENTRY IsTransformFeedback(GLuint id); +ANGLE_EXPORT void GL_APIENTRY PauseTransformFeedback(void); +ANGLE_EXPORT void GL_APIENTRY ResumeTransformFeedback(void); +ANGLE_EXPORT void GL_APIENTRY GetProgramBinary(GLuint program, GLsizei bufSize, GLsizei* length, GLenum* binaryFormat, GLvoid* binary); +ANGLE_EXPORT void GL_APIENTRY ProgramBinary(GLuint program, GLenum binaryFormat, const GLvoid* binary, GLsizei length); +ANGLE_EXPORT void GL_APIENTRY ProgramParameteri(GLuint program, GLenum pname, GLint value); +ANGLE_EXPORT void GL_APIENTRY InvalidateFramebuffer(GLenum target, GLsizei numAttachments, const GLenum* attachments); +ANGLE_EXPORT void GL_APIENTRY InvalidateSubFramebuffer(GLenum target, GLsizei numAttachments, const GLenum* attachments, GLint x, GLint y, GLsizei width, GLsizei height); +ANGLE_EXPORT void GL_APIENTRY TexStorage2D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); +ANGLE_EXPORT void GL_APIENTRY TexStorage3D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); +ANGLE_EXPORT void GL_APIENTRY GetInternalformativ(GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint* params); + +} + +#endif // LIBGLESV2_ENTRYPOINTGLES30_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_0_ext.cpp b/src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_0_ext.cpp new file mode 100644 index 0000000000..6f6983fd91 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_0_ext.cpp @@ -0,0 +1,14 @@ +// +// Copyright(c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// entry_points_gles_3_0_ext.cpp : Implements the GLES 3.0 extension entry points. + +#include "libGLESv2/entry_points_gles_3_0_ext.h" +#include "libGLESv2/global_state.h" + +namespace gl +{ +} diff --git a/src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_0_ext.h b/src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_0_ext.h new file mode 100644 index 0000000000..fec4c1298a --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_0_ext.h @@ -0,0 +1,23 @@ +// +// Copyright(c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// entry_points_gles_3_0_ext.h : Defines the GLES 3.0 extension entry points. + +#ifndef LIBGLESV2_ENTRYPOINTGLES30EXT_H_ +#define LIBGLESV2_ENTRYPOINTGLES30EXT_H_ + +#include +#include +#include + +namespace gl +{ + +// No GLES 3.0 extensions yet + +} + +#endif // LIBGLESV2_ENTRYPOINTGLES30EXT_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/formatutils.cpp b/src/3rdparty/angle/src/libGLESv2/formatutils.cpp deleted file mode 100644 index 8674d5337f..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/formatutils.cpp +++ /dev/null @@ -1,629 +0,0 @@ -// -// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// formatutils.cpp: Queries for GL image formats. - -#include "common/mathutil.h" -#include "libGLESv2/formatutils.h" -#include "libGLESv2/Context.h" -#include "libGLESv2/Framebuffer.h" -#include "libGLESv2/renderer/Renderer.h" -#include "libGLESv2/renderer/imageformats.h" -#include "libGLESv2/renderer/copyimage.h" - -namespace gl -{ - -// ES2 requires that format is equal to internal format at all glTex*Image2D entry points and the implementation -// can decide the true, sized, internal format. The ES2FormatMap determines the internal format for all valid -// format and type combinations. - -FormatType::FormatType() - : internalFormat(GL_NONE), - colorWriteFunction(NULL) -{ -} - -typedef std::pair FormatTypePair; -typedef std::pair FormatPair; -typedef std::map FormatMap; - -// A helper function to insert data into the format map with fewer characters. -static inline void InsertFormatMapping(FormatMap *map, GLenum format, GLenum type, GLenum internalFormat, ColorWriteFunction writeFunc) -{ - FormatType info; - info.internalFormat = internalFormat; - info.colorWriteFunction = writeFunc; - map->insert(FormatPair(FormatTypePair(format, type), info)); -} - -FormatMap BuildFormatMap() -{ - FormatMap map; - - using namespace rx; - - // | Format | Type | Internal format | Color write function | - InsertFormatMapping(&map, GL_RGBA, GL_UNSIGNED_BYTE, GL_RGBA8, WriteColor ); - InsertFormatMapping(&map, GL_RGBA, GL_BYTE, GL_RGBA8_SNORM, WriteColor ); - InsertFormatMapping(&map, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, GL_RGBA4, WriteColor ); - InsertFormatMapping(&map, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, GL_RGB5_A1, WriteColor ); - InsertFormatMapping(&map, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, GL_RGB10_A2, WriteColor ); - InsertFormatMapping(&map, GL_RGBA, GL_FLOAT, GL_RGBA32F, WriteColor); - InsertFormatMapping(&map, GL_RGBA, GL_HALF_FLOAT, GL_RGBA16F, WriteColor); - InsertFormatMapping(&map, GL_RGBA, GL_HALF_FLOAT_OES, GL_RGBA16F, WriteColor); - - InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, GL_RGBA8UI, WriteColor ); - InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_BYTE, GL_RGBA8I, WriteColor ); - InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT, GL_RGBA16UI, WriteColor ); - InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_SHORT, GL_RGBA16I, WriteColor ); - InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_INT, GL_RGBA32UI, WriteColor ); - InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_INT, GL_RGBA32I, WriteColor ); - InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV, GL_RGB10_A2UI, WriteColor ); - - InsertFormatMapping(&map, GL_RGB, GL_UNSIGNED_BYTE, GL_RGB8, WriteColor ); - InsertFormatMapping(&map, GL_RGB, GL_BYTE, GL_RGB8_SNORM, WriteColor ); - InsertFormatMapping(&map, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, GL_RGB565, WriteColor ); - InsertFormatMapping(&map, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV, GL_R11F_G11F_B10F, WriteColor ); - InsertFormatMapping(&map, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV, GL_RGB9_E5, WriteColor ); - InsertFormatMapping(&map, GL_RGB, GL_FLOAT, GL_RGB32F, WriteColor ); - InsertFormatMapping(&map, GL_RGB, GL_HALF_FLOAT, GL_RGB16F, WriteColor ); - InsertFormatMapping(&map, GL_RGB, GL_HALF_FLOAT_OES, GL_RGB16F, WriteColor ); - - InsertFormatMapping(&map, GL_RGB_INTEGER, GL_UNSIGNED_BYTE, GL_RGB8UI, WriteColor ); - InsertFormatMapping(&map, GL_RGB_INTEGER, GL_BYTE, GL_RGB8I, WriteColor ); - InsertFormatMapping(&map, GL_RGB_INTEGER, GL_UNSIGNED_SHORT, GL_RGB16UI, WriteColor ); - InsertFormatMapping(&map, GL_RGB_INTEGER, GL_SHORT, GL_RGB16I, WriteColor ); - InsertFormatMapping(&map, GL_RGB_INTEGER, GL_UNSIGNED_INT, GL_RGB32UI, WriteColor ); - InsertFormatMapping(&map, GL_RGB_INTEGER, GL_INT, GL_RGB32I, WriteColor ); - - InsertFormatMapping(&map, GL_RG, GL_UNSIGNED_BYTE, GL_RG8, WriteColor ); - InsertFormatMapping(&map, GL_RG, GL_BYTE, GL_RG8_SNORM, WriteColor ); - InsertFormatMapping(&map, GL_RG, GL_FLOAT, GL_RG32F, WriteColor ); - InsertFormatMapping(&map, GL_RG, GL_HALF_FLOAT, GL_RG16F, WriteColor ); - InsertFormatMapping(&map, GL_RG, GL_HALF_FLOAT_OES, GL_RG16F, WriteColor ); - - InsertFormatMapping(&map, GL_RG_INTEGER, GL_UNSIGNED_BYTE, GL_RG8UI, WriteColor ); - InsertFormatMapping(&map, GL_RG_INTEGER, GL_BYTE, GL_RG8I, WriteColor ); - InsertFormatMapping(&map, GL_RG_INTEGER, GL_UNSIGNED_SHORT, GL_RG16UI, WriteColor ); - InsertFormatMapping(&map, GL_RG_INTEGER, GL_SHORT, GL_RG16I, WriteColor ); - InsertFormatMapping(&map, GL_RG_INTEGER, GL_UNSIGNED_INT, GL_RG32UI, WriteColor ); - InsertFormatMapping(&map, GL_RG_INTEGER, GL_INT, GL_RG32I, WriteColor ); - - InsertFormatMapping(&map, GL_RED, GL_UNSIGNED_BYTE, GL_R8, WriteColor ); - InsertFormatMapping(&map, GL_RED, GL_BYTE, GL_R8_SNORM, WriteColor ); - InsertFormatMapping(&map, GL_RED, GL_FLOAT, GL_R32F, WriteColor ); - InsertFormatMapping(&map, GL_RED, GL_HALF_FLOAT, GL_R16F, WriteColor ); - InsertFormatMapping(&map, GL_RED, GL_HALF_FLOAT_OES, GL_R16F, WriteColor ); - - InsertFormatMapping(&map, GL_RED_INTEGER, GL_UNSIGNED_BYTE, GL_R8UI, WriteColor ); - InsertFormatMapping(&map, GL_RED_INTEGER, GL_BYTE, GL_R8I, WriteColor ); - InsertFormatMapping(&map, GL_RED_INTEGER, GL_UNSIGNED_SHORT, GL_R16UI, WriteColor ); - InsertFormatMapping(&map, GL_RED_INTEGER, GL_SHORT, GL_R16I, WriteColor ); - InsertFormatMapping(&map, GL_RED_INTEGER, GL_UNSIGNED_INT, GL_R32UI, WriteColor ); - InsertFormatMapping(&map, GL_RED_INTEGER, GL_INT, GL_R32I, WriteColor ); - - InsertFormatMapping(&map, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, GL_LUMINANCE8_ALPHA8_EXT, WriteColor ); - InsertFormatMapping(&map, GL_LUMINANCE, GL_UNSIGNED_BYTE, GL_LUMINANCE8_EXT, WriteColor ); - InsertFormatMapping(&map, GL_ALPHA, GL_UNSIGNED_BYTE, GL_ALPHA8_EXT, WriteColor ); - InsertFormatMapping(&map, GL_LUMINANCE_ALPHA, GL_FLOAT, GL_LUMINANCE_ALPHA32F_EXT, WriteColor ); - InsertFormatMapping(&map, GL_LUMINANCE, GL_FLOAT, GL_LUMINANCE32F_EXT, WriteColor ); - InsertFormatMapping(&map, GL_ALPHA, GL_FLOAT, GL_ALPHA32F_EXT, WriteColor ); - InsertFormatMapping(&map, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT, GL_LUMINANCE_ALPHA16F_EXT, WriteColor ); - InsertFormatMapping(&map, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES, GL_LUMINANCE_ALPHA16F_EXT, WriteColor ); - InsertFormatMapping(&map, GL_LUMINANCE, GL_HALF_FLOAT, GL_LUMINANCE16F_EXT, WriteColor ); - InsertFormatMapping(&map, GL_LUMINANCE, GL_HALF_FLOAT_OES, GL_LUMINANCE16F_EXT, WriteColor ); - InsertFormatMapping(&map, GL_ALPHA, GL_HALF_FLOAT, GL_ALPHA16F_EXT, WriteColor ); - InsertFormatMapping(&map, GL_ALPHA, GL_HALF_FLOAT_OES, GL_ALPHA16F_EXT, WriteColor ); - - InsertFormatMapping(&map, GL_BGRA_EXT, GL_UNSIGNED_BYTE, GL_BGRA8_EXT, WriteColor ); - InsertFormatMapping(&map, GL_BGRA_EXT, GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT, GL_BGRA4_ANGLEX, WriteColor ); - InsertFormatMapping(&map, GL_BGRA_EXT, GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT, GL_BGR5_A1_ANGLEX, WriteColor ); - - InsertFormatMapping(&map, GL_SRGB_EXT, GL_UNSIGNED_BYTE, GL_SRGB8, WriteColor ); - InsertFormatMapping(&map, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE, GL_SRGB8_ALPHA8, WriteColor ); - - InsertFormatMapping(&map, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, NULL ); - InsertFormatMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, NULL ); - InsertFormatMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, GL_UNSIGNED_BYTE, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, NULL ); - InsertFormatMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, GL_UNSIGNED_BYTE, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, NULL ); - - InsertFormatMapping(&map, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, GL_DEPTH_COMPONENT16, NULL ); - InsertFormatMapping(&map, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, GL_DEPTH_COMPONENT32_OES, NULL ); - InsertFormatMapping(&map, GL_DEPTH_COMPONENT, GL_FLOAT, GL_DEPTH_COMPONENT32F, NULL ); - - InsertFormatMapping(&map, GL_STENCIL, GL_UNSIGNED_BYTE, GL_STENCIL_INDEX8, NULL ); - - InsertFormatMapping(&map, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, GL_DEPTH24_STENCIL8, NULL ); - InsertFormatMapping(&map, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, GL_DEPTH32F_STENCIL8, NULL ); - - return map; -} - -Type::Type() - : bytes(0), - specialInterpretation(false) -{ -} - -// Map of sizes of input types -typedef std::pair TypeInfoPair; -typedef std::map TypeInfoMap; - -static inline void InsertTypeInfo(TypeInfoMap *map, GLenum type, GLuint bytes, bool specialInterpretation) -{ - Type info; - info.bytes = bytes; - info.specialInterpretation = specialInterpretation; - - map->insert(std::make_pair(type, info)); -} - -bool operator<(const Type& a, const Type& b) -{ - return memcmp(&a, &b, sizeof(Type)) < 0; -} - -static TypeInfoMap BuildTypeInfoMap() -{ - TypeInfoMap map; - - InsertTypeInfo(&map, GL_UNSIGNED_BYTE, 1, false); - InsertTypeInfo(&map, GL_BYTE, 1, false); - InsertTypeInfo(&map, GL_UNSIGNED_SHORT, 2, false); - InsertTypeInfo(&map, GL_SHORT, 2, false); - InsertTypeInfo(&map, GL_UNSIGNED_INT, 4, false); - InsertTypeInfo(&map, GL_INT, 4, false); - InsertTypeInfo(&map, GL_HALF_FLOAT, 2, false); - InsertTypeInfo(&map, GL_HALF_FLOAT_OES, 2, false); - InsertTypeInfo(&map, GL_FLOAT, 4, false); - InsertTypeInfo(&map, GL_UNSIGNED_SHORT_5_6_5, 2, true ); - InsertTypeInfo(&map, GL_UNSIGNED_SHORT_4_4_4_4, 2, true ); - InsertTypeInfo(&map, GL_UNSIGNED_SHORT_5_5_5_1, 2, true ); - InsertTypeInfo(&map, GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT, 2, true ); - InsertTypeInfo(&map, GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT, 2, true ); - InsertTypeInfo(&map, GL_UNSIGNED_INT_2_10_10_10_REV, 4, true ); - InsertTypeInfo(&map, GL_UNSIGNED_INT_24_8, 4, true ); - InsertTypeInfo(&map, GL_UNSIGNED_INT_10F_11F_11F_REV, 4, true ); - InsertTypeInfo(&map, GL_UNSIGNED_INT_5_9_9_9_REV, 4, true ); - InsertTypeInfo(&map, GL_UNSIGNED_INT_24_8_OES, 4, true ); - InsertTypeInfo(&map, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, 8, true ); - - return map; -} - -// Information about internal formats -static bool AlwaysSupported(GLuint, const Extensions &) -{ - return true; -} - -static bool UnimplementedSupport(GLuint, const Extensions &) -{ - return false; -} - -static bool NeverSupported(GLuint, const Extensions &) -{ - return false; -} - -template -static bool RequireES(GLuint clientVersion, const Extensions &) -{ - return clientVersion >= minCoreGLVersion; -} - -// Pointer to a boolean memeber of the Extensions struct -typedef bool(Extensions::*ExtensionBool); - -// Check support for a single extension -template -static bool RequireExt(GLuint, const Extensions & extensions) -{ - return extensions.*bool1; -} - -// Check for a minimum client version or a single extension -template -static bool RequireESOrExt(GLuint clientVersion, const Extensions &extensions) -{ - return clientVersion >= minCoreGLVersion || extensions.*bool1; -} - -// Check for a minimum client version or two extensions -template -static bool RequireESOrExtAndExt(GLuint clientVersion, const Extensions &extensions) -{ - return clientVersion >= minCoreGLVersion || (extensions.*bool1 && extensions.*bool2); -} - -// Check for a minimum client version or at least one of two extensions -template -static bool RequireESOrExtOrExt(GLuint clientVersion, const Extensions &extensions) -{ - return clientVersion >= minCoreGLVersion || extensions.*bool1 || extensions.*bool2; -} - -// Check support for two extensions -template -static bool RequireExtAndExt(GLuint, const Extensions &extensions) -{ - return extensions.*bool1 && extensions.*bool2; -} - -InternalFormat::InternalFormat() - : redBits(0), - greenBits(0), - blueBits(0), - luminanceBits(0), - alphaBits(0), - sharedBits(0), - depthBits(0), - stencilBits(0), - pixelBytes(0), - componentCount(0), - compressedBlockWidth(0), - compressedBlockHeight(0), - format(GL_NONE), - type(GL_NONE), - componentType(GL_NONE), - colorEncoding(GL_NONE), - compressed(false), - textureSupport(NeverSupported), - renderSupport(NeverSupported), - filterSupport(NeverSupported) -{ -} - -static InternalFormat UnsizedFormat(GLenum format, InternalFormat::SupportCheckFunction textureSupport, - InternalFormat::SupportCheckFunction renderSupport, - InternalFormat::SupportCheckFunction filterSupport) -{ - InternalFormat formatInfo; - formatInfo.format = format; - formatInfo.textureSupport = textureSupport; - formatInfo.renderSupport = renderSupport; - formatInfo.filterSupport = filterSupport; - return formatInfo; -} - -static InternalFormat RGBAFormat(GLuint red, GLuint green, GLuint blue, GLuint alpha, GLuint shared, - GLenum format, GLenum type, GLenum componentType, bool srgb, - InternalFormat::SupportCheckFunction textureSupport, - InternalFormat::SupportCheckFunction renderSupport, - InternalFormat::SupportCheckFunction filterSupport) -{ - InternalFormat formatInfo; - formatInfo.redBits = red; - formatInfo.greenBits = green; - formatInfo.blueBits = blue; - formatInfo.alphaBits = alpha; - formatInfo.sharedBits = shared; - formatInfo.pixelBytes = (red + green + blue + alpha + shared) / 8; - formatInfo.componentCount = ((red > 0) ? 1 : 0) + ((green > 0) ? 1 : 0) + ((blue > 0) ? 1 : 0) + ((alpha > 0) ? 1 : 0); - formatInfo.format = format; - formatInfo.type = type; - formatInfo.componentType = componentType; - formatInfo.colorEncoding = (srgb ? GL_SRGB : GL_LINEAR); - formatInfo.textureSupport = textureSupport; - formatInfo.renderSupport = renderSupport; - formatInfo.filterSupport = filterSupport; - return formatInfo; -} - -static InternalFormat LUMAFormat(GLuint luminance, GLuint alpha, GLenum format, GLenum type, GLenum componentType, - InternalFormat::SupportCheckFunction textureSupport, - InternalFormat::SupportCheckFunction renderSupport, - InternalFormat::SupportCheckFunction filterSupport) -{ - InternalFormat formatInfo; - formatInfo.luminanceBits = luminance; - formatInfo.alphaBits = alpha; - formatInfo.pixelBytes = (luminance + alpha) / 8; - formatInfo.componentCount = ((luminance > 0) ? 1 : 0) + ((alpha > 0) ? 1 : 0); - formatInfo.format = format; - formatInfo.type = type; - formatInfo.componentType = componentType; - formatInfo.colorEncoding = GL_LINEAR; - formatInfo.textureSupport = textureSupport; - formatInfo.renderSupport = renderSupport; - formatInfo.filterSupport = filterSupport; - return formatInfo; -} - -static InternalFormat DepthStencilFormat(GLuint depthBits, GLuint stencilBits, GLuint unusedBits, GLenum format, - GLenum type, GLenum componentType, InternalFormat::SupportCheckFunction textureSupport, - InternalFormat::SupportCheckFunction renderSupport, - InternalFormat::SupportCheckFunction filterSupport) -{ - InternalFormat formatInfo; - formatInfo.depthBits = depthBits; - formatInfo.stencilBits = stencilBits; - formatInfo.pixelBytes = (depthBits + stencilBits + unusedBits) / 8; - formatInfo.componentCount = ((depthBits > 0) ? 1 : 0) + ((stencilBits > 0) ? 1 : 0); - formatInfo.format = format; - formatInfo.type = type; - formatInfo.componentType = componentType; - formatInfo.colorEncoding = GL_LINEAR; - formatInfo.textureSupport = textureSupport; - formatInfo.renderSupport = renderSupport; - formatInfo.filterSupport = filterSupport; - return formatInfo; -} - -static InternalFormat CompressedFormat(GLuint compressedBlockWidth, GLuint compressedBlockHeight, GLuint compressedBlockSize, - GLuint componentCount, GLenum format, GLenum type, bool srgb, - InternalFormat::SupportCheckFunction textureSupport, - InternalFormat::SupportCheckFunction renderSupport, - InternalFormat::SupportCheckFunction filterSupport) -{ - InternalFormat formatInfo; - formatInfo.compressedBlockWidth = compressedBlockWidth; - formatInfo.compressedBlockHeight = compressedBlockHeight; - formatInfo.pixelBytes = compressedBlockSize / 8; - formatInfo.componentCount = componentCount; - formatInfo.format = format; - formatInfo.type = type; - formatInfo.componentType = GL_UNSIGNED_NORMALIZED; - formatInfo.colorEncoding = (srgb ? GL_SRGB : GL_LINEAR); - formatInfo.compressed = true; - formatInfo.textureSupport = textureSupport; - formatInfo.renderSupport = renderSupport; - formatInfo.filterSupport = filterSupport; - return formatInfo; -} - -typedef std::pair InternalFormatInfoPair; -typedef std::map InternalFormatInfoMap; - -static InternalFormatInfoMap BuildInternalFormatInfoMap() -{ - InternalFormatInfoMap map; - - // From ES 3.0.1 spec, table 3.12 - map.insert(InternalFormatInfoPair(GL_NONE, InternalFormat())); - - // | Internal format | | R | G | B | A |S | Format | Type | Component type | SRGB | Texture supported | Renderable | Filterable | - map.insert(InternalFormatInfoPair(GL_R8, RGBAFormat( 8, 0, 0, 0, 0, GL_RED, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, RequireESOrExt<3, &Extensions::textureRG>, RequireESOrExt<3, &Extensions::textureRG>, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_R8_SNORM, RGBAFormat( 8, 0, 0, 0, 0, GL_RED, GL_BYTE, GL_SIGNED_NORMALIZED, false, RequireES<3>, NeverSupported, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_RG8, RGBAFormat( 8, 8, 0, 0, 0, GL_RG, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, RequireESOrExt<3, &Extensions::textureRG>, RequireESOrExt<3, &Extensions::textureRG>, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_RG8_SNORM, RGBAFormat( 8, 8, 0, 0, 0, GL_RG, GL_BYTE, GL_SIGNED_NORMALIZED, false, RequireES<3>, NeverSupported, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_RGB8, RGBAFormat( 8, 8, 8, 0, 0, GL_RGB, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, RequireESOrExt<3, &Extensions::rgb8rgba8>, RequireESOrExt<3, &Extensions::rgb8rgba8>, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_RGB8_SNORM, RGBAFormat( 8, 8, 8, 0, 0, GL_RGB, GL_BYTE, GL_SIGNED_NORMALIZED, false, RequireES<3>, NeverSupported, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_RGB565, RGBAFormat( 5, 6, 5, 0, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_NORMALIZED, false, RequireES<2>, RequireES<2>, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_RGBA4, RGBAFormat( 4, 4, 4, 4, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_NORMALIZED, false, RequireES<2>, RequireES<2>, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_RGB5_A1, RGBAFormat( 5, 5, 5, 1, 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, GL_UNSIGNED_NORMALIZED, false, RequireES<2>, RequireES<2>, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_RGBA8, RGBAFormat( 8, 8, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, RequireESOrExt<3, &Extensions::rgb8rgba8>, RequireESOrExt<3, &Extensions::rgb8rgba8>, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_RGBA8_SNORM, RGBAFormat( 8, 8, 8, 8, 0, GL_RGBA, GL_BYTE, GL_SIGNED_NORMALIZED, false, RequireES<3>, NeverSupported, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_RGB10_A2, RGBAFormat(10, 10, 10, 2, 0, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, GL_UNSIGNED_NORMALIZED, false, RequireES<3>, RequireES<3>, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_RGB10_A2UI, RGBAFormat(10, 10, 10, 2, 0, GL_RGBA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV, GL_UNSIGNED_INT, false, RequireES<3>, NeverSupported, NeverSupported))); - map.insert(InternalFormatInfoPair(GL_SRGB8, RGBAFormat( 8, 8, 8, 0, 0, GL_RGB, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, true, RequireESOrExt<3, &Extensions::sRGB>, NeverSupported, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_SRGB8_ALPHA8, RGBAFormat( 8, 8, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, true, RequireESOrExt<3, &Extensions::sRGB>, RequireESOrExt<3, &Extensions::sRGB>, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_R11F_G11F_B10F, RGBAFormat(11, 11, 10, 0, 0, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV, GL_FLOAT, false, RequireES<3>, RequireExt<&Extensions::colorBufferFloat>, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_RGB9_E5, RGBAFormat( 9, 9, 9, 0, 5, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV, GL_FLOAT, false, RequireES<3>, NeverSupported, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_R8I, RGBAFormat( 8, 0, 0, 0, 0, GL_RED_INTEGER, GL_BYTE, GL_INT, false, RequireES<3>, RequireES<3>, NeverSupported))); - map.insert(InternalFormatInfoPair(GL_R8UI, RGBAFormat( 8, 0, 0, 0, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, GL_UNSIGNED_INT, false, RequireES<3>, RequireES<3>, NeverSupported))); - map.insert(InternalFormatInfoPair(GL_R16I, RGBAFormat(16, 0, 0, 0, 0, GL_RED_INTEGER, GL_SHORT, GL_INT, false, RequireES<3>, RequireES<3>, NeverSupported))); - map.insert(InternalFormatInfoPair(GL_R16UI, RGBAFormat(16, 0, 0, 0, 0, GL_RED_INTEGER, GL_UNSIGNED_SHORT, GL_UNSIGNED_INT, false, RequireES<3>, RequireES<3>, NeverSupported))); - map.insert(InternalFormatInfoPair(GL_R32I, RGBAFormat(32, 0, 0, 0, 0, GL_RED_INTEGER, GL_INT, GL_INT, false, RequireES<3>, RequireES<3>, NeverSupported))); - map.insert(InternalFormatInfoPair(GL_R32UI, RGBAFormat(32, 0, 0, 0, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, GL_UNSIGNED_INT, false, RequireES<3>, RequireES<3>, NeverSupported))); - map.insert(InternalFormatInfoPair(GL_RG8I, RGBAFormat( 8, 8, 0, 0, 0, GL_RG_INTEGER, GL_BYTE, GL_INT, false, RequireES<3>, RequireES<3>, NeverSupported))); - map.insert(InternalFormatInfoPair(GL_RG8UI, RGBAFormat( 8, 8, 0, 0, 0, GL_RG_INTEGER, GL_UNSIGNED_BYTE, GL_UNSIGNED_INT, false, RequireES<3>, RequireES<3>, NeverSupported))); - map.insert(InternalFormatInfoPair(GL_RG16I, RGBAFormat(16, 16, 0, 0, 0, GL_RG_INTEGER, GL_SHORT, GL_INT, false, RequireES<3>, RequireES<3>, NeverSupported))); - map.insert(InternalFormatInfoPair(GL_RG16UI, RGBAFormat(16, 16, 0, 0, 0, GL_RG_INTEGER, GL_UNSIGNED_SHORT, GL_UNSIGNED_INT, false, RequireES<3>, RequireES<3>, NeverSupported))); - map.insert(InternalFormatInfoPair(GL_RG32I, RGBAFormat(32, 32, 0, 0, 0, GL_RG_INTEGER, GL_INT, GL_INT, false, RequireES<3>, RequireES<3>, NeverSupported))); - map.insert(InternalFormatInfoPair(GL_RG32UI, RGBAFormat(32, 32, 0, 0, 0, GL_RG_INTEGER, GL_UNSIGNED_INT, GL_UNSIGNED_INT, false, RequireES<3>, RequireES<3>, NeverSupported))); - map.insert(InternalFormatInfoPair(GL_RGB8I, RGBAFormat( 8, 8, 8, 0, 0, GL_RGB_INTEGER, GL_BYTE, GL_INT, false, RequireES<3>, NeverSupported, NeverSupported))); - map.insert(InternalFormatInfoPair(GL_RGB8UI, RGBAFormat( 8, 8, 8, 0, 0, GL_RGB_INTEGER, GL_UNSIGNED_BYTE, GL_UNSIGNED_INT, false, RequireES<3>, NeverSupported, NeverSupported))); - map.insert(InternalFormatInfoPair(GL_RGB16I, RGBAFormat(16, 16, 16, 0, 0, GL_RGB_INTEGER, GL_SHORT, GL_INT, false, RequireES<3>, NeverSupported, NeverSupported))); - map.insert(InternalFormatInfoPair(GL_RGB16UI, RGBAFormat(16, 16, 16, 0, 0, GL_RGB_INTEGER, GL_UNSIGNED_SHORT, GL_UNSIGNED_INT, false, RequireES<3>, NeverSupported, NeverSupported))); - map.insert(InternalFormatInfoPair(GL_RGB32I, RGBAFormat(32, 32, 32, 0, 0, GL_RGB_INTEGER, GL_INT, GL_INT, false, RequireES<3>, NeverSupported, NeverSupported))); - map.insert(InternalFormatInfoPair(GL_RGB32UI, RGBAFormat(32, 32, 32, 0, 0, GL_RGB_INTEGER, GL_UNSIGNED_INT, GL_UNSIGNED_INT, false, RequireES<3>, NeverSupported, NeverSupported))); - map.insert(InternalFormatInfoPair(GL_RGBA8I, RGBAFormat( 8, 8, 8, 8, 0, GL_RGBA_INTEGER, GL_BYTE, GL_INT, false, RequireES<3>, RequireES<3>, NeverSupported))); - map.insert(InternalFormatInfoPair(GL_RGBA8UI, RGBAFormat( 8, 8, 8, 8, 0, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, GL_UNSIGNED_INT, false, RequireES<3>, RequireES<3>, NeverSupported))); - map.insert(InternalFormatInfoPair(GL_RGBA16I, RGBAFormat(16, 16, 16, 16, 0, GL_RGBA_INTEGER, GL_SHORT, GL_INT, false, RequireES<3>, RequireES<3>, NeverSupported))); - map.insert(InternalFormatInfoPair(GL_RGBA16UI, RGBAFormat(16, 16, 16, 16, 0, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT, GL_UNSIGNED_INT, false, RequireES<3>, RequireES<3>, NeverSupported))); - map.insert(InternalFormatInfoPair(GL_RGBA32I, RGBAFormat(32, 32, 32, 32, 0, GL_RGBA_INTEGER, GL_INT, GL_INT, false, RequireES<3>, RequireES<3>, NeverSupported))); - map.insert(InternalFormatInfoPair(GL_RGBA32UI, RGBAFormat(32, 32, 32, 32, 0, GL_RGBA_INTEGER, GL_UNSIGNED_INT, GL_UNSIGNED_INT, false, RequireES<3>, RequireES<3>, NeverSupported))); - - map.insert(InternalFormatInfoPair(GL_BGRA8_EXT, RGBAFormat( 8, 8, 8, 8, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, RequireExt<&Extensions::textureFormatBGRA8888>, RequireExt<&Extensions::textureFormatBGRA8888>, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_BGRA4_ANGLEX, RGBAFormat( 4, 4, 4, 4, 0, GL_BGRA_EXT, GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT, GL_UNSIGNED_NORMALIZED, false, RequireExt<&Extensions::textureFormatBGRA8888>, RequireExt<&Extensions::textureFormatBGRA8888>, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_BGR5_A1_ANGLEX, RGBAFormat( 5, 5, 5, 1, 0, GL_BGRA_EXT, GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT, GL_UNSIGNED_NORMALIZED, false, RequireExt<&Extensions::textureFormatBGRA8888>, RequireExt<&Extensions::textureFormatBGRA8888>, AlwaysSupported))); - - // Floating point renderability and filtering is provided by OES_texture_float and OES_texture_half_float - // | Internal format | | D |S | Format | Type | Comp | SRGB | Texture supported | Renderable | Filterable | - // | | | | | | | type | | | | | - map.insert(InternalFormatInfoPair(GL_R16F, RGBAFormat(16, 0, 0, 0, 0, GL_RED, GL_HALF_FLOAT, GL_FLOAT, false, RequireESOrExtAndExt<3, &Extensions::textureHalfFloat, &Extensions::textureRG>, RequireESOrExtAndExt<3, &Extensions::textureHalfFloat, &Extensions::textureRG>, RequireExt<&Extensions::textureHalfFloatLinear>))); - map.insert(InternalFormatInfoPair(GL_RG16F, RGBAFormat(16, 16, 0, 0, 0, GL_RG, GL_HALF_FLOAT, GL_FLOAT, false, RequireESOrExtAndExt<3, &Extensions::textureHalfFloat, &Extensions::textureRG>, RequireESOrExtAndExt<3, &Extensions::textureHalfFloat, &Extensions::textureRG>, RequireExt<&Extensions::textureHalfFloatLinear>))); - map.insert(InternalFormatInfoPair(GL_RGB16F, RGBAFormat(16, 16, 16, 0, 0, GL_RGB, GL_HALF_FLOAT, GL_FLOAT, false, RequireESOrExt<3, &Extensions::textureHalfFloat>, RequireESOrExt<3, &Extensions::textureHalfFloat>, RequireExt<&Extensions::textureHalfFloatLinear>))); - map.insert(InternalFormatInfoPair(GL_RGBA16F, RGBAFormat(16, 16, 16, 16, 0, GL_RGBA, GL_HALF_FLOAT, GL_FLOAT, false, RequireESOrExt<3, &Extensions::textureHalfFloat>, RequireESOrExt<3, &Extensions::textureHalfFloat>, RequireExt<&Extensions::textureHalfFloatLinear>))); - map.insert(InternalFormatInfoPair(GL_R32F, RGBAFormat(32, 0, 0, 0, 0, GL_RED, GL_FLOAT, GL_FLOAT, false, RequireESOrExtAndExt<3, &Extensions::textureFloat, &Extensions::textureRG>, RequireESOrExtAndExt<3, &Extensions::textureFloat, &Extensions::textureRG>, RequireExt<&Extensions::textureFloatLinear> ))); - map.insert(InternalFormatInfoPair(GL_RG32F, RGBAFormat(32, 32, 0, 0, 0, GL_RG, GL_FLOAT, GL_FLOAT, false, RequireESOrExtAndExt<3, &Extensions::textureFloat, &Extensions::textureRG>, RequireESOrExtAndExt<3, &Extensions::textureFloat, &Extensions::textureRG>, RequireExt<&Extensions::textureFloatLinear> ))); - map.insert(InternalFormatInfoPair(GL_RGB32F, RGBAFormat(32, 32, 32, 0, 0, GL_RGB, GL_FLOAT, GL_FLOAT, false, RequireESOrExt<3, &Extensions::textureFloat>, RequireESOrExt<3, &Extensions::textureFloat>, RequireExt<&Extensions::textureFloatLinear> ))); - map.insert(InternalFormatInfoPair(GL_RGBA32F, RGBAFormat(32, 32, 32, 32, 0, GL_RGBA, GL_FLOAT, GL_FLOAT, false, RequireESOrExt<3, &Extensions::textureFloat>, RequireESOrExt<3, &Extensions::textureFloat>, RequireExt<&Extensions::textureFloatLinear> ))); - - // Depth stencil formats - // | Internal format | | D |S | X | Format | Type | Component type | Supported | Renderable | Filterable | - map.insert(InternalFormatInfoPair(GL_DEPTH_COMPONENT16, DepthStencilFormat(16, 0, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, GL_UNSIGNED_NORMALIZED, RequireES<2>, RequireES<2>, RequireESOrExt<3, &Extensions::depthTextures>))); - map.insert(InternalFormatInfoPair(GL_DEPTH_COMPONENT24, DepthStencilFormat(24, 0, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, GL_UNSIGNED_NORMALIZED, RequireES<3>, RequireES<3>, RequireESOrExt<3, &Extensions::depthTextures>))); - map.insert(InternalFormatInfoPair(GL_DEPTH_COMPONENT32F, DepthStencilFormat(32, 0, 0, GL_DEPTH_COMPONENT, GL_FLOAT, GL_FLOAT, RequireES<3>, RequireES<3>, RequireESOrExt<3, &Extensions::depthTextures>))); - map.insert(InternalFormatInfoPair(GL_DEPTH_COMPONENT32_OES, DepthStencilFormat(32, 0, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, GL_UNSIGNED_NORMALIZED, RequireExt<&Extensions::depthTextures>, RequireExt<&Extensions::depthTextures>, AlwaysSupported ))); - map.insert(InternalFormatInfoPair(GL_DEPTH24_STENCIL8, DepthStencilFormat(24, 8, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, GL_UNSIGNED_NORMALIZED, RequireESOrExt<3, &Extensions::depthTextures>, RequireESOrExtOrExt<3, &Extensions::depthTextures, &Extensions::packedDepthStencil>, AlwaysSupported ))); - map.insert(InternalFormatInfoPair(GL_DEPTH32F_STENCIL8, DepthStencilFormat(32, 8, 24, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, GL_FLOAT, RequireES<3>, RequireES<3>, AlwaysSupported ))); - map.insert(InternalFormatInfoPair(GL_STENCIL_INDEX8, DepthStencilFormat( 0, 8, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_BYTE, GL_UNSIGNED_INT, RequireES<2>, RequireES<2>, NeverSupported ))); - - // Luminance alpha formats - // | Internal format | | L | A | Format | Type | Component type | Supported | Renderable | Filterable | - map.insert(InternalFormatInfoPair(GL_ALPHA8_EXT, LUMAFormat( 0, 8, GL_ALPHA, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, RequireExt<&Extensions::textureStorage>, NeverSupported, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_LUMINANCE8_EXT, LUMAFormat( 8, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, RequireExt<&Extensions::textureStorage>, NeverSupported, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_ALPHA32F_EXT, LUMAFormat( 0, 32, GL_ALPHA, GL_FLOAT, GL_FLOAT, RequireExtAndExt<&Extensions::textureStorage, &Extensions::textureFloat>, NeverSupported, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_LUMINANCE32F_EXT, LUMAFormat(32, 0, GL_LUMINANCE, GL_FLOAT, GL_FLOAT, RequireExtAndExt<&Extensions::textureStorage, &Extensions::textureFloat>, NeverSupported, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_ALPHA16F_EXT, LUMAFormat( 0, 16, GL_ALPHA, GL_HALF_FLOAT, GL_FLOAT, RequireExtAndExt<&Extensions::textureStorage, &Extensions::textureHalfFloat>, NeverSupported, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_LUMINANCE16F_EXT, LUMAFormat(16, 0, GL_LUMINANCE, GL_HALF_FLOAT, GL_FLOAT, RequireExtAndExt<&Extensions::textureStorage, &Extensions::textureHalfFloat>, NeverSupported, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_LUMINANCE8_ALPHA8_EXT, LUMAFormat( 8, 8, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, RequireExt<&Extensions::textureStorage>, NeverSupported, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_LUMINANCE_ALPHA32F_EXT, LUMAFormat(32, 32, GL_LUMINANCE_ALPHA, GL_FLOAT, GL_FLOAT, RequireExtAndExt<&Extensions::textureStorage, &Extensions::textureFloat>, NeverSupported, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_LUMINANCE_ALPHA16F_EXT, LUMAFormat(16, 16, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT, GL_FLOAT, RequireExtAndExt<&Extensions::textureStorage, &Extensions::textureHalfFloat>, NeverSupported, AlwaysSupported))); - - // Unsized formats - // | Internal format | | Format | Supported | Renderable | Filterable | - map.insert(InternalFormatInfoPair(GL_ALPHA, UnsizedFormat(GL_ALPHA, RequireES<2>, NeverSupported, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_LUMINANCE, UnsizedFormat(GL_LUMINANCE, RequireES<2>, NeverSupported, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_LUMINANCE_ALPHA, UnsizedFormat(GL_LUMINANCE_ALPHA, RequireES<2>, NeverSupported, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_RED, UnsizedFormat(GL_RED, RequireESOrExt<3, &Extensions::textureRG>, NeverSupported, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_RG, UnsizedFormat(GL_RG, RequireESOrExt<3, &Extensions::textureRG>, NeverSupported, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_RGB, UnsizedFormat(GL_RGB, RequireES<2>, RequireES<2>, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_RGBA, UnsizedFormat(GL_RGBA, RequireES<2>, RequireES<2>, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_RED_INTEGER, UnsizedFormat(GL_RED_INTEGER, RequireES<3>, NeverSupported, NeverSupported ))); - map.insert(InternalFormatInfoPair(GL_RG_INTEGER, UnsizedFormat(GL_RG_INTEGER, RequireES<3>, NeverSupported, NeverSupported ))); - map.insert(InternalFormatInfoPair(GL_RGB_INTEGER, UnsizedFormat(GL_RGB_INTEGER, RequireES<3>, NeverSupported, NeverSupported ))); - map.insert(InternalFormatInfoPair(GL_RGBA_INTEGER, UnsizedFormat(GL_RGBA_INTEGER, RequireES<3>, NeverSupported, NeverSupported ))); - map.insert(InternalFormatInfoPair(GL_BGRA_EXT, UnsizedFormat(GL_BGRA_EXT, RequireExt<&Extensions::textureFormatBGRA8888>, RequireExt<&Extensions::textureFormatBGRA8888>, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_DEPTH_COMPONENT, UnsizedFormat(GL_DEPTH_COMPONENT, RequireES<2>, RequireES<2>, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_DEPTH_STENCIL, UnsizedFormat(GL_DEPTH_STENCIL, RequireESOrExt<3, &Extensions::packedDepthStencil>, RequireESOrExt<3, &Extensions::packedDepthStencil>, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_SRGB_EXT, UnsizedFormat(GL_RGB, RequireESOrExt<3, &Extensions::sRGB>, NeverSupported, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_SRGB_ALPHA_EXT, UnsizedFormat(GL_RGBA, RequireESOrExt<3, &Extensions::sRGB>, RequireESOrExt<3, &Extensions::sRGB>, AlwaysSupported))); - - // Compressed formats, From ES 3.0.1 spec, table 3.16 - // | Internal format | |W |H | BS |CC| Format | Type | SRGB | Supported | Renderable | Filterable | - map.insert(InternalFormatInfoPair(GL_COMPRESSED_R11_EAC, CompressedFormat(4, 4, 64, 1, GL_COMPRESSED_R11_EAC, GL_UNSIGNED_BYTE, false, UnimplementedSupport, UnimplementedSupport, UnimplementedSupport))); - map.insert(InternalFormatInfoPair(GL_COMPRESSED_SIGNED_R11_EAC, CompressedFormat(4, 4, 64, 1, GL_COMPRESSED_SIGNED_R11_EAC, GL_UNSIGNED_BYTE, false, UnimplementedSupport, UnimplementedSupport, UnimplementedSupport))); - map.insert(InternalFormatInfoPair(GL_COMPRESSED_RG11_EAC, CompressedFormat(4, 4, 128, 2, GL_COMPRESSED_RG11_EAC, GL_UNSIGNED_BYTE, false, UnimplementedSupport, UnimplementedSupport, UnimplementedSupport))); - map.insert(InternalFormatInfoPair(GL_COMPRESSED_SIGNED_RG11_EAC, CompressedFormat(4, 4, 128, 2, GL_COMPRESSED_SIGNED_RG11_EAC, GL_UNSIGNED_BYTE, false, UnimplementedSupport, UnimplementedSupport, UnimplementedSupport))); - map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGB8_ETC2, CompressedFormat(4, 4, 64, 3, GL_COMPRESSED_RGB8_ETC2, GL_UNSIGNED_BYTE, false, UnimplementedSupport, UnimplementedSupport, UnimplementedSupport))); - map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_ETC2, CompressedFormat(4, 4, 64, 3, GL_COMPRESSED_SRGB8_ETC2, GL_UNSIGNED_BYTE, true, UnimplementedSupport, UnimplementedSupport, UnimplementedSupport))); - map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, CompressedFormat(4, 4, 64, 3, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_UNSIGNED_BYTE, false, UnimplementedSupport, UnimplementedSupport, UnimplementedSupport))); - map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, CompressedFormat(4, 4, 64, 3, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_UNSIGNED_BYTE, true, UnimplementedSupport, UnimplementedSupport, UnimplementedSupport))); - map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA8_ETC2_EAC, CompressedFormat(4, 4, 128, 4, GL_COMPRESSED_RGBA8_ETC2_EAC, GL_UNSIGNED_BYTE, false, UnimplementedSupport, UnimplementedSupport, UnimplementedSupport))); - map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, CompressedFormat(4, 4, 128, 4, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, GL_UNSIGNED_BYTE, true, UnimplementedSupport, UnimplementedSupport, UnimplementedSupport))); - - // From GL_EXT_texture_compression_dxt1 - // | Internal format | |W |H | BS |CC| Format | Type | SRGB | Supported | Renderable | Filterable | - map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGB_S3TC_DXT1_EXT, CompressedFormat(4, 4, 64, 3, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, false, RequireExt<&Extensions::textureCompressionDXT1>, NeverSupported, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, CompressedFormat(4, 4, 64, 4, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, false, RequireExt<&Extensions::textureCompressionDXT1>, NeverSupported, AlwaysSupported))); - - // From GL_ANGLE_texture_compression_dxt3 - map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, CompressedFormat(4, 4, 128, 4, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, GL_UNSIGNED_BYTE, false, RequireExt<&Extensions::textureCompressionDXT5>, NeverSupported, AlwaysSupported))); - - // From GL_ANGLE_texture_compression_dxt5 - map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, CompressedFormat(4, 4, 128, 4, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, GL_UNSIGNED_BYTE, false, RequireExt<&Extensions::textureCompressionDXT5>, NeverSupported, AlwaysSupported))); - - return map; -} - -static const InternalFormatInfoMap &GetInternalFormatMap() -{ - static const InternalFormatInfoMap formatMap = BuildInternalFormatInfoMap(); - return formatMap; -} - -static FormatSet BuildAllSizedInternalFormatSet() -{ - FormatSet result; - - const InternalFormatInfoMap &formats = GetInternalFormatMap(); - for (InternalFormatInfoMap::const_iterator i = formats.begin(); i != formats.end(); i++) - { - if (i->second.pixelBytes > 0) - { - result.insert(i->first); - } - } - - return result; -} - -const FormatType &GetFormatTypeInfo(GLenum format, GLenum type) -{ - static const FormatMap formatMap = BuildFormatMap(); - FormatMap::const_iterator iter = formatMap.find(FormatTypePair(format, type)); - if (iter != formatMap.end()) - { - return iter->second; - } - else - { - static const FormatType defaultInfo; - return defaultInfo; - } -} - -const Type &GetTypeInfo(GLenum type) -{ - static const TypeInfoMap infoMap = BuildTypeInfoMap(); - TypeInfoMap::const_iterator iter = infoMap.find(type); - if (iter != infoMap.end()) - { - return iter->second; - } - else - { - static const Type defaultInfo; - return defaultInfo; - } -} - -const InternalFormat &GetInternalFormatInfo(GLenum internalFormat) -{ - const InternalFormatInfoMap &formatMap = GetInternalFormatMap(); - InternalFormatInfoMap::const_iterator iter = formatMap.find(internalFormat); - if (iter != formatMap.end()) - { - return iter->second; - } - else - { - static const InternalFormat defaultInternalFormat; - return defaultInternalFormat; - } -} - -GLuint InternalFormat::computeRowPitch(GLenum type, GLsizei width, GLint alignment) const -{ - ASSERT(alignment > 0 && isPow2(alignment)); - return rx::roundUp(computeBlockSize(type, width, 1), static_cast(alignment)); -} - -GLuint InternalFormat::computeDepthPitch(GLenum type, GLsizei width, GLsizei height, GLint alignment) const -{ - return computeRowPitch(type, width, alignment) * height; -} - -GLuint InternalFormat::computeBlockSize(GLenum type, GLsizei width, GLsizei height) const -{ - if (compressed) - { - GLsizei numBlocksWide = (width + compressedBlockWidth - 1) / compressedBlockWidth; - GLsizei numBlocksHight = (height + compressedBlockHeight - 1) / compressedBlockHeight; - return (pixelBytes * numBlocksWide * numBlocksHight); - } - else - { - const Type &typeInfo = GetTypeInfo(type); - if (typeInfo.specialInterpretation) - { - return typeInfo.bytes * width * height; - } - else - { - return componentCount * typeInfo.bytes * width * height; - } - } -} - -GLenum GetSizedInternalFormat(GLenum internalFormat, GLenum type) -{ - const InternalFormat& formatInfo = GetInternalFormatInfo(internalFormat); - return (formatInfo.pixelBytes > 0) ? internalFormat : GetFormatTypeInfo(internalFormat, type).internalFormat; -} - -const FormatSet &GetAllSizedInternalFormats() -{ - static FormatSet formatSet = BuildAllSizedInternalFormatSet(); - return formatSet; -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/formatutils.h b/src/3rdparty/angle/src/libGLESv2/formatutils.h deleted file mode 100644 index 25106a52e5..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/formatutils.h +++ /dev/null @@ -1,106 +0,0 @@ -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// formatutils.h: Queries for GL image formats. - -#ifndef LIBGLESV2_FORMATUTILS_H_ -#define LIBGLESV2_FORMATUTILS_H_ - -#include "libGLESv2/Caps.h" -#include "libGLESv2/angletypes.h" - -#include "angle_gl.h" - -#include -#include - -typedef void (*MipGenerationFunction)(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth, - const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch, - uint8_t *destData, size_t destRowPitch, size_t destDepthPitch); - -typedef void (*LoadImageFunction)(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); - -typedef void (*InitializeTextureDataFunction)(size_t width, size_t height, size_t depth, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); - -typedef void (*ColorReadFunction)(const uint8_t *source, uint8_t *dest); -typedef void (*ColorWriteFunction)(const uint8_t *source, uint8_t *dest); -typedef void (*ColorCopyFunction)(const uint8_t *source, uint8_t *dest); - -typedef void (*VertexCopyFunction)(const uint8_t *input, size_t stride, size_t count, uint8_t *output); - -namespace gl -{ - -struct FormatType -{ - FormatType(); - - GLenum internalFormat; - ColorWriteFunction colorWriteFunction; -}; -const FormatType &GetFormatTypeInfo(GLenum format, GLenum type); - -struct Type -{ - Type(); - - GLuint bytes; - bool specialInterpretation; -}; -const Type &GetTypeInfo(GLenum type); - -struct InternalFormat -{ - InternalFormat(); - - GLuint redBits; - GLuint greenBits; - GLuint blueBits; - - GLuint luminanceBits; - - GLuint alphaBits; - GLuint sharedBits; - - GLuint depthBits; - GLuint stencilBits; - - GLuint pixelBytes; - - GLuint componentCount; - - bool compressed; - GLuint compressedBlockWidth; - GLuint compressedBlockHeight; - - GLenum format; - GLenum type; - - GLenum componentType; - GLenum colorEncoding; - - typedef bool (*SupportCheckFunction)(GLuint, const Extensions &); - SupportCheckFunction textureSupport; - SupportCheckFunction renderSupport; - SupportCheckFunction filterSupport; - - GLuint computeRowPitch(GLenum type, GLsizei width, GLint alignment) const; - GLuint computeDepthPitch(GLenum type, GLsizei width, GLsizei height, GLint alignment) const; - GLuint computeBlockSize(GLenum type, GLsizei width, GLsizei height) const; -}; -const InternalFormat &GetInternalFormatInfo(GLenum internalFormat); - -GLenum GetSizedInternalFormat(GLenum internalFormat, GLenum type); - -typedef std::set FormatSet; -const FormatSet &GetAllSizedInternalFormats(); - -} - -#endif // LIBGLESV2_FORMATUTILS_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/global_state.cpp b/src/3rdparty/angle/src/libGLESv2/global_state.cpp new file mode 100644 index 0000000000..686f0bf49b --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/global_state.cpp @@ -0,0 +1,235 @@ +// +// Copyright(c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// global_state.cpp : Implements functions for querying the thread-local GL and EGL state. + +#include "libGLESv2/global_state.h" + +#include "libANGLE/Context.h" +#include "libANGLE/Error.h" + +#include "common/debug.h" +#include "common/platform.h" +#include "common/tls.h" + +namespace +{ + +static TLSIndex currentTLS = TLS_INVALID_INDEX; + +struct Current +{ + EGLint error; + EGLenum API; + egl::Display *display; + egl::Surface *drawSurface; + egl::Surface *readSurface; + gl::Context *context; +}; + +Current *AllocateCurrent() +{ + ASSERT(currentTLS != TLS_INVALID_INDEX); + if (currentTLS == TLS_INVALID_INDEX) + { + return NULL; + } + + Current *current = new Current(); + current->error = EGL_SUCCESS; + current->API = EGL_OPENGL_ES_API; + current->display = reinterpret_cast(EGL_NO_DISPLAY); + current->drawSurface = reinterpret_cast(EGL_NO_SURFACE); + current->readSurface = reinterpret_cast(EGL_NO_SURFACE); + current->context = reinterpret_cast(EGL_NO_CONTEXT); + + if (!SetTLSValue(currentTLS, current)) + { + ERR("Could not set thread local storage."); + return NULL; + } + + return current; +} + +void DeallocateCurrent() +{ + Current *current = reinterpret_cast(GetTLSValue(currentTLS)); + SafeDelete(current); + SetTLSValue(currentTLS, NULL); +} + +Current *GetCurrentData() +{ + // Create a TLS index if one has not been created for this DLL + if (currentTLS == TLS_INVALID_INDEX) + { + currentTLS = CreateTLSIndex(); + } + + Current *current = reinterpret_cast(GetTLSValue(currentTLS)); + + // ANGLE issue 488: when the dll is loaded after thread initialization, + // thread local storage (current) might not exist yet. + return (current ? current : AllocateCurrent()); +} + +#ifdef ANGLE_PLATFORM_WINDOWS +extern "C" BOOL WINAPI DllMain(HINSTANCE, DWORD reason, LPVOID) +{ + switch (reason) + { + case DLL_PROCESS_ATTACH: + currentTLS = CreateTLSIndex(); + if (currentTLS == TLS_INVALID_INDEX) + { + return FALSE; + } + AllocateCurrent(); + break; + + case DLL_THREAD_ATTACH: + AllocateCurrent(); + break; + + case DLL_THREAD_DETACH: + DeallocateCurrent(); + break; + + case DLL_PROCESS_DETACH: + DeallocateCurrent(); + if (currentTLS != TLS_INVALID_INDEX) + { + DestroyTLSIndex(currentTLS); + currentTLS = TLS_INVALID_INDEX; + } + break; + } + + return TRUE; +} +#endif + +} + +namespace gl +{ + +Context *GetGlobalContext() +{ + Current *current = GetCurrentData(); + + return current->context; +} + +Context *GetValidGlobalContext() +{ + gl::Context *context = GetGlobalContext(); + if (context) + { + if (context->isContextLost()) + { + context->recordError(gl::Error(GL_OUT_OF_MEMORY, "Context has been lost.")); + return nullptr; + } + else + { + return context; + } + } + return nullptr; +} + +} + +namespace egl +{ + +void SetGlobalError(const Error &error) +{ + Current *current = GetCurrentData(); + + current->error = error.getCode(); +} + +EGLint GetGlobalError() +{ + Current *current = GetCurrentData(); + + return current->error; +} + +EGLenum GetGlobalAPI() +{ + Current *current = GetCurrentData(); + + return current->API; +} + +void SetGlobalAPI(EGLenum API) +{ + Current *current = GetCurrentData(); + + current->API = API; +} + +void SetGlobalDisplay(Display *dpy) +{ + Current *current = GetCurrentData(); + + current->display = dpy; +} + +Display *GetGlobalDisplay() +{ + Current *current = GetCurrentData(); + + return current->display; +} + +void SetGlobalDrawSurface(Surface *surface) +{ + Current *current = GetCurrentData(); + + current->drawSurface = surface; +} + +Surface *GetGlobalDrawSurface() +{ + Current *current = GetCurrentData(); + + return current->drawSurface; +} + +void SetGlobalReadSurface(Surface *surface) +{ + Current *current = GetCurrentData(); + + current->readSurface = surface; +} + +Surface *GetGlobalReadSurface() +{ + Current *current = GetCurrentData(); + + return current->readSurface; +} + +void SetGlobalContext(gl::Context *context) +{ + Current *current = GetCurrentData(); + + current->context = context; +} + +gl::Context *GetGlobalContext() +{ + Current *current = GetCurrentData(); + + return current->context; +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/global_state.h b/src/3rdparty/angle/src/libGLESv2/global_state.h new file mode 100644 index 0000000000..db202539cb --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/global_state.h @@ -0,0 +1,49 @@ +// +// Copyright(c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// global_state.h : Defines functions for querying the thread-local GL and EGL state. + +#ifndef LIBGLESV2_GLOBALSTATE_H_ +#define LIBGLESV2_GLOBALSTATE_H_ + +#include + +namespace gl +{ +class Context; + +Context *GetGlobalContext(); +Context *GetValidGlobalContext(); + +} + +namespace egl +{ +class Error; +class Display; +class Surface; + +void SetGlobalError(const Error &error); +EGLint GetGlobalError(); + +void SetGlobalAPI(EGLenum API); +EGLenum GetGlobalAPI(); + +void SetGlobalDisplay(Display *dpy); +Display *GetGlobalDisplay(); + +void SetGlobalDrawSurface(Surface *surface); +Surface *GetGlobalDrawSurface(); + +void SetGlobalReadSurface(Surface *surface); +Surface *GetGlobalReadSurface(); + +void SetGlobalContext(gl::Context *context); +gl::Context *GetGlobalContext(); + +} + +#endif // LIBGLESV2_GLOBALSTATE_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp b/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp index 587950a139..e69e04aa60 100644 --- a/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp +++ b/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp @@ -6,8977 +6,1416 @@ // libGLESv2.cpp: Implements the exported OpenGL ES 2.0 functions. -#undef GL_APICALL -#define GL_APICALL -#define GL_GLEXT_PROTOTYPES - -#include "common/version.h" -#include "common/utilities.h" - -#include "libGLESv2/main.h" -#include "libGLESv2/formatutils.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/Texture.h" -#include "libGLESv2/Query.h" -#include "libGLESv2/Context.h" -#include "libGLESv2/VertexArray.h" -#include "libGLESv2/VertexAttribute.h" -#include "libGLESv2/TransformFeedback.h" -#include "libGLESv2/FramebufferAttachment.h" - -#include "libGLESv2/validationES.h" -#include "libGLESv2/validationES2.h" -#include "libGLESv2/validationES3.h" -#include "libGLESv2/queryconversions.h" +#include "libGLESv2/entry_points_gles_2_0.h" +#include "libGLESv2/entry_points_gles_2_0_ext.h" +#include "libGLESv2/entry_points_gles_3_0.h" +#include "libGLESv2/entry_points_gles_3_0_ext.h" + +#include "common/event_tracer.h" extern "C" { -// OpenGL ES 2.0 functions - void GL_APIENTRY glActiveTexture(GLenum texture) { - EVENT("(GLenum texture = 0x%X)", texture); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (texture < GL_TEXTURE0 || texture > GL_TEXTURE0 + context->getCaps().maxCombinedTextureImageUnits - 1) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - context->getState().setActiveSampler(texture - GL_TEXTURE0); - } + return gl::ActiveTexture(texture); } void GL_APIENTRY glAttachShader(GLuint program, GLuint shader) { - EVENT("(GLuint program = %d, GLuint shader = %d)", program, shader); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - gl::Program *programObject = context->getProgram(program); - gl::Shader *shaderObject = context->getShader(shader); - - if (!programObject) - { - if (context->getShader(program)) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - else - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - } - - if (!shaderObject) - { - if (context->getProgram(shader)) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - else - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - } - - if (!programObject->attachShader(shaderObject)) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - } -} - -void GL_APIENTRY glBeginQueryEXT(GLenum target, GLuint id) -{ - EVENT("(GLenum target = 0x%X, GLuint %d)", target, id); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateBeginQuery(context, target, id)) - { - return; - } - - gl::Error error = context->beginQuery(target, id); - if (error.isError()) - { - context->recordError(error); - return; - } - } + return gl::AttachShader(program, shader); } void GL_APIENTRY glBindAttribLocation(GLuint program, GLuint index, const GLchar* name) { - EVENT("(GLuint program = %d, GLuint index = %d, const GLchar* name = 0x%0.8p)", program, index, name); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - gl::Program *programObject = context->getProgram(program); - - if (!programObject) - { - if (context->getShader(program)) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - else - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - } - - if (strncmp(name, "gl_", 3) == 0) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - programObject->bindAttributeLocation(index, name); - } + return gl::BindAttribLocation(program, index, name); } void GL_APIENTRY glBindBuffer(GLenum target, GLuint buffer) { - EVENT("(GLenum target = 0x%X, GLuint buffer = %d)", target, buffer); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!gl::ValidBufferTarget(context, target)) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - switch (target) - { - case GL_ARRAY_BUFFER: - context->bindArrayBuffer(buffer); - return; - case GL_ELEMENT_ARRAY_BUFFER: - context->bindElementArrayBuffer(buffer); - return; - case GL_COPY_READ_BUFFER: - context->bindCopyReadBuffer(buffer); - return; - case GL_COPY_WRITE_BUFFER: - context->bindCopyWriteBuffer(buffer); - return; - case GL_PIXEL_PACK_BUFFER: - context->bindPixelPackBuffer(buffer); - return; - case GL_PIXEL_UNPACK_BUFFER: - context->bindPixelUnpackBuffer(buffer); - return; - case GL_UNIFORM_BUFFER: - context->bindGenericUniformBuffer(buffer); - return; - case GL_TRANSFORM_FEEDBACK_BUFFER: - context->bindGenericTransformFeedbackBuffer(buffer); - return; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - } + return gl::BindBuffer(target, buffer); } void GL_APIENTRY glBindFramebuffer(GLenum target, GLuint framebuffer) { - EVENT("(GLenum target = 0x%X, GLuint framebuffer = %d)", target, framebuffer); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!gl::ValidFramebufferTarget(target)) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - if (target == GL_READ_FRAMEBUFFER_ANGLE || target == GL_FRAMEBUFFER) - { - context->bindReadFramebuffer(framebuffer); - } - - if (target == GL_DRAW_FRAMEBUFFER_ANGLE || target == GL_FRAMEBUFFER) - { - context->bindDrawFramebuffer(framebuffer); - } - } + return gl::BindFramebuffer(target, framebuffer); } void GL_APIENTRY glBindRenderbuffer(GLenum target, GLuint renderbuffer) { - EVENT("(GLenum target = 0x%X, GLuint renderbuffer = %d)", target, renderbuffer); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (target != GL_RENDERBUFFER) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - context->bindRenderbuffer(renderbuffer); - } + return gl::BindRenderbuffer(target, renderbuffer); } void GL_APIENTRY glBindTexture(GLenum target, GLuint texture) { - EVENT("(GLenum target = 0x%X, GLuint texture = %d)", target, texture); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - gl::Texture *textureObject = context->getTexture(texture); - - if (textureObject && textureObject->getTarget() != target && texture != 0) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - switch (target) - { - case GL_TEXTURE_2D: - case GL_TEXTURE_CUBE_MAP: - break; - - case GL_TEXTURE_3D: - case GL_TEXTURE_2D_ARRAY: - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - context->bindTexture(target, texture); - } + return gl::BindTexture(target, texture); } -void GL_APIENTRY glBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) +void GL_APIENTRY glBlendColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) { - EVENT("(GLclampf red = %f, GLclampf green = %f, GLclampf blue = %f, GLclampf alpha = %f)", - red, green, blue, alpha); - - gl::Context* context = gl::getNonLostContext(); - - if (context) - { - context->getState().setBlendColor(gl::clamp01(red), gl::clamp01(green), gl::clamp01(blue), gl::clamp01(alpha)); - } + return gl::BlendColor(red, green, blue, alpha); } void GL_APIENTRY glBlendEquation(GLenum mode) { - glBlendEquationSeparate(mode, mode); + return gl::BlendEquation(mode); } void GL_APIENTRY glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha) { - EVENT("(GLenum modeRGB = 0x%X, GLenum modeAlpha = 0x%X)", modeRGB, modeAlpha); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - switch (modeRGB) - { - case GL_FUNC_ADD: - case GL_FUNC_SUBTRACT: - case GL_FUNC_REVERSE_SUBTRACT: - case GL_MIN: - case GL_MAX: - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - switch (modeAlpha) - { - case GL_FUNC_ADD: - case GL_FUNC_SUBTRACT: - case GL_FUNC_REVERSE_SUBTRACT: - case GL_MIN: - case GL_MAX: - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - context->getState().setBlendEquation(modeRGB, modeAlpha); - } + return gl::BlendEquationSeparate(modeRGB, modeAlpha); } void GL_APIENTRY glBlendFunc(GLenum sfactor, GLenum dfactor) { - glBlendFuncSeparate(sfactor, dfactor, sfactor, dfactor); + return gl::BlendFunc(sfactor, dfactor); } void GL_APIENTRY glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) { - EVENT("(GLenum srcRGB = 0x%X, GLenum dstRGB = 0x%X, GLenum srcAlpha = 0x%X, GLenum dstAlpha = 0x%X)", - srcRGB, dstRGB, srcAlpha, dstAlpha); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - switch (srcRGB) - { - case GL_ZERO: - case GL_ONE: - case GL_SRC_COLOR: - case GL_ONE_MINUS_SRC_COLOR: - case GL_DST_COLOR: - case GL_ONE_MINUS_DST_COLOR: - case GL_SRC_ALPHA: - case GL_ONE_MINUS_SRC_ALPHA: - case GL_DST_ALPHA: - case GL_ONE_MINUS_DST_ALPHA: - case GL_CONSTANT_COLOR: - case GL_ONE_MINUS_CONSTANT_COLOR: - case GL_CONSTANT_ALPHA: - case GL_ONE_MINUS_CONSTANT_ALPHA: - case GL_SRC_ALPHA_SATURATE: - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - switch (dstRGB) - { - case GL_ZERO: - case GL_ONE: - case GL_SRC_COLOR: - case GL_ONE_MINUS_SRC_COLOR: - case GL_DST_COLOR: - case GL_ONE_MINUS_DST_COLOR: - case GL_SRC_ALPHA: - case GL_ONE_MINUS_SRC_ALPHA: - case GL_DST_ALPHA: - case GL_ONE_MINUS_DST_ALPHA: - case GL_CONSTANT_COLOR: - case GL_ONE_MINUS_CONSTANT_COLOR: - case GL_CONSTANT_ALPHA: - case GL_ONE_MINUS_CONSTANT_ALPHA: - break; - - case GL_SRC_ALPHA_SATURATE: - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - switch (srcAlpha) - { - case GL_ZERO: - case GL_ONE: - case GL_SRC_COLOR: - case GL_ONE_MINUS_SRC_COLOR: - case GL_DST_COLOR: - case GL_ONE_MINUS_DST_COLOR: - case GL_SRC_ALPHA: - case GL_ONE_MINUS_SRC_ALPHA: - case GL_DST_ALPHA: - case GL_ONE_MINUS_DST_ALPHA: - case GL_CONSTANT_COLOR: - case GL_ONE_MINUS_CONSTANT_COLOR: - case GL_CONSTANT_ALPHA: - case GL_ONE_MINUS_CONSTANT_ALPHA: - case GL_SRC_ALPHA_SATURATE: - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - switch (dstAlpha) - { - case GL_ZERO: - case GL_ONE: - case GL_SRC_COLOR: - case GL_ONE_MINUS_SRC_COLOR: - case GL_DST_COLOR: - case GL_ONE_MINUS_DST_COLOR: - case GL_SRC_ALPHA: - case GL_ONE_MINUS_SRC_ALPHA: - case GL_DST_ALPHA: - case GL_ONE_MINUS_DST_ALPHA: - case GL_CONSTANT_COLOR: - case GL_ONE_MINUS_CONSTANT_COLOR: - case GL_CONSTANT_ALPHA: - case GL_ONE_MINUS_CONSTANT_ALPHA: - break; - - case GL_SRC_ALPHA_SATURATE: - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - bool constantColorUsed = (srcRGB == GL_CONSTANT_COLOR || srcRGB == GL_ONE_MINUS_CONSTANT_COLOR || - dstRGB == GL_CONSTANT_COLOR || dstRGB == GL_ONE_MINUS_CONSTANT_COLOR); - - bool constantAlphaUsed = (srcRGB == GL_CONSTANT_ALPHA || srcRGB == GL_ONE_MINUS_CONSTANT_ALPHA || - dstRGB == GL_CONSTANT_ALPHA || dstRGB == GL_ONE_MINUS_CONSTANT_ALPHA); - - if (constantColorUsed && constantAlphaUsed) - { - ERR("Simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR invalid under WebGL"); - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - context->getState().setBlendFactors(srcRGB, dstRGB, srcAlpha, dstAlpha); - } + return gl::BlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); } void GL_APIENTRY glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage) { - EVENT("(GLenum target = 0x%X, GLsizeiptr size = %d, const GLvoid* data = 0x%0.8p, GLenum usage = %d)", - target, size, data, usage); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (size < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - switch (usage) - { - case GL_STREAM_DRAW: - case GL_STATIC_DRAW: - case GL_DYNAMIC_DRAW: - break; - - case GL_STREAM_READ: - case GL_STREAM_COPY: - case GL_STATIC_READ: - case GL_STATIC_COPY: - case GL_DYNAMIC_READ: - case GL_DYNAMIC_COPY: - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - if (!gl::ValidBufferTarget(context, target)) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - gl::Buffer *buffer = context->getState().getTargetBuffer(target); - - if (!buffer) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - gl::Error error = buffer->bufferData(data, size, usage); - if (error.isError()) - { - context->recordError(error); - return; - } - } + return gl::BufferData(target, size, data, usage); } void GL_APIENTRY glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data) { - EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr size = %d, const GLvoid* data = 0x%0.8p)", - target, offset, size, data); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (size < 0 || offset < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - if (data == NULL) - { - return; - } - - if (!gl::ValidBufferTarget(context, target)) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - gl::Buffer *buffer = context->getState().getTargetBuffer(target); - - if (!buffer) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (buffer->isMapped()) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - // Check for possible overflow of size + offset - if (!rx::IsUnsignedAdditionSafe(size, offset)) - { - context->recordError(gl::Error(GL_OUT_OF_MEMORY)); - return; - } - - if (size + offset > buffer->getSize()) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - gl::Error error = buffer->bufferSubData(data, size, offset); - if (error.isError()) - { - context->recordError(error); - return; - } - } + return gl::BufferSubData(target, offset, size, data); } GLenum GL_APIENTRY glCheckFramebufferStatus(GLenum target) { - EVENT("(GLenum target = 0x%X)", target); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!gl::ValidFramebufferTarget(target)) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return 0; - } - - gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target); - ASSERT(framebuffer); - - return framebuffer->completeness(context->getData()); - } - - return 0; + return gl::CheckFramebufferStatus(target); } void GL_APIENTRY glClear(GLbitfield mask) { - EVENT("(GLbitfield mask = 0x%X)", mask); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - gl::Framebuffer *framebufferObject = context->getState().getDrawFramebuffer(); - ASSERT(framebufferObject); - - if (framebufferObject->completeness(context->getData()) != GL_FRAMEBUFFER_COMPLETE) - { - context->recordError(gl::Error(GL_INVALID_FRAMEBUFFER_OPERATION)); - return; - } - - if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - gl::Error error = context->clear(mask); - if (error.isError()) - { - context->recordError(error); - return; - } - } + return gl::Clear(mask); } -void GL_APIENTRY glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) +void GL_APIENTRY glClearColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) { - EVENT("(GLclampf red = %f, GLclampf green = %f, GLclampf blue = %f, GLclampf alpha = %f)", - red, green, blue, alpha); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - context->getState().setClearColor(red, green, blue, alpha); - } + return gl::ClearColor(red, green, blue, alpha); } -void GL_APIENTRY glClearDepthf(GLclampf depth) +void GL_APIENTRY glClearDepthf(GLfloat depth) { - EVENT("(GLclampf depth = %f)", depth); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - context->getState().setClearDepth(depth); - } + return gl::ClearDepthf(depth); } void GL_APIENTRY glClearStencil(GLint s) { - EVENT("(GLint s = %d)", s); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - context->getState().setClearStencil(s); - } + return gl::ClearStencil(s); } void GL_APIENTRY glColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) { - EVENT("(GLboolean red = %d, GLboolean green = %u, GLboolean blue = %u, GLboolean alpha = %u)", - red, green, blue, alpha); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - context->getState().setColorMask(red == GL_TRUE, green == GL_TRUE, blue == GL_TRUE, alpha == GL_TRUE); - } + return gl::ColorMask(red, green, blue, alpha); } void GL_APIENTRY glCompileShader(GLuint shader) { - EVENT("(GLuint shader = %d)", shader); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - gl::Shader *shaderObject = context->getShader(shader); - - if (!shaderObject) - { - if (context->getProgram(shader)) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - else - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - } - - shaderObject->compile(context->getData()); - } -} - -void GL_APIENTRY glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, - GLint border, GLsizei imageSize, const GLvoid* data) -{ - EVENT("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, " - "GLsizei height = %d, GLint border = %d, GLsizei imageSize = %d, const GLvoid* data = 0x%0.8p)", - target, level, internalformat, width, height, border, imageSize, data); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3 && - !ValidateES2TexImageParameters(context, target, level, internalformat, true, false, - 0, 0, width, height, border, GL_NONE, GL_NONE, data)) - { - return; - } - - if (context->getClientVersion() >= 3 && - !ValidateES3TexImageParameters(context, target, level, internalformat, true, false, - 0, 0, 0, width, height, 1, border, GL_NONE, GL_NONE, data)) - { - return; - } - - const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat); - if (imageSize < 0 || static_cast(imageSize) != formatInfo.computeBlockSize(GL_UNSIGNED_BYTE, width, height)) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - switch (target) - { - case GL_TEXTURE_2D: - { - gl::Texture2D *texture = context->getTexture2D(); - gl::Error error = texture->setCompressedImage(level, internalformat, width, height, imageSize, context->getState().getUnpackState(), data); - if (error.isError()) - { - context->recordError(error); - return; - } - } - break; - - case GL_TEXTURE_CUBE_MAP_POSITIVE_X: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: - { - gl::TextureCubeMap *texture = context->getTextureCubeMap(); - gl::Error error = texture->setCompressedImage(target, level, internalformat, width, height, imageSize, context->getState().getUnpackState(), data); - if (error.isError()) - { - context->recordError(error); - return; - } - } - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - } -} - -void GL_APIENTRY glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, - GLenum format, GLsizei imageSize, const GLvoid* data) -{ - EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, " - "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, " - "GLsizei imageSize = %d, const GLvoid* data = 0x%0.8p)", - target, level, xoffset, yoffset, width, height, format, imageSize, data); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3 && - !ValidateES2TexImageParameters(context, target, level, GL_NONE, true, true, - xoffset, yoffset, width, height, 0, GL_NONE, GL_NONE, data)) - { - return; - } - - if (context->getClientVersion() >= 3 && - !ValidateES3TexImageParameters(context, target, level, GL_NONE, true, true, - xoffset, yoffset, 0, width, height, 1, 0, GL_NONE, GL_NONE, data)) - { - return; - } - - const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format); - if (imageSize < 0 || static_cast(imageSize) != formatInfo.computeBlockSize(GL_UNSIGNED_BYTE, width, height)) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - switch (target) - { - case GL_TEXTURE_2D: - { - gl::Texture2D *texture = context->getTexture2D(); - gl::Error error = texture->subImageCompressed(level, xoffset, yoffset, width, height, format, imageSize, context->getState().getUnpackState(), data); - if (error.isError()) - { - context->recordError(error); - return; - } - } - break; - - case GL_TEXTURE_CUBE_MAP_POSITIVE_X: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: - { - gl::TextureCubeMap *texture = context->getTextureCubeMap(); - gl::Error error = texture->subImageCompressed(target, level, xoffset, yoffset, width, height, format, imageSize, context->getState().getUnpackState(), data); - if (error.isError()) - { - context->recordError(error); - return; - } - } - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - } + return gl::CompileShader(shader); +} + +void GL_APIENTRY glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data) +{ + return gl::CompressedTexImage2D(target, level, internalformat, width, height, border, imageSize, data); +} + +void GL_APIENTRY glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data) +{ + return gl::CompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, data); } void GL_APIENTRY glCopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) { - EVENT("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, " - "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, GLint border = %d)", - target, level, internalformat, x, y, width, height, border); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3 && - !ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, - 0, 0, x, y, width, height, border)) - { - return; - } - - if (context->getClientVersion() >= 3 && - !ValidateES3CopyTexImageParameters(context, target, level, internalformat, false, - 0, 0, 0, x, y, width, height, border)) - { - return; - } - - gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer(); - - switch (target) - { - case GL_TEXTURE_2D: - { - gl::Texture2D *texture = context->getTexture2D(); - gl::Error error = texture->copyImage(level, internalformat, x, y, width, height, framebuffer); - if (error.isError()) - { - context->recordError(error); - return; - } - } - break; - - case GL_TEXTURE_CUBE_MAP_POSITIVE_X: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: - { - gl::TextureCubeMap *texture = context->getTextureCubeMap(); - gl::Error error = texture->copyImage(target, level, internalformat, x, y, width, height, framebuffer); - if (error.isError()) - { - context->recordError(error); - return; - } - } - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - } + return gl::CopyTexImage2D(target, level, internalformat, x, y, width, height, border); } void GL_APIENTRY glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) { - EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, " - "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", - target, level, xoffset, yoffset, x, y, width, height); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3 && - !ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, - xoffset, yoffset, x, y, width, height, 0)) - { - return; - } - - if (context->getClientVersion() >= 3 && - !ValidateES3CopyTexImageParameters(context, target, level, GL_NONE, true, - xoffset, yoffset, 0, x, y, width, height, 0)) - { - return; - } - - gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer(); - - switch (target) - { - case GL_TEXTURE_2D: - { - gl::Texture2D *texture = context->getTexture2D(); - gl::Error error = texture->copySubImage(target, level, xoffset, yoffset, 0, x, y, width, height, framebuffer); - if (error.isError()) - { - context->recordError(error); - return; - } - } - break; - - case GL_TEXTURE_CUBE_MAP_POSITIVE_X: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: - { - gl::TextureCubeMap *texture = context->getTextureCubeMap(); - gl::Error error = texture->copySubImage(target, level, xoffset, yoffset, 0, x, y, width, height, framebuffer); - if (error.isError()) - { - context->recordError(error); - return; - } - } - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - } + return gl::CopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height); } GLuint GL_APIENTRY glCreateProgram(void) { - EVENT("()"); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - return context->createProgram(); - } - - return 0; + return gl::CreateProgram(); } GLuint GL_APIENTRY glCreateShader(GLenum type) { - EVENT("(GLenum type = 0x%X)", type); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - switch (type) - { - case GL_FRAGMENT_SHADER: - case GL_VERTEX_SHADER: - return context->createShader(type); - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return 0; - } - } - - return 0; + return gl::CreateShader(type); } void GL_APIENTRY glCullFace(GLenum mode) { - EVENT("(GLenum mode = 0x%X)", mode); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - switch (mode) - { - case GL_FRONT: - case GL_BACK: - case GL_FRONT_AND_BACK: - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - context->getState().setCullMode(mode); - } + return gl::CullFace(mode); } void GL_APIENTRY glDeleteBuffers(GLsizei n, const GLuint* buffers) { - EVENT("(GLsizei n = %d, const GLuint* buffers = 0x%0.8p)", n, buffers); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (n < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - for (int i = 0; i < n; i++) - { - context->deleteBuffer(buffers[i]); - } - } -} - -void GL_APIENTRY glDeleteFencesNV(GLsizei n, const GLuint* fences) -{ - EVENT("(GLsizei n = %d, const GLuint* fences = 0x%0.8p)", n, fences); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (n < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - for (int i = 0; i < n; i++) - { - context->deleteFenceNV(fences[i]); - } - } + return gl::DeleteBuffers(n, buffers); } void GL_APIENTRY glDeleteFramebuffers(GLsizei n, const GLuint* framebuffers) { - EVENT("(GLsizei n = %d, const GLuint* framebuffers = 0x%0.8p)", n, framebuffers); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (n < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - for (int i = 0; i < n; i++) - { - if (framebuffers[i] != 0) - { - context->deleteFramebuffer(framebuffers[i]); - } - } - } + return gl::DeleteFramebuffers(n, framebuffers); } void GL_APIENTRY glDeleteProgram(GLuint program) { - EVENT("(GLuint program = %d)", program); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (program == 0) - { - return; - } - - if (!context->getProgram(program)) - { - if(context->getShader(program)) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - else - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - } - - context->deleteProgram(program); - } -} - -void GL_APIENTRY glDeleteQueriesEXT(GLsizei n, const GLuint *ids) -{ - EVENT("(GLsizei n = %d, const GLuint *ids = 0x%0.8p)", n, ids); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (n < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - for (int i = 0; i < n; i++) - { - context->deleteQuery(ids[i]); - } - } + return gl::DeleteProgram(program); } void GL_APIENTRY glDeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers) { - EVENT("(GLsizei n = %d, const GLuint* renderbuffers = 0x%0.8p)", n, renderbuffers); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (n < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - for (int i = 0; i < n; i++) - { - context->deleteRenderbuffer(renderbuffers[i]); - } - } + return gl::DeleteRenderbuffers(n, renderbuffers); } void GL_APIENTRY glDeleteShader(GLuint shader) { - EVENT("(GLuint shader = %d)", shader); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (shader == 0) - { - return; - } - - if (!context->getShader(shader)) - { - if(context->getProgram(shader)) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - else - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - } - - context->deleteShader(shader); - } + return gl::DeleteShader(shader); } void GL_APIENTRY glDeleteTextures(GLsizei n, const GLuint* textures) { - EVENT("(GLsizei n = %d, const GLuint* textures = 0x%0.8p)", n, textures); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (n < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - for (int i = 0; i < n; i++) - { - if (textures[i] != 0) - { - context->deleteTexture(textures[i]); - } - } - } + return gl::DeleteTextures(n, textures); } void GL_APIENTRY glDepthFunc(GLenum func) { - EVENT("(GLenum func = 0x%X)", func); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - switch (func) - { - case GL_NEVER: - case GL_ALWAYS: - case GL_LESS: - case GL_LEQUAL: - case GL_EQUAL: - case GL_GREATER: - case GL_GEQUAL: - case GL_NOTEQUAL: - context->getState().setDepthFunc(func); - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - } + return gl::DepthFunc(func); } void GL_APIENTRY glDepthMask(GLboolean flag) { - EVENT("(GLboolean flag = %u)", flag); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - context->getState().setDepthMask(flag != GL_FALSE); - } + return gl::DepthMask(flag); } -void GL_APIENTRY glDepthRangef(GLclampf zNear, GLclampf zFar) +void GL_APIENTRY glDepthRangef(GLfloat n, GLfloat f) { - EVENT("(GLclampf zNear = %f, GLclampf zFar = %f)", zNear, zFar); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - context->getState().setDepthRange(zNear, zFar); - } + return gl::DepthRangef(n, f); } void GL_APIENTRY glDetachShader(GLuint program, GLuint shader) { - EVENT("(GLuint program = %d, GLuint shader = %d)", program, shader); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - gl::Program *programObject = context->getProgram(program); - gl::Shader *shaderObject = context->getShader(shader); - - if (!programObject) - { - gl::Shader *shaderByProgramHandle; - shaderByProgramHandle = context->getShader(program); - if (!shaderByProgramHandle) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - else - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - } - - if (!shaderObject) - { - gl::Program *programByShaderHandle = context->getProgram(shader); - if (!programByShaderHandle) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - else - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - } - - if (!programObject->detachShader(shaderObject)) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - } + return gl::DetachShader(program, shader); } void GL_APIENTRY glDisable(GLenum cap) { - EVENT("(GLenum cap = 0x%X)", cap); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidCap(context, cap)) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - context->getState().setEnableFeature(cap, false); - } + return gl::Disable(cap); } void GL_APIENTRY glDisableVertexAttribArray(GLuint index) { - EVENT("(GLuint index = %d)", index); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - context->getState().setEnableVertexAttribArray(index, false); - } + return gl::DisableVertexAttribArray(index); } void GL_APIENTRY glDrawArrays(GLenum mode, GLint first, GLsizei count) { - EVENT("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d)", mode, first, count); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateDrawArrays(context, mode, first, count, 0)) - { - return; - } - - gl::Error error = context->drawArrays(mode, first, count, 0); - if (error.isError()) - { - context->recordError(error); - return; - } - } -} - -void GL_APIENTRY glDrawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei count, GLsizei primcount) -{ - EVENT("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d, GLsizei primcount = %d)", mode, first, count, primcount); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateDrawArraysInstancedANGLE(context, mode, first, count, primcount)) - { - return; - } - - gl::Error error = context->drawArrays(mode, first, count, primcount); - if (error.isError()) - { - context->recordError(error); - return; - } - } + return gl::DrawArrays(mode, first, count); } void GL_APIENTRY glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices) { - EVENT("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = 0x%0.8p)", - mode, count, type, indices); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - rx::RangeUI indexRange; - if (!ValidateDrawElements(context, mode, count, type, indices, 0, &indexRange)) - { - return; - } - - gl::Error error = context->drawElements(mode, count, type, indices, 0, indexRange); - if (error.isError()) - { - context->recordError(error); - return; - } - } -} - -void GL_APIENTRY glDrawElementsInstancedANGLE(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount) -{ - EVENT("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = 0x%0.8p, GLsizei primcount = %d)", - mode, count, type, indices, primcount); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - rx::RangeUI indexRange; - if (!ValidateDrawElementsInstancedANGLE(context, mode, count, type, indices, primcount, &indexRange)) - { - return; - } - - gl::Error error = context->drawElements(mode, count, type, indices, primcount, indexRange); - if (error.isError()) - { - context->recordError(error); - return; - } - } + return gl::DrawElements(mode, count, type, indices); } void GL_APIENTRY glEnable(GLenum cap) { - EVENT("(GLenum cap = 0x%X)", cap); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidCap(context, cap)) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - context->getState().setEnableFeature(cap, true); - } + return gl::Enable(cap); } void GL_APIENTRY glEnableVertexAttribArray(GLuint index) { - EVENT("(GLuint index = %d)", index); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - context->getState().setEnableVertexAttribArray(index, true); - } -} - -void GL_APIENTRY glEndQueryEXT(GLenum target) -{ - EVENT("GLenum target = 0x%X)", target); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateEndQuery(context, target)) - { - return; - } - - gl::Error error = context->endQuery(target); - if (error.isError()) - { - context->recordError(error); - return; - } - } -} - -void GL_APIENTRY glFinishFenceNV(GLuint fence) -{ - EVENT("(GLuint fence = %d)", fence); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - gl::FenceNV *fenceObject = context->getFenceNV(fence); - - if (fenceObject == NULL) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (fenceObject->isFence() != GL_TRUE) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - fenceObject->finishFence(); - } + return gl::EnableVertexAttribArray(index); } void GL_APIENTRY glFinish(void) { - EVENT("()"); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - gl::Error error = context->sync(true); - if (error.isError()) - { - context->recordError(error); - return; - } - } + return gl::Finish(); } void GL_APIENTRY glFlush(void) { - EVENT("()"); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - gl::Error error = context->sync(false); - if (error.isError()) - { - context->recordError(error); - return; - } - } + return gl::Flush(); } void GL_APIENTRY glFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) { - EVENT("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum renderbuffertarget = 0x%X, " - "GLuint renderbuffer = %d)", target, attachment, renderbuffertarget, renderbuffer); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!gl::ValidFramebufferTarget(target) || (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0)) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - if (!gl::ValidateFramebufferRenderbufferParameters(context, target, attachment, renderbuffertarget, renderbuffer)) - { - return; - } - - gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target); - ASSERT(framebuffer); - - if (renderbuffer != 0) - { - gl::Renderbuffer *renderbufferObject = context->getRenderbuffer(renderbuffer); - framebuffer->setRenderbufferAttachment(attachment, renderbufferObject); - } - else - { - framebuffer->setNULLAttachment(attachment); - } - } + return gl::FramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer); } void GL_APIENTRY glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) { - EVENT("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum textarget = 0x%X, " - "GLuint texture = %d, GLint level = %d)", target, attachment, textarget, texture, level); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateFramebufferTexture2D(context, target, attachment, textarget, texture, level)) - { - return; - } - - gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target); - ASSERT(framebuffer); - - if (texture != 0) - { - gl::Texture *textureObj = context->getTexture(texture); - gl::ImageIndex index(textarget, level, gl::ImageIndex::ENTIRE_LEVEL); - framebuffer->setTextureAttachment(attachment, textureObj, index); - } - else - { - framebuffer->setNULLAttachment(attachment); - } - } + return gl::FramebufferTexture2D(target, attachment, textarget, texture, level); } void GL_APIENTRY glFrontFace(GLenum mode) { - EVENT("(GLenum mode = 0x%X)", mode); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - switch (mode) - { - case GL_CW: - case GL_CCW: - context->getState().setFrontFace(mode); - break; - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - } + return gl::FrontFace(mode); } void GL_APIENTRY glGenBuffers(GLsizei n, GLuint* buffers) { - EVENT("(GLsizei n = %d, GLuint* buffers = 0x%0.8p)", n, buffers); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (n < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - for (int i = 0; i < n; i++) - { - buffers[i] = context->createBuffer(); - } - } + return gl::GenBuffers(n, buffers); } void GL_APIENTRY glGenerateMipmap(GLenum target) { - EVENT("(GLenum target = 0x%X)", target); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidTextureTarget(context, target)) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - gl::Texture *texture = context->getTargetTexture(target); - - if (texture == NULL) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - GLenum internalFormat = texture->getBaseLevelInternalFormat(); - const gl::TextureCaps &formatCaps = context->getTextureCaps().get(internalFormat); - const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat); - - // GenerateMipmap should not generate an INVALID_OPERATION for textures created with - // unsized formats or that are color renderable and filterable. Since we do not track if - // the texture was created with sized or unsized format (only sized formats are stored), - // it is not possible to make sure the the LUMA formats can generate mipmaps (they should - // be able to) because they aren't color renderable. Simply do a special case for LUMA - // textures since they're the only texture format that can be created with unsized formats - // that is not color renderable. New unsized formats are unlikely to be added, since ES2 - // was the last version to use add them. - bool isLUMA = internalFormat == GL_LUMINANCE8_EXT || - internalFormat == GL_LUMINANCE8_ALPHA8_EXT || - internalFormat == GL_ALPHA8_EXT; - - if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0 || !formatCaps.filterable || - (!formatCaps.renderable && !isLUMA) || formatInfo.compressed) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - // GL_EXT_sRGB does not support mipmap generation on sRGB textures - if (context->getClientVersion() == 2 && formatInfo.colorEncoding == GL_SRGB) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - // Non-power of 2 ES2 check - if (!context->getExtensions().textureNPOT && (!gl::isPow2(texture->getBaseLevelWidth()) || !gl::isPow2(texture->getBaseLevelHeight()))) - { - ASSERT(context->getClientVersion() <= 2 && (target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP)); - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - // Cube completeness check - if (target == GL_TEXTURE_CUBE_MAP) - { - gl::TextureCubeMap *textureCube = static_cast(texture); - if (!textureCube->isCubeComplete()) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - } - - gl::Error error = texture->generateMipmaps(); - if (error.isError()) - { - context->recordError(error); - return; - } - } -} - -void GL_APIENTRY glGenFencesNV(GLsizei n, GLuint* fences) -{ - EVENT("(GLsizei n = %d, GLuint* fences = 0x%0.8p)", n, fences); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (n < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - for (int i = 0; i < n; i++) - { - fences[i] = context->createFenceNV(); - } - } + return gl::GenerateMipmap(target); } void GL_APIENTRY glGenFramebuffers(GLsizei n, GLuint* framebuffers) { - EVENT("(GLsizei n = %d, GLuint* framebuffers = 0x%0.8p)", n, framebuffers); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (n < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - for (int i = 0; i < n; i++) - { - framebuffers[i] = context->createFramebuffer(); - } - } + return gl::GenFramebuffers(n, framebuffers); } -void GL_APIENTRY glGenQueriesEXT(GLsizei n, GLuint* ids) +void GL_APIENTRY glGenRenderbuffers(GLsizei n, GLuint* renderbuffers) { - EVENT("(GLsizei n = %d, GLuint* ids = 0x%0.8p)", n, ids); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (n < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - for (GLsizei i = 0; i < n; i++) - { - ids[i] = context->createQuery(); - } - } + return gl::GenRenderbuffers(n, renderbuffers); } -void GL_APIENTRY glGenRenderbuffers(GLsizei n, GLuint* renderbuffers) +void GL_APIENTRY glGenTextures(GLsizei n, GLuint* textures) { - EVENT("(GLsizei n = %d, GLuint* renderbuffers = 0x%0.8p)", n, renderbuffers); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (n < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - for (int i = 0; i < n; i++) - { - renderbuffers[i] = context->createRenderbuffer(); - } - } + return gl::GenTextures(n, textures); } -void GL_APIENTRY glGenTextures(GLsizei n, GLuint* textures) +void GL_APIENTRY glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name) { - EVENT("(GLsizei n = %d, GLuint* textures = 0x%0.8p)", n, textures); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (n < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - for (int i = 0; i < n; i++) - { - textures[i] = context->createTexture(); - } - } -} - -void GL_APIENTRY glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) -{ - EVENT("(GLuint program = %d, GLuint index = %d, GLsizei bufsize = %d, GLsizei *length = 0x%0.8p, " - "GLint *size = 0x%0.8p, GLenum *type = %0.8p, GLchar *name = %0.8p)", - program, index, bufsize, length, size, type, name); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (bufsize < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - gl::Program *programObject = context->getProgram(program); - - if (!programObject) - { - if (context->getShader(program)) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - else - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - } - - if (index >= (GLuint)programObject->getActiveAttributeCount()) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - programObject->getActiveAttribute(index, bufsize, length, size, type, name); - } + return gl::GetActiveAttrib(program, index, bufsize, length, size, type, name); } void GL_APIENTRY glGetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name) { - EVENT("(GLuint program = %d, GLuint index = %d, GLsizei bufsize = %d, " - "GLsizei* length = 0x%0.8p, GLint* size = 0x%0.8p, GLenum* type = 0x%0.8p, GLchar* name = 0x%0.8p)", - program, index, bufsize, length, size, type, name); - - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (bufsize < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - gl::Program *programObject = context->getProgram(program); - - if (!programObject) - { - if (context->getShader(program)) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - else - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - } - - if (index >= (GLuint)programObject->getActiveUniformCount()) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - programObject->getActiveUniform(index, bufsize, length, size, type, name); - } + return gl::GetActiveUniform(program, index, bufsize, length, size, type, name); } void GL_APIENTRY glGetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders) { - EVENT("(GLuint program = %d, GLsizei maxcount = %d, GLsizei* count = 0x%0.8p, GLuint* shaders = 0x%0.8p)", - program, maxcount, count, shaders); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (maxcount < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - gl::Program *programObject = context->getProgram(program); - - if (!programObject) - { - if (context->getShader(program)) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - else - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - } - - return programObject->getAttachedShaders(maxcount, count, shaders); - } + return gl::GetAttachedShaders(program, maxcount, count, shaders); } GLint GL_APIENTRY glGetAttribLocation(GLuint program, const GLchar* name) { - EVENT("(GLuint program = %d, const GLchar* name = %s)", program, name); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - gl::Program *programObject = context->getProgram(program); - - if (!programObject) - { - if (context->getShader(program)) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return -1; - } - else - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return -1; - } - } - - gl::ProgramBinary *programBinary = programObject->getProgramBinary(); - if (!programObject->isLinked() || !programBinary) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return -1; - } - - return programBinary->getAttributeLocation(name); - } - - return -1; + return gl::GetAttribLocation(program, name); } void GL_APIENTRY glGetBooleanv(GLenum pname, GLboolean* params) { - EVENT("(GLenum pname = 0x%X, GLboolean* params = 0x%0.8p)", pname, params); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - GLenum nativeType; - unsigned int numParams = 0; - if (!ValidateStateQuery(context, pname, &nativeType, &numParams)) - { - return; - } - - if (nativeType == GL_BOOL) - { - context->getBooleanv(pname, params); - } - else - { - CastStateValues(context, nativeType, pname, numParams, params); - } - } + return gl::GetBooleanv(pname, params); } void GL_APIENTRY glGetBufferParameteriv(GLenum target, GLenum pname, GLint* params) { - EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!gl::ValidBufferTarget(context, target)) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - if (!gl::ValidBufferParameter(context, pname)) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - gl::Buffer *buffer = context->getState().getTargetBuffer(target); - - if (!buffer) - { - // A null buffer means that "0" is bound to the requested buffer target - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - switch (pname) - { - case GL_BUFFER_USAGE: - *params = static_cast(buffer->getUsage()); - break; - case GL_BUFFER_SIZE: - *params = gl::clampCast(buffer->getSize()); - break; - case GL_BUFFER_ACCESS_FLAGS: - *params = buffer->getAccessFlags(); - break; - case GL_BUFFER_MAPPED: - *params = static_cast(buffer->isMapped()); - break; - case GL_BUFFER_MAP_OFFSET: - *params = gl::clampCast(buffer->getMapOffset()); - break; - case GL_BUFFER_MAP_LENGTH: - *params = gl::clampCast(buffer->getMapLength()); - break; - default: UNREACHABLE(); break; - } - } + return gl::GetBufferParameteriv(target, pname, params); } GLenum GL_APIENTRY glGetError(void) { - EVENT("()"); - - gl::Context *context = gl::getContext(); - - if (context) - { - return context->getError(); - } - - return GL_NO_ERROR; -} - -void GL_APIENTRY glGetFenceivNV(GLuint fence, GLenum pname, GLint *params) -{ - EVENT("(GLuint fence = %d, GLenum pname = 0x%X, GLint *params = 0x%0.8p)", fence, pname, params); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - gl::FenceNV *fenceObject = context->getFenceNV(fence); - - if (fenceObject == NULL) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (fenceObject->isFence() != GL_TRUE) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - 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. - GLboolean status = GL_TRUE; - if (fenceObject->getStatus() != GL_TRUE) - { - gl::Error error = fenceObject->testFence(&status); - if (error.isError()) - { - context->recordError(error); - return; - } - } - *params = status; - break; - } - - case GL_FENCE_CONDITION_NV: - { - *params = fenceObject->getCondition(); - break; - } - - default: - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - } - } + return gl::GetError(); } void GL_APIENTRY glGetFloatv(GLenum pname, GLfloat* params) { - EVENT("(GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", pname, params); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - GLenum nativeType; - unsigned int numParams = 0; - if (!ValidateStateQuery(context, pname, &nativeType, &numParams)) - { - return; - } - - if (nativeType == GL_FLOAT) - { - context->getFloatv(pname, params); - } - else - { - CastStateValues(context, nativeType, pname, numParams, params); - } - } + return gl::GetFloatv(pname, params); } void GL_APIENTRY glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params) { - EVENT("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", - target, attachment, pname, params); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!gl::ValidFramebufferTarget(target)) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - int clientVersion = context->getClientVersion(); - - switch (pname) - { - case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE: - case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME: - case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL: - case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE: - break; - - case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING: - if (clientVersion < 3 && !context->getExtensions().sRGB) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - break; - - case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE: - case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE: - case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE: - case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE: - case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE: - case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE: - case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE: - case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER: - if (clientVersion < 3) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - // Determine if the attachment is a valid enum - switch (attachment) - { - case GL_BACK: - case GL_FRONT: - case GL_DEPTH: - case GL_STENCIL: - case GL_DEPTH_STENCIL_ATTACHMENT: - if (clientVersion < 3) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - break; - - case GL_DEPTH_ATTACHMENT: - case GL_STENCIL_ATTACHMENT: - break; - - default: - if (attachment < GL_COLOR_ATTACHMENT0_EXT || - (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - break; - } - - GLuint framebufferHandle = context->getState().getTargetFramebuffer(target)->id(); - gl::Framebuffer *framebuffer = context->getFramebuffer(framebufferHandle); - ASSERT(framebuffer); - - if (framebufferHandle == 0) - { - if (clientVersion < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - switch (attachment) - { - case GL_BACK: - case GL_DEPTH: - case GL_STENCIL: - break; - - default: - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - } - else - { - if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT) - { - // Valid attachment query - } - else - { - switch (attachment) - { - case GL_DEPTH_ATTACHMENT: - case GL_STENCIL_ATTACHMENT: - break; - - case GL_DEPTH_STENCIL_ATTACHMENT: - if (framebuffer->hasValidDepthStencil()) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - break; - - default: - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - } - } - - GLenum attachmentType = GL_NONE; - GLuint attachmentHandle = 0; - GLuint attachmentLevel = 0; - GLuint attachmentLayer = 0; - - const gl::FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment); - - if (attachmentObject) - { - attachmentType = attachmentObject->type(); - attachmentHandle = attachmentObject->id(); - attachmentLevel = attachmentObject->mipLevel(); - attachmentLayer = attachmentObject->layer(); - } - - GLenum attachmentObjectType; // Type category - if (framebufferHandle == 0) - { - attachmentObjectType = GL_FRAMEBUFFER_DEFAULT; - } - else if (attachmentType == GL_NONE || attachmentType == GL_RENDERBUFFER) - { - attachmentObjectType = attachmentType; - } - else if (gl::ValidTexture2DDestinationTarget(context, attachmentType)) - { - attachmentObjectType = GL_TEXTURE; - } - else - { - UNREACHABLE(); - return; - } - - if (attachmentObjectType == GL_NONE) - { - // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE - // is NONE, then querying any other pname will generate INVALID_ENUM. - - // ES 3.0.2 spec pg 235 states that if the attachment type is none, - // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an - // INVALID_OPERATION for all other pnames - - switch (pname) - { - case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE: - *params = attachmentObjectType; - break; - - case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME: - if (clientVersion < 3) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - *params = 0; - break; - - default: - if (clientVersion < 3) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - else - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - } - } - else - { - ASSERT(attachmentObjectType == GL_RENDERBUFFER || attachmentObjectType == GL_TEXTURE || - attachmentObjectType == GL_FRAMEBUFFER_DEFAULT); - ASSERT(attachmentObject != NULL); - - switch (pname) - { - case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE: - *params = attachmentObjectType; - break; - - case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME: - if (attachmentObjectType != GL_RENDERBUFFER && attachmentObjectType != GL_TEXTURE) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - *params = attachmentHandle; - break; - - case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL: - if (attachmentObjectType != GL_TEXTURE) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - *params = attachmentLevel; - break; - - case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE: - if (attachmentObjectType != GL_TEXTURE) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - *params = gl::IsCubemapTextureTarget(attachmentType) ? attachmentType : 0; - break; - - case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE: - *params = attachmentObject->getRedSize(); - break; - - case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE: - *params = attachmentObject->getGreenSize(); - break; - - case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE: - *params = attachmentObject->getBlueSize(); - break; - - case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE: - *params = attachmentObject->getAlphaSize(); - break; - - case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE: - *params = attachmentObject->getDepthSize(); - break; - - case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE: - *params = attachmentObject->getStencilSize(); - break; - - case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE: - if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - *params = attachmentObject->getComponentType(); - break; - - case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING: - *params = attachmentObject->getColorEncoding(); - break; - - case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER: - if (attachmentObjectType != GL_TEXTURE) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - *params = attachmentLayer; - break; - - default: - UNREACHABLE(); - break; - } - } - } -} - -GLenum GL_APIENTRY glGetGraphicsResetStatusEXT(void) -{ - EVENT("()"); - - gl::Context *context = gl::getContext(); - - if (context) - { - return context->getResetStatus(); - } - - return GL_NO_ERROR; + return gl::GetFramebufferAttachmentParameteriv(target, attachment, pname, params); } void GL_APIENTRY glGetIntegerv(GLenum pname, GLint* params) { - EVENT("(GLenum pname = 0x%X, GLint* params = 0x%0.8p)", pname, params); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - GLenum nativeType; - unsigned int numParams = 0; - - if (!ValidateStateQuery(context, pname, &nativeType, &numParams)) - { - return; - } - - if (nativeType == GL_INT) - { - context->getIntegerv(pname, params); - } - else - { - CastStateValues(context, nativeType, pname, numParams, params); - } - } + return gl::GetIntegerv(pname, params); } void GL_APIENTRY glGetProgramiv(GLuint program, GLenum pname, GLint* params) { - EVENT("(GLuint program = %d, GLenum pname = %d, GLint* params = 0x%0.8p)", program, pname, params); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - gl::Program *programObject = context->getProgram(program); - - if (!programObject) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - if (context->getClientVersion() < 3) - { - switch (pname) - { - case GL_ACTIVE_UNIFORM_BLOCKS: - case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH: - case GL_TRANSFORM_FEEDBACK_BUFFER_MODE: - case GL_TRANSFORM_FEEDBACK_VARYINGS: - case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - } - - switch (pname) - { - case GL_DELETE_STATUS: - *params = programObject->isFlaggedForDeletion(); - return; - case GL_LINK_STATUS: - *params = programObject->isLinked(); - return; - case GL_VALIDATE_STATUS: - *params = programObject->isValidated(); - return; - case GL_INFO_LOG_LENGTH: - *params = programObject->getInfoLogLength(); - return; - case GL_ATTACHED_SHADERS: - *params = programObject->getAttachedShadersCount(); - return; - case GL_ACTIVE_ATTRIBUTES: - *params = programObject->getActiveAttributeCount(); - return; - case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH: - *params = programObject->getActiveAttributeMaxLength(); - return; - case GL_ACTIVE_UNIFORMS: - *params = programObject->getActiveUniformCount(); - return; - case GL_ACTIVE_UNIFORM_MAX_LENGTH: - *params = programObject->getActiveUniformMaxLength(); - return; - case GL_PROGRAM_BINARY_LENGTH_OES: - *params = programObject->getProgramBinaryLength(); - return; - case GL_ACTIVE_UNIFORM_BLOCKS: - *params = programObject->getActiveUniformBlockCount(); - return; - case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH: - *params = programObject->getActiveUniformBlockMaxLength(); - break; - case GL_TRANSFORM_FEEDBACK_BUFFER_MODE: - *params = programObject->getTransformFeedbackBufferMode(); - break; - case GL_TRANSFORM_FEEDBACK_VARYINGS: - *params = programObject->getTransformFeedbackVaryingCount(); - break; - case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH: - *params = programObject->getTransformFeedbackVaryingMaxLength(); - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - } + return gl::GetProgramiv(program, pname, params); } void GL_APIENTRY glGetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog) { - EVENT("(GLuint program = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* infolog = 0x%0.8p)", - program, bufsize, length, infolog); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (bufsize < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - gl::Program *programObject = context->getProgram(program); - - if (!programObject) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - programObject->getInfoLog(bufsize, length, infolog); - } -} - -void GL_APIENTRY glGetQueryivEXT(GLenum target, GLenum pname, GLint *params) -{ - EVENT("GLenum target = 0x%X, GLenum pname = 0x%X, GLint *params = 0x%0.8p)", target, pname, params); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidQueryType(context, target)) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - switch (pname) - { - case GL_CURRENT_QUERY_EXT: - params[0] = context->getState().getActiveQueryId(target); - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - } -} - -void GL_APIENTRY glGetQueryObjectuivEXT(GLuint id, GLenum pname, GLuint *params) -{ - EVENT("(GLuint id = %d, GLenum pname = 0x%X, GLuint *params = 0x%0.8p)", id, pname, params); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - gl::Query *queryObject = context->getQuery(id, false, GL_NONE); - - if (!queryObject) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (context->getState().getActiveQueryId(queryObject->getType()) == id) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - switch(pname) - { - case GL_QUERY_RESULT_EXT: - { - gl::Error error = queryObject->getResult(params); - if (error.isError()) - { - context->recordError(error); - return; - } - } - break; - - case GL_QUERY_RESULT_AVAILABLE_EXT: - { - gl::Error error = queryObject->isResultAvailable(params); - if (error.isError()) - { - context->recordError(error); - return; - } - } - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - } + return gl::GetProgramInfoLog(program, bufsize, length, infolog); } void GL_APIENTRY glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params) { - EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (target != GL_RENDERBUFFER) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - if (context->getState().getRenderbufferId() == 0) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - gl::Renderbuffer *renderbuffer = context->getRenderbuffer(context->getState().getRenderbufferId()); - - switch (pname) - { - case GL_RENDERBUFFER_WIDTH: *params = renderbuffer->getWidth(); break; - case GL_RENDERBUFFER_HEIGHT: *params = renderbuffer->getHeight(); break; - case GL_RENDERBUFFER_INTERNAL_FORMAT: *params = renderbuffer->getInternalFormat(); break; - case GL_RENDERBUFFER_RED_SIZE: *params = renderbuffer->getRedSize(); break; - case GL_RENDERBUFFER_GREEN_SIZE: *params = renderbuffer->getGreenSize(); break; - case GL_RENDERBUFFER_BLUE_SIZE: *params = renderbuffer->getBlueSize(); break; - case GL_RENDERBUFFER_ALPHA_SIZE: *params = renderbuffer->getAlphaSize(); break; - case GL_RENDERBUFFER_DEPTH_SIZE: *params = renderbuffer->getDepthSize(); break; - case GL_RENDERBUFFER_STENCIL_SIZE: *params = renderbuffer->getStencilSize(); break; - - case GL_RENDERBUFFER_SAMPLES_ANGLE: - if (!context->getExtensions().framebufferMultisample) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - *params = renderbuffer->getSamples(); - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - } + return gl::GetRenderbufferParameteriv(target, pname, params); } void GL_APIENTRY glGetShaderiv(GLuint shader, GLenum pname, GLint* params) { - EVENT("(GLuint shader = %d, GLenum pname = %d, GLint* params = 0x%0.8p)", shader, pname, params); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - gl::Shader *shaderObject = context->getShader(shader); - - if (!shaderObject) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - switch (pname) - { - case GL_SHADER_TYPE: - *params = shaderObject->getType(); - return; - case GL_DELETE_STATUS: - *params = shaderObject->isFlaggedForDeletion(); - return; - case GL_COMPILE_STATUS: - *params = shaderObject->isCompiled() ? GL_TRUE : GL_FALSE; - return; - case GL_INFO_LOG_LENGTH: - *params = shaderObject->getInfoLogLength(); - return; - case GL_SHADER_SOURCE_LENGTH: - *params = shaderObject->getSourceLength(); - return; - case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE: - *params = shaderObject->getTranslatedSourceLength(); - return; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - } + return gl::GetShaderiv(shader, pname, params); } void GL_APIENTRY glGetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog) { - EVENT("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* infolog = 0x%0.8p)", - shader, bufsize, length, infolog); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (bufsize < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - gl::Shader *shaderObject = context->getShader(shader); - - if (!shaderObject) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - shaderObject->getInfoLog(bufsize, length, infolog); - } + return gl::GetShaderInfoLog(shader, bufsize, length, infolog); } void GL_APIENTRY glGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision) { - EVENT("(GLenum shadertype = 0x%X, GLenum precisiontype = 0x%X, GLint* range = 0x%0.8p, GLint* precision = 0x%0.8p)", - shadertype, precisiontype, range, precision); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - switch (shadertype) - { - case GL_VERTEX_SHADER: - case GL_FRAGMENT_SHADER: - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - switch (precisiontype) - { - case GL_LOW_FLOAT: - case GL_MEDIUM_FLOAT: - case GL_HIGH_FLOAT: - // Assume IEEE 754 precision - range[0] = 127; - range[1] = 127; - *precision = 23; - break; - - case GL_LOW_INT: - case GL_MEDIUM_INT: - case GL_HIGH_INT: - // Some (most) hardware only supports single-precision floating-point numbers, - // which can accurately represent integers up to +/-16777216 - range[0] = 24; - range[1] = 24; - *precision = 0; - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - } + return gl::GetShaderPrecisionFormat(shadertype, precisiontype, range, precision); } void GL_APIENTRY glGetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source) { - EVENT("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* source = 0x%0.8p)", - shader, bufsize, length, source); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (bufsize < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - gl::Shader *shaderObject = context->getShader(shader); - - if (!shaderObject) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - shaderObject->getSource(bufsize, length, source); - } -} - -void GL_APIENTRY glGetTranslatedShaderSourceANGLE(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source) -{ - EVENT("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* source = 0x%0.8p)", - shader, bufsize, length, source); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (bufsize < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - gl::Shader *shaderObject = context->getShader(shader); - - if (!shaderObject) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - // Only returns extra info if ANGLE_GENERATE_SHADER_DEBUG_INFO is defined - shaderObject->getTranslatedSourceWithDebugInfo(bufsize, length, source); - } + return gl::GetShaderSource(shader, bufsize, length, source); } const GLubyte* GL_APIENTRY glGetString(GLenum name) { - EVENT("(GLenum name = 0x%X)", name); - - gl::Context *context = gl::getNonLostContext(); - - switch (name) - { - case GL_VENDOR: - return (GLubyte*)"Google Inc."; - - case GL_RENDERER: - return (GLubyte*)((context != NULL) ? context->getRendererString().c_str() : "ANGLE"); - - case GL_VERSION: - if (context->getClientVersion() == 2) - { - return (GLubyte*)"OpenGL ES 2.0 (ANGLE " ANGLE_VERSION_STRING ")"; - } - else - { - return (GLubyte*)"OpenGL ES 3.0 (ANGLE " ANGLE_VERSION_STRING ")"; - } - - case GL_SHADING_LANGUAGE_VERSION: - if (context->getClientVersion() == 2) - { - return (GLubyte*)"OpenGL ES GLSL ES 1.00 (ANGLE " ANGLE_VERSION_STRING ")"; - } - else - { - return (GLubyte*)"OpenGL ES GLSL ES 3.00 (ANGLE " ANGLE_VERSION_STRING ")"; - } - - case GL_EXTENSIONS: - return (GLubyte*)((context != NULL) ? context->getExtensionString().c_str() : ""); - - default: - if (context) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - } - return NULL; - } + return gl::GetString(name); } void GL_APIENTRY glGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params) { - EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", target, pname, params); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - gl::Texture *texture = context->getTargetTexture(target); - - if (!texture) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - switch (pname) - { - case GL_TEXTURE_MAG_FILTER: - *params = (GLfloat)texture->getSamplerState().magFilter; - break; - case GL_TEXTURE_MIN_FILTER: - *params = (GLfloat)texture->getSamplerState().minFilter; - break; - case GL_TEXTURE_WRAP_S: - *params = (GLfloat)texture->getSamplerState().wrapS; - break; - case GL_TEXTURE_WRAP_T: - *params = (GLfloat)texture->getSamplerState().wrapT; - break; - case GL_TEXTURE_WRAP_R: - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - *params = (GLfloat)texture->getSamplerState().wrapR; - break; - case GL_TEXTURE_IMMUTABLE_FORMAT: - // Exposed to ES2.0 through EXT_texture_storage, no client version validation. - *params = (GLfloat)(texture->isImmutable() ? GL_TRUE : GL_FALSE); - break; - case GL_TEXTURE_IMMUTABLE_LEVELS: - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - *params = (GLfloat)texture->immutableLevelCount(); - break; - case GL_TEXTURE_USAGE_ANGLE: - *params = (GLfloat)texture->getUsage(); - break; - case GL_TEXTURE_MAX_ANISOTROPY_EXT: - if (!context->getExtensions().textureFilterAnisotropic) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - *params = (GLfloat)texture->getSamplerState().maxAnisotropy; - break; - case GL_TEXTURE_SWIZZLE_R: - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - *params = (GLfloat)texture->getSamplerState().swizzleRed; - break; - case GL_TEXTURE_SWIZZLE_G: - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - *params = (GLfloat)texture->getSamplerState().swizzleGreen; - break; - case GL_TEXTURE_SWIZZLE_B: - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - *params = (GLfloat)texture->getSamplerState().swizzleBlue; - break; - case GL_TEXTURE_SWIZZLE_A: - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - *params = (GLfloat)texture->getSamplerState().swizzleAlpha; - break; - case GL_TEXTURE_BASE_LEVEL: - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - *params = (GLfloat)texture->getSamplerState().baseLevel; - break; - case GL_TEXTURE_MAX_LEVEL: - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - *params = (GLfloat)texture->getSamplerState().maxLevel; - break; - case GL_TEXTURE_MIN_LOD: - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - *params = texture->getSamplerState().minLod; - break; - case GL_TEXTURE_MAX_LOD: - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - *params = texture->getSamplerState().maxLod; - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - } + return gl::GetTexParameterfv(target, pname, params); } void GL_APIENTRY glGetTexParameteriv(GLenum target, GLenum pname, GLint* params) { - EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - gl::Texture *texture = context->getTargetTexture(target); - - if (!texture) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - switch (pname) - { - case GL_TEXTURE_MAG_FILTER: - *params = texture->getSamplerState().magFilter; - break; - case GL_TEXTURE_MIN_FILTER: - *params = texture->getSamplerState().minFilter; - break; - case GL_TEXTURE_WRAP_S: - *params = texture->getSamplerState().wrapS; - break; - case GL_TEXTURE_WRAP_T: - *params = texture->getSamplerState().wrapT; - break; - case GL_TEXTURE_WRAP_R: - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - *params = texture->getSamplerState().wrapR; - break; - case GL_TEXTURE_IMMUTABLE_FORMAT: - // Exposed to ES2.0 through EXT_texture_storage, no client version validation. - *params = texture->isImmutable() ? GL_TRUE : GL_FALSE; - break; - case GL_TEXTURE_IMMUTABLE_LEVELS: - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - *params = static_cast(texture->immutableLevelCount()); - break; - case GL_TEXTURE_USAGE_ANGLE: - *params = texture->getUsage(); - break; - case GL_TEXTURE_MAX_ANISOTROPY_EXT: - if (!context->getExtensions().textureFilterAnisotropic) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - *params = (GLint)texture->getSamplerState().maxAnisotropy; - break; - case GL_TEXTURE_SWIZZLE_R: - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - *params = texture->getSamplerState().swizzleRed; - break; - case GL_TEXTURE_SWIZZLE_G: - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - *params = texture->getSamplerState().swizzleGreen; - break; - case GL_TEXTURE_SWIZZLE_B: - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - *params = texture->getSamplerState().swizzleBlue; - break; - case GL_TEXTURE_SWIZZLE_A: - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - *params = texture->getSamplerState().swizzleAlpha; - break; - case GL_TEXTURE_BASE_LEVEL: - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - *params = texture->getSamplerState().baseLevel; - break; - case GL_TEXTURE_MAX_LEVEL: - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - *params = texture->getSamplerState().maxLevel; - break; - case GL_TEXTURE_MIN_LOD: - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - *params = (GLint)texture->getSamplerState().minLod; - break; - case GL_TEXTURE_MAX_LOD: - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - *params = (GLint)texture->getSamplerState().maxLod; - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - } -} - -void GL_APIENTRY glGetnUniformfvEXT(GLuint program, GLint location, GLsizei bufSize, GLfloat* params) -{ - EVENT("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLfloat* params = 0x%0.8p)", - program, location, bufSize, params); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateGetnUniformfvEXT(context, program, location, bufSize, params)) - { - return; - } - - gl::Program *programObject = context->getProgram(program); - ASSERT(programObject); - gl::ProgramBinary *programBinary = programObject->getProgramBinary(); - ASSERT(programBinary); - - programBinary->getUniformfv(location, params); - } + return gl::GetTexParameteriv(target, pname, params); } void GL_APIENTRY glGetUniformfv(GLuint program, GLint location, GLfloat* params) { - EVENT("(GLuint program = %d, GLint location = %d, GLfloat* params = 0x%0.8p)", program, location, params); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateGetUniformfv(context, program, location, params)) - { - return; - } - - gl::Program *programObject = context->getProgram(program); - ASSERT(programObject); - gl::ProgramBinary *programBinary = programObject->getProgramBinary(); - ASSERT(programBinary); - - programBinary->getUniformfv(location, params); - } -} - -void GL_APIENTRY glGetnUniformivEXT(GLuint program, GLint location, GLsizei bufSize, GLint* params) -{ - EVENT("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLint* params = 0x%0.8p)", - program, location, bufSize, params); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateGetnUniformivEXT(context, program, location, bufSize, params)) - { - return; - } - - gl::Program *programObject = context->getProgram(program); - ASSERT(programObject); - gl::ProgramBinary *programBinary = programObject->getProgramBinary(); - ASSERT(programBinary); - - programBinary->getUniformiv(location, params); - } + return gl::GetUniformfv(program, location, params); } void GL_APIENTRY glGetUniformiv(GLuint program, GLint location, GLint* params) { - EVENT("(GLuint program = %d, GLint location = %d, GLint* params = 0x%0.8p)", program, location, params); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateGetUniformiv(context, program, location, params)) - { - return; - } - - gl::Program *programObject = context->getProgram(program); - ASSERT(programObject); - gl::ProgramBinary *programBinary = programObject->getProgramBinary(); - ASSERT(programBinary); - - programBinary->getUniformiv(location, params); - } + return gl::GetUniformiv(program, location, params); } GLint GL_APIENTRY glGetUniformLocation(GLuint program, const GLchar* name) { - EVENT("(GLuint program = %d, const GLchar* name = 0x%0.8p)", program, name); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (strstr(name, "gl_") == name) - { - return -1; - } - - gl::Program *programObject = context->getProgram(program); - - if (!programObject) - { - if (context->getShader(program)) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return -1; - } - else - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return -1; - } - } - - gl::ProgramBinary *programBinary = programObject->getProgramBinary(); - if (!programObject->isLinked() || !programBinary) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return -1; - } - - return programBinary->getUniformLocation(name); - } - - return -1; + return gl::GetUniformLocation(program, name); } void GL_APIENTRY glGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params) { - EVENT("(GLuint index = %d, GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", index, pname, params); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - const gl::VertexAttribute &attribState = context->getState().getVertexAttribState(index); - if (!gl::ValidateGetVertexAttribParameters(context, pname)) - { - return; - } - - if (pname == GL_CURRENT_VERTEX_ATTRIB) - { - const gl::VertexAttribCurrentValueData ¤tValueData = context->getState().getVertexAttribCurrentValue(index); - for (int i = 0; i < 4; ++i) - { - params[i] = currentValueData.FloatValues[i]; - } - } - else - { - *params = gl::QuerySingleVertexAttributeParameter(attribState, pname); - } - } + return gl::GetVertexAttribfv(index, pname, params); } void GL_APIENTRY glGetVertexAttribiv(GLuint index, GLenum pname, GLint* params) { - EVENT("(GLuint index = %d, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", index, pname, params); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - const gl::VertexAttribute &attribState = context->getState().getVertexAttribState(index); - - if (!gl::ValidateGetVertexAttribParameters(context, pname)) - { - return; - } - - if (pname == GL_CURRENT_VERTEX_ATTRIB) - { - const gl::VertexAttribCurrentValueData ¤tValueData = context->getState().getVertexAttribCurrentValue(index); - for (int i = 0; i < 4; ++i) - { - float currentValue = currentValueData.FloatValues[i]; - params[i] = gl::iround(currentValue); - } - } - else - { - *params = gl::QuerySingleVertexAttributeParameter(attribState, pname); - } - } + return gl::GetVertexAttribiv(index, pname, params); } void GL_APIENTRY glGetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid** pointer) { - EVENT("(GLuint index = %d, GLenum pname = 0x%X, GLvoid** pointer = 0x%0.8p)", index, pname, pointer); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - *pointer = const_cast(context->getState().getVertexAttribPointer(index)); - } + return gl::GetVertexAttribPointerv(index, pname, pointer); } void GL_APIENTRY glHint(GLenum target, GLenum mode) { - EVENT("(GLenum target = 0x%X, GLenum mode = 0x%X)", target, mode); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - switch (mode) - { - case GL_FASTEST: - case GL_NICEST: - case GL_DONT_CARE: - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - switch (target) - { - case GL_GENERATE_MIPMAP_HINT: - context->getState().setGenerateMipmapHint(mode); - break; - - case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES: - context->getState().setFragmentShaderDerivativeHint(mode); - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - } + return gl::Hint(target, mode); } GLboolean GL_APIENTRY glIsBuffer(GLuint buffer) { - EVENT("(GLuint buffer = %d)", buffer); - - gl::Context *context = gl::getNonLostContext(); - if (context && buffer) - { - gl::Buffer *bufferObject = context->getBuffer(buffer); - - if (bufferObject) - { - return GL_TRUE; - } - } - - return GL_FALSE; + return gl::IsBuffer(buffer); } GLboolean GL_APIENTRY glIsEnabled(GLenum cap) { - EVENT("(GLenum cap = 0x%X)", cap); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidCap(context, cap)) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return GL_FALSE; - } - - return context->getState().getEnableFeature(cap); - } - - return false; -} - -GLboolean GL_APIENTRY glIsFenceNV(GLuint fence) -{ - EVENT("(GLuint fence = %d)", fence); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - gl::FenceNV *fenceObject = context->getFenceNV(fence); - - if (fenceObject == NULL) - { - return GL_FALSE; - } - - return fenceObject->isFence(); - } - - return GL_FALSE; + return gl::IsEnabled(cap); } GLboolean GL_APIENTRY glIsFramebuffer(GLuint framebuffer) { - EVENT("(GLuint framebuffer = %d)", framebuffer); - - gl::Context *context = gl::getNonLostContext(); - if (context && framebuffer) - { - gl::Framebuffer *framebufferObject = context->getFramebuffer(framebuffer); - - if (framebufferObject) - { - return GL_TRUE; - } - } - - return GL_FALSE; + return gl::IsFramebuffer(framebuffer); } GLboolean GL_APIENTRY glIsProgram(GLuint program) { - EVENT("(GLuint program = %d)", program); - - gl::Context *context = gl::getNonLostContext(); - if (context && program) - { - gl::Program *programObject = context->getProgram(program); - - if (programObject) - { - return GL_TRUE; - } - } - - return GL_FALSE; -} - -GLboolean GL_APIENTRY glIsQueryEXT(GLuint id) -{ - EVENT("(GLuint id = %d)", id); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - return (context->getQuery(id, false, GL_NONE) != NULL) ? GL_TRUE : GL_FALSE; - } - - return GL_FALSE; + return gl::IsProgram(program); } GLboolean GL_APIENTRY glIsRenderbuffer(GLuint renderbuffer) { - EVENT("(GLuint renderbuffer = %d)", renderbuffer); - - gl::Context *context = gl::getNonLostContext(); - if (context && renderbuffer) - { - gl::Renderbuffer *renderbufferObject = context->getRenderbuffer(renderbuffer); - - if (renderbufferObject) - { - return GL_TRUE; - } - } - - return GL_FALSE; + return gl::IsRenderbuffer(renderbuffer); } GLboolean GL_APIENTRY glIsShader(GLuint shader) { - EVENT("(GLuint shader = %d)", shader); - - gl::Context *context = gl::getNonLostContext(); - if (context && shader) - { - gl::Shader *shaderObject = context->getShader(shader); - - if (shaderObject) - { - return GL_TRUE; - } - } - - return GL_FALSE; + return gl::IsShader(shader); } GLboolean GL_APIENTRY glIsTexture(GLuint texture) { - EVENT("(GLuint texture = %d)", texture); - - gl::Context *context = gl::getNonLostContext(); - if (context && texture) - { - gl::Texture *textureObject = context->getTexture(texture); - - if (textureObject) - { - return GL_TRUE; - } - } - - return GL_FALSE; + return gl::IsTexture(texture); } void GL_APIENTRY glLineWidth(GLfloat width) { - EVENT("(GLfloat width = %f)", width); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (width <= 0.0f) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - context->getState().setLineWidth(width); - } + return gl::LineWidth(width); } void GL_APIENTRY glLinkProgram(GLuint program) { - EVENT("(GLuint program = %d)", program); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - gl::Program *programObject = context->getProgram(program); - - if (!programObject) - { - if (context->getShader(program)) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - else - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - } - - gl::Error error = context->linkProgram(program); - if (error.isError()) - { - context->recordError(error); - return; - } - } + return gl::LinkProgram(program); } void GL_APIENTRY glPixelStorei(GLenum pname, GLint param) { - EVENT("(GLenum pname = 0x%X, GLint param = %d)", pname, param); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - switch (pname) - { - case GL_UNPACK_ALIGNMENT: - if (param != 1 && param != 2 && param != 4 && param != 8) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - context->getState().setUnpackAlignment(param); - break; - - case GL_PACK_ALIGNMENT: - if (param != 1 && param != 2 && param != 4 && param != 8) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - context->getState().setPackAlignment(param); - break; - - case GL_PACK_REVERSE_ROW_ORDER_ANGLE: - context->getState().setPackReverseRowOrder(param != 0); - break; - - case GL_UNPACK_IMAGE_HEIGHT: - case GL_UNPACK_SKIP_IMAGES: - case GL_UNPACK_ROW_LENGTH: - case GL_UNPACK_SKIP_ROWS: - case GL_UNPACK_SKIP_PIXELS: - case GL_PACK_ROW_LENGTH: - case GL_PACK_SKIP_ROWS: - case GL_PACK_SKIP_PIXELS: - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - UNIMPLEMENTED(); - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - } + return gl::PixelStorei(pname, param); } void GL_APIENTRY glPolygonOffset(GLfloat factor, GLfloat units) { - EVENT("(GLfloat factor = %f, GLfloat units = %f)", factor, units); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - context->getState().setPolygonOffsetParams(factor, units); - } -} - -void GL_APIENTRY glReadnPixelsEXT(GLint x, GLint y, GLsizei width, GLsizei height, - GLenum format, GLenum type, GLsizei bufSize, - GLvoid *data) -{ - EVENT("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, " - "GLenum format = 0x%X, GLenum type = 0x%X, GLsizei bufSize = 0x%d, GLvoid *data = 0x%0.8p)", - x, y, width, height, format, type, bufSize, data); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (width < 0 || height < 0 || bufSize < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - if (!gl::ValidateReadPixelsParameters(context, x, y, width, height, - format, type, &bufSize, data)) - { - return; - } - - gl::Error error = context->readPixels(x, y, width, height, format, type, &bufSize, data); - if (error.isError()) - { - context->recordError(error); - return; - } - } -} - -void GL_APIENTRY glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, - GLenum format, GLenum type, GLvoid* pixels) -{ - EVENT("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, " - "GLenum format = 0x%X, GLenum type = 0x%X, GLvoid* pixels = 0x%0.8p)", - x, y, width, height, format, type, pixels); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (width < 0 || height < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - if (!gl::ValidateReadPixelsParameters(context, x, y, width, height, - format, type, NULL, pixels)) - { - return; - } - - gl::Error error = context->readPixels(x, y, width, height, format, type, NULL, pixels); - if (error.isError()) - { - context->recordError(error); - return; - } - } + return gl::PolygonOffset(factor, units); } -void GL_APIENTRY glReleaseShaderCompiler(void) +void GL_APIENTRY glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels) { - EVENT("()"); - - gl::Context *context = gl::getNonLostContext(); - - if (context) - { - context->releaseShaderCompiler(); - } + return gl::ReadPixels(x, y, width, height, format, type, pixels); } -void GL_APIENTRY glRenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height) +void GL_APIENTRY glReleaseShaderCompiler(void) { - EVENT("(GLenum target = 0x%X, GLsizei samples = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)", - target, samples, internalformat, width, height); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateRenderbufferStorageParameters(context, target, samples, internalformat, - width, height, true)) - { - return; - } - - gl::Renderbuffer *renderbuffer = context->getState().getCurrentRenderbuffer(); - gl::Error error = renderbuffer->setStorage(width, height, internalformat, samples); - if (error.isError()) - { - context->recordError(error); - return; - } - } + return gl::ReleaseShaderCompiler(); } void GL_APIENTRY glRenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height) { - glRenderbufferStorageMultisampleANGLE(target, 0, internalformat, width, height); -} - -void GL_APIENTRY glSampleCoverage(GLclampf value, GLboolean invert) -{ - EVENT("(GLclampf value = %f, GLboolean invert = %u)", value, invert); - - gl::Context* context = gl::getNonLostContext(); - - if (context) - { - context->getState().setSampleCoverageParams(gl::clamp01(value), invert == GL_TRUE); - } + return gl::RenderbufferStorage(target, internalformat, width, height); } -void GL_APIENTRY glSetFenceNV(GLuint fence, GLenum condition) +void GL_APIENTRY glSampleCoverage(GLfloat value, GLboolean invert) { - EVENT("(GLuint fence = %d, GLenum condition = 0x%X)", fence, condition); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (condition != GL_ALL_COMPLETED_NV) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - gl::FenceNV *fenceObject = context->getFenceNV(fence); - - if (fenceObject == NULL) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - gl::Error error = fenceObject->setFence(condition); - if (error.isError()) - { - context->recordError(error); - return; - } - } + return gl::SampleCoverage(value, invert); } void GL_APIENTRY glScissor(GLint x, GLint y, GLsizei width, GLsizei height) { - EVENT("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height); - - gl::Context* context = gl::getNonLostContext(); - if (context) - { - if (width < 0 || height < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - context->getState().setScissorParams(x, y, width, height); - } + return gl::Scissor(x, y, width, height); } void GL_APIENTRY glShaderBinary(GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length) { - EVENT("(GLsizei n = %d, const GLuint* shaders = 0x%0.8p, GLenum binaryformat = 0x%X, " - "const GLvoid* binary = 0x%0.8p, GLsizei length = %d)", - n, shaders, binaryformat, binary, length); - - gl::Context* context = gl::getNonLostContext(); - if (context) - { - const std::vector &shaderBinaryFormats = context->getCaps().shaderBinaryFormats; - if (std::find(shaderBinaryFormats.begin(), shaderBinaryFormats.end(), binaryformat) == shaderBinaryFormats.end()) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - // No binary shader formats are supported. - UNIMPLEMENTED(); - } + return gl::ShaderBinary(n, shaders, binaryformat, binary, length); } void GL_APIENTRY glShaderSource(GLuint shader, GLsizei count, const GLchar* const* string, const GLint* length) { - EVENT("(GLuint shader = %d, GLsizei count = %d, const GLchar** string = 0x%0.8p, const GLint* length = 0x%0.8p)", - shader, count, string, length); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (count < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - gl::Shader *shaderObject = context->getShader(shader); - - if (!shaderObject) - { - if (context->getProgram(shader)) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - else - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - } - - shaderObject->setSource(count, string, length); - } + return gl::ShaderSource(shader, count, string, length); } void GL_APIENTRY glStencilFunc(GLenum func, GLint ref, GLuint mask) { - glStencilFuncSeparate(GL_FRONT_AND_BACK, func, ref, mask); + return gl::StencilFunc(func, ref, mask); } void GL_APIENTRY glStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask) { - EVENT("(GLenum face = 0x%X, GLenum func = 0x%X, GLint ref = %d, GLuint mask = %d)", face, func, ref, mask); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - switch (face) - { - case GL_FRONT: - case GL_BACK: - case GL_FRONT_AND_BACK: - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - switch (func) - { - case GL_NEVER: - case GL_ALWAYS: - case GL_LESS: - case GL_LEQUAL: - case GL_EQUAL: - case GL_GEQUAL: - case GL_GREATER: - case GL_NOTEQUAL: - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - if (face == GL_FRONT || face == GL_FRONT_AND_BACK) - { - context->getState().setStencilParams(func, ref, mask); - } - - if (face == GL_BACK || face == GL_FRONT_AND_BACK) - { - context->getState().setStencilBackParams(func, ref, mask); - } - } + return gl::StencilFuncSeparate(face, func, ref, mask); } void GL_APIENTRY glStencilMask(GLuint mask) { - glStencilMaskSeparate(GL_FRONT_AND_BACK, mask); + return gl::StencilMask(mask); } void GL_APIENTRY glStencilMaskSeparate(GLenum face, GLuint mask) { - EVENT("(GLenum face = 0x%X, GLuint mask = %d)", face, mask); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - switch (face) - { - case GL_FRONT: - case GL_BACK: - case GL_FRONT_AND_BACK: - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - if (face == GL_FRONT || face == GL_FRONT_AND_BACK) - { - context->getState().setStencilWritemask(mask); - } - - if (face == GL_BACK || face == GL_FRONT_AND_BACK) - { - context->getState().setStencilBackWritemask(mask); - } - } + return gl::StencilMaskSeparate(face, mask); } void GL_APIENTRY glStencilOp(GLenum fail, GLenum zfail, GLenum zpass) { - glStencilOpSeparate(GL_FRONT_AND_BACK, fail, zfail, zpass); + return gl::StencilOp(fail, zfail, zpass); } void GL_APIENTRY glStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass) { - EVENT("(GLenum face = 0x%X, GLenum fail = 0x%X, GLenum zfail = 0x%X, GLenum zpas = 0x%Xs)", - face, fail, zfail, zpass); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - switch (face) - { - case GL_FRONT: - case GL_BACK: - case GL_FRONT_AND_BACK: - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - switch (fail) - { - case GL_ZERO: - case GL_KEEP: - case GL_REPLACE: - case GL_INCR: - case GL_DECR: - case GL_INVERT: - case GL_INCR_WRAP: - case GL_DECR_WRAP: - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - switch (zfail) - { - case GL_ZERO: - case GL_KEEP: - case GL_REPLACE: - case GL_INCR: - case GL_DECR: - case GL_INVERT: - case GL_INCR_WRAP: - case GL_DECR_WRAP: - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - switch (zpass) - { - case GL_ZERO: - case GL_KEEP: - case GL_REPLACE: - case GL_INCR: - case GL_DECR: - case GL_INVERT: - case GL_INCR_WRAP: - case GL_DECR_WRAP: - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - if (face == GL_FRONT || face == GL_FRONT_AND_BACK) - { - context->getState().setStencilOperations(fail, zfail, zpass); - } - - if (face == GL_BACK || face == GL_FRONT_AND_BACK) - { - context->getState().setStencilBackOperations(fail, zfail, zpass); - } - } + return gl::StencilOpSeparate(face, fail, zfail, zpass); } -GLboolean GL_APIENTRY glTestFenceNV(GLuint fence) +void GL_APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels) { - EVENT("(GLuint fence = %d)", fence); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - gl::FenceNV *fenceObject = context->getFenceNV(fence); - - if (fenceObject == NULL) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return GL_TRUE; - } - - if (fenceObject->isFence() != GL_TRUE) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return GL_TRUE; - } - - GLboolean result; - gl::Error error = fenceObject->testFence(&result); - if (error.isError()) - { - context->recordError(error); - return GL_TRUE; - } - - return result; - } - - return GL_TRUE; -} - -void GL_APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, - GLint border, GLenum format, GLenum type, const GLvoid* pixels) -{ - EVENT("(GLenum target = 0x%X, GLint level = %d, GLint internalformat = %d, GLsizei width = %d, GLsizei height = %d, " - "GLint border = %d, GLenum format = 0x%X, GLenum type = 0x%X, const GLvoid* pixels = 0x%0.8p)", - target, level, internalformat, width, height, border, format, type, pixels); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3 && - !ValidateES2TexImageParameters(context, target, level, internalformat, false, false, - 0, 0, width, height, border, format, type, pixels)) - { - return; - } - - if (context->getClientVersion() >= 3 && - !ValidateES3TexImageParameters(context, target, level, internalformat, false, false, - 0, 0, 0, width, height, 1, border, format, type, pixels)) - { - return; - } - - switch (target) - { - case GL_TEXTURE_2D: - { - gl::Texture2D *texture = context->getTexture2D(); - gl::Error error = texture->setImage(level, width, height, internalformat, format, type, context->getState().getUnpackState(), pixels); - if (error.isError()) - { - context->recordError(error); - return; - } - } - break; - - case GL_TEXTURE_CUBE_MAP_POSITIVE_X: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: - { - gl::TextureCubeMap *texture = context->getTextureCubeMap(); - gl::Error error = texture->setImage(target, level, width, height, internalformat, format, type, context->getState().getUnpackState(), pixels); - if (error.isError()) - { - context->recordError(error); - return; - } - } - break; - - default: UNREACHABLE(); - } - } + return gl::TexImage2D(target, level, internalformat, width, height, border, format, type, pixels); } void GL_APIENTRY glTexParameterf(GLenum target, GLenum pname, GLfloat param) { - EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %f)", target, pname, param); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateTexParamParameters(context, pname, static_cast(param))) - { - return; - } - - gl::Texture *texture = context->getTargetTexture(target); - - if (!texture) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - switch (pname) - { - case GL_TEXTURE_WRAP_S: texture->getSamplerState().wrapS = gl::uiround(param); break; - case GL_TEXTURE_WRAP_T: texture->getSamplerState().wrapT = gl::uiround(param); break; - case GL_TEXTURE_WRAP_R: texture->getSamplerState().wrapR = gl::uiround(param); break; - case GL_TEXTURE_MIN_FILTER: texture->getSamplerState().minFilter = gl::uiround(param); break; - case GL_TEXTURE_MAG_FILTER: texture->getSamplerState().magFilter = gl::uiround(param); break; - case GL_TEXTURE_USAGE_ANGLE: texture->setUsage(gl::uiround(param)); break; - case GL_TEXTURE_MAX_ANISOTROPY_EXT: texture->getSamplerState().maxAnisotropy = std::min(param, context->getExtensions().maxTextureAnisotropy); break; - case GL_TEXTURE_COMPARE_MODE: texture->getSamplerState().compareMode = gl::uiround(param); break; - case GL_TEXTURE_COMPARE_FUNC: texture->getSamplerState().compareFunc = gl::uiround(param); break; - case GL_TEXTURE_SWIZZLE_R: texture->getSamplerState().swizzleRed = gl::uiround(param); break; - case GL_TEXTURE_SWIZZLE_G: texture->getSamplerState().swizzleGreen = gl::uiround(param); break; - case GL_TEXTURE_SWIZZLE_B: texture->getSamplerState().swizzleBlue = gl::uiround(param); break; - case GL_TEXTURE_SWIZZLE_A: texture->getSamplerState().swizzleAlpha = gl::uiround(param); break; - case GL_TEXTURE_BASE_LEVEL: texture->getSamplerState().baseLevel = gl::iround(param); break; - case GL_TEXTURE_MAX_LEVEL: texture->getSamplerState().maxLevel = gl::iround(param); break; - case GL_TEXTURE_MIN_LOD: texture->getSamplerState().minLod = param; break; - case GL_TEXTURE_MAX_LOD: texture->getSamplerState().maxLod = param; break; - default: UNREACHABLE(); break; - } - } + return gl::TexParameterf(target, pname, param); } void GL_APIENTRY glTexParameterfv(GLenum target, GLenum pname, const GLfloat* params) { - glTexParameterf(target, pname, (GLfloat)*params); + return gl::TexParameterfv(target, pname, params); } void GL_APIENTRY glTexParameteri(GLenum target, GLenum pname, GLint param) { - EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %d)", target, pname, param); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateTexParamParameters(context, pname, param)) - { - return; - } - - gl::Texture *texture = context->getTargetTexture(target); - - if (!texture) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - switch (pname) - { - case GL_TEXTURE_WRAP_S: texture->getSamplerState().wrapS = (GLenum)param; break; - case GL_TEXTURE_WRAP_T: texture->getSamplerState().wrapT = (GLenum)param; break; - case GL_TEXTURE_WRAP_R: texture->getSamplerState().wrapR = (GLenum)param; break; - case GL_TEXTURE_MIN_FILTER: texture->getSamplerState().minFilter = (GLenum)param; break; - case GL_TEXTURE_MAG_FILTER: texture->getSamplerState().magFilter = (GLenum)param; break; - case GL_TEXTURE_USAGE_ANGLE: texture->setUsage((GLenum)param); break; - case GL_TEXTURE_MAX_ANISOTROPY_EXT: texture->getSamplerState().maxAnisotropy = std::min((float)param, context->getExtensions().maxTextureAnisotropy); break; - case GL_TEXTURE_COMPARE_MODE: texture->getSamplerState().compareMode = (GLenum)param; break; - case GL_TEXTURE_COMPARE_FUNC: texture->getSamplerState().compareFunc = (GLenum)param; break; - case GL_TEXTURE_SWIZZLE_R: texture->getSamplerState().swizzleRed = (GLenum)param; break; - case GL_TEXTURE_SWIZZLE_G: texture->getSamplerState().swizzleGreen = (GLenum)param; break; - case GL_TEXTURE_SWIZZLE_B: texture->getSamplerState().swizzleBlue = (GLenum)param; break; - case GL_TEXTURE_SWIZZLE_A: texture->getSamplerState().swizzleAlpha = (GLenum)param; break; - case GL_TEXTURE_BASE_LEVEL: texture->getSamplerState().baseLevel = param; break; - case GL_TEXTURE_MAX_LEVEL: texture->getSamplerState().maxLevel = param; break; - case GL_TEXTURE_MIN_LOD: texture->getSamplerState().minLod = (GLfloat)param; break; - case GL_TEXTURE_MAX_LOD: texture->getSamplerState().maxLod = (GLfloat)param; break; - default: UNREACHABLE(); break; - } - } + return gl::TexParameteri(target, pname, param); } void GL_APIENTRY glTexParameteriv(GLenum target, GLenum pname, const GLint* params) { - glTexParameteri(target, pname, *params); + return gl::TexParameteriv(target, pname, params); } -void GL_APIENTRY glTexStorage2DEXT(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) +void GL_APIENTRY glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels) { - EVENT("(GLenum target = 0x%X, GLsizei levels = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)", - target, levels, internalformat, width, height); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!context->getExtensions().textureStorage) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (context->getClientVersion() < 3 && - !ValidateES2TexStorageParameters(context, target, levels, internalformat, width, height)) - { - return; - } - - if (context->getClientVersion() >= 3 && - !ValidateES3TexStorageParameters(context, target, levels, internalformat, width, height, 1)) - { - return; - } - - switch (target) - { - case GL_TEXTURE_2D: - { - gl::Texture2D *texture2d = context->getTexture2D(); - gl::Error error = texture2d->storage(levels, internalformat, width, height); - if (error.isError()) - { - context->recordError(error); - return; - } - } - break; - - case GL_TEXTURE_CUBE_MAP: - { - gl::TextureCubeMap *textureCube = context->getTextureCubeMap(); - gl::Error error = textureCube->storage(levels, internalformat, width); - if (error.isError()) - { - context->recordError(error); - return; - } - } - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - } -} - -void GL_APIENTRY glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, - GLenum format, GLenum type, const GLvoid* pixels) -{ - EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, " - "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, GLenum type = 0x%X, " - "const GLvoid* pixels = 0x%0.8p)", - target, level, xoffset, yoffset, width, height, format, type, pixels); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3 && - !ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, - xoffset, yoffset, width, height, 0, format, type, pixels)) - { - return; - } - - if (context->getClientVersion() >= 3 && - !ValidateES3TexImageParameters(context, target, level, GL_NONE, false, true, - xoffset, yoffset, 0, width, height, 1, 0, format, type, pixels)) - { - return; - } - - // Zero sized uploads are valid but no-ops - if (width == 0 || height == 0) - { - return; - } - - switch (target) - { - case GL_TEXTURE_2D: - { - gl::Texture2D *texture = context->getTexture2D(); - gl::Error error = texture->subImage(level, xoffset, yoffset, width, height, format, type, context->getState().getUnpackState(), pixels); - if (error.isError()) - { - context->recordError(error); - return; - } - } - break; - - case GL_TEXTURE_CUBE_MAP_POSITIVE_X: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: - { - gl::TextureCubeMap *texture = context->getTextureCubeMap(); - gl::Error error = texture->subImage(target, level, xoffset, yoffset, width, height, format, type, context->getState().getUnpackState(), pixels); - if (error.isError()) - { - context->recordError(error); - return; - } - } - break; - - default: - UNREACHABLE(); - } - } + return gl::TexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels); } void GL_APIENTRY glUniform1f(GLint location, GLfloat x) { - glUniform1fv(location, 1, &x); + return gl::Uniform1f(location, x); } void GL_APIENTRY glUniform1fv(GLint location, GLsizei count, const GLfloat* v) { - EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateUniform(context, GL_FLOAT, location, count)) - { - return; - } - - gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); - programBinary->setUniform1fv(location, count, v); - } + return gl::Uniform1fv(location, count, v); } void GL_APIENTRY glUniform1i(GLint location, GLint x) { - glUniform1iv(location, 1, &x); + return gl::Uniform1i(location, x); } void GL_APIENTRY glUniform1iv(GLint location, GLsizei count, const GLint* v) { - EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateUniform(context, GL_INT, location, count)) - { - return; - } - - gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); - programBinary->setUniform1iv(location, count, v); - } + return gl::Uniform1iv(location, count, v); } void GL_APIENTRY glUniform2f(GLint location, GLfloat x, GLfloat y) { - GLfloat xy[2] = {x, y}; - - glUniform2fv(location, 1, xy); + return gl::Uniform2f(location, x, y); } void GL_APIENTRY glUniform2fv(GLint location, GLsizei count, const GLfloat* v) { - EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateUniform(context, GL_FLOAT_VEC2, location, count)) - { - return; - } - - gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); - programBinary->setUniform2fv(location, count, v); - } + return gl::Uniform2fv(location, count, v); } void GL_APIENTRY glUniform2i(GLint location, GLint x, GLint y) { - GLint xy[2] = {x, y}; - - glUniform2iv(location, 1, xy); + return gl::Uniform2i(location, x, y); } void GL_APIENTRY glUniform2iv(GLint location, GLsizei count, const GLint* v) { - EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateUniform(context, GL_INT_VEC2, location, count)) - { - return; - } - - gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); - programBinary->setUniform2iv(location, count, v); - } + return gl::Uniform2iv(location, count, v); } void GL_APIENTRY glUniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z) { - GLfloat xyz[3] = {x, y, z}; - - glUniform3fv(location, 1, xyz); + return gl::Uniform3f(location, x, y, z); } void GL_APIENTRY glUniform3fv(GLint location, GLsizei count, const GLfloat* v) { - EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateUniform(context, GL_FLOAT_VEC3, location, count)) - { - return; - } - - gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); - programBinary->setUniform3fv(location, count, v); - } + return gl::Uniform3fv(location, count, v); } void GL_APIENTRY glUniform3i(GLint location, GLint x, GLint y, GLint z) { - GLint xyz[3] = {x, y, z}; - - glUniform3iv(location, 1, xyz); + return gl::Uniform3i(location, x, y, z); } void GL_APIENTRY glUniform3iv(GLint location, GLsizei count, const GLint* v) { - EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateUniform(context, GL_INT_VEC3, location, count)) - { - return; - } - - gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); - programBinary->setUniform3iv(location, count, v); - } + return gl::Uniform3iv(location, count, v); } void GL_APIENTRY glUniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w) { - GLfloat xyzw[4] = {x, y, z, w}; - - glUniform4fv(location, 1, xyzw); + return gl::Uniform4f(location, x, y, z, w); } void GL_APIENTRY glUniform4fv(GLint location, GLsizei count, const GLfloat* v) { - EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateUniform(context, GL_FLOAT_VEC4, location, count)) - { - return; - } - - gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); - programBinary->setUniform4fv(location, count, v); - } + return gl::Uniform4fv(location, count, v); } void GL_APIENTRY glUniform4i(GLint location, GLint x, GLint y, GLint z, GLint w) { - GLint xyzw[4] = {x, y, z, w}; - - glUniform4iv(location, 1, xyzw); + return gl::Uniform4i(location, x, y, z, w); } void GL_APIENTRY glUniform4iv(GLint location, GLsizei count, const GLint* v) { - EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateUniform(context, GL_INT_VEC4, location, count)) - { - return; - } - - gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); - programBinary->setUniform4iv(location, count, v); - } + return gl::Uniform4iv(location, count, v); } void GL_APIENTRY glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) { - EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)", - location, count, transpose, value); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateUniformMatrix(context, GL_FLOAT_MAT2, location, count, transpose)) - { - return; - } - - gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); - programBinary->setUniformMatrix2fv(location, count, transpose, value); - } + return gl::UniformMatrix2fv(location, count, transpose, value); } void GL_APIENTRY glUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) { - EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)", - location, count, transpose, value); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateUniformMatrix(context, GL_FLOAT_MAT3, location, count, transpose)) - { - return; - } - - gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); - programBinary->setUniformMatrix3fv(location, count, transpose, value); - } + return gl::UniformMatrix3fv(location, count, transpose, value); } void GL_APIENTRY glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) { - EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)", - location, count, transpose, value); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateUniformMatrix(context, GL_FLOAT_MAT4, location, count, transpose)) - { - return; - } - - gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); - programBinary->setUniformMatrix4fv(location, count, transpose, value); - } + return gl::UniformMatrix4fv(location, count, transpose, value); } void GL_APIENTRY glUseProgram(GLuint program) { - EVENT("(GLuint program = %d)", program); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - gl::Program *programObject = context->getProgram(program); - - if (!programObject && program != 0) - { - if (context->getShader(program)) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - else - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - } - - if (program != 0 && !programObject->isLinked()) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - context->useProgram(program); - } + return gl::UseProgram(program); } void GL_APIENTRY glValidateProgram(GLuint program) { - EVENT("(GLuint program = %d)", program); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - gl::Program *programObject = context->getProgram(program); - - if (!programObject) - { - if (context->getShader(program)) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - else - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - } - - programObject->validate(context->getCaps()); - } + return gl::ValidateProgram(program); } -void GL_APIENTRY glVertexAttrib1f(GLuint index, GLfloat x) +void GL_APIENTRY glVertexAttrib1f(GLuint indx, GLfloat x) { - EVENT("(GLuint index = %d, GLfloat x = %f)", index, x); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - GLfloat vals[4] = { x, 0, 0, 1 }; - context->getState().setVertexAttribf(index, vals); - } + return gl::VertexAttrib1f(indx, x); } -void GL_APIENTRY glVertexAttrib1fv(GLuint index, const GLfloat* values) +void GL_APIENTRY glVertexAttrib1fv(GLuint indx, const GLfloat* values) { - EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - GLfloat vals[4] = { values[0], 0, 0, 1 }; - context->getState().setVertexAttribf(index, vals); - } + return gl::VertexAttrib1fv(indx, values); } -void GL_APIENTRY glVertexAttrib2f(GLuint index, GLfloat x, GLfloat y) +void GL_APIENTRY glVertexAttrib2f(GLuint indx, GLfloat x, GLfloat y) { - EVENT("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f)", index, x, y); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - GLfloat vals[4] = { x, y, 0, 1 }; - context->getState().setVertexAttribf(index, vals); - } + return gl::VertexAttrib2f(indx, x, y); } -void GL_APIENTRY glVertexAttrib2fv(GLuint index, const GLfloat* values) +void GL_APIENTRY glVertexAttrib2fv(GLuint indx, const GLfloat* values) { - EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - GLfloat vals[4] = { values[0], values[1], 0, 1 }; - context->getState().setVertexAttribf(index, vals); - } + return gl::VertexAttrib2fv(indx, values); } -void GL_APIENTRY glVertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z) +void GL_APIENTRY glVertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z) { - EVENT("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f)", index, x, y, z); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - GLfloat vals[4] = { x, y, z, 1 }; - context->getState().setVertexAttribf(index, vals); - } + return gl::VertexAttrib3f(indx, x, y, z); } -void GL_APIENTRY glVertexAttrib3fv(GLuint index, const GLfloat* values) +void GL_APIENTRY glVertexAttrib3fv(GLuint indx, const GLfloat* values) { - EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - GLfloat vals[4] = { values[0], values[1], values[2], 1 }; - context->getState().setVertexAttribf(index, vals); - } + return gl::VertexAttrib3fv(indx, values); } -void GL_APIENTRY glVertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +void GL_APIENTRY glVertexAttrib4f(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w) { - EVENT("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f, GLfloat w = %f)", index, x, y, z, w); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - GLfloat vals[4] = { x, y, z, w }; - context->getState().setVertexAttribf(index, vals); - } + return gl::VertexAttrib4f(indx, x, y, z, w); } -void GL_APIENTRY glVertexAttrib4fv(GLuint index, const GLfloat* values) +void GL_APIENTRY glVertexAttrib4fv(GLuint indx, const GLfloat* values) { - EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - context->getState().setVertexAttribf(index, values); - } + return gl::VertexAttrib4fv(indx, values); } -void GL_APIENTRY glVertexAttribDivisorANGLE(GLuint index, GLuint divisor) +void GL_APIENTRY glVertexAttribPointer(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr) { - EVENT("(GLuint index = %d, GLuint divisor = %d)", index, divisor); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - context->setVertexAttribDivisor(index, divisor); - } -} - -void GL_APIENTRY glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr) -{ - EVENT("(GLuint index = %d, GLint size = %d, GLenum type = 0x%X, " - "GLboolean normalized = %u, GLsizei stride = %d, const GLvoid* ptr = 0x%0.8p)", - index, size, type, normalized, stride, ptr); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - if (size < 1 || size > 4) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - switch (type) - { - case GL_BYTE: - case GL_UNSIGNED_BYTE: - case GL_SHORT: - case GL_UNSIGNED_SHORT: - case GL_FIXED: - case GL_FLOAT: - break; - - case GL_HALF_FLOAT: - case GL_INT: - case GL_UNSIGNED_INT: - case GL_INT_2_10_10_10_REV: - case GL_UNSIGNED_INT_2_10_10_10_REV: - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - if (stride < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - if ((type == GL_INT_2_10_10_10_REV || type == GL_UNSIGNED_INT_2_10_10_10_REV) && size != 4) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - // [OpenGL ES 3.0.2] Section 2.8 page 24: - // An INVALID_OPERATION error is generated when a non-zero vertex array object - // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point, - // and the pointer argument is not NULL. - if (context->getState().getVertexArray()->id() != 0 && context->getState().getArrayBufferId() == 0 && ptr != NULL) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - context->getState().setVertexAttribState(index, context->getState().getTargetBuffer(GL_ARRAY_BUFFER), size, type, - normalized == GL_TRUE, false, stride, ptr); - } + return gl::VertexAttribPointer(indx, size, type, normalized, stride, ptr); } void GL_APIENTRY glViewport(GLint x, GLint y, GLsizei width, GLsizei height) { - EVENT("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (width < 0 || height < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - context->getState().setViewportParams(x, y, width, height); - } + return gl::Viewport(x, y, width, height); } -// OpenGL ES 3.0 functions - void GL_APIENTRY glReadBuffer(GLenum mode) { - EVENT("(GLenum mode = 0x%X)", mode); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - // glReadBuffer - UNIMPLEMENTED(); - } + return gl::ReadBuffer(mode); } void GL_APIENTRY glDrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid* indices) { - EVENT("(GLenum mode = 0x%X, GLuint start = %u, GLuint end = %u, GLsizei count = %d, GLenum type = 0x%X, " - "const GLvoid* indices = 0x%0.8p)", mode, start, end, count, type, indices); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - // glDrawRangeElements - UNIMPLEMENTED(); - } + return gl::DrawRangeElements(mode, start, end, count, type, indices); } void GL_APIENTRY glTexImage3D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* pixels) { - EVENT("(GLenum target = 0x%X, GLint level = %d, GLint internalformat = %d, GLsizei width = %d, " - "GLsizei height = %d, GLsizei depth = %d, GLint border = %d, GLenum format = 0x%X, " - "GLenum type = 0x%X, const GLvoid* pixels = 0x%0.8p)", - target, level, internalformat, width, height, depth, border, format, type, pixels); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - // validateES3TexImageFormat sets the error code if there is an error - if (!ValidateES3TexImageParameters(context, target, level, internalformat, false, false, - 0, 0, 0, width, height, depth, border, format, type, pixels)) - { - return; - } - - switch(target) - { - case GL_TEXTURE_3D: - { - gl::Texture3D *texture = context->getTexture3D(); - gl::Error error = texture->setImage(level, width, height, depth, internalformat, format, type, context->getState().getUnpackState(), pixels); - if (error.isError()) - { - context->recordError(error); - return; - } - } - break; - - case GL_TEXTURE_2D_ARRAY: - { - gl::Texture2DArray *texture = context->getTexture2DArray(); - gl::Error error = texture->setImage(level, width, height, depth, internalformat, format, type, context->getState().getUnpackState(), pixels); - if (error.isError()) - { - context->recordError(error); - return; - } - } - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - } + return gl::TexImage3D(target, level, internalformat, width, height, depth, border, format, type, pixels); } void GL_APIENTRY glTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* pixels) { - EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, " - "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, " - "GLenum format = 0x%X, GLenum type = 0x%X, const GLvoid* pixels = 0x%0.8p)", - target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - // validateES3TexImageFormat sets the error code if there is an error - if (!ValidateES3TexImageParameters(context, target, level, GL_NONE, false, true, - xoffset, yoffset, zoffset, width, height, depth, 0, - format, type, pixels)) - { - return; - } - - // Zero sized uploads are valid but no-ops - if (width == 0 || height == 0 || depth == 0) - { - return; - } - - switch(target) - { - case GL_TEXTURE_3D: - { - gl::Texture3D *texture = context->getTexture3D(); - gl::Error error = texture->subImage(level, xoffset, yoffset, zoffset, width, height, depth, format, type, context->getState().getUnpackState(), pixels); - if (error.isError()) - { - context->recordError(error); - return; - } - } - break; - - case GL_TEXTURE_2D_ARRAY: - { - gl::Texture2DArray *texture = context->getTexture2DArray(); - gl::Error error = texture->subImage(level, xoffset, yoffset, zoffset, width, height, depth, format, type, context->getState().getUnpackState(), pixels); - if (error.isError()) - { - context->recordError(error); - return; - } - } - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - } + return gl::TexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels); } void GL_APIENTRY glCopyTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height) { - EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, " - "GLint zoffset = %d, GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", - target, level, xoffset, yoffset, zoffset, x, y, width, height); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (!ValidateES3CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset, yoffset, zoffset, - x, y, width, height, 0)) - { - return; - } - - gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer(); - gl::Texture *texture = NULL; - switch (target) - { - case GL_TEXTURE_3D: - texture = context->getTexture3D(); - break; - - case GL_TEXTURE_2D_ARRAY: - texture = context->getTexture2DArray(); - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - gl::Error error = texture->copySubImage(target, level, xoffset, yoffset, zoffset, x, y, width, height, framebuffer); - if (error.isError()) - { - context->recordError(error); - return; - } - } + return gl::CopyTexSubImage3D(target, level, xoffset, yoffset, zoffset, x, y, width, height); } void GL_APIENTRY glCompressedTexImage3D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data) { - EVENT("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, " - "GLsizei height = %d, GLsizei depth = %d, GLint border = %d, GLsizei imageSize = %d, " - "const GLvoid* data = 0x%0.8p)", - target, level, internalformat, width, height, depth, border, imageSize, data); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat); - if (imageSize < 0 || static_cast(imageSize) != formatInfo.computeBlockSize(GL_UNSIGNED_BYTE, width, height)) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - // validateES3TexImageFormat sets the error code if there is an error - if (!ValidateES3TexImageParameters(context, target, level, internalformat, true, false, - 0, 0, 0, width, height, depth, border, GL_NONE, GL_NONE, data)) - { - return; - } - - switch(target) - { - case GL_TEXTURE_3D: - { - gl::Texture3D *texture = context->getTexture3D(); - gl::Error error = texture->setCompressedImage(level, internalformat, width, height, depth, imageSize, context->getState().getUnpackState(), data); - if (error.isError()) - { - context->recordError(error); - return; - } - } - break; - - case GL_TEXTURE_2D_ARRAY: - { - gl::Texture2DArray *texture = context->getTexture2DArray(); - gl::Error error = texture->setCompressedImage(level, internalformat, width, height, depth, imageSize, context->getState().getUnpackState(), data); - if (error.isError()) - { - context->recordError(error); - return; - } - } - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - } + return gl::CompressedTexImage3D(target, level, internalformat, width, height, depth, border, imageSize, data); } void GL_APIENTRY glCompressedTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid* data) { - EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, " - "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, " - "GLenum format = 0x%X, GLsizei imageSize = %d, const GLvoid* data = 0x%0.8p)", - target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format); - if (imageSize < 0 || static_cast(imageSize) != formatInfo.computeBlockSize(GL_UNSIGNED_BYTE, width, height)) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - if (!data) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - // validateES3TexImageFormat sets the error code if there is an error - if (!ValidateES3TexImageParameters(context, target, level, GL_NONE, true, true, - 0, 0, 0, width, height, depth, 0, GL_NONE, GL_NONE, data)) - { - return; - } - - // Zero sized uploads are valid but no-ops - if (width == 0 || height == 0) - { - return; - } - - switch(target) - { - case GL_TEXTURE_3D: - { - gl::Texture3D *texture = context->getTexture3D(); - gl::Error error = texture->subImageCompressed(level, xoffset, yoffset, zoffset, width, height, depth, - format, imageSize, context->getState().getUnpackState(), data); - if (error.isError()) - { - context->recordError(error); - return; - } - } - break; - - case GL_TEXTURE_2D_ARRAY: - { - gl::Texture2DArray *texture = context->getTexture2DArray(); - gl::Error error = texture->subImageCompressed(level, xoffset, yoffset, zoffset, width, height, depth, - format, imageSize, context->getState().getUnpackState(), data); - if (error.isError()) - { - context->recordError(error); - return; - } - } - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - } + return gl::CompressedTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data); } void GL_APIENTRY glGenQueries(GLsizei n, GLuint* ids) { - EVENT("(GLsizei n = %d, GLuint* ids = 0x%0.8p)", n, ids); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (n < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - for (GLsizei i = 0; i < n; i++) - { - ids[i] = context->createQuery(); - } - } + return gl::GenQueries(n, ids); } void GL_APIENTRY glDeleteQueries(GLsizei n, const GLuint* ids) { - EVENT("(GLsizei n = %d, GLuint* ids = 0x%0.8p)", n, ids); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (n < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - for (GLsizei i = 0; i < n; i++) - { - context->deleteQuery(ids[i]); - } - } + return gl::DeleteQueries(n, ids); } GLboolean GL_APIENTRY glIsQuery(GLuint id) { - EVENT("(GLuint id = %u)", id); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return GL_FALSE; - } - - return (context->getQuery(id, false, GL_NONE) != NULL) ? GL_TRUE : GL_FALSE; - } - - return GL_FALSE; + return gl::IsQuery(id); } void GL_APIENTRY glBeginQuery(GLenum target, GLuint id) { - EVENT("(GLenum target = 0x%X, GLuint id = %u)", target, id); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (!ValidateBeginQuery(context, target, id)) - { - return; - } - - gl::Error error = context->beginQuery(target, id); - if (error.isError()) - { - context->recordError(error); - return; - } - } + return gl::BeginQuery(target, id); } void GL_APIENTRY glEndQuery(GLenum target) { - EVENT("(GLenum target = 0x%X)", target); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (!ValidateEndQuery(context, target)) - { - return; - } - - gl::Error error = context->endQuery(target); - if (error.isError()) - { - context->recordError(error); - return; - } - } + return gl::EndQuery(target); } void GL_APIENTRY glGetQueryiv(GLenum target, GLenum pname, GLint* params) { - EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (!ValidQueryType(context, target)) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - switch (pname) - { - case GL_CURRENT_QUERY: - params[0] = static_cast(context->getState().getActiveQueryId(target)); - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - } + return gl::GetQueryiv(target, pname, params); } void GL_APIENTRY glGetQueryObjectuiv(GLuint id, GLenum pname, GLuint* params) { - EVENT("(GLuint id = %u, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", id, pname, params); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - gl::Query *queryObject = context->getQuery(id, false, GL_NONE); - - if (!queryObject) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (context->getState().getActiveQueryId(queryObject->getType()) == id) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - switch(pname) - { - case GL_QUERY_RESULT_EXT: - { - gl::Error error = queryObject->getResult(params); - if (error.isError()) - { - context->recordError(error); - return; - } - } - break; - - case GL_QUERY_RESULT_AVAILABLE_EXT: - { - gl::Error error = queryObject->isResultAvailable(params); - if (error.isError()) - { - context->recordError(error); - return; - } - } - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - } + return gl::GetQueryObjectuiv(id, pname, params); } GLboolean GL_APIENTRY glUnmapBuffer(GLenum target) { - EVENT("(GLenum target = 0x%X)", target); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return GL_FALSE; - } - - return glUnmapBufferOES(target); - } - - return GL_FALSE; + return gl::UnmapBuffer(target); } void GL_APIENTRY glGetBufferPointerv(GLenum target, GLenum pname, GLvoid** params) { - EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLvoid** params = 0x%0.8p)", target, pname, params); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - glGetBufferPointervOES(target, pname, params); - } + return gl::GetBufferPointerv(target, pname, params); } void GL_APIENTRY glDrawBuffers(GLsizei n, const GLenum* bufs) { - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - glDrawBuffersEXT(n, bufs); - } + return gl::DrawBuffers(n, bufs); } void GL_APIENTRY glUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) { - EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)", - location, count, transpose, value); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateUniformMatrix(context, GL_FLOAT_MAT2x3, location, count, transpose)) - { - return; - } - - gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); - programBinary->setUniformMatrix2x3fv(location, count, transpose, value); - } + return gl::UniformMatrix2x3fv(location, count, transpose, value); } void GL_APIENTRY glUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) { - EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)", - location, count, transpose, value); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateUniformMatrix(context, GL_FLOAT_MAT3x2, location, count, transpose)) - { - return; - } - - gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); - programBinary->setUniformMatrix3x2fv(location, count, transpose, value); - } + return gl::UniformMatrix3x2fv(location, count, transpose, value); } void GL_APIENTRY glUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) { - EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)", - location, count, transpose, value); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateUniformMatrix(context, GL_FLOAT_MAT2x4, location, count, transpose)) - { - return; - } - - gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); - programBinary->setUniformMatrix2x4fv(location, count, transpose, value); - } + return gl::UniformMatrix2x4fv(location, count, transpose, value); } void GL_APIENTRY glUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) { - EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)", - location, count, transpose, value); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateUniformMatrix(context, GL_FLOAT_MAT4x2, location, count, transpose)) - { - return; - } - - gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); - programBinary->setUniformMatrix4x2fv(location, count, transpose, value); - } + return gl::UniformMatrix4x2fv(location, count, transpose, value); } void GL_APIENTRY glUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) { - EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)", - location, count, transpose, value); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateUniformMatrix(context, GL_FLOAT_MAT3x4, location, count, transpose)) - { - return; - } - - gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); - programBinary->setUniformMatrix3x4fv(location, count, transpose, value); - } + return gl::UniformMatrix3x4fv(location, count, transpose, value); } void GL_APIENTRY glUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) { - EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)", - location, count, transpose, value); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateUniformMatrix(context, GL_FLOAT_MAT4x3, location, count, transpose)) - { - return; - } - - gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); - programBinary->setUniformMatrix4x3fv(location, count, transpose, value); - } + return gl::UniformMatrix4x3fv(location, count, transpose, value); } void GL_APIENTRY glBlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) { - EVENT("(GLint srcX0 = %d, GLint srcY0 = %d, GLint srcX1 = %d, GLint srcY1 = %d, GLint dstX0 = %d, " - "GLint dstY0 = %d, GLint dstX1 = %d, GLint dstY1 = %d, GLbitfield mask = 0x%X, GLenum filter = 0x%X)", - srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (!ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, - dstX0, dstY0, dstX1, dstY1, mask, filter, - false)) - { - return; - } - - gl::Error error = context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, - mask, filter); - if (error.isError()) - { - context->recordError(error); - return; - } - } + return gl::BlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); } void GL_APIENTRY glRenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height) { - EVENT("(GLenum target = 0x%X, GLsizei samples = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)", - target, samples, internalformat, width, height); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (!ValidateRenderbufferStorageParameters(context, target, samples, internalformat, - width, height, false)) - { - return; - } - - gl::Renderbuffer *renderbuffer = context->getState().getCurrentRenderbuffer(); - renderbuffer->setStorage(width, height, internalformat, samples); - } + return gl::RenderbufferStorageMultisample(target, samples, internalformat, width, height); } void GL_APIENTRY glFramebufferTextureLayer(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer) { - EVENT("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLuint texture = %u, GLint level = %d, GLint layer = %d)", - target, attachment, texture, level, layer); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateFramebufferTextureLayer(context, target, attachment, texture, - level, layer)) - { - return; - } - - gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target); - ASSERT(framebuffer); - - if (texture != 0) - { - gl::Texture *textureObject = context->getTexture(texture); - gl::ImageIndex index(textureObject->getTarget(), level, layer); - framebuffer->setTextureAttachment(attachment, textureObject, index); - } - else - { - framebuffer->setNULLAttachment(attachment); - } - } + return gl::FramebufferTextureLayer(target, attachment, texture, level, layer); } GLvoid* GL_APIENTRY glMapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access) { - EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d, GLbitfield access = 0x%X)", - target, offset, length, access); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return NULL; - } - - return glMapBufferRangeEXT(target, offset, length, access); - } - - return NULL; + return gl::MapBufferRange(target, offset, length, access); } void GL_APIENTRY glFlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length) { - EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d)", target, offset, length); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - glFlushMappedBufferRangeEXT(target, offset, length); - } + return gl::FlushMappedBufferRange(target, offset, length); } void GL_APIENTRY glBindVertexArray(GLuint array) { - EVENT("(GLuint array = %u)", array); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - gl::VertexArray *vao = context->getVertexArray(array); - - if (!vao) - { - // The default VAO should always exist - ASSERT(array != 0); - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - context->bindVertexArray(array); - } + return gl::BindVertexArray(array); } void GL_APIENTRY glDeleteVertexArrays(GLsizei n, const GLuint* arrays) { - EVENT("(GLsizei n = %d, const GLuint* arrays = 0x%0.8p)", n, arrays); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (n < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - for (int arrayIndex = 0; arrayIndex < n; arrayIndex++) - { - if (arrays[arrayIndex] != 0) - { - context->deleteVertexArray(arrays[arrayIndex]); - } - } - } + return gl::DeleteVertexArrays(n, arrays); } void GL_APIENTRY glGenVertexArrays(GLsizei n, GLuint* arrays) { - EVENT("(GLsizei n = %d, GLuint* arrays = 0x%0.8p)", n, arrays); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (n < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - for (int arrayIndex = 0; arrayIndex < n; arrayIndex++) - { - arrays[arrayIndex] = context->createVertexArray(); - } - } + return gl::GenVertexArrays(n, arrays); } GLboolean GL_APIENTRY glIsVertexArray(GLuint array) { - EVENT("(GLuint array = %u)", array); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return GL_FALSE; - } - - if (array == 0) - { - return GL_FALSE; - } - - gl::VertexArray *vao = context->getVertexArray(array); - - return (vao != NULL ? GL_TRUE : GL_FALSE); - } - - return GL_FALSE; + return gl::IsVertexArray(array); } void GL_APIENTRY glGetIntegeri_v(GLenum target, GLuint index, GLint* data) { - EVENT("(GLenum target = 0x%X, GLuint index = %u, GLint* data = 0x%0.8p)", - target, index, data); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - const gl::Caps &caps = context->getCaps(); - switch (target) - { - case GL_TRANSFORM_FEEDBACK_BUFFER_START: - case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE: - case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: - if (index >= caps.maxTransformFeedbackSeparateAttributes) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - break; - - case GL_UNIFORM_BUFFER_START: - case GL_UNIFORM_BUFFER_SIZE: - case GL_UNIFORM_BUFFER_BINDING: - if (index >= caps.maxCombinedUniformBlocks) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - if (!(context->getIndexedIntegerv(target, index, data))) - { - GLenum nativeType; - unsigned int numParams = 0; - if (!context->getIndexedQueryParameterInfo(target, &nativeType, &numParams)) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - if (numParams == 0) - { - return; // it is known that pname is valid, but there are no parameters to return - } - - if (nativeType == GL_INT_64_ANGLEX) - { - GLint64 minIntValue = static_cast(std::numeric_limits::min()); - GLint64 maxIntValue = static_cast(std::numeric_limits::max()); - GLint64 *int64Params = new GLint64[numParams]; - - context->getIndexedInteger64v(target, index, int64Params); - - for (unsigned int i = 0; i < numParams; ++i) - { - GLint64 clampedValue = std::max(std::min(int64Params[i], maxIntValue), minIntValue); - data[i] = static_cast(clampedValue); - } - - delete [] int64Params; - } - else - { - UNREACHABLE(); - } - } - } + return gl::GetIntegeri_v(target, index, data); } void GL_APIENTRY glBeginTransformFeedback(GLenum primitiveMode) { - EVENT("(GLenum primitiveMode = 0x%X)", primitiveMode); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - switch (primitiveMode) - { - case GL_TRIANGLES: - case GL_LINES: - case GL_POINTS: - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - gl::TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback(); - ASSERT(transformFeedback != NULL); - - if (transformFeedback->isStarted()) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (transformFeedback->isPaused()) - { - transformFeedback->resume(); - } - else - { - transformFeedback->start(primitiveMode); - } - } + return gl::BeginTransformFeedback(primitiveMode); } void GL_APIENTRY glEndTransformFeedback(void) { - EVENT("(void)"); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - gl::TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback(); - ASSERT(transformFeedback != NULL); - - if (!transformFeedback->isStarted()) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - transformFeedback->stop(); - } + return gl::EndTransformFeedback(); } void GL_APIENTRY glBindBufferRange(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size) { - EVENT("(GLenum target = 0x%X, GLuint index = %u, GLuint buffer = %u, GLintptr offset = %d, GLsizeiptr size = %d)", - target, index, buffer, offset, size); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - const gl::Caps &caps = context->getCaps(); - switch (target) - { - case GL_TRANSFORM_FEEDBACK_BUFFER: - if (index >= caps.maxTransformFeedbackSeparateAttributes) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - break; - - case GL_UNIFORM_BUFFER: - if (index >= caps.maxUniformBufferBindings) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - if (buffer != 0 && size <= 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - switch (target) - { - case GL_TRANSFORM_FEEDBACK_BUFFER: - - // size and offset must be a multiple of 4 - if (buffer != 0 && ((offset % 4) != 0 || (size % 4) != 0)) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - context->bindIndexedTransformFeedbackBuffer(buffer, index, offset, size); - context->bindGenericTransformFeedbackBuffer(buffer); - break; - - case GL_UNIFORM_BUFFER: - - // it is an error to bind an offset not a multiple of the alignment - if (buffer != 0 && (offset % caps.uniformBufferOffsetAlignment) != 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - context->bindIndexedUniformBuffer(buffer, index, offset, size); - context->bindGenericUniformBuffer(buffer); - break; - - default: - UNREACHABLE(); - } - } + return gl::BindBufferRange(target, index, buffer, offset, size); } void GL_APIENTRY glBindBufferBase(GLenum target, GLuint index, GLuint buffer) { - EVENT("(GLenum target = 0x%X, GLuint index = %u, GLuint buffer = %u)", - target, index, buffer); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - const gl::Caps &caps = context->getCaps(); - switch (target) - { - case GL_TRANSFORM_FEEDBACK_BUFFER: - if (index >= caps.maxTransformFeedbackSeparateAttributes) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - break; - - case GL_UNIFORM_BUFFER: - if (index >= caps.maxUniformBufferBindings) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - switch (target) - { - case GL_TRANSFORM_FEEDBACK_BUFFER: - context->bindIndexedTransformFeedbackBuffer(buffer, index, 0, 0); - context->bindGenericTransformFeedbackBuffer(buffer); - break; - - case GL_UNIFORM_BUFFER: - context->bindIndexedUniformBuffer(buffer, index, 0, 0); - context->bindGenericUniformBuffer(buffer); - break; - - default: - UNREACHABLE(); - } - } + return gl::BindBufferBase(target, index, buffer); } void GL_APIENTRY glTransformFeedbackVaryings(GLuint program, GLsizei count, const GLchar* const* varyings, GLenum bufferMode) { - EVENT("(GLuint program = %u, GLsizei count = %d, const GLchar* const* varyings = 0x%0.8p, GLenum bufferMode = 0x%X)", - program, count, varyings, bufferMode); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (count < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - const gl::Caps &caps = context->getCaps(); - switch (bufferMode) - { - case GL_INTERLEAVED_ATTRIBS: - break; - case GL_SEPARATE_ATTRIBS: - if (static_cast(count) > caps.maxTransformFeedbackSeparateAttributes) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - break; - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - if (!gl::ValidProgram(context, program)) - { - return; - } - - gl::Program *programObject = context->getProgram(program); - ASSERT(programObject); - - programObject->setTransformFeedbackVaryings(count, varyings, bufferMode); - } + return gl::TransformFeedbackVaryings(program, count, varyings, bufferMode); } void GL_APIENTRY glGetTransformFeedbackVarying(GLuint program, GLuint index, GLsizei bufSize, GLsizei* length, GLsizei* size, GLenum* type, GLchar* name) { - EVENT("(GLuint program = %u, GLuint index = %u, GLsizei bufSize = %d, GLsizei* length = 0x%0.8p, " - "GLsizei* size = 0x%0.8p, GLenum* type = 0x%0.8p, GLchar* name = 0x%0.8p)", - program, index, bufSize, length, size, type, name); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (bufSize < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - if (!gl::ValidProgram(context, program)) - { - return; - } - - gl::Program *programObject = context->getProgram(program); - ASSERT(programObject); - - if (index >= static_cast(programObject->getTransformFeedbackVaryingCount())) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - programObject->getTransformFeedbackVarying(index, bufSize, length, size, type, name); - } + return gl::GetTransformFeedbackVarying(program, index, bufSize, length, size, type, name); } void GL_APIENTRY glVertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid* pointer) { - EVENT("(GLuint index = %u, GLint size = %d, GLenum type = 0x%X, GLsizei stride = %d, const GLvoid* pointer = 0x%0.8p)", - index, size, type, stride, pointer); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - if (size < 1 || size > 4) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - switch (type) - { - case GL_BYTE: - case GL_UNSIGNED_BYTE: - case GL_SHORT: - case GL_UNSIGNED_SHORT: - case GL_INT: - case GL_UNSIGNED_INT: - case GL_INT_2_10_10_10_REV: - case GL_UNSIGNED_INT_2_10_10_10_REV: - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - if (stride < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - if ((type == GL_INT_2_10_10_10_REV || type == GL_UNSIGNED_INT_2_10_10_10_REV) && size != 4) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - // [OpenGL ES 3.0.2] Section 2.8 page 24: - // An INVALID_OPERATION error is generated when a non-zero vertex array object - // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point, - // and the pointer argument is not NULL. - if (context->getState().getVertexArray()->id() != 0 && context->getState().getArrayBufferId() == 0 && pointer != NULL) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - context->getState().setVertexAttribState(index, context->getState().getTargetBuffer(GL_ARRAY_BUFFER), size, type, false, true, - stride, pointer); - } + return gl::VertexAttribIPointer(index, size, type, stride, pointer); } void GL_APIENTRY glGetVertexAttribIiv(GLuint index, GLenum pname, GLint* params) { - EVENT("(GLuint index = %u, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", - index, pname, params); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - const gl::VertexAttribute &attribState = context->getState().getVertexAttribState(index); - - if (!gl::ValidateGetVertexAttribParameters(context, pname)) - { - return; - } - - if (pname == GL_CURRENT_VERTEX_ATTRIB) - { - const gl::VertexAttribCurrentValueData ¤tValueData = context->getState().getVertexAttribCurrentValue(index); - for (int i = 0; i < 4; ++i) - { - params[i] = currentValueData.IntValues[i]; - } - } - else - { - *params = gl::QuerySingleVertexAttributeParameter(attribState, pname); - } - } + return gl::GetVertexAttribIiv(index, pname, params); } void GL_APIENTRY glGetVertexAttribIuiv(GLuint index, GLenum pname, GLuint* params) { - EVENT("(GLuint index = %u, GLenum pname = 0x%X, GLuint* params = 0x%0.8p)", - index, pname, params); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - const gl::VertexAttribute &attribState = context->getState().getVertexAttribState(index); - - if (!gl::ValidateGetVertexAttribParameters(context, pname)) - { - return; - } - - if (pname == GL_CURRENT_VERTEX_ATTRIB) - { - const gl::VertexAttribCurrentValueData ¤tValueData = context->getState().getVertexAttribCurrentValue(index); - for (int i = 0; i < 4; ++i) - { - params[i] = currentValueData.UnsignedIntValues[i]; - } - } - else - { - *params = gl::QuerySingleVertexAttributeParameter(attribState, pname); - } - } + return gl::GetVertexAttribIuiv(index, pname, params); } void GL_APIENTRY glVertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint w) { - EVENT("(GLuint index = %u, GLint x = %d, GLint y = %d, GLint z = %d, GLint w = %d)", - index, x, y, z, w); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - GLint vals[4] = { x, y, z, w }; - context->getState().setVertexAttribi(index, vals); - } + return gl::VertexAttribI4i(index, x, y, z, w); } void GL_APIENTRY glVertexAttribI4ui(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w) { - EVENT("(GLuint index = %u, GLuint x = %u, GLuint y = %u, GLuint z = %u, GLuint w = %u)", - index, x, y, z, w); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - GLuint vals[4] = { x, y, z, w }; - context->getState().setVertexAttribu(index, vals); - } + return gl::VertexAttribI4ui(index, x, y, z, w); } void GL_APIENTRY glVertexAttribI4iv(GLuint index, const GLint* v) { - EVENT("(GLuint index = %u, const GLint* v = 0x%0.8p)", index, v); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - context->getState().setVertexAttribi(index, v); - } + return gl::VertexAttribI4iv(index, v); } void GL_APIENTRY glVertexAttribI4uiv(GLuint index, const GLuint* v) { - EVENT("(GLuint index = %u, const GLuint* v = 0x%0.8p)", index, v); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - context->getState().setVertexAttribu(index, v); - } + return gl::VertexAttribI4uiv(index, v); } void GL_APIENTRY glGetUniformuiv(GLuint program, GLint location, GLuint* params) { - EVENT("(GLuint program = %u, GLint location = %d, GLuint* params = 0x%0.8p)", - program, location, params); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateGetUniformuiv(context, program, location, params)) - { - return; - } - - gl::Program *programObject = context->getProgram(program); - ASSERT(programObject); - gl::ProgramBinary *programBinary = programObject->getProgramBinary(); - ASSERT(programBinary); - - programBinary->getUniformuiv(location, params); - } + return gl::GetUniformuiv(program, location, params); } GLint GL_APIENTRY glGetFragDataLocation(GLuint program, const GLchar *name) { - EVENT("(GLuint program = %u, const GLchar *name = 0x%0.8p)", - program, name); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return -1; - } - - if (program == 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return -1; - } - - gl::Program *programObject = context->getProgram(program); - - if (!programObject || !programObject->isLinked()) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return -1; - } - - gl::ProgramBinary *programBinary = programObject->getProgramBinary(); - if (!programBinary) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return -1; - } - - return programBinary->getFragDataLocation(name); - } - - return 0; + return gl::GetFragDataLocation(program, name); } void GL_APIENTRY glUniform1ui(GLint location, GLuint v0) { - glUniform1uiv(location, 1, &v0); + return gl::Uniform1ui(location, v0); } void GL_APIENTRY glUniform2ui(GLint location, GLuint v0, GLuint v1) { - const GLuint xy[] = { v0, v1 }; - glUniform2uiv(location, 1, xy); + return gl::Uniform2ui(location, v0, v1); } void GL_APIENTRY glUniform3ui(GLint location, GLuint v0, GLuint v1, GLuint v2) { - const GLuint xyz[] = { v0, v1, v2 }; - glUniform3uiv(location, 1, xyz); + return gl::Uniform3ui(location, v0, v1, v2); } void GL_APIENTRY glUniform4ui(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3) { - const GLuint xyzw[] = { v0, v1, v2, v3 }; - glUniform4uiv(location, 1, xyzw); + return gl::Uniform4ui(location, v0, v1, v2, v3); } void GL_APIENTRY glUniform1uiv(GLint location, GLsizei count, const GLuint* value) { - EVENT("(GLint location = %d, GLsizei count = %d, const GLuint* value = 0x%0.8p)", - location, count, value); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateUniform(context, GL_UNSIGNED_INT, location, count)) - { - return; - } - - gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); - programBinary->setUniform1uiv(location, count, value); - } + return gl::Uniform1uiv(location, count, value); } void GL_APIENTRY glUniform2uiv(GLint location, GLsizei count, const GLuint* value) { - EVENT("(GLint location = %d, GLsizei count = %d, const GLuint* value = 0x%0.8p)", - location, count, value); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateUniform(context, GL_UNSIGNED_INT_VEC2, location, count)) - { - return; - } - - gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); - programBinary->setUniform2uiv(location, count, value); - } + return gl::Uniform2uiv(location, count, value); } void GL_APIENTRY glUniform3uiv(GLint location, GLsizei count, const GLuint* value) { - EVENT("(GLint location = %d, GLsizei count = %d, const GLuint* value)", - location, count, value); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateUniform(context, GL_UNSIGNED_INT_VEC3, location, count)) - { - return; - } - - gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); - programBinary->setUniform3uiv(location, count, value); - } + return gl::Uniform3uiv(location, count, value); } void GL_APIENTRY glUniform4uiv(GLint location, GLsizei count, const GLuint* value) { - EVENT("(GLint location = %d, GLsizei count = %d, const GLuint* value = 0x%0.8p)", - location, count, value); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateUniform(context, GL_UNSIGNED_INT_VEC4, location, count)) - { - return; - } - - gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); - programBinary->setUniform4uiv(location, count, value); - } + return gl::Uniform4uiv(location, count, value); } void GL_APIENTRY glClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint* value) { - EVENT("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLint* value = 0x%0.8p)", - buffer, drawbuffer, value); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateClearBuffer(context)) - { - return; - } - - switch (buffer) - { - case GL_COLOR: - if (drawbuffer < 0 || static_cast(drawbuffer) >= context->getCaps().maxDrawBuffers) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - break; - - case GL_STENCIL: - if (drawbuffer != 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - gl::Error error = context->clearBufferiv(buffer, drawbuffer, value); - if (error.isError()) - { - context->recordError(error); - return; - } - } + return gl::ClearBufferiv(buffer, drawbuffer, value); } void GL_APIENTRY glClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint* value) { - EVENT("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLuint* value = 0x%0.8p)", - buffer, drawbuffer, value); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateClearBuffer(context)) - { - return; - } - - switch (buffer) - { - case GL_COLOR: - if (drawbuffer < 0 || static_cast(drawbuffer) >= context->getCaps().maxDrawBuffers) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - gl::Error error = context->clearBufferuiv(buffer, drawbuffer, value); - if (error.isError()) - { - context->recordError(error); - return; - } - } + return gl::ClearBufferuiv(buffer, drawbuffer, value); } void GL_APIENTRY glClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat* value) { - EVENT("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLfloat* value = 0x%0.8p)", - buffer, drawbuffer, value); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateClearBuffer(context)) - { - return; - } - - switch (buffer) - { - case GL_COLOR: - if (drawbuffer < 0 || static_cast(drawbuffer) >= context->getCaps().maxDrawBuffers) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - break; - - case GL_DEPTH: - if (drawbuffer != 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - gl::Error error = context->clearBufferfv(buffer, drawbuffer, value); - if (error.isError()) - { - context->recordError(error); - return; - } - } + return gl::ClearBufferfv(buffer, drawbuffer, value); } void GL_APIENTRY glClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) { - EVENT("(GLenum buffer = 0x%X, GLint drawbuffer = %d, GLfloat depth, GLint stencil = %d)", - buffer, drawbuffer, depth, stencil); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateClearBuffer(context)) - { - return; - } - - switch (buffer) - { - case GL_DEPTH_STENCIL: - if (drawbuffer != 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - gl::Error error = context->clearBufferfi(buffer, drawbuffer, depth, stencil); - if (error.isError()) - { - context->recordError(error); - return; - } - } + return gl::ClearBufferfi(buffer, drawbuffer, depth, stencil); } const GLubyte* GL_APIENTRY glGetStringi(GLenum name, GLuint index) { - EVENT("(GLenum name = 0x%X, GLuint index = %u)", name, index); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return NULL; - } - - if (name != GL_EXTENSIONS) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return NULL; - } - - if (index >= context->getExtensionStringCount()) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return NULL; - } - - return reinterpret_cast(context->getExtensionString(index).c_str()); - } - - return NULL; + return gl::GetStringi(name, index); } void GL_APIENTRY glCopyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size) { - EVENT("(GLenum readTarget = 0x%X, GLenum writeTarget = 0x%X, GLintptr readOffset = %d, GLintptr writeOffset = %d, GLsizeiptr size = %d)", - readTarget, writeTarget, readOffset, writeOffset, size); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (!gl::ValidBufferTarget(context, readTarget) || !gl::ValidBufferTarget(context, writeTarget)) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - gl::Buffer *readBuffer = context->getState().getTargetBuffer(readTarget); - gl::Buffer *writeBuffer = context->getState().getTargetBuffer(writeTarget); - - if (!readBuffer || !writeBuffer) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - // Verify that readBuffer and writeBuffer are not currently mapped - if (readBuffer->isMapped() || writeBuffer->isMapped()) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (readOffset < 0 || writeOffset < 0 || size < 0 || - static_cast(readOffset + size) > readBuffer->getSize() || - static_cast(writeOffset + size) > writeBuffer->getSize()) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - if (readBuffer == writeBuffer && std::abs(readOffset - writeOffset) < size) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - // if size is zero, the copy is a successful no-op - if (size > 0) - { - gl::Error error = writeBuffer->copyBufferSubData(readBuffer, readOffset, writeOffset, size); - if (error.isError()) - { - context->recordError(error); - return; - } - } - } + return gl::CopyBufferSubData(readTarget, writeTarget, readOffset, writeOffset, size); } void GL_APIENTRY glGetUniformIndices(GLuint program, GLsizei uniformCount, const GLchar* const* uniformNames, GLuint* uniformIndices) { - EVENT("(GLuint program = %u, GLsizei uniformCount = %d, const GLchar* const* uniformNames = 0x%0.8p, GLuint* uniformIndices = 0x%0.8p)", - program, uniformCount, uniformNames, uniformIndices); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (uniformCount < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - gl::Program *programObject = context->getProgram(program); - - if (!programObject) - { - if (context->getShader(program)) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - else - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - } - - gl::ProgramBinary *programBinary = programObject->getProgramBinary(); - if (!programObject->isLinked() || !programBinary) - { - for (int uniformId = 0; uniformId < uniformCount; uniformId++) - { - uniformIndices[uniformId] = GL_INVALID_INDEX; - } - } - else - { - for (int uniformId = 0; uniformId < uniformCount; uniformId++) - { - uniformIndices[uniformId] = programBinary->getUniformIndex(uniformNames[uniformId]); - } - } - } + return gl::GetUniformIndices(program, uniformCount, uniformNames, uniformIndices); } void GL_APIENTRY glGetActiveUniformsiv(GLuint program, GLsizei uniformCount, const GLuint* uniformIndices, GLenum pname, GLint* params) { - EVENT("(GLuint program = %u, GLsizei uniformCount = %d, const GLuint* uniformIndices = 0x%0.8p, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", - program, uniformCount, uniformIndices, pname, params); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (uniformCount < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - gl::Program *programObject = context->getProgram(program); - - if (!programObject) - { - if (context->getShader(program)) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - else - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - } - - switch (pname) - { - case GL_UNIFORM_TYPE: - case GL_UNIFORM_SIZE: - case GL_UNIFORM_NAME_LENGTH: - case GL_UNIFORM_BLOCK_INDEX: - case GL_UNIFORM_OFFSET: - case GL_UNIFORM_ARRAY_STRIDE: - case GL_UNIFORM_MATRIX_STRIDE: - case GL_UNIFORM_IS_ROW_MAJOR: - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - gl::ProgramBinary *programBinary = programObject->getProgramBinary(); - - if (!programBinary && uniformCount > 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - for (int uniformId = 0; uniformId < uniformCount; uniformId++) - { - const GLuint index = uniformIndices[uniformId]; - - if (index >= (GLuint)programBinary->getActiveUniformCount()) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - } - - for (int uniformId = 0; uniformId < uniformCount; uniformId++) - { - const GLuint index = uniformIndices[uniformId]; - params[uniformId] = programBinary->getActiveUniformi(index, pname); - } - } + return gl::GetActiveUniformsiv(program, uniformCount, uniformIndices, pname, params); } GLuint GL_APIENTRY glGetUniformBlockIndex(GLuint program, const GLchar* uniformBlockName) { - EVENT("(GLuint program = %u, const GLchar* uniformBlockName = 0x%0.8p)", program, uniformBlockName); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return GL_INVALID_INDEX; - } - - gl::Program *programObject = context->getProgram(program); - - if (!programObject) - { - if (context->getShader(program)) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return GL_INVALID_INDEX; - } - else - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return GL_INVALID_INDEX; - } - } - - gl::ProgramBinary *programBinary = programObject->getProgramBinary(); - if (!programBinary) - { - return GL_INVALID_INDEX; - } - - return programBinary->getUniformBlockIndex(uniformBlockName); - } - - return 0; + return gl::GetUniformBlockIndex(program, uniformBlockName); } void GL_APIENTRY glGetActiveUniformBlockiv(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params) { - EVENT("(GLuint program = %u, GLuint uniformBlockIndex = %u, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", - program, uniformBlockIndex, pname, params); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - gl::Program *programObject = context->getProgram(program); - - if (!programObject) - { - if (context->getShader(program)) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - else - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - } - - gl::ProgramBinary *programBinary = programObject->getProgramBinary(); - - if (!programBinary || uniformBlockIndex >= programBinary->getActiveUniformBlockCount()) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - switch (pname) - { - case GL_UNIFORM_BLOCK_BINDING: - *params = static_cast(programObject->getUniformBlockBinding(uniformBlockIndex)); - break; - - case GL_UNIFORM_BLOCK_DATA_SIZE: - case GL_UNIFORM_BLOCK_NAME_LENGTH: - case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS: - case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES: - case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER: - case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER: - programBinary->getActiveUniformBlockiv(uniformBlockIndex, pname, params); - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - } + return gl::GetActiveUniformBlockiv(program, uniformBlockIndex, pname, params); } void GL_APIENTRY glGetActiveUniformBlockName(GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei* length, GLchar* uniformBlockName) { - EVENT("(GLuint program = %u, GLuint uniformBlockIndex = %u, GLsizei bufSize = %d, GLsizei* length = 0x%0.8p, GLchar* uniformBlockName = 0x%0.8p)", - program, uniformBlockIndex, bufSize, length, uniformBlockName); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - gl::Program *programObject = context->getProgram(program); - - if (!programObject) - { - if (context->getShader(program)) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - else - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - } - - gl::ProgramBinary *programBinary = programObject->getProgramBinary(); - - if (!programBinary || uniformBlockIndex >= programBinary->getActiveUniformBlockCount()) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - programBinary->getActiveUniformBlockName(uniformBlockIndex, bufSize, length, uniformBlockName); - } + return gl::GetActiveUniformBlockName(program, uniformBlockIndex, bufSize, length, uniformBlockName); } void GL_APIENTRY glUniformBlockBinding(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding) { - EVENT("(GLuint program = %u, GLuint uniformBlockIndex = %u, GLuint uniformBlockBinding = %u)", - program, uniformBlockIndex, uniformBlockBinding); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (uniformBlockBinding >= context->getCaps().maxUniformBufferBindings) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - gl::Program *programObject = context->getProgram(program); - - if (!programObject) - { - if (context->getShader(program)) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - else - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - } - - gl::ProgramBinary *programBinary = programObject->getProgramBinary(); - - // if never linked, there won't be any uniform blocks - if (!programBinary || uniformBlockIndex >= programBinary->getActiveUniformBlockCount()) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - programObject->bindUniformBlock(uniformBlockIndex, uniformBlockBinding); - } + return gl::UniformBlockBinding(program, uniformBlockIndex, uniformBlockBinding); } void GL_APIENTRY glDrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount) { - EVENT("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d, GLsizei instanceCount = %d)", - mode, first, count, instanceCount); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - // glDrawArraysInstanced - UNIMPLEMENTED(); - } + return gl::DrawArraysInstanced(mode, first, count, instanceCount); } void GL_APIENTRY glDrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices, GLsizei instanceCount) { - EVENT("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = 0x%0.8p, GLsizei instanceCount = %d)", - mode, count, type, indices, instanceCount); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - // glDrawElementsInstanced - UNIMPLEMENTED(); - } + return gl::DrawElementsInstanced(mode, count, type, indices, instanceCount); } GLsync GL_APIENTRY glFenceSync(GLenum condition, GLbitfield flags) { - EVENT("(GLenum condition = 0x%X, GLbitfield flags = 0x%X)", condition, flags); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return 0; - } - - if (condition != GL_SYNC_GPU_COMMANDS_COMPLETE) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return 0; - } - - if (flags != 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return 0; - } - - GLsync fenceSync = context->createFenceSync(); - - gl::FenceSync *fenceSyncObject = context->getFenceSync(fenceSync); - gl::Error error = fenceSyncObject->set(condition); - if (error.isError()) - { - context->deleteFenceSync(fenceSync); - context->recordError(error); - return NULL; - } - - return fenceSync; - } - - return NULL; + return gl::FenceSync_(condition, flags); } GLboolean GL_APIENTRY glIsSync(GLsync sync) { - EVENT("(GLsync sync = 0x%0.8p)", sync); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return GL_FALSE; - } - - return (context->getFenceSync(sync) != NULL); - } - - return GL_FALSE; + return gl::IsSync(sync); } void GL_APIENTRY glDeleteSync(GLsync sync) { - EVENT("(GLsync sync = 0x%0.8p)", sync); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (sync != static_cast(0) && !context->getFenceSync(sync)) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - context->deleteFenceSync(sync); - } + return gl::DeleteSync(sync); } GLenum GL_APIENTRY glClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout) { - EVENT("(GLsync sync = 0x%0.8p, GLbitfield flags = 0x%X, GLuint64 timeout = %llu)", - sync, flags, timeout); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return GL_WAIT_FAILED; - } - - if ((flags & ~(GL_SYNC_FLUSH_COMMANDS_BIT)) != 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return GL_WAIT_FAILED; - } - - gl::FenceSync *fenceSync = context->getFenceSync(sync); - - if (!fenceSync) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return GL_WAIT_FAILED; - } - - GLenum result = GL_WAIT_FAILED; - gl::Error error = fenceSync->clientWait(flags, timeout, &result); - if (error.isError()) - { - context->recordError(error); - return GL_WAIT_FAILED; - } - - return result; - } - - return GL_FALSE; + return gl::ClientWaitSync(sync, flags, timeout); } void GL_APIENTRY glWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout) { - EVENT("(GLsync sync = 0x%0.8p, GLbitfield flags = 0x%X, GLuint64 timeout = %llu)", - sync, flags, timeout); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (flags != 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - if (timeout != GL_TIMEOUT_IGNORED) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - gl::FenceSync *fenceSync = context->getFenceSync(sync); - - if (!fenceSync) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - gl::Error error = fenceSync->serverWait(flags, timeout); - if (error.isError()) - { - context->recordError(error); - } - } + return gl::WaitSync(sync, flags, timeout); } void GL_APIENTRY glGetInteger64v(GLenum pname, GLint64* params) { - EVENT("(GLenum pname = 0x%X, GLint64* params = 0x%0.8p)", - pname, params); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - GLenum nativeType; - unsigned int numParams = 0; - if (!ValidateStateQuery(context, pname, &nativeType, &numParams)) - { - return; - } - - if (nativeType == GL_INT_64_ANGLEX) - { - context->getInteger64v(pname, params); - } - else - { - CastStateValues(context, nativeType, pname, numParams, params); - } - } + return gl::GetInteger64v(pname, params); } void GL_APIENTRY glGetSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei* length, GLint* values) { - EVENT("(GLsync sync = 0x%0.8p, GLenum pname = 0x%X, GLsizei bufSize = %d, GLsizei* length = 0x%0.8p, GLint* values = 0x%0.8p)", - sync, pname, bufSize, length, values); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (bufSize < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - gl::FenceSync *fenceSync = context->getFenceSync(sync); - - if (!fenceSync) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - switch (pname) - { - case GL_OBJECT_TYPE: values[0] = static_cast(GL_SYNC_FENCE); break; - case GL_SYNC_CONDITION: values[0] = static_cast(fenceSync->getCondition()); break; - case GL_SYNC_FLAGS: values[0] = 0; break; - - case GL_SYNC_STATUS: - { - gl::Error error = fenceSync->getStatus(values); - if (error.isError()) - { - context->recordError(error); - return; - } - break; - } - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - } + return gl::GetSynciv(sync, pname, bufSize, length, values); } void GL_APIENTRY glGetInteger64i_v(GLenum target, GLuint index, GLint64* data) { - EVENT("(GLenum target = 0x%X, GLuint index = %u, GLint64* data = 0x%0.8p)", - target, index, data); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - const gl::Caps &caps = context->getCaps(); - switch (target) - { - case GL_TRANSFORM_FEEDBACK_BUFFER_START: - case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE: - case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: - if (index >= caps.maxTransformFeedbackSeparateAttributes) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - break; - - case GL_UNIFORM_BUFFER_START: - case GL_UNIFORM_BUFFER_SIZE: - case GL_UNIFORM_BUFFER_BINDING: - if (index >= caps.maxUniformBufferBindings) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - if (!(context->getIndexedInteger64v(target, index, data))) - { - GLenum nativeType; - unsigned int numParams = 0; - if (!context->getIndexedQueryParameterInfo(target, &nativeType, &numParams)) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - if (numParams == 0) - return; // it is known that pname is valid, but there are no parameters to return - - if (nativeType == GL_INT) - { - GLint *intParams = new GLint[numParams]; - - context->getIndexedIntegerv(target, index, intParams); - - for (unsigned int i = 0; i < numParams; ++i) - { - data[i] = static_cast(intParams[i]); - } - - delete [] intParams; - } - else - { - UNREACHABLE(); - } - } - } + return gl::GetInteger64i_v(target, index, data); } void GL_APIENTRY glGetBufferParameteri64v(GLenum target, GLenum pname, GLint64* params) { - EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint64* params = 0x%0.8p)", - target, pname, params); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (!gl::ValidBufferTarget(context, target)) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - if (!gl::ValidBufferParameter(context, pname)) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - gl::Buffer *buffer = context->getState().getTargetBuffer(target); - - if (!buffer) - { - // A null buffer means that "0" is bound to the requested buffer target - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - switch (pname) - { - case GL_BUFFER_USAGE: - *params = static_cast(buffer->getUsage()); - break; - case GL_BUFFER_SIZE: - *params = buffer->getSize(); - break; - case GL_BUFFER_ACCESS_FLAGS: - *params = static_cast(buffer->getAccessFlags()); - break; - case GL_BUFFER_MAPPED: - *params = static_cast(buffer->isMapped()); - break; - case GL_BUFFER_MAP_OFFSET: - *params = buffer->getMapOffset(); - break; - case GL_BUFFER_MAP_LENGTH: - *params = buffer->getMapLength(); - break; - default: UNREACHABLE(); break; - } - } + return gl::GetBufferParameteri64v(target, pname, params); } void GL_APIENTRY glGenSamplers(GLsizei count, GLuint* samplers) { - EVENT("(GLsizei count = %d, GLuint* samplers = 0x%0.8p)", count, samplers); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (count < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - for (int i = 0; i < count; i++) - { - samplers[i] = context->createSampler(); - } - } + return gl::GenSamplers(count, samplers); } void GL_APIENTRY glDeleteSamplers(GLsizei count, const GLuint* samplers) { - EVENT("(GLsizei count = %d, const GLuint* samplers = 0x%0.8p)", count, samplers); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (count < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - for (int i = 0; i < count; i++) - { - context->deleteSampler(samplers[i]); - } - } + return gl::DeleteSamplers(count, samplers); } GLboolean GL_APIENTRY glIsSampler(GLuint sampler) { - EVENT("(GLuint sampler = %u)", sampler); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return GL_FALSE; - } - - return context->isSampler(sampler); - } - - return GL_FALSE; + return gl::IsSampler(sampler); } void GL_APIENTRY glBindSampler(GLuint unit, GLuint sampler) { - EVENT("(GLuint unit = %u, GLuint sampler = %u)", unit, sampler); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (sampler != 0 && !context->isSampler(sampler)) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (unit >= context->getCaps().maxCombinedTextureImageUnits) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - context->bindSampler(unit, sampler); - } + return gl::BindSampler(unit, sampler); } void GL_APIENTRY glSamplerParameteri(GLuint sampler, GLenum pname, GLint param) { - EVENT("(GLuint sampler = %u, GLenum pname = 0x%X, GLint param = %d)", sampler, pname, param); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (!gl::ValidateSamplerObjectParameter(context, pname)) - { - return; - } - - if (!gl::ValidateTexParamParameters(context, pname, param)) - { - return; - } - - if (!context->isSampler(sampler)) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - context->samplerParameteri(sampler, pname, param); - } + return gl::SamplerParameteri(sampler, pname, param); } void GL_APIENTRY glSamplerParameteriv(GLuint sampler, GLenum pname, const GLint* param) { - glSamplerParameteri(sampler, pname, *param); + return gl::SamplerParameteriv(sampler, pname, param); } void GL_APIENTRY glSamplerParameterf(GLuint sampler, GLenum pname, GLfloat param) { - EVENT("(GLuint sampler = %u, GLenum pname = 0x%X, GLfloat param = %g)", sampler, pname, param); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (!gl::ValidateSamplerObjectParameter(context, pname)) - { - return; - } - - if (!gl::ValidateTexParamParameters(context, pname, static_cast(param))) - { - return; - } - - if (!context->isSampler(sampler)) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - context->samplerParameterf(sampler, pname, param); - } + return gl::SamplerParameterf(sampler, pname, param); } void GL_APIENTRY glSamplerParameterfv(GLuint sampler, GLenum pname, const GLfloat* param) { - glSamplerParameterf(sampler, pname, *param); + return gl::SamplerParameterfv(sampler, pname, param); } void GL_APIENTRY glGetSamplerParameteriv(GLuint sampler, GLenum pname, GLint* params) { - EVENT("(GLuint sampler = %u, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", sampler, pname, params); + return gl::GetSamplerParameteriv(sampler, pname, params); +} - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } +void GL_APIENTRY glGetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat* params) +{ + return gl::GetSamplerParameterfv(sampler, pname, params); +} - if (!gl::ValidateSamplerObjectParameter(context, pname)) - { - return; - } +void GL_APIENTRY glVertexAttribDivisor(GLuint index, GLuint divisor) +{ + return gl::VertexAttribDivisor(index, divisor); +} - if (!context->isSampler(sampler)) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } +void GL_APIENTRY glBindTransformFeedback(GLenum target, GLuint id) +{ + return gl::BindTransformFeedback(target, id); +} - *params = context->getSamplerParameteri(sampler, pname); - } +void GL_APIENTRY glDeleteTransformFeedbacks(GLsizei n, const GLuint* ids) +{ + return gl::DeleteTransformFeedbacks(n, ids); } -void GL_APIENTRY glGetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat* params) +void GL_APIENTRY glGenTransformFeedbacks(GLsizei n, GLuint* ids) { - EVENT("(GLuint sample = %ur, GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", sampler, pname, params); + return gl::GenTransformFeedbacks(n, ids); +} - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } +GLboolean GL_APIENTRY glIsTransformFeedback(GLuint id) +{ + return gl::IsTransformFeedback(id); +} - if (!gl::ValidateSamplerObjectParameter(context, pname)) - { - return; - } +void GL_APIENTRY glPauseTransformFeedback(void) +{ + return gl::PauseTransformFeedback(); +} - if (!context->isSampler(sampler)) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } +void GL_APIENTRY glResumeTransformFeedback(void) +{ + return gl::ResumeTransformFeedback(); +} - *params = context->getSamplerParameterf(sampler, pname); - } +void GL_APIENTRY glGetProgramBinary(GLuint program, GLsizei bufSize, GLsizei* length, GLenum* binaryFormat, GLvoid* binary) +{ + return gl::GetProgramBinary(program, bufSize, length, binaryFormat, binary); } -void GL_APIENTRY glVertexAttribDivisor(GLuint index, GLuint divisor) +void GL_APIENTRY glProgramBinary(GLuint program, GLenum binaryFormat, const GLvoid* binary, GLsizei length) { - EVENT("(GLuint index = %u, GLuint divisor = %u)", index, divisor); + return gl::ProgramBinary(program, binaryFormat, binary, length); +} - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } +void GL_APIENTRY glProgramParameteri(GLuint program, GLenum pname, GLint value) +{ + return gl::ProgramParameteri(program, pname, value); +} - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } +void GL_APIENTRY glInvalidateFramebuffer(GLenum target, GLsizei numAttachments, const GLenum* attachments) +{ + return gl::InvalidateFramebuffer(target, numAttachments, attachments); +} - context->setVertexAttribDivisor(index, divisor); - } +void GL_APIENTRY glInvalidateSubFramebuffer(GLenum target, GLsizei numAttachments, const GLenum* attachments, GLint x, GLint y, GLsizei width, GLsizei height) +{ + return gl::InvalidateSubFramebuffer(target, numAttachments, attachments, x, y, width, height); } -void GL_APIENTRY glBindTransformFeedback(GLenum target, GLuint id) +void GL_APIENTRY glTexStorage2D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) { - EVENT("(GLenum target = 0x%X, GLuint id = %u)", target, id); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - switch (target) - { - case GL_TRANSFORM_FEEDBACK: - { - // Cannot bind a transform feedback object if the current one is started and not paused (3.0.2 pg 85 section 2.14.1) - gl::TransformFeedback *curTransformFeedback = context->getState().getCurrentTransformFeedback(); - if (curTransformFeedback && curTransformFeedback->isStarted() && !curTransformFeedback->isPaused()) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - // Cannot bind a transform feedback object that does not exist (3.0.2 pg 85 section 2.14.1) - if (context->getTransformFeedback(id) == NULL) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - context->bindTransformFeedback(id); - } - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - } + return gl::TexStorage2D(target, levels, internalformat, width, height); } -void GL_APIENTRY glDeleteTransformFeedbacks(GLsizei n, const GLuint* ids) +void GL_APIENTRY glTexStorage3D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) { - EVENT("(GLsizei n = %d, const GLuint* ids = 0x%0.8p)", n, ids); + return gl::TexStorage3D(target, levels, internalformat, width, height, depth); +} - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } +void GL_APIENTRY glGetInternalformativ(GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint* params) +{ + return gl::GetInternalformativ(target, internalformat, pname, bufSize, params); +} - for (int i = 0; i < n; i++) - { - context->deleteTransformFeedback(ids[i]); - } - } +void GL_APIENTRY glBlitFramebufferANGLE(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) +{ + return gl::BlitFramebufferANGLE(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); } -void GL_APIENTRY glGenTransformFeedbacks(GLsizei n, GLuint* ids) +void GL_APIENTRY glRenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height) { - EVENT("(GLsizei n = %d, GLuint* ids = 0x%0.8p)", n, ids); + return gl::RenderbufferStorageMultisampleANGLE(target, samples, internalformat, width, height); +} - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } +void GL_APIENTRY glDeleteFencesNV(GLsizei n, const GLuint* fences) +{ + return gl::DeleteFencesNV(n, fences); +} - for (int i = 0; i < n; i++) - { - ids[i] = context->createTransformFeedback(); - } - } +void GL_APIENTRY glGenFencesNV(GLsizei n, GLuint* fences) +{ + return gl::GenFencesNV(n, fences); } -GLboolean GL_APIENTRY glIsTransformFeedback(GLuint id) +GLboolean GL_APIENTRY glIsFenceNV(GLuint fence) { - EVENT("(GLuint id = %u)", id); + return gl::IsFenceNV(fence); +} - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return GL_FALSE; - } +GLboolean GL_APIENTRY glTestFenceNV(GLuint fence) +{ + return gl::TestFenceNV(fence); +} - return ((context->getTransformFeedback(id) != NULL) ? GL_TRUE : GL_FALSE); - } +void GL_APIENTRY glGetFenceivNV(GLuint fence, GLenum pname, GLint *params) +{ + return gl::GetFenceivNV(fence, pname, params); +} - return GL_FALSE; +void GL_APIENTRY glFinishFenceNV(GLuint fence) +{ + return gl::FinishFenceNV(fence); } -void GL_APIENTRY glPauseTransformFeedback(void) +void GL_APIENTRY glSetFenceNV(GLuint fence, GLenum condition) { - EVENT("(void)"); + return gl::SetFenceNV(fence, condition); +} - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } +void GL_APIENTRY glGetTranslatedShaderSourceANGLE(GLuint shader, GLsizei bufsize, GLsizei *length, GLchar *source) +{ + return gl::GetTranslatedShaderSourceANGLE(shader, bufsize, length, source); +} - gl::TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback(); - ASSERT(transformFeedback != NULL); +void GL_APIENTRY glTexStorage2DEXT(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) +{ + return gl::TexStorage2DEXT(target, levels, internalformat, width, height); +} - // Current transform feedback must be started and not paused in order to pause (3.0.2 pg 86) - if (!transformFeedback->isStarted() || transformFeedback->isPaused()) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } +GLenum GL_APIENTRY glGetGraphicsResetStatusEXT(void) +{ + return gl::GetGraphicsResetStatusEXT(); +} - transformFeedback->pause(); - } +void GL_APIENTRY glReadnPixelsEXT(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data) +{ + return gl::ReadnPixelsEXT(x, y, width, height, format, type, bufSize, data); } -void GL_APIENTRY glResumeTransformFeedback(void) +void GL_APIENTRY glGetnUniformfvEXT(GLuint program, GLint location, GLsizei bufSize, float *params) { - EVENT("(void)"); + return gl::GetnUniformfvEXT(program, location, bufSize, params); +} - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } +void GL_APIENTRY glGetnUniformivEXT(GLuint program, GLint location, GLsizei bufSize, GLint *params) +{ + return gl::GetnUniformivEXT(program, location, bufSize, params); +} - gl::TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback(); - ASSERT(transformFeedback != NULL); +void GL_APIENTRY glGenQueriesEXT(GLsizei n, GLuint *ids) +{ + return gl::GenQueriesEXT(n, ids); +} - // Current transform feedback must be started and paused in order to resume (3.0.2 pg 86) - if (!transformFeedback->isStarted() || !transformFeedback->isPaused()) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } +void GL_APIENTRY glDeleteQueriesEXT(GLsizei n, const GLuint *ids) +{ + return gl::DeleteQueriesEXT(n, ids); +} - transformFeedback->resume(); - } +GLboolean GL_APIENTRY glIsQueryEXT(GLuint id) +{ + return gl::IsQueryEXT(id); } -void GL_APIENTRY glGetProgramBinary(GLuint program, GLsizei bufSize, GLsizei* length, GLenum* binaryFormat, GLvoid* binary) +void GL_APIENTRY glBeginQueryEXT(GLenum target, GLuint id) { - EVENT("(GLuint program = %u, GLsizei bufSize = %d, GLsizei* length = 0x%0.8p, GLenum* binaryFormat = 0x%0.8p, GLvoid* binary = 0x%0.8p)", - program, bufSize, length, binaryFormat, binary); + return gl::BeginQueryEXT(target, id); +} - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } +void GL_APIENTRY glEndQueryEXT(GLenum target) +{ + return gl::EndQueryEXT(target); +} - // glGetProgramBinary - UNIMPLEMENTED(); - } +void GL_APIENTRY glGetQueryivEXT(GLenum target, GLenum pname, GLint *params) +{ + return gl::GetQueryivEXT(target, pname, params); } -void GL_APIENTRY glProgramBinary(GLuint program, GLenum binaryFormat, const GLvoid* binary, GLsizei length) +void GL_APIENTRY glGetQueryObjectuivEXT(GLuint id, GLenum pname, GLuint *params) { - EVENT("(GLuint program = %u, GLenum binaryFormat = 0x%X, const GLvoid* binary = 0x%0.8p, GLsizei length = %d)", - program, binaryFormat, binary, length); + return gl::GetQueryObjectuivEXT(id, pname, params); +} - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } +void GL_APIENTRY glDrawBuffersEXT(GLsizei n, const GLenum *bufs) +{ + return gl::DrawBuffersEXT(n, bufs); +} - // glProgramBinary - UNIMPLEMENTED(); - } +void GL_APIENTRY glDrawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei count, GLsizei primcount) +{ + return gl::DrawArraysInstancedANGLE(mode, first, count, primcount); } -void GL_APIENTRY glProgramParameteri(GLuint program, GLenum pname, GLint value) +void GL_APIENTRY glDrawElementsInstancedANGLE(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount) { - EVENT("(GLuint program = %u, GLenum pname = 0x%X, GLint value = %d)", - program, pname, value); + return gl::DrawElementsInstancedANGLE(mode, count, type, indices, primcount); +} - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } +void GL_APIENTRY glVertexAttribDivisorANGLE(GLuint index, GLuint divisor) +{ + return gl::VertexAttribDivisorANGLE(index, divisor); +} - // glProgramParameteri - UNIMPLEMENTED(); - } +void GL_APIENTRY glGetProgramBinaryOES(GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, GLvoid *binary) +{ + return gl::GetProgramBinaryOES(program, bufSize, length, binaryFormat, binary); } -void GL_APIENTRY glInvalidateFramebuffer(GLenum target, GLsizei numAttachments, const GLenum* attachments) +void GL_APIENTRY glProgramBinaryOES(GLuint program, GLenum binaryFormat, const GLvoid *binary, GLint length) { - EVENT("(GLenum target = 0x%X, GLsizei numAttachments = %d, const GLenum* attachments = 0x%0.8p)", - target, numAttachments, attachments); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (!ValidateInvalidateFramebufferParameters(context, target, numAttachments, attachments)) - { - return; - } - - gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target); - ASSERT(framebuffer); - - if (framebuffer->completeness(context->getData()) == GL_FRAMEBUFFER_COMPLETE) - { - gl::Error error = framebuffer->invalidate(context->getCaps(), numAttachments, attachments); - if (error.isError()) - { - context->recordError(error); - return; - } - } - } + return gl::ProgramBinaryOES(program, binaryFormat, binary, length); } -void GL_APIENTRY glInvalidateSubFramebuffer(GLenum target, GLsizei numAttachments, const GLenum* attachments, GLint x, GLint y, GLsizei width, GLsizei height) +void* GL_APIENTRY glMapBufferOES(GLenum target, GLenum access) { - EVENT("(GLenum target = 0x%X, GLsizei numAttachments = %d, const GLenum* attachments = 0x%0.8p, GLint x = %d, " - "GLint y = %d, GLsizei width = %d, GLsizei height = %d)", - target, numAttachments, attachments, x, y, width, height); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (!ValidateInvalidateFramebufferParameters(context, target, numAttachments, attachments)) - { - return; - } - - gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target); - ASSERT(framebuffer); - - if (framebuffer->completeness(context->getData()) == GL_FRAMEBUFFER_COMPLETE) - { - gl::Error error = framebuffer->invalidateSub(numAttachments, attachments, x, y, width, height); - if (error.isError()) - { - context->recordError(error); - return; - } - } - } + return gl::MapBufferOES(target, access); } -void GL_APIENTRY glTexStorage2D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) +GLboolean GL_APIENTRY glUnmapBufferOES(GLenum target) { - EVENT("(GLenum target = 0x%X, GLsizei levels = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)", - target, levels, internalformat, width, height); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (!ValidateES3TexStorageParameters(context, target, levels, internalformat, width, height, 1)) - { - return; - } - - switch (target) - { - case GL_TEXTURE_2D: - { - gl::Texture2D *texture2d = context->getTexture2D(); - gl::Error error = texture2d->storage(levels, internalformat, width, height); - if (error.isError()) - { - context->recordError(error); - return; - } - } - break; - - case GL_TEXTURE_CUBE_MAP: - { - gl::TextureCubeMap *textureCube = context->getTextureCubeMap(); - gl::Error error = textureCube->storage(levels, internalformat, width); - if (error.isError()) - { - context->recordError(error); - return; - } - } - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - } + return gl::UnmapBufferOES(target); } -void GL_APIENTRY glTexStorage3D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) +void GL_APIENTRY glGetBufferPointervOES(GLenum target, GLenum pname, GLvoid **params) { - EVENT("(GLenum target = 0x%X, GLsizei levels = %d, GLenum internalformat = 0x%X, GLsizei width = %d, " - "GLsizei height = %d, GLsizei depth = %d)", - target, levels, internalformat, width, height, depth); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (!ValidateES3TexStorageParameters(context, target, levels, internalformat, width, height, depth)) - { - return; - } - - switch (target) - { - case GL_TEXTURE_3D: - { - gl::Texture3D *texture3d = context->getTexture3D(); - gl::Error error = texture3d->storage(levels, internalformat, width, height, depth); - if (error.isError()) - { - context->recordError(error); - return; - } - } - break; - - case GL_TEXTURE_2D_ARRAY: - { - gl::Texture2DArray *texture2darray = context->getTexture2DArray(); - gl::Error error = texture2darray->storage(levels, internalformat, width, height, depth); - if (error.isError()) - { - context->recordError(error); - return; - } - } - break; - - default: - UNREACHABLE(); - } - } + return gl::GetBufferPointervOES(target, pname, params); } -void GL_APIENTRY glGetInternalformativ(GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint* params) +void* GL_APIENTRY glMapBufferRangeEXT(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access) { - EVENT("(GLenum target = 0x%X, GLenum internalformat = 0x%X, GLenum pname = 0x%X, GLsizei bufSize = %d, " - "GLint* params = 0x%0.8p)", - target, internalformat, pname, bufSize, params); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (context->getClientVersion() < 3) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - const gl::TextureCaps &formatCaps = context->getTextureCaps().get(internalformat); - if (!formatCaps.renderable) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - if (target != GL_RENDERBUFFER) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - if (bufSize < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - switch (pname) - { - case GL_NUM_SAMPLE_COUNTS: - if (bufSize != 0) - { - *params = formatCaps.sampleCounts.size(); - } - break; - - case GL_SAMPLES: - std::copy_n(formatCaps.sampleCounts.rbegin(), std::min(bufSize, formatCaps.sampleCounts.size()), params); - break; - - default: - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - } -} - -// Extension functions - -void GL_APIENTRY glBlitFramebufferANGLE(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, - GLbitfield mask, GLenum filter) -{ - EVENT("(GLint srcX0 = %d, GLint srcY0 = %d, GLint srcX1 = %d, GLint srcY1 = %d, " - "GLint dstX0 = %d, GLint dstY0 = %d, GLint dstX1 = %d, GLint dstY1 = %d, " - "GLbitfield mask = 0x%X, GLenum filter = 0x%X)", - srcX0, srcY0, srcX1, srcX1, dstX0, dstY0, dstX1, dstY1, mask, filter); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, - dstX0, dstY0, dstX1, dstY1, mask, filter, - true)) - { - return; - } - - gl::Error error = context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, - mask, filter); - if (error.isError()) - { - context->recordError(error); - return; - } - } -} - -void GL_APIENTRY glTexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, - GLint border, GLenum format, GLenum type, const GLvoid* pixels) -{ - EVENT("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, " - "GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, GLint border = %d, " - "GLenum format = 0x%X, GLenum type = 0x%x, const GLvoid* pixels = 0x%0.8p)", - target, level, internalformat, width, height, depth, border, format, type, pixels); - - UNIMPLEMENTED(); // FIXME -} - -void GL_APIENTRY glGetProgramBinaryOES(GLuint program, GLsizei bufSize, GLsizei *length, - GLenum *binaryFormat, void *binary) -{ - EVENT("(GLenum program = 0x%X, bufSize = %d, length = 0x%0.8p, binaryFormat = 0x%0.8p, binary = 0x%0.8p)", - program, bufSize, length, binaryFormat, binary); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - gl::Program *programObject = context->getProgram(program); - - if (!programObject || !programObject->isLinked()) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - gl::ProgramBinary *programBinary = programObject->getProgramBinary(); - - if (!programBinary) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - gl::Error error = programBinary->save(binaryFormat, binary, bufSize, length); - if (error.isError()) - { - context->recordError(error); - return; - } - } -} - -void GL_APIENTRY glProgramBinaryOES(GLuint program, GLenum binaryFormat, - const void *binary, GLint length) -{ - EVENT("(GLenum program = 0x%X, binaryFormat = 0x%x, binary = 0x%0.8p, length = %d)", - program, binaryFormat, binary, length); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - const std::vector &programBinaryFormats = context->getCaps().programBinaryFormats; - if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) == programBinaryFormats.end()) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - gl::Program *programObject = context->getProgram(program); - if (!programObject) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - gl::Error error = context->setProgramBinary(program, binaryFormat, binary, length); - if (error.isError()) - { - context->recordError(error); - return; - } - } + return gl::MapBufferRangeEXT(target, offset, length, access); } -void GL_APIENTRY glDrawBuffersEXT(GLsizei n, const GLenum *bufs) +void GL_APIENTRY glFlushMappedBufferRangeEXT(GLenum target, GLintptr offset, GLsizeiptr length) { - EVENT("(GLenum n = %d, bufs = 0x%0.8p)", n, bufs); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (n < 0 || static_cast(n) > context->getCaps().maxDrawBuffers) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - ASSERT(context->getState().getDrawFramebuffer()); - - if (context->getState().getDrawFramebuffer()->id() == 0) - { - if (n != 1) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (bufs[0] != GL_NONE && bufs[0] != GL_BACK) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - } - else - { - for (int colorAttachment = 0; colorAttachment < n; colorAttachment++) - { - const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment; - if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - } - } - - gl::Framebuffer *framebuffer = context->getState().getDrawFramebuffer(); - ASSERT(framebuffer); - - for (unsigned int colorAttachment = 0; colorAttachment < static_cast(n); colorAttachment++) - { - framebuffer->setDrawBufferState(colorAttachment, bufs[colorAttachment]); - } - - for (unsigned int colorAttachment = n; colorAttachment < context->getCaps().maxDrawBuffers; colorAttachment++) - { - framebuffer->setDrawBufferState(colorAttachment, GL_NONE); - } - } -} - -void GL_APIENTRY glGetBufferPointervOES(GLenum target, GLenum pname, void** params) -{ - EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLvoid** params = 0x%0.8p)", target, pname, params); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!gl::ValidBufferTarget(context, target)) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - if (pname != GL_BUFFER_MAP_POINTER) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - gl::Buffer *buffer = context->getState().getTargetBuffer(target); - - if (!buffer || !buffer->isMapped()) - { - *params = NULL; - } - else - { - *params = buffer->getMapPointer(); - } - } -} - -void * GL_APIENTRY glMapBufferOES(GLenum target, GLenum access) -{ - EVENT("(GLenum target = 0x%X, GLbitfield access = 0x%X)", target, access); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!gl::ValidBufferTarget(context, target)) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return NULL; - } - - gl::Buffer *buffer = context->getState().getTargetBuffer(target); - - if (buffer == NULL) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return NULL; - } - - if (access != GL_WRITE_ONLY_OES) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return NULL; - } - - if (buffer->isMapped()) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return NULL; - } - - gl::Error error = buffer->mapRange(0, buffer->getSize(), GL_MAP_WRITE_BIT); - if (error.isError()) - { - context->recordError(error); - return NULL; - } - - return buffer->getMapPointer(); - } - - return NULL; + return gl::FlushMappedBufferRangeEXT(target, offset, length); } -GLboolean GL_APIENTRY glUnmapBufferOES(GLenum target) +void GL_APIENTRY SetTraceFunctionPointers(GetCategoryEnabledFlagFunc getCategoryEnabledFlag, + AddTraceEventFunc addTraceEvent) { - EVENT("(GLenum target = 0x%X)", target); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!gl::ValidBufferTarget(context, target)) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return GL_FALSE; - } - - gl::Buffer *buffer = context->getState().getTargetBuffer(target); - - if (buffer == NULL || !buffer->isMapped()) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return GL_FALSE; - } - - // TODO: detect if we had corruption. if so, throw an error and return false. - - gl::Error error = buffer->unmap(); - if (error.isError()) - { - context->recordError(error); - return GL_FALSE; - } - - return GL_TRUE; - } - - return GL_FALSE; -} - -void* GL_APIENTRY glMapBufferRangeEXT (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access) -{ - EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d, GLbitfield access = 0x%X)", - target, offset, length, access); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (!gl::ValidBufferTarget(context, target)) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return NULL; - } - - if (offset < 0 || length < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return NULL; - } - - gl::Buffer *buffer = context->getState().getTargetBuffer(target); - - if (buffer == NULL) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return NULL; - } - - // Check for buffer overflow - size_t offsetSize = static_cast(offset); - size_t lengthSize = static_cast(length); - - if (!rx::IsUnsignedAdditionSafe(offsetSize, lengthSize) || - offsetSize + lengthSize > static_cast(buffer->getSize())) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return NULL; - } - - // Check for invalid bits in the mask - GLbitfield allAccessBits = GL_MAP_READ_BIT | - GL_MAP_WRITE_BIT | - GL_MAP_INVALIDATE_RANGE_BIT | - GL_MAP_INVALIDATE_BUFFER_BIT | - GL_MAP_FLUSH_EXPLICIT_BIT | - GL_MAP_UNSYNCHRONIZED_BIT; - - if (access & ~(allAccessBits)) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return NULL; - } - - if (length == 0 || buffer->isMapped()) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return NULL; - } - - // Check for invalid bit combinations - if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return NULL; - } - - GLbitfield writeOnlyBits = GL_MAP_INVALIDATE_RANGE_BIT | - GL_MAP_INVALIDATE_BUFFER_BIT | - GL_MAP_UNSYNCHRONIZED_BIT; - - if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return NULL; - } - - if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return NULL; - } - - gl::Error error = buffer->mapRange(offset, length, access); - if (error.isError()) - { - context->recordError(error); - return NULL; - } - - return buffer->getMapPointer(); - } - - return NULL; -} - -void GL_APIENTRY glFlushMappedBufferRangeEXT (GLenum target, GLintptr offset, GLsizeiptr length) -{ - EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d)", target, offset, length); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - if (offset < 0 || length < 0) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - if (!gl::ValidBufferTarget(context, target)) - { - context->recordError(gl::Error(GL_INVALID_ENUM)); - return; - } - - gl::Buffer *buffer = context->getState().getTargetBuffer(target); - - if (buffer == NULL) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0) - { - context->recordError(gl::Error(GL_INVALID_OPERATION)); - return; - } - - // Check for buffer overflow - size_t offsetSize = static_cast(offset); - size_t lengthSize = static_cast(length); - - if (!rx::IsUnsignedAdditionSafe(offsetSize, lengthSize) || - offsetSize + lengthSize > static_cast(buffer->getMapLength())) - { - context->recordError(gl::Error(GL_INVALID_VALUE)); - return; - } - - // We do not currently support a non-trivial implementation of FlushMappedBufferRange - } -} - -__eglMustCastToProperFunctionPointerType EGLAPIENTRY glGetProcAddress(const char *procname) -{ - struct Extension - { - const char *name; - __eglMustCastToProperFunctionPointerType address; - }; - - static const Extension glExtensions[] = - { - {"glTexImage3DOES", (__eglMustCastToProperFunctionPointerType)glTexImage3DOES}, - {"glBlitFramebufferANGLE", (__eglMustCastToProperFunctionPointerType)glBlitFramebufferANGLE}, - {"glRenderbufferStorageMultisampleANGLE", (__eglMustCastToProperFunctionPointerType)glRenderbufferStorageMultisampleANGLE}, - {"glDeleteFencesNV", (__eglMustCastToProperFunctionPointerType)glDeleteFencesNV}, - {"glGenFencesNV", (__eglMustCastToProperFunctionPointerType)glGenFencesNV}, - {"glIsFenceNV", (__eglMustCastToProperFunctionPointerType)glIsFenceNV}, - {"glTestFenceNV", (__eglMustCastToProperFunctionPointerType)glTestFenceNV}, - {"glGetFenceivNV", (__eglMustCastToProperFunctionPointerType)glGetFenceivNV}, - {"glFinishFenceNV", (__eglMustCastToProperFunctionPointerType)glFinishFenceNV}, - {"glSetFenceNV", (__eglMustCastToProperFunctionPointerType)glSetFenceNV}, - {"glGetTranslatedShaderSourceANGLE", (__eglMustCastToProperFunctionPointerType)glGetTranslatedShaderSourceANGLE}, - {"glTexStorage2DEXT", (__eglMustCastToProperFunctionPointerType)glTexStorage2DEXT}, - {"glGetGraphicsResetStatusEXT", (__eglMustCastToProperFunctionPointerType)glGetGraphicsResetStatusEXT}, - {"glReadnPixelsEXT", (__eglMustCastToProperFunctionPointerType)glReadnPixelsEXT}, - {"glGetnUniformfvEXT", (__eglMustCastToProperFunctionPointerType)glGetnUniformfvEXT}, - {"glGetnUniformivEXT", (__eglMustCastToProperFunctionPointerType)glGetnUniformivEXT}, - {"glGenQueriesEXT", (__eglMustCastToProperFunctionPointerType)glGenQueriesEXT}, - {"glDeleteQueriesEXT", (__eglMustCastToProperFunctionPointerType)glDeleteQueriesEXT}, - {"glIsQueryEXT", (__eglMustCastToProperFunctionPointerType)glIsQueryEXT}, - {"glBeginQueryEXT", (__eglMustCastToProperFunctionPointerType)glBeginQueryEXT}, - {"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}, - {"glGetBufferPointervOES", (__eglMustCastToProperFunctionPointerType)glGetBufferPointervOES}, - {"glMapBufferOES", (__eglMustCastToProperFunctionPointerType)glMapBufferOES}, - {"glUnmapBufferOES", (__eglMustCastToProperFunctionPointerType)glUnmapBufferOES}, - {"glMapBufferRangeEXT", (__eglMustCastToProperFunctionPointerType)glMapBufferRangeEXT}, - {"glFlushMappedBufferRangeEXT", (__eglMustCastToProperFunctionPointerType)glFlushMappedBufferRangeEXT}, }; - - for (unsigned int ext = 0; ext < ArraySize(glExtensions); ext++) - { - if (strcmp(procname, glExtensions[ext].name) == 0) - { - return (__eglMustCastToProperFunctionPointerType)glExtensions[ext].address; - } - } - - return NULL; -} - -// Non-public functions used by EGL - -bool EGLAPIENTRY glBindTexImage(egl::Surface *surface) -{ - EVENT("(egl::Surface* surface = 0x%0.8p)", - surface); - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - gl::Texture2D *textureObject = context->getTexture2D(); - ASSERT(textureObject != NULL); - - if (textureObject->isImmutable()) - { - return false; - } - - textureObject->bindTexImage(surface); - } - - return true; + gl::g_getCategoryEnabledFlag = getCategoryEnabledFlag; + gl::g_addTraceEvent = addTraceEvent; } } diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2.def b/src/3rdparty/angle/src/libGLESv2/libGLESv2.def index 33557eb1c9..9c6dc497d0 100644 --- a/src/3rdparty/angle/src/libGLESv2/libGLESv2.def +++ b/src/3rdparty/angle/src/libGLESv2/libGLESv2.def @@ -144,7 +144,6 @@ EXPORTS glViewport @142 ; Extensions - glTexImage3DOES @143 glBlitFramebufferANGLE @149 glRenderbufferStorageMultisampleANGLE @150 glDeleteFencesNV @151 @@ -285,12 +284,5 @@ EXPORTS glTexStorage3D @282 glGetInternalformativ @283 - ; EGL dependencies - glCreateContext @144 NONAME - glDestroyContext @145 NONAME - glMakeCurrent @146 NONAME - glGetCurrentContext @147 NONAME - glGetProcAddress @148 NONAME - glBindTexImage @158 NONAME - glCreateRenderer @177 NONAME - glDestroyRenderer @178 NONAME + ; Setting up TRACE macro callbacks + SetTraceFunctionPointers @284 diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2.rc b/src/3rdparty/angle/src/libGLESv2/libGLESv2.rc deleted file mode 100644 index 76cd05566e..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/libGLESv2.rc +++ /dev/null @@ -1,103 +0,0 @@ -// Microsoft Visual C++ generated resource script. -// -#include "resource.h" - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#include -#include "../common/version.h" - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// English (U.S.) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -#ifdef _WIN32 -LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US -#pragma code_page(1252) -#endif //_WIN32 - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE -BEGIN - "resource.h\0" -END - -2 TEXTINCLUDE -BEGIN - "#include ""afxres.h""\r\n" - "#include ""../common/version.h""\0" -END - -3 TEXTINCLUDE -BEGIN - "\r\n" - "\0" -END - -#endif // APSTUDIO_INVOKED - - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION ANGLE_MAJOR_VERSION,ANGLE_MINOR_VERSION,0,0 - PRODUCTVERSION ANGLE_MAJOR_VERSION,ANGLE_MINOR_VERSION,0,0 - FILEFLAGSMASK 0x17L -#ifdef _DEBUG - FILEFLAGS 0x1L -#else - FILEFLAGS 0x0L -#endif - FILEOS 0x4L - FILETYPE 0x2L - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904b0" - BEGIN - VALUE "FileDescription", "ANGLE libGLESv2 Dynamic Link Library" - VALUE "FileVersion", ANGLE_VERSION_STRING - VALUE "InternalName", "libGLESv2" - VALUE "LegalCopyright", "Copyright (C) 2011 Google Inc." - VALUE "OriginalFilename", "libGLESv2.dll" - VALUE "PrivateBuild", ANGLE_VERSION_STRING - VALUE "ProductName", "ANGLE libGLESv2 Dynamic Link Library" - VALUE "ProductVersion", ANGLE_VERSION_STRING - VALUE "Comments", "Build Date: " ANGLE_COMMIT_DATE - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x409, 1200 - END -END - -#endif // English (U.S.) resources -///////////////////////////////////////////////////////////////////////////// - - - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// - - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2_mingw32.def b/src/3rdparty/angle/src/libGLESv2/libGLESv2_mingw32.def index 18ffcf6a0d..e02b85bcf2 100644 --- a/src/3rdparty/angle/src/libGLESv2/libGLESv2_mingw32.def +++ b/src/3rdparty/angle/src/libGLESv2/libGLESv2_mingw32.def @@ -144,7 +144,6 @@ EXPORTS glViewport@16 @142 ; Extensions - glTexImage3DOES@40 @143 glBlitFramebufferANGLE@40 @149 glRenderbufferStorageMultisampleANGLE@20 @150 glDeleteFencesNV@8 @151 @@ -285,12 +284,5 @@ EXPORTS glTexStorage3D@24 @282 glGetInternalformativ@20 @283 - ; EGL dependencies - glCreateContext @144 NONAME - glDestroyContext @145 NONAME - glMakeCurrent @146 NONAME - glGetCurrentContext @147 NONAME - glGetProcAddress@4 @148 NONAME - glBindTexImage@4 @158 NONAME - glCreateRenderer @177 NONAME - glDestroyRenderer @178 NONAME + ; Setting up TRACE macro callbacks + SetTraceFunctionPointers@8 @284 diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2d.def b/src/3rdparty/angle/src/libGLESv2/libGLESv2d.def index 120371e013..d35309c6ce 100644 --- a/src/3rdparty/angle/src/libGLESv2/libGLESv2d.def +++ b/src/3rdparty/angle/src/libGLESv2/libGLESv2d.def @@ -144,7 +144,6 @@ EXPORTS glViewport @142 ; Extensions - glTexImage3DOES @143 glBlitFramebufferANGLE @149 glRenderbufferStorageMultisampleANGLE @150 glDeleteFencesNV @151 @@ -285,12 +284,5 @@ EXPORTS glTexStorage3D @282 glGetInternalformativ @283 - ; EGL dependencies - glCreateContext @144 NONAME - glDestroyContext @145 NONAME - glMakeCurrent @146 NONAME - glGetCurrentContext @147 NONAME - glGetProcAddress @148 NONAME - glBindTexImage @158 NONAME - glCreateRenderer @177 NONAME - glDestroyRenderer @178 NONAME + ; Setting up TRACE macro callbacks + SetTraceFunctionPointers @284 diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2d_mingw32.def b/src/3rdparty/angle/src/libGLESv2/libGLESv2d_mingw32.def index 8c1306a703..e2b2c333a1 100644 --- a/src/3rdparty/angle/src/libGLESv2/libGLESv2d_mingw32.def +++ b/src/3rdparty/angle/src/libGLESv2/libGLESv2d_mingw32.def @@ -144,7 +144,6 @@ EXPORTS glViewport@16 @142 ; Extensions - glTexImage3DOES@40 @143 glBlitFramebufferANGLE@40 @149 glRenderbufferStorageMultisampleANGLE@20 @150 glDeleteFencesNV@8 @151 @@ -285,12 +284,5 @@ EXPORTS glTexStorage3D@24 @282 glGetInternalformativ@20 @283 - ; EGL dependencies - glCreateContext @144 NONAME - glDestroyContext @145 NONAME - glMakeCurrent @146 NONAME - glGetCurrentContext @147 NONAME - glGetProcAddress@4 @148 NONAME - glBindTexImage@4 @158 NONAME - glCreateRenderer @177 NONAME - glDestroyRenderer @178 NONAME + ; Setting up TRACE macro callbacks + SetTraceFunctionPointers@8 @284 diff --git a/src/3rdparty/angle/src/libGLESv2/main.cpp b/src/3rdparty/angle/src/libGLESv2/main.cpp deleted file mode 100644 index 00f63ae079..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/main.cpp +++ /dev/null @@ -1,186 +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. -// - -// main.cpp: DLL entry point and management of thread-local data. - -#include "libGLESv2/main.h" -#include "libGLESv2/Context.h" - -#include "common/tls.h" - -static TLSIndex currentTLS = TLS_INVALID_INDEX; - -namespace gl -{ - -// TODO(kbr): figure out how these are going to be managed on -// non-Windows platforms. These routines would need to be exported -// from ANGLE and called cooperatively when users create and destroy -// threads -- or the initialization of the TLS index, and allocation -// of thread-local data, will have to be done lazily. Will have to use -// destructor function with pthread_create_key on POSIX platforms to -// clean up thread-local data. - -// Call this exactly once at process startup. -bool CreateThreadLocalIndex() -{ - currentTLS = CreateTLSIndex(); - if (currentTLS == TLS_INVALID_INDEX) - { - return false; - } - return true; -} - -// Call this exactly once at process shutdown. -void DestroyThreadLocalIndex() -{ - DestroyTLSIndex(currentTLS); - currentTLS = TLS_INVALID_INDEX; -} - -// Call this upon thread startup. -Current *AllocateCurrent() -{ - ASSERT(currentTLS != TLS_INVALID_INDEX); - if (currentTLS == TLS_INVALID_INDEX) - { - return NULL; - } - - Current *current = new Current(); - current->context = NULL; - current->display = NULL; - - if (!SetTLSValue(currentTLS, current)) - { - ERR("Could not set thread local storage."); - return NULL; - } - - return current; -} - -// Call this upon thread shutdown. -void DeallocateCurrent() -{ - Current *current = reinterpret_cast(GetTLSValue(currentTLS)); - SafeDelete(current); - SetTLSValue(currentTLS, NULL); -} - -} - -#if defined(ANGLE_PLATFORM_WINDOWS) && !defined(QT_OPENGL_ES_2_ANGLE_STATIC) -extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved) -{ - switch (reason) - { - case DLL_PROCESS_ATTACH: - { - if (!gl::CreateThreadLocalIndex()) - { - return FALSE; - } - -#ifdef ANGLE_ENABLE_DEBUG_ANNOTATIONS - gl::InitializeDebugAnnotations(); -#endif - } - // Fall through to initialize index - case DLL_THREAD_ATTACH: - { - gl::AllocateCurrent(); - } - break; - case DLL_THREAD_DETACH: - { - gl::DeallocateCurrent(); - } - break; - case DLL_PROCESS_DETACH: - { - gl::DeallocateCurrent(); - gl::DestroyThreadLocalIndex(); - -#ifdef ANGLE_ENABLE_DEBUG_ANNOTATIONS - gl::UninitializeDebugAnnotations(); -#endif - } - break; - default: - break; - } - - return TRUE; -} -#endif // ANGLE_PLATFORM_WINDOWS && !QT_OPENGL_ES_2_ANGLE_STATIC - -namespace gl -{ - -Current *GetCurrentData() -{ -#ifndef QT_OPENGL_ES_2_ANGLE_STATIC - Current *current = reinterpret_cast(GetTLSValue(currentTLS)); - - // ANGLE issue 488: when the dll is loaded after thread initialization, - // thread local storage (current) might not exist yet. - return (current ? current : AllocateCurrent()); -#else - // No precautions for thread safety taken as ANGLE is used single-threaded in Qt. - static Current current = { 0, 0 }; - return ¤t; -#endif -} - -void makeCurrent(Context *context, egl::Display *display, egl::Surface *surface) -{ - Current *current = GetCurrentData(); - - current->context = context; - current->display = display; - - if (context && display && surface) - { - context->makeCurrent(surface); - } -} - -Context *getContext() -{ - Current *current = GetCurrentData(); - - return current->context; -} - -Context *getNonLostContext() -{ - Context *context = getContext(); - - if (context) - { - if (context->isContextLost()) - { - context->recordError(Error(GL_OUT_OF_MEMORY, "Context has been lost.")); - return NULL; - } - else - { - return context; - } - } - return NULL; -} - -egl::Display *getDisplay() -{ - Current *current = GetCurrentData(); - - return current->display; -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/main.h b/src/3rdparty/angle/src/libGLESv2/main.h deleted file mode 100644 index dff02787f5..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/main.h +++ /dev/null @@ -1,61 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// main.h: Management of thread-local data. - -#ifndef LIBGLESV2_MAIN_H_ -#define LIBGLESV2_MAIN_H_ - -#include "common/debug.h" - -#include -#include - -namespace egl -{ -class Display; -class Surface; -class AttributeMap; -} - -namespace gl -{ -class Context; - -struct Current -{ - Context *context; - egl::Display *display; -}; - -void makeCurrent(Context *context, egl::Display *display, egl::Surface *surface); - -Context *getContext(); -Context *getNonLostContext(); -egl::Display *getDisplay(); - -} - -namespace rx -{ -class Renderer; -} - -extern "C" -{ -// Exported functions for use by EGL -gl::Context *glCreateContext(int clientVersion, 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, EGLNativeDisplayType nativeDisplay, const egl::AttributeMap &attribMap); -void glDestroyRenderer(rx::Renderer *renderer); - -__eglMustCastToProperFunctionPointerType EGLAPIENTRY glGetProcAddress(const char *procname); -bool EGLAPIENTRY glBindTexImage(egl::Surface *surface); -} - -#endif // LIBGLESV2_MAIN_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/queryconversions.cpp b/src/3rdparty/angle/src/libGLESv2/queryconversions.cpp deleted file mode 100644 index 7245902c51..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/queryconversions.cpp +++ /dev/null @@ -1,147 +0,0 @@ -// -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// queryconversions.cpp: Implementation of state query cast conversions - -#include "libGLESv2/Context.h" -#include "common/utilities.h" - -namespace gl -{ - -// Helper class for converting a GL type to a GLenum: -// We can't use CastStateValueEnum generally, because of GLboolean + GLubyte overlap. -// We restrict our use to CastStateValue, where it eliminates duplicate parameters. - -template -struct CastStateValueEnum { static GLenum mEnumForType; }; - -template <> GLenum CastStateValueEnum::mEnumForType = GL_INT; -template <> GLenum CastStateValueEnum::mEnumForType = GL_UNSIGNED_INT; -template <> GLenum CastStateValueEnum::mEnumForType = GL_BOOL; -template <> GLenum CastStateValueEnum::mEnumForType = GL_INT_64_ANGLEX; -template <> GLenum CastStateValueEnum::mEnumForType = GL_FLOAT; - -template -QueryT CastStateValueToInt(GLenum pname, NativeT value) -{ - GLenum queryType = CastStateValueEnum::mEnumForType; - GLenum nativeType = CastStateValueEnum::mEnumForType; - - if (nativeType == GL_FLOAT) - { - // RGBA color values and DepthRangeF values are converted to integer using Equation 2.4 from Table 4.5 - if (pname == GL_DEPTH_RANGE || pname == GL_COLOR_CLEAR_VALUE || pname == GL_DEPTH_CLEAR_VALUE || pname == GL_BLEND_COLOR) - { - return static_cast((static_cast(0xFFFFFFFF) * value - 1.0f) / 2.0f); - } - else - { - return gl::iround(value); - } - } - - // Clamp 64-bit int values when casting to int - if (nativeType == GL_INT_64_ANGLEX && queryType == GL_INT) - { - GLint64 minIntValue = static_cast(std::numeric_limits::min()); - GLint64 maxIntValue = static_cast(std::numeric_limits::max()); - GLint64 clampedValue = std::max(std::min(static_cast(value), maxIntValue), minIntValue); - return static_cast(clampedValue); - } - - return static_cast(value); -} - -template -QueryT CastStateValue(GLenum pname, NativeT value) -{ - GLenum queryType = CastStateValueEnum::mEnumForType; - - switch (queryType) - { - case GL_INT: return CastStateValueToInt(pname, value); - case GL_INT_64_ANGLEX: return CastStateValueToInt(pname, value); - case GL_FLOAT: return static_cast(value); - case GL_BOOL: return (value == static_cast(0) ? GL_FALSE : GL_TRUE); - default: UNREACHABLE(); return 0; - } -} - -template -void CastStateValues(Context *context, GLenum nativeType, GLenum pname, - unsigned int numParams, QueryT *outParams) -{ - if (nativeType == GL_INT) - { - GLint *intParams = NULL; - intParams = new GLint[numParams]; - - context->getIntegerv(pname, intParams); - - for (unsigned int i = 0; i < numParams; ++i) - { - outParams[i] = CastStateValue(pname, intParams[i]); - } - - delete [] intParams; - } - else if (nativeType == GL_BOOL) - { - GLboolean *boolParams = NULL; - boolParams = new GLboolean[numParams]; - - context->getBooleanv(pname, boolParams); - - for (unsigned int i = 0; i < numParams; ++i) - { - outParams[i] = (boolParams[i] == GL_FALSE ? static_cast(0) : static_cast(1)); - } - - delete [] boolParams; - } - else if (nativeType == GL_FLOAT) - { - GLfloat *floatParams = NULL; - floatParams = new GLfloat[numParams]; - - context->getFloatv(pname, floatParams); - - for (unsigned int i = 0; i < numParams; ++i) - { - outParams[i] = CastStateValue(pname, floatParams[i]); - } - - delete [] floatParams; - } - else if (nativeType == GL_INT_64_ANGLEX) - { - GLint64 *int64Params = NULL; - int64Params = new GLint64[numParams]; - - context->getInteger64v(pname, int64Params); - - for (unsigned int i = 0; i < numParams; ++i) - { - outParams[i] = CastStateValue(pname, int64Params[i]); - } - - delete [] int64Params; - } - else UNREACHABLE(); -} - -// Explicit template instantiation (how we export template functions in different files) -// The calls below will make CastStateValues successfully link with the GL state query types -// The GL state query API types are: bool, int, uint, float, int64 - -template void CastStateValues(Context *, GLenum, GLenum, unsigned int, GLboolean *); -template void CastStateValues(Context *, GLenum, GLenum, unsigned int, GLint *); -template void CastStateValues(Context *, GLenum, GLenum, unsigned int, GLuint *); -template void CastStateValues(Context *, GLenum, GLenum, unsigned int, GLfloat *); -template void CastStateValues(Context *, GLenum, GLenum, unsigned int, GLint64 *); - -} diff --git a/src/3rdparty/angle/src/libGLESv2/queryconversions.h b/src/3rdparty/angle/src/libGLESv2/queryconversions.h deleted file mode 100644 index da7047f730..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/queryconversions.h +++ /dev/null @@ -1,17 +0,0 @@ -// -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// queryconversions.h: Declaration of state query cast conversions - -namespace gl -{ - -// The GL state query API types are: bool, int, uint, float, int64 -template -void CastStateValues(Context *context, GLenum nativeType, GLenum pname, - unsigned int numParams, QueryT *outParams); - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/BufferImpl.h b/src/3rdparty/angle/src/libGLESv2/renderer/BufferImpl.h deleted file mode 100644 index c031effabd..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/BufferImpl.h +++ /dev/null @@ -1,35 +0,0 @@ -// -// Copyright 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// BufferImpl.h: Defines the abstract rx::BufferImpl class. - -#ifndef LIBGLESV2_RENDERER_BUFFERIMPL_H_ -#define LIBGLESV2_RENDERER_BUFFERIMPL_H_ - -#include "common/angleutils.h" -#include "libGLESv2/Buffer.h" - -#include - -namespace rx -{ - -class BufferImpl -{ - public: - virtual ~BufferImpl() { } - - virtual gl::Error setData(const void* data, size_t size, GLenum usage) = 0; - virtual gl::Error setSubData(const void* data, size_t size, size_t offset) = 0; - virtual gl::Error copySubData(BufferImpl* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size) = 0; - virtual gl::Error map(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr) = 0; - virtual gl::Error unmap() = 0; - virtual void markTransformFeedbackUsage() = 0; -}; - -} - -#endif // LIBGLESV2_RENDERER_BUFFERIMPL_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/FenceImpl.h b/src/3rdparty/angle/src/libGLESv2/renderer/FenceImpl.h deleted file mode 100644 index 1dd46785d9..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/FenceImpl.h +++ /dev/null @@ -1,52 +0,0 @@ -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// FenceImpl.h: Defines the rx::FenceNVImpl and rx::FenceSyncImpl classes. - -#ifndef LIBGLESV2_RENDERER_FENCEIMPL_H_ -#define LIBGLESV2_RENDERER_FENCEIMPL_H_ - -#include "libGLESv2/Error.h" - -#include "common/angleutils.h" - -#include "angle_gl.h" - -namespace rx -{ - -class FenceNVImpl -{ - public: - FenceNVImpl() { }; - virtual ~FenceNVImpl() { }; - - virtual gl::Error set() = 0; - virtual gl::Error test(bool flushCommandBuffer, GLboolean *outFinished) = 0; - virtual gl::Error finishFence(GLboolean *outFinished) = 0; - - private: - DISALLOW_COPY_AND_ASSIGN(FenceNVImpl); -}; - -class FenceSyncImpl -{ - public: - FenceSyncImpl() { }; - virtual ~FenceSyncImpl() { }; - - virtual gl::Error set() = 0; - virtual gl::Error clientWait(GLbitfield flags, GLuint64 timeout, GLenum *outResult) = 0; - virtual gl::Error serverWait(GLbitfield flags, GLuint64 timeout) = 0; - virtual gl::Error getStatus(GLint *outResult) = 0; - - private: - DISALLOW_COPY_AND_ASSIGN(FenceSyncImpl); -}; - -} - -#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 deleted file mode 100644 index 5b9b75f562..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Image.cpp +++ /dev/null @@ -1,46 +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. -// - -// 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" -#include "libGLESv2/Framebuffer.h" -#include "libGLESv2/main.h" - -namespace rx -{ - -Image::Image() -{ - mWidth = 0; - mHeight = 0; - mDepth = 0; - mInternalFormat = GL_NONE; - mActualFormat = GL_NONE; - mTarget = GL_NONE; - mRenderable = false; - mDirty = false; -} - -gl::Error Image::copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &area, gl::Framebuffer *source) -{ - gl::FramebufferAttachment *colorbuffer = source->getReadColorbuffer(); - ASSERT(colorbuffer); - - RenderTarget *renderTarget = NULL; - gl::Error error = GetAttachmentRenderTarget(colorbuffer, &renderTarget); - if (error.isError()) - { - return error; - } - - ASSERT(renderTarget); - return copy(xoffset, yoffset, zoffset, area, renderTarget); -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Image.h b/src/3rdparty/angle/src/libGLESv2/renderer/Image.h deleted file mode 100644 index 9071a88c67..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Image.h +++ /dev/null @@ -1,79 +0,0 @@ -// -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// 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" -#include "libGLESv2/Error.h" - -#include - -namespace gl -{ -class Framebuffer; -struct Rectangle; -struct ImageIndex; -} - -namespace rx -{ -class RendererD3D; -class RenderTarget; -class TextureStorage; - -class Image -{ - public: - Image(); - virtual ~Image() {}; - - GLsizei getWidth() const { return mWidth; } - GLsizei getHeight() const { return mHeight; } - GLsizei getDepth() const { return mDepth; } - GLenum getInternalFormat() const { return mInternalFormat; } - GLenum getActualFormat() const { return mActualFormat; } - GLenum getTarget() const { return mTarget; } - bool isRenderableFormat() const { return mRenderable; } - - void markDirty() {mDirty = true;} - void markClean() {mDirty = false;} - virtual bool isDirty() const = 0; - - virtual bool redefine(RendererD3D *renderer, GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, bool forceRelease) = 0; - - virtual gl::Error loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, - GLint unpackAlignment, GLenum type, const void *input) = 0; - virtual gl::Error loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, - const void *input) = 0; - - gl::Error copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea, gl::Framebuffer *source); - virtual gl::Error copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea, RenderTarget *source) = 0; - virtual gl::Error copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea, - const gl::ImageIndex &sourceIndex, TextureStorage *source) = 0; - - protected: - GLsizei mWidth; - GLsizei mHeight; - GLsizei mDepth; - GLenum mInternalFormat; - GLenum mActualFormat; - bool mRenderable; - GLenum mTarget; - - bool mDirty; - - private: - DISALLOW_COPY_AND_ASSIGN(Image); -}; - -} - -#endif // LIBGLESV2_RENDERER_IMAGE_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.cpp deleted file mode 100644 index d472e1499e..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.cpp +++ /dev/null @@ -1,128 +0,0 @@ -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// IndexRangeCache.cpp: Defines the rx::IndexRangeCache class which stores information about -// ranges of indices. - -#include "libGLESv2/renderer/IndexRangeCache.h" -#include "libGLESv2/formatutils.h" - -#include "common/debug.h" - -#include - -namespace rx -{ - -template -static RangeUI ComputeTypedRange(const IndexType *indices, GLsizei count) -{ - unsigned int minIndex = indices[0]; - unsigned int maxIndex = indices[0]; - - for (GLsizei i = 1; i < count; i++) - { - if (minIndex > indices[i]) minIndex = indices[i]; - if (maxIndex < indices[i]) maxIndex = indices[i]; - } - - return RangeUI(minIndex, maxIndex); -} - -RangeUI IndexRangeCache::ComputeRange(GLenum type, const GLvoid *indices, GLsizei count) -{ - switch (type) - { - case GL_UNSIGNED_BYTE: - return ComputeTypedRange(static_cast(indices), count); - case GL_UNSIGNED_INT: - return ComputeTypedRange(static_cast(indices), count); - case GL_UNSIGNED_SHORT: - return ComputeTypedRange(static_cast(indices), count); - default: - UNREACHABLE(); - return RangeUI(); - } -} - -void IndexRangeCache::addRange(GLenum type, unsigned int offset, GLsizei count, const RangeUI &range, - unsigned int streamOffset) -{ - mIndexRangeCache[IndexRange(type, offset, count)] = IndexBounds(range, streamOffset); -} - -void IndexRangeCache::invalidateRange(unsigned int offset, unsigned int size) -{ - unsigned int invalidateStart = offset; - unsigned int invalidateEnd = offset + size; - - IndexRangeMap::iterator i = mIndexRangeCache.begin(); - while (i != mIndexRangeCache.end()) - { - unsigned int rangeStart = i->second.streamOffset; - unsigned int rangeEnd = i->second.streamOffset + (gl::GetTypeInfo(i->first.type).bytes * i->first.count); - - if (invalidateEnd < rangeStart || invalidateStart > rangeEnd) - { - ++i; - } - else - { - i = mIndexRangeCache.erase(i); - } - } -} - -bool IndexRangeCache::findRange(GLenum type, unsigned int offset, GLsizei count, - RangeUI *outRange, unsigned int *outStreamOffset) const -{ - IndexRangeMap::const_iterator i = mIndexRangeCache.find(IndexRange(type, offset, count)); - if (i != mIndexRangeCache.end()) - { - if (outRange) *outRange = i->second.range; - if (outStreamOffset) *outStreamOffset = i->second.streamOffset; - return true; - } - else - { - if (outRange) *outRange = RangeUI(0, 0); - if (outStreamOffset) *outStreamOffset = 0; - return false; - } -} - -void IndexRangeCache::clear() -{ - mIndexRangeCache.clear(); -} - -IndexRangeCache::IndexRange::IndexRange() - : type(GL_NONE), offset(0), count(0) -{ -} - -IndexRangeCache::IndexRange::IndexRange(GLenum typ, intptr_t off, GLsizei c) - : type(typ), offset(off), count(c) -{ -} - -bool IndexRangeCache::IndexRange::operator<(const IndexRange& rhs) const -{ - return std::make_tuple(type, offset, count) < std::make_tuple(rhs.type, rhs.offset, rhs.count); -} - -IndexRangeCache::IndexBounds::IndexBounds() - : range(0, 0), - streamOffset(0) -{ -} - -IndexRangeCache::IndexBounds::IndexBounds(const RangeUI &rangeIn, unsigned int offset) - : range(rangeIn), streamOffset(offset) -{ -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.h b/src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.h deleted file mode 100644 index a7d91e035b..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.h +++ /dev/null @@ -1,64 +0,0 @@ -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// IndexRangeCache.h: Defines the rx::IndexRangeCache class which stores information about -// ranges of indices. - -#ifndef LIBGLESV2_RENDERER_INDEXRANGECACHE_H_ -#define LIBGLESV2_RENDERER_INDEXRANGECACHE_H_ - -#include "common/angleutils.h" -#include "common/mathutil.h" - -#include "angle_gl.h" - -#include - -namespace rx -{ - -class IndexRangeCache -{ - public: - void addRange(GLenum type, unsigned int offset, GLsizei count, const RangeUI &range, - unsigned int streamOffset); - bool findRange(GLenum type, unsigned int offset, GLsizei count, RangeUI *rangeOut, - unsigned int *outStreamOffset) const; - - void invalidateRange(unsigned int offset, unsigned int size); - void clear(); - - static RangeUI ComputeRange(GLenum type, const GLvoid *indices, GLsizei count); - - private: - struct IndexRange - { - GLenum type; - unsigned int offset; - GLsizei count; - - IndexRange(); - IndexRange(GLenum type, intptr_t offset, GLsizei count); - - bool operator<(const IndexRange& rhs) const; - }; - - struct IndexBounds - { - RangeUI range; - unsigned int streamOffset; - - IndexBounds(); - IndexBounds(const RangeUI &range, unsigned int offset); - }; - - typedef std::map IndexRangeMap; - IndexRangeMap mIndexRangeCache; -}; - -} - -#endif // LIBGLESV2_RENDERER_INDEXRANGECACHE_H diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/ProgramImpl.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/ProgramImpl.cpp deleted file mode 100644 index f9fcad38a4..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/ProgramImpl.cpp +++ /dev/null @@ -1,146 +0,0 @@ -// -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// ProgramD3D.cpp: Defines the rx::ProgramD3D class which implements rx::ProgramImpl. - -#include "libGLESv2/renderer/ProgramImpl.h" - -#include "common/utilities.h" -#include "libGLESv2/main.h" - -namespace rx -{ - -namespace -{ - -unsigned int ParseAndStripArrayIndex(std::string* name) -{ - unsigned int subscript = GL_INVALID_INDEX; - - // Strip any trailing array operator and retrieve the subscript - size_t open = name->find_last_of('['); - size_t close = name->find_last_of(']'); - if (open != std::string::npos && close == name->length() - 1) - { - subscript = atoi(name->substr(open + 1).c_str()); - name->erase(open); - } - - return subscript; -} - -} - -ProgramImpl::~ProgramImpl() -{ - // Ensure that reset was called by the inherited class during destruction - ASSERT(mUniformIndex.size() == 0); -} - -gl::LinkedUniform *ProgramImpl::getUniformByLocation(GLint location) const -{ - ASSERT(location >= 0 && static_cast(location) < mUniformIndex.size()); - return mUniforms[mUniformIndex[location].index]; -} - -gl::LinkedUniform *ProgramImpl::getUniformByName(const std::string &name) const -{ - for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++) - { - if (mUniforms[uniformIndex]->name == name) - { - return mUniforms[uniformIndex]; - } - } - - return NULL; -} - -gl::UniformBlock *ProgramImpl::getUniformBlockByIndex(GLuint blockIndex) const -{ - ASSERT(blockIndex < mUniformBlocks.size()); - return mUniformBlocks[blockIndex]; -} - -GLint ProgramImpl::getUniformLocation(std::string name) -{ - unsigned int subscript = ParseAndStripArrayIndex(&name); - - unsigned int numUniforms = mUniformIndex.size(); - for (unsigned int location = 0; location < numUniforms; location++) - { - if (mUniformIndex[location].name == name) - { - const int index = mUniformIndex[location].index; - const bool isArray = mUniforms[index]->isArray(); - - if ((isArray && mUniformIndex[location].element == subscript) || - (subscript == GL_INVALID_INDEX)) - { - return location; - } - } - } - - return -1; -} - -GLuint ProgramImpl::getUniformIndex(std::string name) -{ - unsigned int subscript = ParseAndStripArrayIndex(&name); - - // The app is not allowed to specify array indices other than 0 for arrays of basic types - if (subscript != 0 && subscript != GL_INVALID_INDEX) - { - return GL_INVALID_INDEX; - } - - unsigned int numUniforms = mUniforms.size(); - for (unsigned int index = 0; index < numUniforms; index++) - { - if (mUniforms[index]->name == name) - { - if (mUniforms[index]->isArray() || subscript == GL_INVALID_INDEX) - { - return index; - } - } - } - - return GL_INVALID_INDEX; -} - -GLuint ProgramImpl::getUniformBlockIndex(std::string name) const -{ - unsigned int subscript = ParseAndStripArrayIndex(&name); - - unsigned int numUniformBlocks = mUniformBlocks.size(); - for (unsigned int blockIndex = 0; blockIndex < numUniformBlocks; blockIndex++) - { - const gl::UniformBlock &uniformBlock = *mUniformBlocks[blockIndex]; - if (uniformBlock.name == name) - { - const bool arrayElementZero = (subscript == GL_INVALID_INDEX && uniformBlock.elementIndex == 0); - if (subscript == uniformBlock.elementIndex || arrayElementZero) - { - return blockIndex; - } - } - } - - return GL_INVALID_INDEX; -} - -void ProgramImpl::reset() -{ - SafeDeleteContainer(mUniforms); - mUniformIndex.clear(); - SafeDeleteContainer(mUniformBlocks); - mTransformFeedbackLinkedVaryings.clear(); -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/ProgramImpl.h b/src/3rdparty/angle/src/libGLESv2/renderer/ProgramImpl.h deleted file mode 100644 index 6aaa23cf89..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/ProgramImpl.h +++ /dev/null @@ -1,127 +0,0 @@ -// -// Copyright 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// ProgramImpl.h: Defines the abstract rx::ProgramImpl class. - -#ifndef LIBGLESV2_RENDERER_PROGRAMIMPL_H_ -#define LIBGLESV2_RENDERER_PROGRAMIMPL_H_ - -#include "common/angleutils.h" -#include "libGLESv2/BinaryStream.h" -#include "libGLESv2/Constants.h" -#include "libGLESv2/ProgramBinary.h" -#include "libGLESv2/Shader.h" -#include "libGLESv2/renderer/Renderer.h" - -#include - -namespace rx -{ - -class ProgramImpl -{ - public: - ProgramImpl() { } - virtual ~ProgramImpl(); - - const std::vector &getUniforms() const { return mUniforms; } - const std::vector &getUniformIndices() const { return mUniformIndex; } - const std::vector &getUniformBlocks() const { return mUniformBlocks; } - const std::vector &getTransformFeedbackLinkedVaryings() const { return mTransformFeedbackLinkedVaryings; } - const sh::Attribute *getShaderAttributes() const { return mShaderAttributes; } - - std::vector &getUniforms() { return mUniforms; } - std::vector &getUniformIndices() { return mUniformIndex; } - std::vector &getUniformBlocks() { return mUniformBlocks; } - std::vector &getTransformFeedbackLinkedVaryings() { return mTransformFeedbackLinkedVaryings; } - sh::Attribute *getShaderAttributes() { return mShaderAttributes; } - - gl::LinkedUniform *getUniformByLocation(GLint location) const; - gl::LinkedUniform *getUniformByName(const std::string &name) const; - gl::UniformBlock *getUniformBlockByIndex(GLuint blockIndex) const; - - GLint getUniformLocation(std::string name); - GLuint getUniformIndex(std::string name); - GLuint getUniformBlockIndex(std::string name) const; - - virtual bool usesPointSize() const = 0; - virtual int getShaderVersion() const = 0; - virtual GLenum getTransformFeedbackBufferMode() const = 0; - - virtual GLenum getBinaryFormat() = 0; - virtual gl::LinkResult load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) = 0; - virtual gl::Error save(gl::BinaryOutputStream *stream) = 0; - - virtual gl::LinkResult link(const gl::Data &data, gl::InfoLog &infoLog, - gl::Shader *fragmentShader, gl::Shader *vertexShader, - const std::vector &transformFeedbackVaryings, - GLenum transformFeedbackBufferMode, - int *registers, std::vector *linkedVaryings, - std::map *outputVariables) = 0; - - virtual void setUniform1fv(GLint location, GLsizei count, const GLfloat *v) = 0; - virtual void setUniform2fv(GLint location, GLsizei count, const GLfloat *v) = 0; - virtual void setUniform3fv(GLint location, GLsizei count, const GLfloat *v) = 0; - virtual void setUniform4fv(GLint location, GLsizei count, const GLfloat *v) = 0; - virtual void setUniform1iv(GLint location, GLsizei count, const GLint *v) = 0; - virtual void setUniform2iv(GLint location, GLsizei count, const GLint *v) = 0; - virtual void setUniform3iv(GLint location, GLsizei count, const GLint *v) = 0; - virtual void setUniform4iv(GLint location, GLsizei count, const GLint *v) = 0; - virtual void setUniform1uiv(GLint location, GLsizei count, const GLuint *v) = 0; - virtual void setUniform2uiv(GLint location, GLsizei count, const GLuint *v) = 0; - virtual void setUniform3uiv(GLint location, GLsizei count, const GLuint *v) = 0; - virtual void setUniform4uiv(GLint location, GLsizei count, const GLuint *v) = 0; - virtual void setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) = 0; - virtual void setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) = 0; - virtual void setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) = 0; - virtual void setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) = 0; - virtual void setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) = 0; - virtual void setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) = 0; - virtual void setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) = 0; - virtual void setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) = 0; - virtual void setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) = 0; - - virtual void getUniformfv(GLint location, GLfloat *params) = 0; - virtual void getUniformiv(GLint location, GLint *params) = 0; - virtual void getUniformuiv(GLint location, GLuint *params) = 0; - - virtual void reset(); - - // TODO: The following functions are possibly only applicable to D3D backends. The should be carefully evaluated to - // determine if they can be removed from this interface. - virtual GLint getSamplerMapping(gl::SamplerType type, unsigned int samplerIndex, const gl::Caps &caps) const = 0; - virtual GLenum getSamplerTextureType(gl::SamplerType type, unsigned int samplerIndex) const = 0; - virtual GLint getUsedSamplerRange(gl::SamplerType type) const = 0; - virtual void updateSamplerMapping() = 0; - virtual bool validateSamplers(gl::InfoLog *infoLog, const gl::Caps &caps) = 0; - - virtual gl::LinkResult compileProgramExecutables(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader, - int registers) = 0; - - virtual bool linkUniforms(gl::InfoLog &infoLog, const gl::Shader &vertexShader, const gl::Shader &fragmentShader, - const gl::Caps &caps) = 0; - virtual bool defineUniformBlock(gl::InfoLog &infoLog, const gl::Shader &shader, const sh::InterfaceBlock &interfaceBlock, - const gl::Caps &caps) = 0; - - virtual gl::Error applyUniforms() = 0; - virtual gl::Error applyUniformBuffers(const std::vector boundBuffers, const gl::Caps &caps) = 0; - virtual bool assignUniformBlockRegister(gl::InfoLog &infoLog, gl::UniformBlock *uniformBlock, GLenum shader, - unsigned int registerIndex, const gl::Caps &caps) = 0; - - protected: - DISALLOW_COPY_AND_ASSIGN(ProgramImpl); - - std::vector mUniforms; - std::vector mUniformIndex; - std::vector mUniformBlocks; - std::vector mTransformFeedbackLinkedVaryings; - - sh::Attribute mShaderAttributes[gl::MAX_VERTEX_ATTRIBS]; -}; - -} - -#endif // LIBGLESV2_RENDERER_PROGRAMIMPL_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/QueryImpl.h b/src/3rdparty/angle/src/libGLESv2/renderer/QueryImpl.h deleted file mode 100644 index 6b45810a3b..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/QueryImpl.h +++ /dev/null @@ -1,42 +0,0 @@ -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// QueryImpl.h: Defines the abstract rx::QueryImpl class. - -#ifndef LIBGLESV2_RENDERER_QUERYIMPL_H_ -#define LIBGLESV2_RENDERER_QUERYIMPL_H_ - -#include "libGLESv2/Error.h" - -#include "common/angleutils.h" - -#include - -namespace rx -{ - -class QueryImpl -{ - public: - explicit QueryImpl(GLenum type) { mType = type; } - virtual ~QueryImpl() { } - - virtual gl::Error begin() = 0; - virtual gl::Error end() = 0; - virtual gl::Error getResult(GLuint *params) = 0; - virtual gl::Error isResultAvailable(GLuint *available) = 0; - - GLenum getType() const { return mType; } - - private: - DISALLOW_COPY_AND_ASSIGN(QueryImpl); - - GLenum mType; -}; - -} - -#endif // LIBGLESV2_RENDERER_QUERYIMPL_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget.cpp deleted file mode 100644 index 857fdc9dae..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget.cpp +++ /dev/null @@ -1,36 +0,0 @@ -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// RenderTarget.cpp: Implements serial handling for rx::RenderTarget - -#include "libGLESv2/renderer/RenderTarget.h" - -namespace rx -{ -unsigned int RenderTarget::mCurrentSerial = 1; - -RenderTarget::RenderTarget() - : mSerial(issueSerials(1)) -{ -} - -RenderTarget::~RenderTarget() -{ -} - -unsigned int RenderTarget::getSerial() const -{ - return mSerial; -} - -unsigned int RenderTarget::issueSerials(unsigned int count) -{ - unsigned int firstSerial = mCurrentSerial; - mCurrentSerial += count; - return firstSerial; -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget.h b/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget.h deleted file mode 100644 index 3bdfb0cc98..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget.h +++ /dev/null @@ -1,53 +0,0 @@ -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// 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" -#include "libGLESv2/angletypes.h" - -namespace rx -{ -class RenderTarget -{ - public: - RenderTarget(); - virtual ~RenderTarget(); - - virtual GLsizei getWidth() const = 0; - virtual GLsizei getHeight() const = 0; - virtual GLsizei getDepth() const = 0; - virtual GLenum getInternalFormat() const = 0; - virtual GLenum getActualFormat() const = 0; - virtual GLsizei getSamples() const = 0; - gl::Extents getExtents() const { return gl::Extents(getWidth(), getHeight(), getDepth()); } - - virtual void invalidate(GLint x, GLint y, GLsizei width, GLsizei height) = 0; - - virtual unsigned int getSerial() const; - static unsigned int issueSerials(unsigned int count); - - struct Desc { - GLsizei width; - GLsizei height; - GLsizei depth; - GLenum format; - }; - - private: - DISALLOW_COPY_AND_ASSIGN(RenderTarget); - - const unsigned int mSerial; - static unsigned int mCurrentSerial; -}; - -} - -#endif // LIBGLESV2_RENDERTARGET_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/RenderbufferImpl.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/RenderbufferImpl.cpp deleted file mode 100644 index 770ae8e9c6..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/RenderbufferImpl.cpp +++ /dev/null @@ -1,21 +0,0 @@ -// -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// RenderbufferImpl.h: Implements the shared methods of the abstract class gl::RenderbufferImpl - -#include "libGLESv2/renderer/RenderbufferImpl.h" - -namespace rx -{ -RenderbufferImpl::RenderbufferImpl() -{ -} - -RenderbufferImpl::~RenderbufferImpl() -{ -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/RenderbufferImpl.h b/src/3rdparty/angle/src/libGLESv2/renderer/RenderbufferImpl.h deleted file mode 100644 index 52e070f1d3..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/RenderbufferImpl.h +++ /dev/null @@ -1,41 +0,0 @@ -// -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// RenderbufferImpl.h: Defines the abstract class gl::RenderbufferImpl - -#ifndef LIBGLESV2_RENDERER_RENDERBUFFERIMPL_H_ -#define LIBGLESV2_RENDERER_RENDERBUFFERIMPL_H_ - -#include "angle_gl.h" - -#include "libGLESv2/Error.h" - -#include "common/angleutils.h" - -namespace rx -{ - -class RenderbufferImpl -{ - public: - RenderbufferImpl(); - virtual ~RenderbufferImpl() = 0; - - virtual gl::Error setStorage(GLsizei width, GLsizei height, GLenum internalformat, GLsizei samples) = 0; - - virtual GLsizei getWidth() const = 0; - virtual GLsizei getHeight() const = 0; - virtual GLenum getInternalFormat() const = 0; - virtual GLenum getActualFormat() const = 0; - virtual GLsizei getSamples() const = 0; - - private: - DISALLOW_COPY_AND_ASSIGN(RenderbufferImpl); -}; - -} - -#endif // LIBGLESV2_RENDERER_RENDERBUFFERIMPL_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp deleted file mode 100644 index df3dae1e38..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp +++ /dev/null @@ -1,172 +0,0 @@ -// -// Copyright (c) 2012-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Renderer.cpp: Implements EGL dependencies for creating and destroying Renderer instances. - -#include "common/utilities.h" -#include "libEGL/AttributeMap.h" -#include "libGLESv2/main.h" -#include "libGLESv2/renderer/Renderer.h" - -#include - -#if defined (ANGLE_ENABLE_D3D9) -#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" -#endif // ANGLE_ENABLE_D3D9 - -#if defined (ANGLE_ENABLE_D3D11) -#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" -#endif // ANGLE_ENABLE_D3D11 - -#if defined (ANGLE_TEST_CONFIG) -#define ANGLE_DEFAULT_D3D11 1 -#endif - -#if !defined(ANGLE_DEFAULT_D3D11) -// Enables use of the Direct3D 11 API for a default display, when available -#define ANGLE_DEFAULT_D3D11 0 -#endif - -namespace rx -{ - -Renderer::Renderer() - : mCapsInitialized(false), - mWorkaroundsInitialized(false) -{ -} - -Renderer::~Renderer() -{ -} - -const gl::Caps &Renderer::getRendererCaps() const -{ - if (!mCapsInitialized) - { - generateCaps(&mCaps, &mTextureCaps, &mExtensions); - mCapsInitialized = true; - } - - return mCaps; -} - -const gl::TextureCapsMap &Renderer::getRendererTextureCaps() const -{ - if (!mCapsInitialized) - { - generateCaps(&mCaps, &mTextureCaps, &mExtensions); - mCapsInitialized = true; - } - - return mTextureCaps; -} - -const gl::Extensions &Renderer::getRendererExtensions() const -{ - if (!mCapsInitialized) - { - generateCaps(&mCaps, &mTextureCaps, &mExtensions); - mCapsInitialized = true; - } - - return mExtensions; -} - -const Workarounds &Renderer::getWorkarounds() const -{ - if (!mWorkaroundsInitialized) - { - mWorkarounds = generateWorkarounds(); - mWorkaroundsInitialized = true; - } - - return mWorkarounds; -} - -typedef Renderer *(*CreateRendererFunction)(egl::Display*, EGLNativeDisplayType, const egl::AttributeMap &); - -template -Renderer *CreateRenderer(egl::Display *display, EGLNativeDisplayType nativeDisplay, const egl::AttributeMap &attributes) -{ - return new RendererType(display, nativeDisplay, attributes); -} - -} - -extern "C" -{ - -rx::Renderer *glCreateRenderer(egl::Display *display, EGLNativeDisplayType nativeDisplay, const egl::AttributeMap &attribMap) -{ - std::vector rendererCreationFunctions; - - EGLint requestedDisplayType = attribMap.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE); - -# if defined(ANGLE_ENABLE_D3D11) - if (nativeDisplay == EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE || - nativeDisplay == EGL_D3D11_ONLY_DISPLAY_ANGLE || - requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE) - { - rendererCreationFunctions.push_back(rx::CreateRenderer); - } -# endif - -# if defined(ANGLE_ENABLE_D3D9) - if (nativeDisplay == EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE || - requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE) - { - rendererCreationFunctions.push_back(rx::CreateRenderer); - } -# endif - - if (nativeDisplay != EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE && - nativeDisplay != EGL_D3D11_ONLY_DISPLAY_ANGLE && - requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE) - { - // The default display is requested, try the D3D9 and D3D11 renderers, order them using - // the definition of ANGLE_DEFAULT_D3D11 -# if ANGLE_DEFAULT_D3D11 -# if defined(ANGLE_ENABLE_D3D11) - rendererCreationFunctions.push_back(rx::CreateRenderer); -# endif -# if defined(ANGLE_ENABLE_D3D9) - rendererCreationFunctions.push_back(rx::CreateRenderer); -# endif -# else -# if defined(ANGLE_ENABLE_D3D9) - rendererCreationFunctions.push_back(rx::CreateRenderer); -# endif -# if defined(ANGLE_ENABLE_D3D11) - rendererCreationFunctions.push_back(rx::CreateRenderer); -# endif -# endif - } - - for (size_t i = 0; i < rendererCreationFunctions.size(); i++) - { - rx::Renderer *renderer = rendererCreationFunctions[i](display, nativeDisplay, attribMap); - if (renderer->initialize() == EGL_SUCCESS) - { - return renderer; - } - else - { - // Failed to create the renderer, try the next - SafeDelete(renderer); - } - } - - return NULL; -} - -void glDestroyRenderer(rx::Renderer *renderer) -{ - ASSERT(renderer); - SafeDelete(renderer); -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h deleted file mode 100644 index b85895a938..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h +++ /dev/null @@ -1,193 +0,0 @@ -// -// Copyright (c) 2012-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// 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/Caps.h" -#include "libGLESv2/Error.h" -#include "libGLESv2/Uniform.h" -#include "libGLESv2/angletypes.h" -#include "libGLESv2/renderer/Workarounds.h" -#include "common/NativeWindow.h" -#include "common/mathutil.h" - -#include - -#include - -#if !defined(ANGLE_COMPILE_OPTIMIZATION_LEVEL) -// WARNING: D3DCOMPILE_OPTIMIZATION_LEVEL3 may lead to a DX9 shader compiler hang. -// It should only be used selectively to work around specific bugs. -#define ANGLE_COMPILE_OPTIMIZATION_LEVEL D3DCOMPILE_OPTIMIZATION_LEVEL1 -#endif - -namespace egl -{ -class Display; -} - -namespace gl -{ -class Buffer; -class Framebuffer; -struct Data; -} - -namespace rx -{ -class QueryImpl; -class FenceNVImpl; -class FenceSyncImpl; -class BufferImpl; -class VertexArrayImpl; -class ShaderImpl; -class ProgramImpl; -class TextureImpl; -class TransformFeedbackImpl; -class RenderbufferImpl; -struct TranslatedIndexData; -struct Workarounds; -class SwapChain; - -struct ConfigDesc -{ - GLenum renderTargetFormat; - GLenum depthStencilFormat; - GLint multiSample; - bool fastConfig; - bool es3Capable; -}; - -class Renderer -{ - public: - Renderer(); - virtual ~Renderer(); - - virtual EGLint initialize() = 0; - virtual bool resetDevice() = 0; - - virtual int generateConfigs(ConfigDesc **configDescList) = 0; - virtual void deleteConfigs(ConfigDesc *configDescList) = 0; - - virtual gl::Error sync(bool block) = 0; - - virtual gl::Error drawArrays(const gl::Data &data, GLenum mode, - GLint first, GLsizei count, GLsizei instances) = 0; - virtual gl::Error drawElements(const gl::Data &data, GLenum mode, GLsizei count, GLenum type, - const GLvoid *indices, GLsizei instances, - const RangeUI &indexRange) = 0; - - virtual gl::Error clear(const gl::Data &data, GLbitfield mask) = 0; - virtual gl::Error clearBufferfv(const gl::Data &data, GLenum buffer, GLint drawbuffer, const GLfloat *values) = 0; - virtual gl::Error clearBufferuiv(const gl::Data &data, GLenum buffer, GLint drawbuffer, const GLuint *values) = 0; - virtual gl::Error clearBufferiv(const gl::Data &data, GLenum buffer, GLint drawbuffer, const GLint *values) = 0; - virtual gl::Error clearBufferfi(const gl::Data &data, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) = 0; - - virtual gl::Error readPixels(const gl::Data &data, GLint x, GLint y, GLsizei width, GLsizei height, - GLenum format, GLenum type, GLsizei *bufSize, void* pixels) = 0; - - virtual gl::Error blitFramebuffer(const gl::Data &data, - GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, - GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, - GLbitfield mask, GLenum filter) = 0; - - // TODO(jmadill): caps? and virtual for egl::Display - virtual bool getShareHandleSupport() const = 0; - virtual bool getPostSubBufferSupport() const = 0; - - // Shader creation - virtual ShaderImpl *createShader(const gl::Data &data, GLenum type) = 0; - virtual ProgramImpl *createProgram() = 0; - - // Shader operations - virtual void releaseShaderCompiler() = 0; - - // Texture creation - virtual TextureImpl *createTexture(GLenum target) = 0; - - // Renderbuffer creation - virtual RenderbufferImpl *createRenderbuffer() = 0; - virtual RenderbufferImpl *createRenderbuffer(SwapChain *swapChain, bool depth) = 0; - - // Buffer creation - virtual BufferImpl *createBuffer() = 0; - - // Vertex Array creation - virtual VertexArrayImpl *createVertexArray() = 0; - - // Query and Fence creation - virtual QueryImpl *createQuery(GLenum type) = 0; - virtual FenceNVImpl *createFenceNV() = 0; - virtual FenceSyncImpl *createFenceSync() = 0; - - // Transform Feedback creation - virtual TransformFeedbackImpl *createTransformFeedback() = 0; - - // lost device - //TODO(jmadill): investigate if this stuff is necessary in GL - virtual void notifyDeviceLost() = 0; - virtual bool isDeviceLost() = 0; - virtual bool testDeviceLost(bool notify) = 0; - virtual bool testDeviceResettable() = 0; - - virtual DWORD getAdapterVendor() const = 0; - virtual std::string getRendererDescription() const = 0; - virtual GUID getAdapterIdentifier() const = 0; - - // Renderer capabilities (virtual because of egl::Display) - virtual const gl::Caps &getRendererCaps() const; - const gl::TextureCapsMap &getRendererTextureCaps() const; - virtual const gl::Extensions &getRendererExtensions() const; - const Workarounds &getWorkarounds() const; - - // TODO(jmadill): needed by egl::Display, probably should be removed - virtual int getMajorShaderModel() const = 0; - virtual int getMinSwapInterval() const = 0; - virtual int getMaxSwapInterval() const = 0; - virtual bool getLUID(LUID *adapterLuid) const = 0; - - private: - DISALLOW_COPY_AND_ASSIGN(Renderer); - - virtual void generateCaps(gl::Caps *outCaps, gl::TextureCapsMap* outTextureCaps, gl::Extensions *outExtensions) const = 0; - virtual Workarounds generateWorkarounds() const = 0; - - mutable bool mCapsInitialized; - mutable gl::Caps mCaps; - mutable gl::TextureCapsMap mTextureCaps; - mutable gl::Extensions mExtensions; - - mutable bool mWorkaroundsInitialized; - mutable Workarounds mWorkarounds; -}; - -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 -}; - -} -#endif // LIBGLESV2_RENDERER_RENDERER_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable.h b/src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable.h deleted file mode 100644 index f1a96d74fb..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable.h +++ /dev/null @@ -1,78 +0,0 @@ -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// 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" -#include "common/debug.h" - -#include -#include - -namespace rx -{ - -class ShaderExecutable -{ - public: - ShaderExecutable(const void *function, size_t length) - : mFunctionBuffer(length) - { - memcpy(mFunctionBuffer.data(), function, length); - } - - virtual ~ShaderExecutable() {} - - const uint8_t *getFunction() const - { - return mFunctionBuffer.data(); - } - - size_t getLength() const - { - return mFunctionBuffer.size(); - } - - const std::string &getDebugInfo() const - { - return mDebugInfo; - } - - void appendDebugInfo(const std::string &info) - { - mDebugInfo += info; - } - - private: - DISALLOW_COPY_AND_ASSIGN(ShaderExecutable); - - std::vector mFunctionBuffer; - std::string mDebugInfo; -}; - -class UniformStorage -{ - public: - UniformStorage(size_t initialSize) - : mSize(initialSize) - { - } - - virtual ~UniformStorage() {} - - size_t size() const { return mSize; } - - private: - size_t mSize; -}; - -} - -#endif // LIBGLESV2_RENDERER_SHADEREXECUTABLE_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/ShaderImpl.h b/src/3rdparty/angle/src/libGLESv2/renderer/ShaderImpl.h deleted file mode 100644 index cb0d360f0b..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/ShaderImpl.h +++ /dev/null @@ -1,55 +0,0 @@ -// -// Copyright 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// ShaderImpl.h: Defines the abstract rx::ShaderImpl class. - -#ifndef LIBGLESV2_RENDERER_SHADERIMPL_H_ -#define LIBGLESV2_RENDERER_SHADERIMPL_H_ - -#include - -#include "common/angleutils.h" -#include "libGLESv2/Shader.h" - -namespace rx -{ - -class ShaderImpl -{ - public: - ShaderImpl() { } - virtual ~ShaderImpl() { } - - virtual bool compile(const gl::Data &data, const std::string &source) = 0; - virtual const std::string &getInfoLog() const = 0; - virtual const std::string &getTranslatedSource() const = 0; - virtual std::string getDebugInfo() const = 0; - - const std::vector &getVaryings() const { return mVaryings; } - const std::vector &getUniforms() const { return mUniforms; } - const std::vector &getInterfaceBlocks() const { return mInterfaceBlocks; } - const std::vector &getActiveAttributes() const { return mActiveAttributes; } - const std::vector &getActiveOutputVariables() const { return mActiveOutputVariables; } - - std::vector &getVaryings() { return mVaryings; } - std::vector &getUniforms() { return mUniforms; } - std::vector &getInterfaceBlocks() { return mInterfaceBlocks; } - std::vector &getActiveAttributes() { return mActiveAttributes; } - std::vector &getActiveOutputVariables() { return mActiveOutputVariables; } - - protected: - DISALLOW_COPY_AND_ASSIGN(ShaderImpl); - - std::vector mVaryings; - std::vector mUniforms; - std::vector mInterfaceBlocks; - std::vector mActiveAttributes; - std::vector mActiveOutputVariables; -}; - -} - -#endif // LIBGLESV2_RENDERER_SHADERIMPL_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.h b/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.h deleted file mode 100644 index 1417e0bdf6..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.h +++ /dev/null @@ -1,56 +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. -// - -// 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" -#include "common/NativeWindow.h" -#include "common/platform.h" - -#include -#include - -#if !defined(ANGLE_FORCE_VSYNC_OFF) -#define ANGLE_FORCE_VSYNC_OFF 0 -#endif - -namespace rx -{ - -class SwapChain -{ - public: - SwapChain(rx::NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) - : mNativeWindow(nativeWindow), 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; - - GLenum GetBackBufferInternalFormat() const { return mBackBufferFormat; } - GLenum GetDepthBufferInternalFormat() const { return mDepthBufferFormat; } - - virtual HANDLE getShareHandle() {return mShareHandle;}; - - protected: - rx::NativeWindow mNativeWindow; // Handler for the 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/TextureImpl.h b/src/3rdparty/angle/src/libGLESv2/renderer/TextureImpl.h deleted file mode 100644 index 3e662557e4..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/TextureImpl.h +++ /dev/null @@ -1,64 +0,0 @@ -// -// Copyright 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// TextureImpl.h: Defines the abstract rx::TextureImpl classes. - -#ifndef LIBGLESV2_RENDERER_TEXTUREIMPL_H_ -#define LIBGLESV2_RENDERER_TEXTUREIMPL_H_ - -#include "common/angleutils.h" -#include "libGLESv2/Error.h" - -#include "angle_gl.h" - -#include "libGLESv2/ImageIndex.h" - -namespace egl -{ -class Surface; -} - -namespace gl -{ -class Framebuffer; -struct PixelUnpackState; -struct SamplerState; -} - -namespace rx -{ - -class Image; - -class TextureImpl -{ - public: - virtual ~TextureImpl() {}; - - // Deprecated in favour of the ImageIndex method - virtual Image *getImage(int level, int layer) const = 0; - virtual Image *getImage(const gl::ImageIndex &index) const = 0; - virtual GLsizei getLayerCount(int level) const = 0; - - virtual void setUsage(GLenum usage) = 0; - - virtual gl::Error setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels) = 0; - virtual gl::Error setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels) = 0; - virtual gl::Error subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels) = 0; - virtual gl::Error subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels) = 0; - virtual gl::Error copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) = 0; - virtual gl::Error copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) = 0; - virtual gl::Error storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) = 0; - - virtual gl::Error generateMipmaps() = 0; - - virtual void bindTexImage(egl::Surface *surface) = 0; - virtual void releaseTexImage() = 0; -}; - -} - -#endif // LIBGLESV2_RENDERER_TEXTUREIMPL_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/TransformFeedbackImpl.h b/src/3rdparty/angle/src/libGLESv2/renderer/TransformFeedbackImpl.h deleted file mode 100644 index 8425604d87..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/TransformFeedbackImpl.h +++ /dev/null @@ -1,31 +0,0 @@ -// -// Copyright 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// TransformFeedbackImpl.h: Defines the abstract rx::TransformFeedbackImpl class. - -#ifndef LIBGLESV2_RENDERER_TRANSFORMFEEDBACKIMPL_H_ -#define LIBGLESV2_RENDERER_TRANSFORMFEEDBACKIMPL_H_ - -#include "common/angleutils.h" -#include "libGLESv2/TransformFeedback.h" - -namespace rx -{ - -class TransformFeedbackImpl -{ - public: - virtual ~TransformFeedbackImpl() { } - - virtual void begin(GLenum primitiveMode) = 0; - virtual void end() = 0; - virtual void pause() = 0; - virtual void resume() = 0; -}; - -} - -#endif // LIBGLESV2_RENDERER_TRANSFORMFEEDBACKIMPL_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/VertexArrayImpl.h b/src/3rdparty/angle/src/libGLESv2/renderer/VertexArrayImpl.h deleted file mode 100644 index b013f9cdf4..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/VertexArrayImpl.h +++ /dev/null @@ -1,32 +0,0 @@ -// -// Copyright 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// VertexAttribImpl.h: Defines the abstract rx::VertexAttribImpl class. - -#ifndef LIBGLESV2_RENDERER_VERTEXARRAYIMPL_H_ -#define LIBGLESV2_RENDERER_VERTEXARRAYIMPL_H_ - -#include "common/angleutils.h" -#include "libGLESv2/Buffer.h" -#include "libGLESv2/VertexAttribute.h" - -namespace rx -{ - -class VertexArrayImpl -{ - public: - virtual ~VertexArrayImpl() { } - - virtual void setElementArrayBuffer(const gl::Buffer *buffer) = 0; - virtual void setAttribute(size_t idx, const gl::VertexAttribute &attr) = 0; - virtual void setAttributeDivisor(size_t idx, GLuint divisor) = 0; - virtual void enableAttribute(size_t idx, bool enabledState) = 0; -}; - -} - -#endif // LIBGLESV2_RENDERER_VERTEXARRAYIMPL_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Workarounds.h b/src/3rdparty/angle/src/libGLESv2/renderer/Workarounds.h deleted file mode 100644 index 20a166fb7a..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Workarounds.h +++ /dev/null @@ -1,39 +0,0 @@ -// -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// angletypes.h: Workarounds for driver bugs and other issues. - -#ifndef LIBGLESV2_RENDERER_WORKAROUNDS_H_ -#define LIBGLESV2_RENDERER_WORKAROUNDS_H_ - -// TODO(jmadill,zmo,geofflang): make a workarounds library that can operate -// independent of ANGLE's renderer. Workarounds should also be accessible -// outside of the Renderer. - -namespace rx -{ - -enum D3DWorkaroundType -{ - ANGLE_D3D_WORKAROUND_NONE, - ANGLE_D3D_WORKAROUND_SKIP_OPTIMIZATION, - ANGLE_D3D_WORKAROUND_MAX_OPTIMIZATION -}; - -struct Workarounds -{ - Workarounds() - : mrtPerfWorkaround(false), - setDataFasterThanImageUpload(false) - {} - - bool mrtPerfWorkaround; - bool setDataFasterThanImageUpload; -}; - -} - -#endif // LIBGLESV2_RENDERER_WORKAROUNDS_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/copyimage.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/copyimage.cpp deleted file mode 100644 index aabc9f04e9..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/copyimage.cpp +++ /dev/null @@ -1,22 +0,0 @@ -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// copyimage.cpp: Defines image copying functions - -#include "libGLESv2/renderer/copyimage.h" - -namespace rx -{ - -void CopyBGRA8ToRGBA8(const uint8_t *source, uint8_t *dest) -{ - uint32_t argb = *reinterpret_cast(source); - *reinterpret_cast(dest) = (argb & 0xFF00FF00) | // Keep alpha and green - (argb & 0x00FF0000) >> 16 | // Move red to blue - (argb & 0x000000FF) << 16; // Move blue to red -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/copyimage.h b/src/3rdparty/angle/src/libGLESv2/renderer/copyimage.h deleted file mode 100644 index 513eb5cb3d..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/copyimage.h +++ /dev/null @@ -1,35 +0,0 @@ -// -// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// copyimage.h: Defines image copying functions - -#ifndef LIBGLESV2_RENDERER_COPYIMAGE_H_ -#define LIBGLESV2_RENDERER_COPYIMAGE_H_ - -#include "common/mathutil.h" -#include "libGLESv2/angletypes.h" - -#include - -namespace rx -{ - -template -void ReadColor(const uint8_t *source, uint8_t *dest); - -template -void WriteColor(const uint8_t *source, uint8_t *dest); - -template -void CopyPixel(const uint8_t *source, uint8_t *dest); - -void CopyBGRA8ToRGBA8(const uint8_t *source, uint8_t *dest); - -} - -#include "copyimage.inl" - -#endif // LIBGLESV2_RENDERER_COPYIMAGE_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/copyimage.inl b/src/3rdparty/angle/src/libGLESv2/renderer/copyimage.inl deleted file mode 100644 index 0498cf7750..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/copyimage.inl +++ /dev/null @@ -1,32 +0,0 @@ -// -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// copyimage.inl: Defines image copying functions - -namespace rx -{ - -template -inline void ReadColor(const uint8_t *source, uint8_t *dest) -{ - sourceType::readColor(reinterpret_cast*>(dest), reinterpret_cast(source)); -} - -template -inline void WriteColor(const uint8_t *source, uint8_t *dest) -{ - destType::writeColor(reinterpret_cast(dest), reinterpret_cast*>(source)); -} - -template -inline void CopyPixel(const uint8_t *source, uint8_t *dest) -{ - colorDataType temp; - ReadColor(source, &temp); - WriteColor(&temp, dest); -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/copyvertex.h b/src/3rdparty/angle/src/libGLESv2/renderer/copyvertex.h deleted file mode 100644 index e0e8af166b..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/copyvertex.h +++ /dev/null @@ -1,35 +0,0 @@ -// -// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// copyvertex.h: Defines vertex buffer copying and conversion functions - -#ifndef LIBGLESV2_RENDERER_COPYVERTEX_H_ -#define LIBGLESV2_RENDERER_COPYVERTEX_H_ - -#include "common/mathutil.h" - -namespace rx -{ - -// 'widenDefaultValueBits' gives the default value for the alpha channel (4th component) -// the sentinel value 0 means we do not want to widen the input or add an alpha channel -template -inline void CopyNativeVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output); - -template -inline void Copy32FixedTo32FVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output); - -template -inline void CopyTo32FVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output); - -template -inline void CopyXYZ10W2ToXYZW32FVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output); - -} - -#include "copyvertex.inl" - -#endif // LIBGLESV2_RENDERER_COPYVERTEX_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/copyvertex.inl b/src/3rdparty/angle/src/libGLESv2/renderer/copyvertex.inl deleted file mode 100644 index 7eef17b22b..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/copyvertex.inl +++ /dev/null @@ -1,288 +0,0 @@ -// -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -namespace rx -{ - -template -inline void CopyNativeVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output) -{ - const size_t attribSize = sizeof(T)* componentCount; - const T defaultValue = gl::bitCast(widenDefaultValueBits); - const bool widen = (widenDefaultValueBits != 0); - - if (attribSize == stride && !widen) - { - memcpy(output, input, count * attribSize); - } - else - { - size_t outputStride = widen ? 4 : componentCount; - - for (size_t i = 0; i < count; i++) - { - const T *offsetInput = reinterpret_cast(input + (i * stride)); - T *offsetOutput = reinterpret_cast(output) + i * outputStride; - - for (size_t j = 0; j < componentCount; j++) - { - offsetOutput[j] = offsetInput[j]; - } - - if (widen) - { - offsetOutput[3] = defaultValue; - } - } - } -} - -template -inline void Copy32FixedTo32FVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output) -{ - static const float divisor = 1.0f / (1 << 16); - - for (size_t i = 0; i < count; i++) - { - const GLfixed* offsetInput = reinterpret_cast(input + (stride * i)); - float* offsetOutput = reinterpret_cast(output) + i * componentCount; - - for (size_t j = 0; j < componentCount; j++) - { - offsetOutput[j] = static_cast(offsetInput[j]) * divisor; - } - } -} - -template -inline void CopyTo32FVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output) -{ - typedef std::numeric_limits NL; - - for (size_t i = 0; i < count; i++) - { - const T *offsetInput = reinterpret_cast(input + (stride * i)); - float *offsetOutput = reinterpret_cast(output) + i * componentCount; - - for (size_t 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]); - } - } - } -} - -namespace priv -{ - -template -static inline void CopyPackedRGB(uint32_t data, uint8_t *output) -{ - const uint32_t rgbSignMask = 0x200; // 1 set at the 9 bit - const uint32_t negativeMask = 0xFFFFFC00; // All bits from 10 to 31 set to 1 - - if (toFloat) - { - GLfloat *floatOutput = reinterpret_cast(output); - if (isSigned) - { - GLfloat finalValue = 0; - if (data & rgbSignMask) - { - int negativeNumber = data | negativeMask; - finalValue = static_cast(negativeNumber); - } - else - { - finalValue = static_cast(data); - } - - if (normalized) - { - const int32_t maxValue = 0x1FF; // 1 set in bits 0 through 8 - const int32_t minValue = 0xFFFFFE01; // Inverse of maxValue - - // A 10-bit two's complement number has the possibility of being minValue - 1 but - // OpenGL's normalization rules dictate that it should be clamped to minValue in this - // case. - if (finalValue < minValue) - { - finalValue = minValue; - } - - const int32_t halfRange = (maxValue - minValue) >> 1; - *floatOutput = ((finalValue - minValue) / halfRange) - 1.0f; - } - else - { - *floatOutput = finalValue; - } - } - else - { - if (normalized) - { - const uint32_t maxValue = 0x3FF; // 1 set in bits 0 through 9 - *floatOutput = static_cast(data) / static_cast(maxValue); - } - else - { - *floatOutput = static_cast(data); - } - } - } - else - { - if (isSigned) - { - GLshort *intOutput = reinterpret_cast(output); - - if (data & rgbSignMask) - { - *intOutput = data | negativeMask; - } - else - { - *intOutput = data; - } - } - else - { - GLushort *uintOutput = reinterpret_cast(output); - *uintOutput = data; - } - } -} - -template -inline void CopyPackedAlpha(uint32_t data, uint8_t *output) -{ - if (toFloat) - { - GLfloat *floatOutput = reinterpret_cast(output); - if (isSigned) - { - if (normalized) - { - switch (data) - { - case 0x0: *floatOutput = 0.0f; break; - case 0x1: *floatOutput = 1.0f; break; - case 0x2: *floatOutput = -1.0f; break; - case 0x3: *floatOutput = -1.0f; break; - default: UNREACHABLE(); - } - } - else - { - switch (data) - { - case 0x0: *floatOutput = 0.0f; break; - case 0x1: *floatOutput = 1.0f; break; - case 0x2: *floatOutput = -2.0f; break; - case 0x3: *floatOutput = -1.0f; break; - default: UNREACHABLE(); - } - } - } - else - { - if (normalized) - { - switch (data) - { - case 0x0: *floatOutput = 0.0f / 3.0f; break; - case 0x1: *floatOutput = 1.0f / 3.0f; break; - case 0x2: *floatOutput = 2.0f / 3.0f; break; - case 0x3: *floatOutput = 3.0f / 3.0f; break; - default: UNREACHABLE(); - } - } - else - { - switch (data) - { - case 0x0: *floatOutput = 0.0f; break; - case 0x1: *floatOutput = 1.0f; break; - case 0x2: *floatOutput = 2.0f; break; - case 0x3: *floatOutput = 3.0f; break; - default: UNREACHABLE(); - } - } - } - } - else - { - if (isSigned) - { - GLshort *intOutput = reinterpret_cast(output); - switch (data) - { - case 0x0: *intOutput = 0; break; - case 0x1: *intOutput = 1; break; - case 0x2: *intOutput = -2; break; - case 0x3: *intOutput = -1; break; - default: UNREACHABLE(); - } - } - else - { - GLushort *uintOutput = reinterpret_cast(output); - switch (data) - { - case 0x0: *uintOutput = 0; break; - case 0x1: *uintOutput = 1; break; - case 0x2: *uintOutput = 2; break; - case 0x3: *uintOutput = 3; break; - default: UNREACHABLE(); - } - } - } -} - -} - -template -inline void CopyXYZ10W2ToXYZW32FVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output) -{ - const size_t outputComponentSize = toFloat ? 4 : 2; - const size_t componentCount = 4; - - const uint32_t rgbMask = 0x3FF; // 1 set in bits 0 through 9 - const size_t redShift = 0; // red is bits 0 through 9 - const size_t greenShift = 10; // green is bits 10 through 19 - const size_t blueShift = 20; // blue is bits 20 through 29 - - const uint32_t alphaMask = 0x3; // 1 set in bits 0 and 1 - const size_t alphaShift = 30; // Alpha is the 30 and 31 bits - - for (size_t i = 0; i < count; i++) - { - GLuint packedValue = *reinterpret_cast(input + (i * stride)); - uint8_t *offsetOutput = output + (i * outputComponentSize * componentCount); - - priv::CopyPackedRGB( (packedValue >> redShift) & rgbMask, offsetOutput + (0 * outputComponentSize)); - priv::CopyPackedRGB( (packedValue >> greenShift) & rgbMask, offsetOutput + (1 * outputComponentSize)); - priv::CopyPackedRGB( (packedValue >> blueShift) & rgbMask, offsetOutput + (2 * outputComponentSize)); - priv::CopyPackedAlpha((packedValue >> alphaShift) & alphaMask, offsetOutput + (3 * outputComponentSize)); - } -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/BufferD3D.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/BufferD3D.cpp deleted file mode 100644 index dd0d3f52ad..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/BufferD3D.cpp +++ /dev/null @@ -1,88 +0,0 @@ -// -// Copyright 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// BufferD3D.cpp Defines common functionality between the Buffer9 and Buffer11 classes. - -#include "libGLESv2/renderer/d3d/BufferD3D.h" -#include "libGLESv2/renderer/d3d/VertexBuffer.h" -#include "libGLESv2/renderer/d3d/IndexBuffer.h" -#include "libGLESv2/main.h" - -namespace rx -{ - -unsigned int BufferD3D::mNextSerial = 1; - -BufferD3D::BufferD3D() - : BufferImpl(), - mStaticVertexBuffer(NULL), - mStaticIndexBuffer(NULL) -{ - updateSerial(); -} - -BufferD3D::~BufferD3D() -{ - SafeDelete(mStaticVertexBuffer); - SafeDelete(mStaticIndexBuffer); -} - -BufferD3D *BufferD3D::makeBufferD3D(BufferImpl *buffer) -{ - ASSERT(HAS_DYNAMIC_TYPE(BufferD3D*, buffer)); - return static_cast(buffer); -} - -BufferD3D *BufferD3D::makeFromBuffer(gl::Buffer *buffer) -{ - BufferImpl *impl = buffer->getImplementation(); - ASSERT(impl); - return makeBufferD3D(impl); -} - -void BufferD3D::updateSerial() -{ - mSerial = mNextSerial++; -} - -void BufferD3D::initializeStaticData() -{ - if (!mStaticVertexBuffer) - { - mStaticVertexBuffer = new StaticVertexBufferInterface(getRenderer()); - } - if (!mStaticIndexBuffer) - { - mStaticIndexBuffer = new StaticIndexBufferInterface(getRenderer()); - } -} - -void BufferD3D::invalidateStaticData() -{ - if ((mStaticVertexBuffer && mStaticVertexBuffer->getBufferSize() != 0) || (mStaticIndexBuffer && mStaticIndexBuffer->getBufferSize() != 0)) - { - SafeDelete(mStaticVertexBuffer); - SafeDelete(mStaticIndexBuffer); - } - - mUnmodifiedDataUse = 0; -} - -// Creates static buffers if sufficient used data has been left unmodified -void BufferD3D::promoteStaticUsage(int dataSize) -{ - if (!mStaticVertexBuffer && !mStaticIndexBuffer) - { - mUnmodifiedDataUse += dataSize; - - if (mUnmodifiedDataUse > 3 * getSize()) - { - initializeStaticData(); - } - } -} - -} \ No newline at end of file diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/BufferD3D.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/BufferD3D.h deleted file mode 100644 index 1a1308c545..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/BufferD3D.h +++ /dev/null @@ -1,59 +0,0 @@ -// -// Copyright 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// BufferImpl.h: Defines the abstract rx::BufferImpl class. - -#ifndef LIBGLESV2_RENDERER_BUFFERD3D_H_ -#define LIBGLESV2_RENDERER_BUFFERD3D_H_ - -#include "libGLESv2/renderer/BufferImpl.h" -#include "libGLESv2/angletypes.h" - -#include - -namespace rx -{ -class RendererD3D; -class StaticIndexBufferInterface; -class StaticVertexBufferInterface; - -class BufferD3D : public BufferImpl -{ - public: - BufferD3D(); - virtual ~BufferD3D(); - - static BufferD3D *makeBufferD3D(BufferImpl *buffer); - static BufferD3D *makeFromBuffer(gl::Buffer *buffer); - - unsigned int getSerial() const { return mSerial; } - - virtual gl::Error getData(const uint8_t **outData) = 0; - virtual size_t getSize() const = 0; - virtual bool supportsDirectBinding() const = 0; - virtual RendererD3D *getRenderer() = 0; - - StaticVertexBufferInterface *getStaticVertexBuffer() { return mStaticVertexBuffer; } - StaticIndexBufferInterface *getStaticIndexBuffer() { return mStaticIndexBuffer; } - - void initializeStaticData(); - void invalidateStaticData(); - void promoteStaticUsage(int dataSize); - - protected: - unsigned int mSerial; - static unsigned int mNextSerial; - - void updateSerial(); - - StaticVertexBufferInterface *mStaticVertexBuffer; - StaticIndexBufferInterface *mStaticIndexBuffer; - unsigned int mUnmodifiedDataUse; -}; - -} - -#endif // LIBGLESV2_RENDERER_BUFFERIMPLD3D_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/DynamicHLSL.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/DynamicHLSL.cpp deleted file mode 100644 index 3d5bfe0cbe..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/DynamicHLSL.cpp +++ /dev/null @@ -1,1148 +0,0 @@ -// -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// DynamicHLSL.cpp: Implementation for link and run-time HLSL generation -// - -#include "libGLESv2/renderer/d3d/DynamicHLSL.h" -#include "libGLESv2/renderer/d3d/ShaderD3D.h" -#include "libGLESv2/renderer/d3d/RendererD3D.h" -#include "libGLESv2/Program.h" -#include "libGLESv2/ProgramBinary.h" -#include "libGLESv2/Shader.h" -#include "libGLESv2/formatutils.h" - -#include "common/utilities.h" -#include "common/blocklayout.h" - -// For use with ArrayString, see angleutils.h -META_ASSERT(GL_INVALID_INDEX == UINT_MAX); - -using namespace gl; - -namespace rx -{ - -namespace -{ - -std::string HLSLComponentTypeString(GLenum componentType) -{ - switch (componentType) - { - case GL_UNSIGNED_INT: return "uint"; - case GL_INT: return "int"; - case GL_UNSIGNED_NORMALIZED: - case GL_SIGNED_NORMALIZED: - case GL_FLOAT: return "float"; - default: UNREACHABLE(); return "not-component-type"; - } -} - -std::string HLSLComponentTypeString(GLenum componentType, int componentCount) -{ - return HLSLComponentTypeString(componentType) + (componentCount > 1 ? Str(componentCount) : ""); -} - -std::string HLSLMatrixTypeString(GLenum type) -{ - switch (type) - { - case GL_FLOAT_MAT2: return "float2x2"; - case GL_FLOAT_MAT3: return "float3x3"; - case GL_FLOAT_MAT4: return "float4x4"; - case GL_FLOAT_MAT2x3: return "float2x3"; - case GL_FLOAT_MAT3x2: return "float3x2"; - case GL_FLOAT_MAT2x4: return "float2x4"; - case GL_FLOAT_MAT4x2: return "float4x2"; - case GL_FLOAT_MAT3x4: return "float3x4"; - case GL_FLOAT_MAT4x3: return "float4x3"; - default: UNREACHABLE(); return "not-matrix-type"; - } -} - -std::string HLSLTypeString(GLenum type) -{ - if (gl::IsMatrixType(type)) - { - return HLSLMatrixTypeString(type); - } - - return HLSLComponentTypeString(gl::VariableComponentType(type), gl::VariableComponentCount(type)); -} - -const PixelShaderOutputVariable &GetOutputAtLocation(const std::vector &outputVariables, - unsigned int location) -{ - for (size_t variableIndex = 0; variableIndex < outputVariables.size(); ++variableIndex) - { - if (outputVariables[variableIndex].outputIndex == location) - { - return outputVariables[variableIndex]; - } - } - - UNREACHABLE(); - return outputVariables[0]; -} - -const std::string VERTEX_ATTRIBUTE_STUB_STRING = "@@ VERTEX ATTRIBUTES @@"; -const std::string PIXEL_OUTPUT_STUB_STRING = "@@ PIXEL OUTPUT @@"; - -} - -DynamicHLSL::DynamicHLSL(RendererD3D *const renderer) - : mRenderer(renderer) -{ -} - -static bool packVarying(PackedVarying *varying, const int maxVaryingVectors, VaryingPacking packing) -{ - GLenum transposedType = TransposeMatrixType(varying->type); - - // matrices within varying structs are not transposed - int registers = (varying->isStruct() ? HLSLVariableRegisterCount(*varying) : VariableRowCount(transposedType)) * varying->elementCount(); - int elements = (varying->isStruct() ? 4 : VariableColumnCount(transposedType)); - - if (elements >= 2 && elements <= 4) - { - for (int r = 0; r <= maxVaryingVectors - registers; r++) - { - bool available = true; - - for (int y = 0; y < registers && available; y++) - { - for (int x = 0; x < elements && available; x++) - { - if (packing[r + y][x]) - { - available = false; - } - } - } - - if (available) - { - varying->registerIndex = r; - varying->columnIndex = 0; - - for (int y = 0; y < registers; y++) - { - for (int x = 0; x < elements; x++) - { - packing[r + y][x] = &*varying; - } - } - - return true; - } - } - - if (elements == 2) - { - for (int r = maxVaryingVectors - registers; r >= 0; r--) - { - bool available = true; - - for (int y = 0; y < registers && available; y++) - { - for (int x = 2; x < 4 && available; x++) - { - if (packing[r + y][x]) - { - available = false; - } - } - } - - if (available) - { - varying->registerIndex = r; - varying->columnIndex = 2; - - for (int y = 0; y < registers; y++) - { - for (int x = 2; x < 4; x++) - { - packing[r + y][x] = &*varying; - } - } - - return true; - } - } - } - } - else if (elements == 1) - { - int space[4] = { 0 }; - - for (int y = 0; y < maxVaryingVectors; y++) - { - for (int x = 0; x < 4; x++) - { - space[x] += packing[y][x] ? 0 : 1; - } - } - - int column = 0; - - for (int x = 0; x < 4; x++) - { - if (space[x] >= registers && (space[column] < registers || space[x] < space[column])) - { - column = x; - } - } - - if (space[column] >= registers) - { - for (int r = 0; r < maxVaryingVectors; r++) - { - if (!packing[r][column]) - { - varying->registerIndex = r; - varying->columnIndex = column; - - for (int y = r; y < r + registers; y++) - { - packing[y][column] = &*varying; - } - - break; - } - } - - return true; - } - } - else UNREACHABLE(); - - return false; -} - -// 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 DynamicHLSL::packVaryings(InfoLog &infoLog, VaryingPacking packing, ShaderD3D *fragmentShader, - ShaderD3D *vertexShader, const std::vector &transformFeedbackVaryings) -{ - // TODO (geofflang): Use context's caps - const int maxVaryingVectors = mRenderer->getRendererCaps().maxVaryingVectors; - - vertexShader->resetVaryingsRegisterAssignment(); - fragmentShader->resetVaryingsRegisterAssignment(); - - std::set packedVaryings; - - std::vector &fragmentVaryings = fragmentShader->getVaryings(); - std::vector &vertexVaryings = vertexShader->getVaryings(); - for (unsigned int varyingIndex = 0; varyingIndex < fragmentVaryings.size(); varyingIndex++) - { - PackedVarying *varying = &fragmentVaryings[varyingIndex]; - - // Do not assign registers to built-in or unreferenced varyings - if (varying->isBuiltIn() || !varying->staticUse) - { - continue; - } - - if (packVarying(varying, maxVaryingVectors, packing)) - { - packedVaryings.insert(varying->name); - } - else - { - infoLog.append("Could not pack varying %s", varying->name.c_str()); - return -1; - } - } - - for (unsigned int feedbackVaryingIndex = 0; feedbackVaryingIndex < transformFeedbackVaryings.size(); feedbackVaryingIndex++) - { - const std::string &transformFeedbackVarying = transformFeedbackVaryings[feedbackVaryingIndex]; - - if (transformFeedbackVarying == "gl_Position" || transformFeedbackVarying == "gl_PointSize") - { - // do not pack builtin XFB varyings - continue; - } - - if (packedVaryings.find(transformFeedbackVarying) == packedVaryings.end()) - { - bool found = false; - for (unsigned int varyingIndex = 0; varyingIndex < vertexVaryings.size(); varyingIndex++) - { - PackedVarying *varying = &vertexVaryings[varyingIndex]; - if (transformFeedbackVarying == varying->name) - { - if (!packVarying(varying, maxVaryingVectors, packing)) - { - infoLog.append("Could not pack varying %s", varying->name.c_str()); - return -1; - } - - found = true; - break; - } - } - - if (!found) - { - infoLog.append("Transform feedback varying %s does not exist in the vertex shader.", transformFeedbackVarying.c_str()); - return -1; - } - } - } - - // Return the number of used registers - int registers = 0; - - for (int r = 0; r < maxVaryingVectors; r++) - { - if (packing[r][0] || packing[r][1] || packing[r][2] || packing[r][3]) - { - registers++; - } - } - - return registers; -} - -std::string DynamicHLSL::generateVaryingHLSL(const ShaderD3D *shader) const -{ - std::string varyingSemantic = getVaryingSemantic(shader->mUsesPointSize); - std::string varyingHLSL; - - const std::vector &varyings = shader->getVaryings(); - - for (unsigned int varyingIndex = 0; varyingIndex < varyings.size(); varyingIndex++) - { - const PackedVarying &varying = varyings[varyingIndex]; - if (varying.registerAssigned()) - { - ASSERT(!varying.isBuiltIn()); - GLenum transposedType = TransposeMatrixType(varying.type); - int variableRows = (varying.isStruct() ? 1 : VariableRowCount(transposedType)); - - for (unsigned int elementIndex = 0; elementIndex < varying.elementCount(); elementIndex++) - { - for (int row = 0; row < variableRows; row++) - { - // TODO: Add checks to ensure D3D interpolation modifiers don't result in too many registers being used. - // For example, if there are N registers, and we have N vec3 varyings and 1 float varying, then D3D will pack them into N registers. - // If the float varying has the 'nointerpolation' modifier on it then we would need N + 1 registers, and D3D compilation will fail. - - switch (varying.interpolation) - { - case sh::INTERPOLATION_SMOOTH: varyingHLSL += " "; break; - case sh::INTERPOLATION_FLAT: varyingHLSL += " nointerpolation "; break; - case sh::INTERPOLATION_CENTROID: varyingHLSL += " centroid "; break; - default: UNREACHABLE(); - } - - unsigned int semanticIndex = elementIndex * variableRows + varying.columnIndex * mRenderer->getRendererCaps().maxVaryingVectors + varying.registerIndex + row; - std::string n = Str(semanticIndex); - - std::string typeString; - - if (varying.isStruct()) - { - // matrices within structs are not transposed, so - // do not use the special struct prefix "rm" - typeString = decorateVariable(varying.structName); - } - else - { - GLenum componentType = VariableComponentType(transposedType); - int columnCount = VariableColumnCount(transposedType); - typeString = HLSLComponentTypeString(componentType, columnCount); - } - varyingHLSL += typeString + " v" + n + " : " + varyingSemantic + n + ";\n"; - } - } - } - } - - return varyingHLSL; -} - -std::string DynamicHLSL::generateVertexShaderForInputLayout(const std::string &sourceShader, - const VertexFormat inputLayout[], - const sh::Attribute shaderAttributes[]) const -{ - std::string structHLSL, initHLSL; - - int semanticIndex = 0; - unsigned int inputIndex = 0; - - for (unsigned int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++) - { - const sh::Attribute &shaderAttribute = shaderAttributes[attributeIndex]; - if (!shaderAttribute.name.empty()) - { - ASSERT(inputIndex < MAX_VERTEX_ATTRIBS); - const VertexFormat &vertexFormat = inputLayout[inputIndex]; - - // HLSL code for input structure - if (IsMatrixType(shaderAttribute.type)) - { - // Matrix types are always transposed - structHLSL += " " + HLSLMatrixTypeString(TransposeMatrixType(shaderAttribute.type)); - } - else - { - GLenum componentType = mRenderer->getVertexComponentType(vertexFormat); - structHLSL += " " + HLSLComponentTypeString(componentType, VariableComponentCount(shaderAttribute.type)); - } - - structHLSL += " " + decorateVariable(shaderAttribute.name) + " : TEXCOORD" + Str(semanticIndex) + ";\n"; - semanticIndex += VariableRegisterCount(shaderAttribute.type); - - // HLSL code for initialization - initHLSL += " " + decorateVariable(shaderAttribute.name) + " = "; - - // Mismatched vertex attribute to vertex input may result in an undefined - // data reinterpretation (eg for pure integer->float, float->pure integer) - // TODO: issue warning with gl debug info extension, when supported - if (IsMatrixType(shaderAttribute.type) || - (mRenderer->getVertexConversionType(vertexFormat) & VERTEX_CONVERT_GPU) != 0) - { - initHLSL += generateAttributeConversionHLSL(vertexFormat, shaderAttribute); - } - else - { - initHLSL += "input." + decorateVariable(shaderAttribute.name); - } - - initHLSL += ";\n"; - - inputIndex += VariableRowCount(TransposeMatrixType(shaderAttribute.type)); - } - } - - std::string replacementHLSL = "struct VS_INPUT\n" - "{\n" + - structHLSL + - "};\n" - "\n" - "void initAttributes(VS_INPUT input)\n" - "{\n" + - initHLSL + - "}\n"; - - std::string vertexHLSL(sourceShader); - - size_t copyInsertionPos = vertexHLSL.find(VERTEX_ATTRIBUTE_STUB_STRING); - vertexHLSL.replace(copyInsertionPos, VERTEX_ATTRIBUTE_STUB_STRING.length(), replacementHLSL); - - return vertexHLSL; -} - -std::string DynamicHLSL::generatePixelShaderForOutputSignature(const std::string &sourceShader, const std::vector &outputVariables, - bool usesFragDepth, const std::vector &outputLayout) const -{ - const int shaderModel = mRenderer->getMajorShaderModel(); - std::string targetSemantic = (shaderModel >= 4) ? "SV_TARGET" : "COLOR"; - std::string depthSemantic = (shaderModel >= 4) ? "SV_Depth" : "DEPTH"; - - std::string declarationHLSL; - std::string copyHLSL; - - for (size_t layoutIndex = 0; layoutIndex < outputLayout.size(); ++layoutIndex) - { - GLenum binding = outputLayout[layoutIndex]; - - if (binding != GL_NONE) - { - unsigned int location = (binding - GL_COLOR_ATTACHMENT0); - - const PixelShaderOutputVariable &outputVariable = GetOutputAtLocation(outputVariables, location); - - declarationHLSL += " " + HLSLTypeString(outputVariable.type) + " " + outputVariable.name + - " : " + targetSemantic + Str(layoutIndex) + ";\n"; - - copyHLSL += " output." + outputVariable.name + " = " + outputVariable.source + ";\n"; - } - } - - if (usesFragDepth) - { - declarationHLSL += " float gl_Depth : " + depthSemantic + ";\n"; - copyHLSL += " output.gl_Depth = gl_Depth; \n"; - } - - std::string replacementHLSL = "struct PS_OUTPUT\n" - "{\n" + - declarationHLSL + - "};\n" - "\n" - "PS_OUTPUT generateOutput()\n" - "{\n" - " PS_OUTPUT output;\n" + - copyHLSL + - " return output;\n" - "}\n"; - - std::string pixelHLSL(sourceShader); - - size_t outputInsertionPos = pixelHLSL.find(PIXEL_OUTPUT_STUB_STRING); - pixelHLSL.replace(outputInsertionPos, PIXEL_OUTPUT_STUB_STRING.length(), replacementHLSL); - - return pixelHLSL; -} - -std::string DynamicHLSL::getVaryingSemantic(bool pointSize) const -{ - // SM3 reserves the TEXCOORD semantic for point sprite texcoords (gl_PointCoord) - // In D3D11 we manually compute gl_PointCoord in the GS. - int shaderModel = mRenderer->getMajorShaderModel(); - return ((pointSize && shaderModel < 4) ? "COLOR" : "TEXCOORD"); -} - -struct DynamicHLSL::SemanticInfo -{ - struct BuiltinInfo - { - BuiltinInfo() - : enabled(false), - index(0), - systemValue(false) - {} - - bool enabled; - std::string semantic; - unsigned int index; - bool systemValue; - - std::string str() const - { - return (systemValue ? semantic : (semantic + Str(index))); - } - - void enableSystem(const std::string &systemValueSemantic) - { - enabled = true; - semantic = systemValueSemantic; - systemValue = true; - } - - void enable(const std::string &semanticVal, unsigned int indexVal) - { - enabled = true; - semantic = semanticVal; - index = indexVal; - } - }; - - BuiltinInfo dxPosition; - BuiltinInfo glPosition; - BuiltinInfo glFragCoord; - BuiltinInfo glPointCoord; - BuiltinInfo glPointSize; -}; - -DynamicHLSL::SemanticInfo DynamicHLSL::getSemanticInfo(int startRegisters, bool fragCoord, bool pointCoord, - bool pointSize, bool pixelShader) const -{ - SemanticInfo info; - bool hlsl4 = (mRenderer->getMajorShaderModel() >= 4); - const std::string &varyingSemantic = getVaryingSemantic(pointSize); - - int reservedRegisterIndex = startRegisters; - - if (hlsl4) - { - info.dxPosition.enableSystem("SV_Position"); - } - else if (pixelShader) - { - info.dxPosition.enableSystem("VPOS"); - } - else - { - info.dxPosition.enableSystem("POSITION"); - } - - info.glPosition.enable(varyingSemantic, reservedRegisterIndex++); - - if (fragCoord) - { - info.glFragCoord.enable(varyingSemantic, reservedRegisterIndex++); - } - - if (pointCoord) - { - // SM3 reserves the TEXCOORD semantic for point sprite texcoords (gl_PointCoord) - // In D3D11 we manually compute gl_PointCoord in the GS. - if (hlsl4) - { - info.glPointCoord.enable(varyingSemantic, reservedRegisterIndex++); - } - else - { - info.glPointCoord.enable("TEXCOORD", 0); - } - } - - // Special case: do not include PSIZE semantic in HLSL 3 pixel shaders - if (pointSize && (!pixelShader || hlsl4)) - { - info.glPointSize.enableSystem("PSIZE"); - } - - return info; -} - -std::string DynamicHLSL::generateVaryingLinkHLSL(const SemanticInfo &info, const std::string &varyingHLSL) const -{ - std::string linkHLSL = "{\n"; - - ASSERT(info.dxPosition.enabled && info.glPosition.enabled); - - linkHLSL += " float4 dx_Position : " + info.dxPosition.str() + ";\n"; - linkHLSL += " float4 gl_Position : " + info.glPosition.str() + ";\n"; - - if (info.glFragCoord.enabled) - { - linkHLSL += " float4 gl_FragCoord : " + info.glFragCoord.str() + ";\n"; - } - - if (info.glPointCoord.enabled) - { - linkHLSL += " float2 gl_PointCoord : " + info.glPointCoord.str() + ";\n"; - } - - linkHLSL += varyingHLSL; - - if (info.glPointSize.enabled) - { - linkHLSL += " float gl_PointSize : " + info.glPointSize.str() + ";\n"; - } - - linkHLSL += "};\n"; - - return linkHLSL; -} - -void DynamicHLSL::storeBuiltinLinkedVaryings(const SemanticInfo &info, - std::vector *linkedVaryings) const -{ - ASSERT(info.glPosition.enabled); - - linkedVaryings->push_back(LinkedVarying("gl_Position", GL_FLOAT_VEC4, 1, info.glPosition.semantic, - info.glPosition.index, 1)); - - if (info.glFragCoord.enabled) - { - linkedVaryings->push_back(LinkedVarying("gl_FragCoord", GL_FLOAT_VEC4, 1, info.glFragCoord.semantic, - info.glFragCoord.index, 1)); - } - - if (info.glPointSize.enabled) - { - linkedVaryings->push_back(LinkedVarying("gl_PointSize", GL_FLOAT, 1, "PSIZE", 0, 1)); - } -} - -void DynamicHLSL::storeUserLinkedVaryings(const ShaderD3D *vertexShader, - std::vector *linkedVaryings) const -{ - const std::string &varyingSemantic = getVaryingSemantic(vertexShader->mUsesPointSize); - const std::vector &varyings = vertexShader->getVaryings(); - - for (unsigned int varyingIndex = 0; varyingIndex < varyings.size(); varyingIndex++) - { - const PackedVarying &varying = varyings[varyingIndex]; - - if (varying.registerAssigned()) - { - ASSERT(!varying.isBuiltIn()); - GLenum transposedType = TransposeMatrixType(varying.type); - int variableRows = (varying.isStruct() ? 1 : VariableRowCount(transposedType)); - - linkedVaryings->push_back(LinkedVarying(varying.name, varying.type, varying.elementCount(), - varyingSemantic, varying.registerIndex, - variableRows * varying.elementCount())); - } - } -} - -bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data, InfoLog &infoLog, int registers, - const VaryingPacking packing, - std::string &pixelHLSL, std::string &vertexHLSL, - ShaderD3D *fragmentShader, ShaderD3D *vertexShader, - const std::vector &transformFeedbackVaryings, - std::vector *linkedVaryings, - std::map *programOutputVars, - std::vector *outPixelShaderKey, - bool *outUsesFragDepth) const -{ - if (pixelHLSL.empty() || vertexHLSL.empty()) - { - return false; - } - - bool usesMRT = fragmentShader->mUsesMultipleRenderTargets; - bool usesFragColor = fragmentShader->mUsesFragColor; - bool usesFragData = fragmentShader->mUsesFragData; - bool usesFragCoord = fragmentShader->mUsesFragCoord; - bool usesPointCoord = fragmentShader->mUsesPointCoord; - bool usesPointSize = vertexShader->mUsesPointSize; - - if (usesFragColor && usesFragData) - { - infoLog.append("Cannot use both gl_FragColor and gl_FragData in the same fragment shader."); - return false; - } - - // Write the HLSL input/output declarations - const int shaderModel = mRenderer->getMajorShaderModel(); - const int registersNeeded = registers + (usesFragCoord ? 1 : 0) + (usesPointCoord ? 1 : 0); - - // Two cases when writing to gl_FragColor and using ESSL 1.0: - // - with a 3.0 context, the output color is copied to channel 0 - // - with a 2.0 context, the output color is broadcast to all channels - const bool broadcast = (fragmentShader->mUsesFragColor && data.clientVersion < 3); - const unsigned int numRenderTargets = (broadcast || usesMRT ? data.caps->maxDrawBuffers : 1); - - int shaderVersion = vertexShader->getShaderVersion(); - - if (static_cast(registersNeeded) > data.caps->maxVaryingVectors) - { - infoLog.append("No varying registers left to support gl_FragCoord/gl_PointCoord"); - return false; - } - - const std::string &varyingHLSL = generateVaryingHLSL(vertexShader); - const SemanticInfo &vertexSemantics = getSemanticInfo(registers, usesFragCoord, - false, usesPointSize, false); - - storeUserLinkedVaryings(vertexShader, linkedVaryings); - storeBuiltinLinkedVaryings(vertexSemantics, linkedVaryings); - - // Add stub string to be replaced when shader is dynamically defined by its layout - vertexHLSL += "\n" + VERTEX_ATTRIBUTE_STUB_STRING + "\n" - "struct VS_OUTPUT\n" + generateVaryingLinkHLSL(vertexSemantics, varyingHLSL) + "\n" - "VS_OUTPUT main(VS_INPUT input)\n" - "{\n" - " initAttributes(input);\n"; - - if (shaderModel >= 4) - { - vertexHLSL += "\n" - " gl_main();\n" - "\n" - " VS_OUTPUT output;\n" - " output.gl_Position = gl_Position;\n" - " output.dx_Position.x = gl_Position.x;\n" - " output.dx_Position.y = -gl_Position.y;\n" - " output.dx_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n" - " output.dx_Position.w = gl_Position.w;\n"; - } - else - { - vertexHLSL += "\n" - " gl_main();\n" - "\n" - " VS_OUTPUT output;\n" - " output.gl_Position = gl_Position;\n" - " output.dx_Position.x = gl_Position.x * dx_ViewAdjust.z + dx_ViewAdjust.x * gl_Position.w;\n" - " output.dx_Position.y = -(gl_Position.y * dx_ViewAdjust.w + dx_ViewAdjust.y * gl_Position.w);\n" - " output.dx_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n" - " output.dx_Position.w = gl_Position.w;\n"; - } - - if (usesPointSize && shaderModel >= 3) - { - vertexHLSL += " output.gl_PointSize = gl_PointSize;\n"; - } - - if (usesFragCoord) - { - vertexHLSL += " output.gl_FragCoord = gl_Position;\n"; - } - - const std::vector &vertexVaryings = vertexShader->getVaryings(); - for (unsigned int vertVaryingIndex = 0; vertVaryingIndex < vertexVaryings.size(); vertVaryingIndex++) - { - const PackedVarying &varying = vertexVaryings[vertVaryingIndex]; - if (varying.registerAssigned()) - { - for (unsigned int elementIndex = 0; elementIndex < varying.elementCount(); elementIndex++) - { - int variableRows = (varying.isStruct() ? 1 : VariableRowCount(TransposeMatrixType(varying.type))); - - for (int row = 0; row < variableRows; row++) - { - int r = varying.registerIndex + varying.columnIndex * data.caps->maxVaryingVectors + elementIndex * variableRows + row; - vertexHLSL += " output.v" + Str(r); - - vertexHLSL += " = _" + varying.name; - - if (varying.isArray()) - { - vertexHLSL += ArrayString(elementIndex); - } - - if (variableRows > 1) - { - vertexHLSL += ArrayString(row); - } - - vertexHLSL += ";\n"; - } - } - } - } - - vertexHLSL += "\n" - " return output;\n" - "}\n"; - - const SemanticInfo &pixelSemantics = getSemanticInfo(registers, usesFragCoord, usesPointCoord, - usesPointSize, true); - - pixelHLSL += "struct PS_INPUT\n" + generateVaryingLinkHLSL(pixelSemantics, varyingHLSL) + "\n"; - - if (shaderVersion < 300) - { - for (unsigned int renderTargetIndex = 0; renderTargetIndex < numRenderTargets; renderTargetIndex++) - { - PixelShaderOutputVariable outputKeyVariable; - outputKeyVariable.type = GL_FLOAT_VEC4; - outputKeyVariable.name = "gl_Color" + Str(renderTargetIndex); - outputKeyVariable.source = broadcast ? "gl_Color[0]" : "gl_Color[" + Str(renderTargetIndex) + "]"; - outputKeyVariable.outputIndex = renderTargetIndex; - - outPixelShaderKey->push_back(outputKeyVariable); - } - - *outUsesFragDepth = fragmentShader->mUsesFragDepth; - } - else - { - defineOutputVariables(fragmentShader, programOutputVars); - - const std::vector &shaderOutputVars = fragmentShader->getActiveOutputVariables(); - for (auto locationIt = programOutputVars->begin(); locationIt != programOutputVars->end(); locationIt++) - { - const VariableLocation &outputLocation = locationIt->second; - const sh::ShaderVariable &outputVariable = shaderOutputVars[outputLocation.index]; - const std::string &variableName = "out_" + outputLocation.name; - const std::string &elementString = (outputLocation.element == GL_INVALID_INDEX ? "" : Str(outputLocation.element)); - - ASSERT(outputVariable.staticUse); - - PixelShaderOutputVariable outputKeyVariable; - outputKeyVariable.type = outputVariable.type; - outputKeyVariable.name = variableName + elementString; - outputKeyVariable.source = variableName + ArrayString(outputLocation.element); - outputKeyVariable.outputIndex = locationIt->first; - - outPixelShaderKey->push_back(outputKeyVariable); - } - - *outUsesFragDepth = false; - } - - pixelHLSL += PIXEL_OUTPUT_STUB_STRING + "\n"; - - if (fragmentShader->mUsesFrontFacing) - { - 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"; - } - - if (usesFragCoord) - { - pixelHLSL += " float rhw = 1.0 / input.gl_FragCoord.w;\n"; - - if (shaderModel >= 4) - { - pixelHLSL += " gl_FragCoord.x = input.dx_Position.x;\n" - " gl_FragCoord.y = input.dx_Position.y;\n"; - } - else if (shaderModel >= 3) - { - pixelHLSL += " gl_FragCoord.x = input.dx_Position.x + 0.5;\n" - " gl_FragCoord.y = input.dx_Position.y + 0.5;\n"; - } - else - { - // 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_DepthFront.x + dx_DepthFront.y;\n" - " gl_FragCoord.w = rhw;\n"; - } - - if (usesPointCoord && shaderModel >= 3) - { - pixelHLSL += " gl_PointCoord.x = input.gl_PointCoord.x;\n"; - pixelHLSL += " gl_PointCoord.y = 1.0 - input.gl_PointCoord.y;\n"; - } - - if (fragmentShader->mUsesFrontFacing) - { - if (shaderModel <= 3) - { - pixelHLSL += " gl_FrontFacing = (vFace * dx_DepthFront.z >= 0.0);\n"; - } - else - { - pixelHLSL += " gl_FrontFacing = isFrontFace;\n"; - } - } - - const std::vector &fragmentVaryings = fragmentShader->getVaryings(); - for (unsigned int varyingIndex = 0; varyingIndex < fragmentVaryings.size(); varyingIndex++) - { - const PackedVarying &varying = fragmentVaryings[varyingIndex]; - if (varying.registerAssigned()) - { - ASSERT(!varying.isBuiltIn()); - for (unsigned int elementIndex = 0; elementIndex < varying.elementCount(); elementIndex++) - { - GLenum transposedType = TransposeMatrixType(varying.type); - int variableRows = (varying.isStruct() ? 1 : VariableRowCount(transposedType)); - for (int row = 0; row < variableRows; row++) - { - std::string n = Str(varying.registerIndex + varying.columnIndex * data.caps->maxVaryingVectors + elementIndex * variableRows + row); - pixelHLSL += " _" + varying.name; - - if (varying.isArray()) - { - pixelHLSL += ArrayString(elementIndex); - } - - if (variableRows > 1) - { - pixelHLSL += ArrayString(row); - } - - if (varying.isStruct()) - { - pixelHLSL += " = input.v" + n + ";\n"; break; - } - else - { - switch (VariableColumnCount(transposedType)) - { - 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(); - } - } - } - } - } - else - { - ASSERT(varying.isBuiltIn() || !varying.staticUse); - } - } - - pixelHLSL += "\n" - " gl_main();\n" - "\n" - " return generateOutput();\n" - "}\n"; - - return true; -} - -void DynamicHLSL::defineOutputVariables(ShaderD3D *fragmentShader, std::map *programOutputVars) const -{ - const std::vector &shaderOutputVars = fragmentShader->getActiveOutputVariables(); - - for (unsigned int outputVariableIndex = 0; outputVariableIndex < shaderOutputVars.size(); outputVariableIndex++) - { - const sh::Attribute &outputVariable = shaderOutputVars[outputVariableIndex]; - const int baseLocation = outputVariable.location == -1 ? 0 : outputVariable.location; - - ASSERT(outputVariable.staticUse); - - if (outputVariable.arraySize > 0) - { - for (unsigned int elementIndex = 0; elementIndex < outputVariable.arraySize; elementIndex++) - { - const int location = baseLocation + elementIndex; - ASSERT(programOutputVars->count(location) == 0); - (*programOutputVars)[location] = VariableLocation(outputVariable.name, elementIndex, outputVariableIndex); - } - } - else - { - ASSERT(programOutputVars->count(baseLocation) == 0); - (*programOutputVars)[baseLocation] = VariableLocation(outputVariable.name, GL_INVALID_INDEX, outputVariableIndex); - } - } -} - -std::string DynamicHLSL::generateGeometryShaderHLSL(int registers, ShaderD3D *fragmentShader, ShaderD3D *vertexShader) const -{ - // for now we only handle point sprite emulation - ASSERT(vertexShader->mUsesPointSize && mRenderer->getMajorShaderModel() >= 4); - return generatePointSpriteHLSL(registers, fragmentShader, vertexShader); -} - -std::string DynamicHLSL::generatePointSpriteHLSL(int registers, ShaderD3D *fragmentShader, ShaderD3D *vertexShader) const -{ - ASSERT(registers >= 0); - ASSERT(vertexShader->mUsesPointSize); - ASSERT(mRenderer->getMajorShaderModel() >= 4); - - std::string geomHLSL; - - const SemanticInfo &inSemantics = getSemanticInfo(registers, fragmentShader->mUsesFragCoord, - false, true, false); - const SemanticInfo &outSemantics = getSemanticInfo(registers, fragmentShader->mUsesFragCoord, - fragmentShader->mUsesPointCoord, true, false); - - std::string varyingHLSL = generateVaryingHLSL(vertexShader); - std::string inLinkHLSL = generateVaryingLinkHLSL(inSemantics, varyingHLSL); - std::string outLinkHLSL = generateVaryingLinkHLSL(outSemantics, varyingHLSL); - - // TODO(geofflang): use context's caps - geomHLSL += "uniform float4 dx_ViewCoords : register(c1);\n" - "\n" - "struct GS_INPUT\n" + inLinkHLSL + "\n" + - "struct GS_OUTPUT\n" + outLinkHLSL + "\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(mRenderer->getRendererCaps().minAliasedPointSize) + ".0f;\n" - "static float maxPointSize = " + Str(mRenderer->getRendererCaps().maxAliasedPointSize) + ".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_Position = input[0].gl_Position;\n" - " output.gl_PointSize = input[0].gl_PointSize;\n"; - - for (int r = 0; r < registers; r++) - { - geomHLSL += " output.v" + Str(r) + " = input[0].v" + Str(r) + ";\n"; - } - - if (fragmentShader->mUsesFragCoord) - { - geomHLSL += " output.gl_FragCoord = input[0].gl_FragCoord;\n"; - } - - geomHLSL += " \n" - " float gl_PointSize = clamp(input[0].gl_PointSize, minPointSize, maxPointSize);\n" - " float4 dx_Position = input[0].dx_Position;\n" - " float2 viewportScale = float2(1.0f / dx_ViewCoords.x, 1.0f / dx_ViewCoords.y) * dx_Position.w;\n"; - - for (int corner = 0; corner < 4; corner++) - { - geomHLSL += " \n" - " output.dx_Position = dx_Position + float4(pointSpriteCorners[" + Str(corner) + "] * viewportScale * gl_PointSize, 0.0f, 0.0f);\n"; - - if (fragmentShader->mUsesPointCoord) - { - geomHLSL += " output.gl_PointCoord = pointSpriteTexcoords[" + Str(corner) + "];\n"; - } - - geomHLSL += " outStream.Append(output);\n"; - } - - geomHLSL += " \n" - " outStream.RestartStrip();\n" - "}\n"; - - return geomHLSL; -} - -// This method needs to match OutputHLSL::decorate -std::string DynamicHLSL::decorateVariable(const std::string &name) -{ - if (name.compare(0, 3, "gl_") != 0) - { - return "_" + name; - } - - return name; -} - -std::string DynamicHLSL::generateAttributeConversionHLSL(const VertexFormat &vertexFormat, const sh::ShaderVariable &shaderAttrib) const -{ - std::string attribString = "input." + decorateVariable(shaderAttrib.name); - - // Matrix - if (IsMatrixType(shaderAttrib.type)) - { - return "transpose(" + attribString + ")"; - } - - GLenum shaderComponentType = VariableComponentType(shaderAttrib.type); - int shaderComponentCount = VariableComponentCount(shaderAttrib.type); - - // Perform integer to float conversion (if necessary) - bool requiresTypeConversion = (shaderComponentType == GL_FLOAT && vertexFormat.mType != GL_FLOAT); - - if (requiresTypeConversion) - { - // TODO: normalization for 32-bit integer formats - ASSERT(!vertexFormat.mNormalized && !vertexFormat.mPureInteger); - return "float" + Str(shaderComponentCount) + "(" + attribString + ")"; - } - - // No conversion necessary - return attribString; -} - -void DynamicHLSL::getInputLayoutSignature(const VertexFormat inputLayout[], GLenum signature[]) const -{ - for (size_t inputIndex = 0; inputIndex < MAX_VERTEX_ATTRIBS; inputIndex++) - { - const VertexFormat &vertexFormat = inputLayout[inputIndex]; - - if (vertexFormat.mType == GL_NONE) - { - signature[inputIndex] = GL_NONE; - } - else - { - bool gpuConverted = ((mRenderer->getVertexConversionType(vertexFormat) & VERTEX_CONVERT_GPU) != 0); - signature[inputIndex] = (gpuConverted ? GL_TRUE : GL_FALSE); - } - } -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/DynamicHLSL.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/DynamicHLSL.h deleted file mode 100644 index c46bbf6ce0..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/DynamicHLSL.h +++ /dev/null @@ -1,101 +0,0 @@ -// -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// DynamicHLSL.h: Interface for link and run-time HLSL generation -// - -#ifndef LIBGLESV2_RENDERER_DYNAMIC_HLSL_H_ -#define LIBGLESV2_RENDERER_DYNAMIC_HLSL_H_ - -#include "common/angleutils.h" -#include "libGLESv2/Constants.h" - -#include "angle_gl.h" - -#include -#include - -namespace sh -{ -struct Attribute; -struct ShaderVariable; -} - -namespace gl -{ -class InfoLog; -struct VariableLocation; -struct LinkedVarying; -struct VertexAttribute; -struct VertexFormat; -struct PackedVarying; -struct Data; -} - -namespace rx -{ -class RendererD3D; -class ShaderD3D; - -typedef const gl::PackedVarying *VaryingPacking[gl::IMPLEMENTATION_MAX_VARYING_VECTORS][4]; - -struct PixelShaderOutputVariable -{ - GLenum type; - std::string name; - std::string source; - size_t outputIndex; -}; - -class DynamicHLSL -{ - public: - explicit DynamicHLSL(RendererD3D *const renderer); - - int packVaryings(gl::InfoLog &infoLog, VaryingPacking packing, ShaderD3D *fragmentShader, - ShaderD3D *vertexShader, const std::vector& transformFeedbackVaryings); - std::string generateVertexShaderForInputLayout(const std::string &sourceShader, const gl::VertexFormat inputLayout[], - const sh::Attribute shaderAttributes[]) const; - std::string generatePixelShaderForOutputSignature(const std::string &sourceShader, const std::vector &outputVariables, - bool usesFragDepth, const std::vector &outputLayout) const; - bool generateShaderLinkHLSL(const gl::Data &data, gl::InfoLog &infoLog, int registers, - const VaryingPacking packing, - std::string &pixelHLSL, std::string &vertexHLSL, - ShaderD3D *fragmentShader, ShaderD3D *vertexShader, - const std::vector &transformFeedbackVaryings, - std::vector *linkedVaryings, - std::map *programOutputVars, - std::vector *outPixelShaderKey, - bool *outUsesFragDepth) const; - - std::string generateGeometryShaderHLSL(int registers, ShaderD3D *fragmentShader, ShaderD3D *vertexShader) const; - void getInputLayoutSignature(const gl::VertexFormat inputLayout[], GLenum signature[]) const; - - private: - DISALLOW_COPY_AND_ASSIGN(DynamicHLSL); - - RendererD3D *const mRenderer; - - struct SemanticInfo; - - std::string getVaryingSemantic(bool pointSize) const; - SemanticInfo getSemanticInfo(int startRegisters, bool fragCoord, bool pointCoord, bool pointSize, - bool pixelShader) const; - std::string generateVaryingLinkHLSL(const SemanticInfo &info, const std::string &varyingHLSL) const; - std::string generateVaryingHLSL(const ShaderD3D *shader) const; - void storeUserLinkedVaryings(const ShaderD3D *vertexShader, std::vector *linkedVaryings) const; - void storeBuiltinLinkedVaryings(const SemanticInfo &info, std::vector *linkedVaryings) const; - void defineOutputVariables(ShaderD3D *fragmentShader, std::map *programOutputVars) const; - std::string generatePointSpriteHLSL(int registers, ShaderD3D *fragmentShader, ShaderD3D *vertexShader) const; - - // Prepend an underscore - static std::string decorateVariable(const std::string &name); - - std::string generateAttributeConversionHLSL(const gl::VertexFormat &vertexFormat, const sh::ShaderVariable &shaderAttrib) const; -}; - -} - -#endif // LIBGLESV2_RENDERER_DYNAMIC_HLSL_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp deleted file mode 100644 index 776d92b202..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp +++ /dev/null @@ -1,333 +0,0 @@ -// -// Copyright 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "libGLESv2/renderer/d3d/HLSLCompiler.h" -#include "libGLESv2/Program.h" -#include "libGLESv2/main.h" - -#include "common/features.h" -#include "common/utilities.h" - -#ifndef QT_D3DCOMPILER_DLL -#define QT_D3DCOMPILER_DLL D3DCOMPILER_DLL -#endif -#ifndef D3DCOMPILE_RESERVED16 -#define D3DCOMPILE_RESERVED16 (1 << 16) -#endif -#ifndef D3DCOMPILE_RESERVED17 -#define D3DCOMPILE_RESERVED17 (1 << 17) -#endif - -// Definitions local to the translation unit -namespace -{ - -#ifdef CREATE_COMPILER_FLAG_INFO - #undef CREATE_COMPILER_FLAG_INFO -#endif - -#define CREATE_COMPILER_FLAG_INFO(flag) { flag, #flag } - -struct CompilerFlagInfo -{ - UINT mFlag; - const char *mName; -}; - -CompilerFlagInfo CompilerFlagInfos[] = -{ - // NOTE: The data below is copied from d3dcompiler.h - // If something changes there it should be changed here as well - CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_DEBUG), // (1 << 0) - CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_SKIP_VALIDATION), // (1 << 1) - CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_SKIP_OPTIMIZATION), // (1 << 2) - CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_PACK_MATRIX_ROW_MAJOR), // (1 << 3) - CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_PACK_MATRIX_COLUMN_MAJOR), // (1 << 4) - CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_PARTIAL_PRECISION), // (1 << 5) - CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_FORCE_VS_SOFTWARE_NO_OPT), // (1 << 6) - CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_FORCE_PS_SOFTWARE_NO_OPT), // (1 << 7) - CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_NO_PRESHADER), // (1 << 8) - CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_AVOID_FLOW_CONTROL), // (1 << 9) - CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_PREFER_FLOW_CONTROL), // (1 << 10) - CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_ENABLE_STRICTNESS), // (1 << 11) - CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_ENABLE_BACKWARDS_COMPATIBILITY), // (1 << 12) - CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_IEEE_STRICTNESS), // (1 << 13) - CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_OPTIMIZATION_LEVEL0), // (1 << 14) - CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_OPTIMIZATION_LEVEL1), // 0 - CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_OPTIMIZATION_LEVEL2), // ((1 << 14) | (1 << 15)) - CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_OPTIMIZATION_LEVEL3), // (1 << 15) - CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_RESERVED16), // (1 << 16) - CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_RESERVED17), // (1 << 17) - CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_WARNINGS_ARE_ERRORS) // (1 << 18) -}; - -#undef CREATE_COMPILER_FLAG_INFO - -bool IsCompilerFlagSet(UINT mask, UINT flag) -{ - bool isFlagSet = IsMaskFlagSet(mask, flag); - - switch(flag) - { - case D3DCOMPILE_OPTIMIZATION_LEVEL0: - return isFlagSet && !IsMaskFlagSet(mask, UINT(D3DCOMPILE_OPTIMIZATION_LEVEL3)); - - case D3DCOMPILE_OPTIMIZATION_LEVEL1: - return (mask & D3DCOMPILE_OPTIMIZATION_LEVEL2) == UINT(0); - - case D3DCOMPILE_OPTIMIZATION_LEVEL3: - return isFlagSet && !IsMaskFlagSet(mask, UINT(D3DCOMPILE_OPTIMIZATION_LEVEL0)); - - default: - return isFlagSet; - } -} - -const char *GetCompilerFlagName(UINT mask, size_t flagIx) -{ - const CompilerFlagInfo &flagInfo = CompilerFlagInfos[flagIx]; - if (IsCompilerFlagSet(mask, flagInfo.mFlag)) - { - return flagInfo.mName; - } - - return nullptr; -} - -} - -namespace rx -{ - -CompileConfig::CompileConfig() - : flags(0), - name() -{ -} - -CompileConfig::CompileConfig(UINT flags, const std::string &name) - : flags(flags), - name(name) -{ -} - -HLSLCompiler::HLSLCompiler() - : mD3DCompilerModule(NULL), - mD3DCompileFunc(NULL), - mD3DDisassembleFunc(NULL) -{ -} - -HLSLCompiler::~HLSLCompiler() -{ - release(); -} - -bool HLSLCompiler::initialize() -{ -#if !defined(ANGLE_ENABLE_WINDOWS_STORE) -#if defined(ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES) - // Find a D3DCompiler module that had already been loaded based on a predefined list of versions. - static const char *d3dCompilerNames[] = ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES; - - for (size_t i = 0; i < ArraySize(d3dCompilerNames); ++i) - { - if (GetModuleHandleExA(0, d3dCompilerNames[i], &mD3DCompilerModule)) - { - break; - } - } -#endif // ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES - - // Load the compiler DLL specified by the environment, or default to QT_D3DCOMPILER_DLL - const wchar_t *defaultCompiler = _wgetenv(L"QT_D3DCOMPILER_DLL"); - if (!defaultCompiler) - defaultCompiler = QT_D3DCOMPILER_DLL; - - const wchar_t *compilerDlls[] = { - defaultCompiler, - L"d3dcompiler_47.dll", - L"d3dcompiler_46.dll", - L"d3dcompiler_45.dll", - L"d3dcompiler_44.dll", - L"d3dcompiler_43.dll", - 0 - }; - - // Load the first available known compiler DLL - for (int i = 0; compilerDlls[i]; ++i) - { - mD3DCompilerModule = LoadLibrary(compilerDlls[i]); - if (mD3DCompilerModule) - break; - } - - if (!mD3DCompilerModule) - { - // Load the version of the D3DCompiler DLL associated with the Direct3D version ANGLE was built with. - mD3DCompilerModule = LoadLibrary(D3DCOMPILER_DLL); - } - - if (!mD3DCompilerModule) - { - ERR("No D3D compiler module found - aborting!\n"); - return false; - } - - mD3DCompileFunc = reinterpret_cast(GetProcAddress(mD3DCompilerModule, "D3DCompile")); - ASSERT(mD3DCompileFunc); - - mD3DDisassembleFunc = reinterpret_cast(GetProcAddress(mD3DCompilerModule, "D3DDisassemble")); - ASSERT(mD3DDisassembleFunc); - -#else - // D3D Shader compiler is linked already into this module, so the export - // can be directly assigned. - mD3DCompilerModule = NULL; - mD3DCompileFunc = reinterpret_cast(D3DCompile); - mD3DDisassembleFunc = reinterpret_cast(D3DDisassemble); -#endif - - return mD3DCompileFunc != NULL; -} - -void HLSLCompiler::release() -{ - if (mD3DCompilerModule) - { - FreeLibrary(mD3DCompilerModule); - mD3DCompilerModule = NULL; - mD3DCompileFunc = NULL; - mD3DDisassembleFunc = NULL; - } -} - -gl::Error HLSLCompiler::compileToBinary(gl::InfoLog &infoLog, const std::string &hlsl, const std::string &profile, - const std::vector &configs, const D3D_SHADER_MACRO *overrideMacros, - ID3DBlob **outCompiledBlob, std::string *outDebugInfo) const -{ -#if !defined(ANGLE_ENABLE_WINDOWS_STORE) - ASSERT(mD3DCompilerModule); -#endif - ASSERT(mD3DCompileFunc); - -#if !defined(ANGLE_ENABLE_WINDOWS_STORE) - if (gl::perfActive()) - { - std::string sourcePath = getTempPath(); - std::string sourceText = FormatString("#line 2 \"%s\"\n\n%s", sourcePath.c_str(), hlsl.c_str()); - writeFile(sourcePath.c_str(), sourceText.c_str(), sourceText.size()); - } -#endif - - const D3D_SHADER_MACRO *macros = overrideMacros ? overrideMacros : NULL; - - for (size_t i = 0; i < configs.size(); ++i) - { - ID3DBlob *errorMessage = NULL; - ID3DBlob *binary = NULL; - - HRESULT result = mD3DCompileFunc(hlsl.c_str(), hlsl.length(), gl::g_fakepath, macros, NULL, "main", profile.c_str(), - configs[i].flags, 0, &binary, &errorMessage); - - if (errorMessage) - { - std::string message = reinterpret_cast(errorMessage->GetBufferPointer()); - SafeRelease(errorMessage); - - infoLog.appendSanitized(message.c_str()); - TRACE("\n%s", hlsl.c_str()); - TRACE("\n%s", message.c_str()); - - if (message.find("error X3531:") != std::string::npos) // "can't unroll loops marked with loop attribute" - { - macros = NULL; // Disable [loop] and [flatten] - - // Retry without changing compiler flags - i--; - continue; - } - } - - if (SUCCEEDED(result)) - { - *outCompiledBlob = binary; - -#if ANGLE_SHADER_DEBUG_INFO == ANGLE_ENABLED - (*outDebugInfo) += "// COMPILER INPUT HLSL BEGIN\n\n" + hlsl + "\n// COMPILER INPUT HLSL END\n"; - (*outDebugInfo) += "\n\n// ASSEMBLY BEGIN\n\n"; - (*outDebugInfo) += "// Compiler configuration: " + configs[i].name + "\n// Flags:\n"; - for (size_t fIx = 0; fIx < ArraySize(CompilerFlagInfos); ++fIx) - { - const char *flagName = GetCompilerFlagName(configs[i].flags, fIx); - if (flagName != nullptr) - { - (*outDebugInfo) += std::string("// ") + flagName + "\n"; - } - } - - (*outDebugInfo) += "// Macros:\n"; - if (macros == nullptr) - { - (*outDebugInfo) += "// - : -\n"; - } - else - { - for (const D3D_SHADER_MACRO *mIt = macros; mIt->Name != nullptr; ++mIt) - { - (*outDebugInfo) += std::string("// ") + mIt->Name + " : " + mIt->Definition + "\n"; - } - } - - (*outDebugInfo) += "\n" + disassembleBinary(binary) + "\n// ASSEMBLY END\n"; -#endif - - return gl::Error(GL_NO_ERROR); - } - else - { - if (result == E_OUTOFMEMORY) - { - *outCompiledBlob = NULL; - return gl::Error(GL_OUT_OF_MEMORY, "HLSL compiler had an unexpected failure, result: 0x%X.", result); - } - - infoLog.append("Warning: D3D shader compilation failed with %s flags.", configs[i].name.c_str()); - - if (i + 1 < configs.size()) - { - infoLog.append(" Retrying with %s.\n", configs[i + 1].name.c_str()); - } - } - } - - // None of the configurations succeeded in compiling this shader but the compiler is still intact - *outCompiledBlob = NULL; - return gl::Error(GL_NO_ERROR); -} - -std::string HLSLCompiler::disassembleBinary(ID3DBlob *shaderBinary) const -{ - // Retrieve disassembly - UINT flags = D3D_DISASM_ENABLE_DEFAULT_VALUE_PRINTS | D3D_DISASM_ENABLE_INSTRUCTION_NUMBERING; - ID3DBlob *disassembly = NULL; - pD3DDisassemble disassembleFunc = reinterpret_cast(mD3DDisassembleFunc); - LPCVOID buffer = shaderBinary->GetBufferPointer(); - SIZE_T bufSize = shaderBinary->GetBufferSize(); - HRESULT result = disassembleFunc(buffer, bufSize, flags, "", &disassembly); - - std::string asmSrc; - if (SUCCEEDED(result)) - { - asmSrc = reinterpret_cast(disassembly->GetBufferPointer()); - } - - SafeRelease(disassembly); - - return asmSrc; -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.h deleted file mode 100644 index ff56f8035a..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef LIBGLESV2_RENDERER_HLSL_D3DCOMPILER_H_ -#define LIBGLESV2_RENDERER_HLSL_D3DCOMPILER_H_ - -#include "libGLESv2/Error.h" - -#include "common/angleutils.h" -#include "common/platform.h" - -#include -#include - -namespace gl -{ -class InfoLog; -} - -namespace rx -{ - -struct CompileConfig -{ - UINT flags; - std::string name; - - CompileConfig(); - CompileConfig(UINT flags, const std::string &name); -}; - -class HLSLCompiler -{ - public: - HLSLCompiler(); - ~HLSLCompiler(); - - bool initialize(); - void release(); - - // Attempt to compile a HLSL shader using the supplied configurations, may output a NULL compiled blob - // even if no GL errors are returned. - gl::Error compileToBinary(gl::InfoLog &infoLog, const std::string &hlsl, const std::string &profile, - const std::vector &configs, const D3D_SHADER_MACRO *overrideMacros, - ID3DBlob **outCompiledBlob, std::string *outDebugInfo) const; - - std::string disassembleBinary(ID3DBlob* shaderBinary) const; - - private: - DISALLOW_COPY_AND_ASSIGN(HLSLCompiler); - - HMODULE mD3DCompilerModule; - pD3DCompile mD3DCompileFunc; - pD3DDisassemble mD3DDisassembleFunc; -}; - -} - -#endif // LIBGLESV2_RENDERER_HLSL_D3DCOMPILER_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ImageD3D.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ImageD3D.cpp deleted file mode 100644 index 12b919ab5a..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ImageD3D.cpp +++ /dev/null @@ -1,26 +0,0 @@ -// -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// 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/d3d/ImageD3D.h" - -namespace rx -{ - -ImageD3D::ImageD3D() -{ -} - -ImageD3D *ImageD3D::makeImageD3D(Image *img) -{ - ASSERT(HAS_DYNAMIC_TYPE(ImageD3D*, img)); - return static_cast(img); -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ImageD3D.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ImageD3D.h deleted file mode 100644 index 554ca0cee0..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ImageD3D.h +++ /dev/null @@ -1,50 +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. -// - -// 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_IMAGED3D_H_ -#define LIBGLESV2_RENDERER_IMAGED3D_H_ - -#include "common/debug.h" -#include "libGLESv2/renderer/Image.h" - -namespace gl -{ -class Framebuffer; -struct ImageIndex; -struct Box; -} - -namespace rx -{ -class TextureStorage; - -class ImageD3D : public Image -{ - public: - ImageD3D(); - virtual ~ImageD3D() {}; - - static ImageD3D *makeImageD3D(Image *img); - - virtual bool isDirty() const = 0; - - virtual gl::Error setManagedSurface2D(TextureStorage *storage, int level) { return gl::Error(GL_NO_ERROR); }; - virtual gl::Error setManagedSurfaceCube(TextureStorage *storage, int face, int level) { return gl::Error(GL_NO_ERROR); }; - virtual gl::Error setManagedSurface3D(TextureStorage *storage, int level) { return gl::Error(GL_NO_ERROR); }; - virtual gl::Error setManagedSurface2DArray(TextureStorage *storage, int layer, int level) { return gl::Error(GL_NO_ERROR); }; - virtual gl::Error copyToStorage(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box ®ion) = 0; - - private: - DISALLOW_COPY_AND_ASSIGN(ImageD3D); -}; - -} - -#endif // LIBGLESV2_RENDERER_IMAGED3D_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexBuffer.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexBuffer.cpp deleted file mode 100644 index aa614f6cc4..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexBuffer.cpp +++ /dev/null @@ -1,199 +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. -// - -// IndexBuffer.cpp: Defines the abstract IndexBuffer class and IndexBufferInterface -// class with derivations, classes that perform graphics API agnostic index buffer operations. - -#include "libGLESv2/renderer/d3d/IndexBuffer.h" -#include "libGLESv2/renderer/d3d/RendererD3D.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(RendererD3D *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(); -} - -gl::Error IndexBufferInterface::mapBuffer(unsigned int size, void** outMappedMemory, unsigned int *streamOffset) -{ - // Protect against integer overflow - if (mWritePosition + size < mWritePosition) - { - return gl::Error(GL_OUT_OF_MEMORY, "Mapping of internal index buffer would cause an integer overflow."); - } - - gl::Error error = mIndexBuffer->mapBuffer(mWritePosition, size, outMappedMemory); - if (error.isError()) - { - if (outMappedMemory) - { - *outMappedMemory = NULL; - } - return error; - } - - if (streamOffset) - { - *streamOffset = mWritePosition; - } - - mWritePosition += size; - return gl::Error(GL_NO_ERROR); -} - -gl::Error 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; -} - -gl::Error IndexBufferInterface::discard() -{ - return mIndexBuffer->discard(); -} - -gl::Error 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(RendererD3D *renderer) : IndexBufferInterface(renderer, true) -{ -} - -StreamingIndexBufferInterface::~StreamingIndexBufferInterface() -{ -} - -gl::Error StreamingIndexBufferInterface::reserveBufferSpace(unsigned int size, GLenum indexType) -{ - unsigned int curBufferSize = getBufferSize(); - unsigned int writePos = getWritePosition(); - if (size > curBufferSize) - { - gl::Error error = setBufferSize(std::max(size, 2 * curBufferSize), indexType); - if (error.isError()) - { - return error; - } - setWritePosition(0); - } - else if (writePos + size > curBufferSize || writePos + size < writePos) - { - gl::Error error = discard(); - if (error.isError()) - { - return error; - } - setWritePosition(0); - } - - return gl::Error(GL_NO_ERROR); -} - - -StaticIndexBufferInterface::StaticIndexBufferInterface(RendererD3D *renderer) : IndexBufferInterface(renderer, false) -{ -} - -StaticIndexBufferInterface::~StaticIndexBufferInterface() -{ -} - -gl::Error 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 gl::Error(GL_NO_ERROR); - } - else - { - UNREACHABLE(); - return gl::Error(GL_INVALID_OPERATION, "Internal static index buffers can't be resized"); - } -} - -IndexRangeCache *StaticIndexBufferInterface::getIndexRangeCache() -{ - return &mIndexRangeCache; -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexBuffer.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexBuffer.h deleted file mode 100644 index a34d30bbf3..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexBuffer.h +++ /dev/null @@ -1,112 +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. -// - -// 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" -#include "libGLESv2/Error.h" -#include "libGLESv2/renderer/IndexRangeCache.h" - -namespace rx -{ -class RendererD3D; - -class IndexBuffer -{ - public: - IndexBuffer(); - virtual ~IndexBuffer(); - - virtual gl::Error initialize(unsigned int bufferSize, GLenum indexType, bool dynamic) = 0; - - virtual gl::Error mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory) = 0; - virtual gl::Error unmapBuffer() = 0; - - virtual gl::Error discard() = 0; - - virtual GLenum getIndexType() const = 0; - virtual unsigned int getBufferSize() const = 0; - virtual gl::Error 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(RendererD3D *renderer, bool dynamic); - virtual ~IndexBufferInterface(); - - virtual gl::Error reserveBufferSpace(unsigned int size, GLenum indexType) = 0; - - GLenum getIndexType() const; - unsigned int getBufferSize() const; - - unsigned int getSerial() const; - - gl::Error mapBuffer(unsigned int size, void** outMappedMemory, unsigned int *streamOffset); - gl::Error unmapBuffer(); - - IndexBuffer *getIndexBuffer() const; - - protected: - unsigned int getWritePosition() const; - void setWritePosition(unsigned int writePosition); - - gl::Error discard(); - - gl::Error setBufferSize(unsigned int bufferSize, GLenum indexType); - - private: - DISALLOW_COPY_AND_ASSIGN(IndexBufferInterface); - - RendererD3D *const mRenderer; - - IndexBuffer* mIndexBuffer; - - unsigned int mWritePosition; - bool mDynamic; -}; - -class StreamingIndexBufferInterface : public IndexBufferInterface -{ - public: - StreamingIndexBufferInterface(RendererD3D *renderer); - ~StreamingIndexBufferInterface(); - - virtual gl::Error reserveBufferSpace(unsigned int size, GLenum indexType); -}; - -class StaticIndexBufferInterface : public IndexBufferInterface -{ - public: - explicit StaticIndexBufferInterface(RendererD3D *renderer); - ~StaticIndexBufferInterface(); - - virtual gl::Error reserveBufferSpace(unsigned int size, GLenum indexType); - - IndexRangeCache *getIndexRangeCache(); - - private: - IndexRangeCache mIndexRangeCache; -}; - -} - -#endif // LIBGLESV2_RENDERER_INDEXBUFFER_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexDataManager.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexDataManager.cpp deleted file mode 100644 index eddd9de887..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexDataManager.cpp +++ /dev/null @@ -1,271 +0,0 @@ -// -// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// IndexDataManager.cpp: Defines the IndexDataManager, a class that -// runs the Buffer translation process for index buffers. - -#include "libGLESv2/renderer/d3d/IndexDataManager.h" -#include "libGLESv2/renderer/d3d/BufferD3D.h" -#include "libGLESv2/renderer/d3d/IndexBuffer.h" -#include "libGLESv2/renderer/d3d/RendererD3D.h" -#include "libGLESv2/Buffer.h" -#include "libGLESv2/main.h" -#include "libGLESv2/formatutils.h" - -namespace rx -{ - -static void ConvertIndices(GLenum sourceType, GLenum destinationType, const void *input, GLsizei count, void *output) -{ - if (sourceType == GL_UNSIGNED_BYTE) - { - ASSERT(destinationType == GL_UNSIGNED_SHORT); - const GLubyte *in = static_cast(input); - GLushort *out = static_cast(output); - - for (GLsizei i = 0; i < count; i++) - { - out[i] = in[i]; - } - } - else if (sourceType == GL_UNSIGNED_INT) - { - ASSERT(destinationType == GL_UNSIGNED_INT); - memcpy(output, input, count * sizeof(GLuint)); - } - else if (sourceType == GL_UNSIGNED_SHORT) - { - if (destinationType == GL_UNSIGNED_SHORT) - { - memcpy(output, input, count * sizeof(GLushort)); - } - else if (destinationType == GL_UNSIGNED_INT) - { - const GLushort *in = static_cast(input); - GLuint *out = static_cast(output); - - for (GLsizei i = 0; i < count; i++) - { - out[i] = in[i]; - } - } - else UNREACHABLE(); - } - else UNREACHABLE(); -} - -IndexDataManager::IndexDataManager(RendererD3D *renderer) - : mRenderer(renderer), - mStreamingBufferShort(NULL), - mStreamingBufferInt(NULL) -{ -} - -IndexDataManager::~IndexDataManager() -{ - SafeDelete(mStreamingBufferShort); - SafeDelete(mStreamingBufferInt); -} - -gl::Error IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer *buffer, const GLvoid *indices, TranslatedIndexData *translated) -{ - const gl::Type &typeInfo = gl::GetTypeInfo(type); - - GLenum destinationIndexType = (type == GL_UNSIGNED_INT) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT; - - unsigned int offset = 0; - bool alignedOffset = false; - - BufferD3D *storage = NULL; - - if (buffer != NULL) - { - offset = static_cast(reinterpret_cast(indices)); - - storage = BufferD3D::makeBufferD3D(buffer->getImplementation()); - - 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; - } - - ASSERT(typeInfo.bytes * static_cast(count) + offset <= storage->getSize()); - - const uint8_t *bufferData = NULL; - gl::Error error = storage->getData(&bufferData); - if (error.isError()) - { - return error; - } - - indices = bufferData + offset; - } - - StaticIndexBufferInterface *staticBuffer = storage ? storage->getStaticIndexBuffer() : NULL; - IndexBufferInterface *indexBuffer = NULL; - bool directStorage = alignedOffset && storage && storage->supportsDirectBinding() && - destinationIndexType == type; - unsigned int streamOffset = 0; - - if (directStorage) - { - streamOffset = offset; - - if (!buffer->getIndexRangeCache()->findRange(type, offset, count, NULL, NULL)) - { - buffer->getIndexRangeCache()->addRange(type, offset, count, translated->indexRange, offset); - } - } - else if (staticBuffer && staticBuffer->getBufferSize() != 0 && staticBuffer->getIndexType() == type && alignedOffset) - { - indexBuffer = staticBuffer; - - if (!staticBuffer->getIndexRangeCache()->findRange(type, offset, count, NULL, &streamOffset)) - { - streamOffset = (offset / typeInfo.bytes) * gl::GetTypeInfo(destinationIndexType).bytes; - staticBuffer->getIndexRangeCache()->addRange(type, offset, count, translated->indexRange, streamOffset); - } - } - - // Avoid D3D11's primitive restart index value - // see http://msdn.microsoft.com/en-us/library/windows/desktop/bb205124(v=vs.85).aspx - if (translated->indexRange.end == 0xFFFF && type == GL_UNSIGNED_SHORT && mRenderer->getMajorShaderModel() > 3) - { - destinationIndexType = GL_UNSIGNED_INT; - directStorage = false; - indexBuffer = NULL; - } - - const gl::Type &destTypeInfo = gl::GetTypeInfo(destinationIndexType); - - if (!directStorage && !indexBuffer) - { - gl::Error error = getStreamingIndexBuffer(destinationIndexType, &indexBuffer); - if (error.isError()) - { - return error; - } - - unsigned int convertCount = count; - - if (staticBuffer) - { - if (staticBuffer->getBufferSize() == 0 && alignedOffset) - { - indexBuffer = staticBuffer; - convertCount = storage->getSize() / typeInfo.bytes; - } - else - { - storage->invalidateStaticData(); - staticBuffer = NULL; - } - } - - ASSERT(indexBuffer); - - if (convertCount > std::numeric_limits::max() / destTypeInfo.bytes) - { - return gl::Error(GL_OUT_OF_MEMORY, "Reserving %u indices of %u bytes each exceeds the maximum buffer size.", - convertCount, destTypeInfo.bytes); - } - - unsigned int bufferSizeRequired = convertCount * destTypeInfo.bytes; - error = indexBuffer->reserveBufferSpace(bufferSizeRequired, type); - if (error.isError()) - { - return error; - } - - void* output = NULL; - error = indexBuffer->mapBuffer(bufferSizeRequired, &output, &streamOffset); - if (error.isError()) - { - return error; - } - - const uint8_t *dataPointer = reinterpret_cast(indices); - if (staticBuffer) - { - error = storage->getData(&dataPointer); - if (error.isError()) - { - return error; - } - } - ConvertIndices(type, destinationIndexType, dataPointer, convertCount, output); - - error = indexBuffer->unmapBuffer(); - if (error.isError()) - { - return error; - } - - if (staticBuffer) - { - streamOffset = (offset / typeInfo.bytes) * destTypeInfo.bytes; - staticBuffer->getIndexRangeCache()->addRange(type, offset, count, translated->indexRange, streamOffset); - } - } - - translated->storage = directStorage ? storage : NULL; - translated->indexBuffer = indexBuffer ? indexBuffer->getIndexBuffer() : NULL; - translated->serial = directStorage ? storage->getSerial() : indexBuffer->getSerial(); - translated->startIndex = streamOffset / destTypeInfo.bytes; - translated->startOffset = streamOffset; - translated->indexType = destinationIndexType; - - if (storage) - { - storage->promoteStaticUsage(count * typeInfo.bytes); - } - - return gl::Error(GL_NO_ERROR); -} - -gl::Error IndexDataManager::getStreamingIndexBuffer(GLenum destinationIndexType, IndexBufferInterface **outBuffer) -{ - ASSERT(outBuffer); - if (destinationIndexType == GL_UNSIGNED_INT) - { - if (!mStreamingBufferInt) - { - mStreamingBufferInt = new StreamingIndexBufferInterface(mRenderer); - gl::Error error = mStreamingBufferInt->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT); - if (error.isError()) - { - SafeDelete(mStreamingBufferInt); - return error; - } - } - - *outBuffer = mStreamingBufferInt; - return gl::Error(GL_NO_ERROR); - } - else - { - ASSERT(destinationIndexType == GL_UNSIGNED_SHORT); - - if (!mStreamingBufferShort) - { - mStreamingBufferShort = new StreamingIndexBufferInterface(mRenderer); - gl::Error error = mStreamingBufferShort->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_SHORT); - if (error.isError()) - { - SafeDelete(mStreamingBufferShort); - return error; - } - } - - *outBuffer = mStreamingBufferShort; - return gl::Error(GL_NO_ERROR); - } -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexDataManager.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexDataManager.h deleted file mode 100644 index a1aee1588b..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexDataManager.h +++ /dev/null @@ -1,71 +0,0 @@ -// -// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// 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" -#include "common/mathutil.h" -#include "libGLESv2/Error.h" - -#include - -namespace -{ - enum { INITIAL_INDEX_BUFFER_SIZE = 4096 * sizeof(GLuint) }; -} - -namespace gl -{ -class Buffer; -} - -namespace rx -{ -class IndexBufferInterface; -class StaticIndexBufferInterface; -class StreamingIndexBufferInterface; -class IndexBuffer; -class BufferD3D; -class RendererD3D; - -struct TranslatedIndexData -{ - RangeUI indexRange; - unsigned int startIndex; - unsigned int startOffset; // In bytes - - IndexBuffer *indexBuffer; - BufferD3D *storage; - GLenum indexType; - unsigned int serial; -}; - -class IndexDataManager -{ - public: - explicit IndexDataManager(RendererD3D *renderer); - virtual ~IndexDataManager(); - - gl::Error prepareIndexData(GLenum type, GLsizei count, gl::Buffer *arrayElementBuffer, const GLvoid *indices, TranslatedIndexData *translated); - - private: - gl::Error getStreamingIndexBuffer(GLenum destinationIndexType, IndexBufferInterface **outBuffer); - - DISALLOW_COPY_AND_ASSIGN(IndexDataManager); - - RendererD3D *const mRenderer; - - StreamingIndexBufferInterface *mStreamingBufferShort; - StreamingIndexBufferInterface *mStreamingBufferInt; -}; - -} - -#endif // LIBGLESV2_INDEXDATAMANAGER_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/MemoryBuffer.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/MemoryBuffer.cpp deleted file mode 100644 index 2b5b09a324..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/MemoryBuffer.cpp +++ /dev/null @@ -1,74 +0,0 @@ -// -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "libGLESv2/renderer/d3d/MemoryBuffer.h" -#include "common/debug.h" - -#include -#include - -namespace rx -{ - -MemoryBuffer::MemoryBuffer() - : mSize(0), - mData(NULL) -{ -} - -MemoryBuffer::~MemoryBuffer() -{ - free(mData); - mData = NULL; -} - -bool MemoryBuffer::resize(size_t size) -{ - if (size == 0) - { - free(mData); - mData = NULL; - mSize = 0; - } - else - { - uint8_t *newMemory = reinterpret_cast(malloc(sizeof(uint8_t) * size)); - if (newMemory == NULL) - { - return false; - } - - if (mData) - { - // Copy the intersection of the old data and the new data - std::copy(mData, mData + std::min(mSize, size), newMemory); - free(mData); - } - - mData = newMemory; - mSize = size; - } - - return true; -} - -size_t MemoryBuffer::size() const -{ - return mSize; -} - -const uint8_t *MemoryBuffer::data() const -{ - return mData; -} - -uint8_t *MemoryBuffer::data() -{ - ASSERT(mData); - return mData; -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/MemoryBuffer.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/MemoryBuffer.h deleted file mode 100644 index c65f79fe10..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/MemoryBuffer.h +++ /dev/null @@ -1,36 +0,0 @@ -// -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef LIBGLESV2_RENDERER_D3D_MEMORYBUFFER_H_ -#define LIBGLESV2_RENDERER_D3D_MEMORYBUFFER_H_ - -#include -#include - -namespace rx -{ - -class MemoryBuffer -{ - public: - MemoryBuffer(); - ~MemoryBuffer(); - - bool resize(size_t size); - size_t size() const; - bool empty() const { return mSize == 0; } - - const uint8_t *data() const; - uint8_t *data(); - - private: - size_t mSize; - uint8_t *mData; -}; - -} - -#endif // LIBGLESV2_RENDERER_D3D_MEMORYBUFFER_H diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ProgramD3D.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ProgramD3D.cpp deleted file mode 100644 index 75da78110e..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ProgramD3D.cpp +++ /dev/null @@ -1,1925 +0,0 @@ -// -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// ProgramD3D.cpp: Defines the rx::ProgramD3D class which implements rx::ProgramImpl. - -#include "libGLESv2/renderer/d3d/ProgramD3D.h" - -#include "common/features.h" -#include "common/utilities.h" -#include "libGLESv2/Framebuffer.h" -#include "libGLESv2/FramebufferAttachment.h" -#include "libGLESv2/Program.h" -#include "libGLESv2/ProgramBinary.h" -#include "libGLESv2/main.h" -#include "libGLESv2/renderer/ShaderExecutable.h" -#include "libGLESv2/renderer/d3d/DynamicHLSL.h" -#include "libGLESv2/renderer/d3d/RendererD3D.h" -#include "libGLESv2/renderer/d3d/ShaderD3D.h" - -namespace rx -{ - -namespace -{ - -GLenum GetTextureType(GLenum samplerType) -{ - switch (samplerType) - { - case GL_SAMPLER_2D: - case GL_INT_SAMPLER_2D: - case GL_UNSIGNED_INT_SAMPLER_2D: - case GL_SAMPLER_2D_SHADOW: - return GL_TEXTURE_2D; - case GL_SAMPLER_3D: - case GL_INT_SAMPLER_3D: - case GL_UNSIGNED_INT_SAMPLER_3D: - return GL_TEXTURE_3D; - case GL_SAMPLER_CUBE: - case GL_SAMPLER_CUBE_SHADOW: - return GL_TEXTURE_CUBE_MAP; - case GL_INT_SAMPLER_CUBE: - case GL_UNSIGNED_INT_SAMPLER_CUBE: - return GL_TEXTURE_CUBE_MAP; - case GL_SAMPLER_2D_ARRAY: - case GL_INT_SAMPLER_2D_ARRAY: - case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: - case GL_SAMPLER_2D_ARRAY_SHADOW: - return GL_TEXTURE_2D_ARRAY; - default: UNREACHABLE(); - } - - return GL_TEXTURE_2D; -} - -void GetDefaultInputLayoutFromShader(const std::vector &shaderAttributes, gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS]) -{ - size_t layoutIndex = 0; - for (size_t attributeIndex = 0; attributeIndex < shaderAttributes.size(); attributeIndex++) - { - ASSERT(layoutIndex < gl::MAX_VERTEX_ATTRIBS); - - const sh::Attribute &shaderAttr = shaderAttributes[attributeIndex]; - - if (shaderAttr.type != GL_NONE) - { - GLenum transposedType = gl::TransposeMatrixType(shaderAttr.type); - - for (size_t rowIndex = 0; static_cast(rowIndex) < gl::VariableRowCount(transposedType); rowIndex++, layoutIndex++) - { - gl::VertexFormat *defaultFormat = &inputLayout[layoutIndex]; - - defaultFormat->mType = gl::VariableComponentType(transposedType); - defaultFormat->mNormalized = false; - defaultFormat->mPureInteger = (defaultFormat->mType != GL_FLOAT); // note: inputs can not be bool - defaultFormat->mComponents = gl::VariableColumnCount(transposedType); - } - } - } -} - -std::vector GetDefaultOutputLayoutFromShader(const std::vector &shaderOutputVars) -{ - std::vector defaultPixelOutput(1); - - ASSERT(!shaderOutputVars.empty()); - defaultPixelOutput[0] = GL_COLOR_ATTACHMENT0 + shaderOutputVars[0].outputIndex; - - return defaultPixelOutput; -} - -bool IsRowMajorLayout(const sh::InterfaceBlockField &var) -{ - return var.isRowMajorLayout; -} - -bool IsRowMajorLayout(const sh::ShaderVariable &var) -{ - return false; -} - -} - -ProgramD3D::VertexExecutable::VertexExecutable(const gl::VertexFormat inputLayout[], - const GLenum signature[], - ShaderExecutable *shaderExecutable) - : mShaderExecutable(shaderExecutable) -{ - for (size_t attributeIndex = 0; attributeIndex < gl::MAX_VERTEX_ATTRIBS; attributeIndex++) - { - mInputs[attributeIndex] = inputLayout[attributeIndex]; - mSignature[attributeIndex] = signature[attributeIndex]; - } -} - -ProgramD3D::VertexExecutable::~VertexExecutable() -{ - SafeDelete(mShaderExecutable); -} - -bool ProgramD3D::VertexExecutable::matchesSignature(const GLenum signature[]) const -{ - for (size_t attributeIndex = 0; attributeIndex < gl::MAX_VERTEX_ATTRIBS; attributeIndex++) - { - if (mSignature[attributeIndex] != signature[attributeIndex]) - { - return false; - } - } - - return true; -} - -ProgramD3D::PixelExecutable::PixelExecutable(const std::vector &outputSignature, ShaderExecutable *shaderExecutable) - : mOutputSignature(outputSignature), - mShaderExecutable(shaderExecutable) -{ -} - -ProgramD3D::PixelExecutable::~PixelExecutable() -{ - SafeDelete(mShaderExecutable); -} - -ProgramD3D::Sampler::Sampler() : active(false), logicalTextureUnit(0), textureType(GL_TEXTURE_2D) -{ -} - -ProgramD3D::ProgramD3D(RendererD3D *renderer) - : ProgramImpl(), - mRenderer(renderer), - mDynamicHLSL(NULL), - mGeometryExecutable(NULL), - mVertexWorkarounds(ANGLE_D3D_WORKAROUND_NONE), - mPixelWorkarounds(ANGLE_D3D_WORKAROUND_NONE), - mUsesPointSize(false), - mVertexUniformStorage(NULL), - mFragmentUniformStorage(NULL), - mUsedVertexSamplerRange(0), - mUsedPixelSamplerRange(0), - mDirtySamplerMapping(true), - mShaderVersion(100) -{ - mDynamicHLSL = new DynamicHLSL(renderer); -} - -ProgramD3D::~ProgramD3D() -{ - reset(); - SafeDelete(mDynamicHLSL); -} - -ProgramD3D *ProgramD3D::makeProgramD3D(ProgramImpl *impl) -{ - ASSERT(HAS_DYNAMIC_TYPE(ProgramD3D*, impl)); - return static_cast(impl); -} - -const ProgramD3D *ProgramD3D::makeProgramD3D(const ProgramImpl *impl) -{ - ASSERT(HAS_DYNAMIC_TYPE(const ProgramD3D*, impl)); - return static_cast(impl); -} - -bool ProgramD3D::usesPointSpriteEmulation() const -{ - return mUsesPointSize && mRenderer->getMajorShaderModel() >= 4; -} - -bool ProgramD3D::usesGeometryShader() const -{ - return usesPointSpriteEmulation(); -} - -GLint ProgramD3D::getSamplerMapping(gl::SamplerType type, unsigned int samplerIndex, const gl::Caps &caps) const -{ - GLint logicalTextureUnit = -1; - - switch (type) - { - case gl::SAMPLER_PIXEL: - ASSERT(samplerIndex < caps.maxTextureImageUnits); - if (samplerIndex < mSamplersPS.size() && mSamplersPS[samplerIndex].active) - { - logicalTextureUnit = mSamplersPS[samplerIndex].logicalTextureUnit; - } - break; - case gl::SAMPLER_VERTEX: - ASSERT(samplerIndex < caps.maxVertexTextureImageUnits); - if (samplerIndex < mSamplersVS.size() && mSamplersVS[samplerIndex].active) - { - logicalTextureUnit = mSamplersVS[samplerIndex].logicalTextureUnit; - } - break; - default: UNREACHABLE(); - } - - if (logicalTextureUnit >= 0 && logicalTextureUnit < static_cast(caps.maxCombinedTextureImageUnits)) - { - return logicalTextureUnit; - } - - return -1; -} - -// Returns the texture type for a given Direct3D 9 sampler type and -// index (0-15 for the pixel shader and 0-3 for the vertex shader). -GLenum ProgramD3D::getSamplerTextureType(gl::SamplerType type, unsigned int samplerIndex) const -{ - switch (type) - { - case gl::SAMPLER_PIXEL: - ASSERT(samplerIndex < mSamplersPS.size()); - ASSERT(mSamplersPS[samplerIndex].active); - return mSamplersPS[samplerIndex].textureType; - case gl::SAMPLER_VERTEX: - ASSERT(samplerIndex < mSamplersVS.size()); - ASSERT(mSamplersVS[samplerIndex].active); - return mSamplersVS[samplerIndex].textureType; - default: UNREACHABLE(); - } - - return GL_TEXTURE_2D; -} - -GLint ProgramD3D::getUsedSamplerRange(gl::SamplerType type) const -{ - switch (type) - { - case gl::SAMPLER_PIXEL: - return mUsedPixelSamplerRange; - case gl::SAMPLER_VERTEX: - return mUsedVertexSamplerRange; - default: - UNREACHABLE(); - return 0; - } -} - -void ProgramD3D::updateSamplerMapping() -{ - if (!mDirtySamplerMapping) - { - return; - } - - mDirtySamplerMapping = false; - - // Retrieve sampler uniform values - for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++) - { - gl::LinkedUniform *targetUniform = mUniforms[uniformIndex]; - - if (targetUniform->dirty) - { - if (gl::IsSampler(targetUniform->type)) - { - int count = targetUniform->elementCount(); - GLint (*v)[4] = reinterpret_cast(targetUniform->data); - - if (targetUniform->isReferencedByFragmentShader()) - { - unsigned int firstIndex = targetUniform->psRegisterIndex; - - for (int i = 0; i < count; i++) - { - unsigned int samplerIndex = firstIndex + i; - - if (samplerIndex < mSamplersPS.size()) - { - ASSERT(mSamplersPS[samplerIndex].active); - mSamplersPS[samplerIndex].logicalTextureUnit = v[i][0]; - } - } - } - - if (targetUniform->isReferencedByVertexShader()) - { - unsigned int firstIndex = targetUniform->vsRegisterIndex; - - for (int i = 0; i < count; i++) - { - unsigned int samplerIndex = firstIndex + i; - - if (samplerIndex < mSamplersVS.size()) - { - ASSERT(mSamplersVS[samplerIndex].active); - mSamplersVS[samplerIndex].logicalTextureUnit = v[i][0]; - } - } - } - } - } - } -} - -bool ProgramD3D::validateSamplers(gl::InfoLog *infoLog, const gl::Caps &caps) -{ - // if any two active samplers in a program are of different types, but refer to the same - // texture image unit, and this is the current program, then ValidateProgram will fail, and - // DrawArrays and DrawElements will issue the INVALID_OPERATION error. - updateSamplerMapping(); - - std::vector textureUnitTypes(caps.maxCombinedTextureImageUnits, GL_NONE); - - for (unsigned int i = 0; i < mUsedPixelSamplerRange; ++i) - { - if (mSamplersPS[i].active) - { - unsigned int unit = mSamplersPS[i].logicalTextureUnit; - - if (unit >= textureUnitTypes.size()) - { - if (infoLog) - { - infoLog->append("Sampler uniform (%d) exceeds GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, textureUnitTypes.size()); - } - - return false; - } - - if (textureUnitTypes[unit] != GL_NONE) - { - if (mSamplersPS[i].textureType != textureUnitTypes[unit]) - { - if (infoLog) - { - infoLog->append("Samplers of conflicting types refer to the same texture image unit (%d).", unit); - } - - return false; - } - } - else - { - textureUnitTypes[unit] = mSamplersPS[i].textureType; - } - } - } - - for (unsigned int i = 0; i < mUsedVertexSamplerRange; ++i) - { - if (mSamplersVS[i].active) - { - unsigned int unit = mSamplersVS[i].logicalTextureUnit; - - if (unit >= textureUnitTypes.size()) - { - if (infoLog) - { - infoLog->append("Sampler uniform (%d) exceeds GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, textureUnitTypes.size()); - } - - return false; - } - - if (textureUnitTypes[unit] != GL_NONE) - { - if (mSamplersVS[i].textureType != textureUnitTypes[unit]) - { - if (infoLog) - { - infoLog->append("Samplers of conflicting types refer to the same texture image unit (%d).", unit); - } - - return false; - } - } - else - { - textureUnitTypes[unit] = mSamplersVS[i].textureType; - } - } - } - - return true; -} - -gl::LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) -{ - stream->readInt(&mShaderVersion); - - const unsigned int psSamplerCount = stream->readInt(); - for (unsigned int i = 0; i < psSamplerCount; ++i) - { - Sampler sampler; - stream->readBool(&sampler.active); - stream->readInt(&sampler.logicalTextureUnit); - stream->readInt(&sampler.textureType); - mSamplersPS.push_back(sampler); - } - const unsigned int vsSamplerCount = stream->readInt(); - for (unsigned int i = 0; i < vsSamplerCount; ++i) - { - Sampler sampler; - stream->readBool(&sampler.active); - stream->readInt(&sampler.logicalTextureUnit); - stream->readInt(&sampler.textureType); - mSamplersVS.push_back(sampler); - } - - stream->readInt(&mUsedVertexSamplerRange); - stream->readInt(&mUsedPixelSamplerRange); - - const unsigned int uniformCount = stream->readInt(); - if (stream->error()) - { - infoLog.append("Invalid program binary."); - return gl::LinkResult(false, gl::Error(GL_NO_ERROR)); - } - - mUniforms.resize(uniformCount); - for (unsigned int uniformIndex = 0; uniformIndex < uniformCount; uniformIndex++) - { - GLenum type = stream->readInt(); - GLenum precision = stream->readInt(); - std::string name = stream->readString(); - unsigned int arraySize = stream->readInt(); - int blockIndex = stream->readInt(); - - int offset = stream->readInt(); - int arrayStride = stream->readInt(); - int matrixStride = stream->readInt(); - bool isRowMajorMatrix = stream->readBool(); - - const sh::BlockMemberInfo blockInfo(offset, arrayStride, matrixStride, isRowMajorMatrix); - - gl::LinkedUniform *uniform = new gl::LinkedUniform(type, precision, name, arraySize, blockIndex, blockInfo); - - stream->readInt(&uniform->psRegisterIndex); - stream->readInt(&uniform->vsRegisterIndex); - stream->readInt(&uniform->registerCount); - stream->readInt(&uniform->registerElement); - - mUniforms[uniformIndex] = uniform; - } - - const unsigned int uniformIndexCount = stream->readInt(); - if (stream->error()) - { - infoLog.append("Invalid program binary."); - return gl::LinkResult(false, gl::Error(GL_NO_ERROR)); - } - - mUniformIndex.resize(uniformIndexCount); - for (unsigned int uniformIndexIndex = 0; uniformIndexIndex < uniformIndexCount; uniformIndexIndex++) - { - stream->readString(&mUniformIndex[uniformIndexIndex].name); - stream->readInt(&mUniformIndex[uniformIndexIndex].element); - stream->readInt(&mUniformIndex[uniformIndexIndex].index); - } - - unsigned int uniformBlockCount = stream->readInt(); - if (stream->error()) - { - infoLog.append("Invalid program binary."); - return gl::LinkResult(false, gl::Error(GL_NO_ERROR)); - } - - mUniformBlocks.resize(uniformBlockCount); - for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < uniformBlockCount; ++uniformBlockIndex) - { - std::string name = stream->readString(); - unsigned int elementIndex = stream->readInt(); - unsigned int dataSize = stream->readInt(); - - gl::UniformBlock *uniformBlock = new gl::UniformBlock(name, elementIndex, dataSize); - - stream->readInt(&uniformBlock->psRegisterIndex); - stream->readInt(&uniformBlock->vsRegisterIndex); - - unsigned int numMembers = stream->readInt(); - uniformBlock->memberUniformIndexes.resize(numMembers); - for (unsigned int blockMemberIndex = 0; blockMemberIndex < numMembers; blockMemberIndex++) - { - stream->readInt(&uniformBlock->memberUniformIndexes[blockMemberIndex]); - } - - mUniformBlocks[uniformBlockIndex] = uniformBlock; - } - - stream->readInt(&mTransformFeedbackBufferMode); - const unsigned int transformFeedbackVaryingCount = stream->readInt(); - mTransformFeedbackLinkedVaryings.resize(transformFeedbackVaryingCount); - for (unsigned int varyingIndex = 0; varyingIndex < transformFeedbackVaryingCount; varyingIndex++) - { - gl::LinkedVarying &varying = mTransformFeedbackLinkedVaryings[varyingIndex]; - - stream->readString(&varying.name); - stream->readInt(&varying.type); - stream->readInt(&varying.size); - stream->readString(&varying.semanticName); - stream->readInt(&varying.semanticIndex); - stream->readInt(&varying.semanticIndexCount); - } - - stream->readString(&mVertexHLSL); - stream->readInt(&mVertexWorkarounds); - stream->readString(&mPixelHLSL); - stream->readInt(&mPixelWorkarounds); - stream->readBool(&mUsesFragDepth); - stream->readBool(&mUsesPointSize); - - const size_t pixelShaderKeySize = stream->readInt(); - mPixelShaderKey.resize(pixelShaderKeySize); - for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKeySize; pixelShaderKeyIndex++) - { - stream->readInt(&mPixelShaderKey[pixelShaderKeyIndex].type); - stream->readString(&mPixelShaderKey[pixelShaderKeyIndex].name); - stream->readString(&mPixelShaderKey[pixelShaderKeyIndex].source); - stream->readInt(&mPixelShaderKey[pixelShaderKeyIndex].outputIndex); - } - - const unsigned char* binary = reinterpret_cast(stream->data()); - - const unsigned int vertexShaderCount = stream->readInt(); - for (unsigned int vertexShaderIndex = 0; vertexShaderIndex < vertexShaderCount; vertexShaderIndex++) - { - gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS]; - - for (size_t inputIndex = 0; inputIndex < gl::MAX_VERTEX_ATTRIBS; inputIndex++) - { - gl::VertexFormat *vertexInput = &inputLayout[inputIndex]; - stream->readInt(&vertexInput->mType); - stream->readInt(&vertexInput->mNormalized); - stream->readInt(&vertexInput->mComponents); - stream->readBool(&vertexInput->mPureInteger); - } - - unsigned int vertexShaderSize = stream->readInt(); - const unsigned char *vertexShaderFunction = binary + stream->offset(); - - ShaderExecutable *shaderExecutable = NULL; - gl::Error error = mRenderer->loadExecutable(vertexShaderFunction, vertexShaderSize, - SHADER_VERTEX, - mTransformFeedbackLinkedVaryings, - (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS), - &shaderExecutable); - if (error.isError()) - { - return gl::LinkResult(false, error); - } - - if (!shaderExecutable) - { - infoLog.append("Could not create vertex shader."); - return gl::LinkResult(false, gl::Error(GL_NO_ERROR)); - } - - // generated converted input layout - GLenum signature[gl::MAX_VERTEX_ATTRIBS]; - getInputLayoutSignature(inputLayout, signature); - - // add new binary - mVertexExecutables.push_back(new VertexExecutable(inputLayout, signature, shaderExecutable)); - - stream->skip(vertexShaderSize); - } - - const size_t pixelShaderCount = stream->readInt(); - for (size_t pixelShaderIndex = 0; pixelShaderIndex < pixelShaderCount; pixelShaderIndex++) - { - const size_t outputCount = stream->readInt(); - std::vector outputs(outputCount); - for (size_t outputIndex = 0; outputIndex < outputCount; outputIndex++) - { - stream->readInt(&outputs[outputIndex]); - } - - const size_t pixelShaderSize = stream->readInt(); - const unsigned char *pixelShaderFunction = binary + stream->offset(); - ShaderExecutable *shaderExecutable = NULL; - gl::Error error = mRenderer->loadExecutable(pixelShaderFunction, pixelShaderSize, SHADER_PIXEL, - mTransformFeedbackLinkedVaryings, - (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS), - &shaderExecutable); - if (error.isError()) - { - return gl::LinkResult(false, error); - } - - if (!shaderExecutable) - { - infoLog.append("Could not create pixel shader."); - return gl::LinkResult(false, gl::Error(GL_NO_ERROR)); - } - - // add new binary - mPixelExecutables.push_back(new PixelExecutable(outputs, shaderExecutable)); - - stream->skip(pixelShaderSize); - } - - unsigned int geometryShaderSize = stream->readInt(); - - if (geometryShaderSize > 0) - { - const unsigned char *geometryShaderFunction = binary + stream->offset(); - gl::Error error = mRenderer->loadExecutable(geometryShaderFunction, geometryShaderSize, SHADER_GEOMETRY, - mTransformFeedbackLinkedVaryings, - (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS), - &mGeometryExecutable); - if (error.isError()) - { - return gl::LinkResult(false, error); - } - - if (!mGeometryExecutable) - { - infoLog.append("Could not create geometry shader."); - return gl::LinkResult(false, gl::Error(GL_NO_ERROR)); - } - stream->skip(geometryShaderSize); - } - - GUID binaryIdentifier = {0}; - stream->readBytes(reinterpret_cast(&binaryIdentifier), sizeof(GUID)); - - GUID identifier = mRenderer->getAdapterIdentifier(); - if (memcmp(&identifier, &binaryIdentifier, sizeof(GUID)) != 0) - { - infoLog.append("Invalid program binary."); - return gl::LinkResult(false, gl::Error(GL_NO_ERROR)); - } - - initializeUniformStorage(); - - return gl::LinkResult(true, gl::Error(GL_NO_ERROR)); -} - -gl::Error ProgramD3D::save(gl::BinaryOutputStream *stream) -{ - stream->writeInt(mShaderVersion); - - stream->writeInt(mSamplersPS.size()); - for (unsigned int i = 0; i < mSamplersPS.size(); ++i) - { - stream->writeInt(mSamplersPS[i].active); - stream->writeInt(mSamplersPS[i].logicalTextureUnit); - stream->writeInt(mSamplersPS[i].textureType); - } - - stream->writeInt(mSamplersVS.size()); - for (unsigned int i = 0; i < mSamplersVS.size(); ++i) - { - stream->writeInt(mSamplersVS[i].active); - stream->writeInt(mSamplersVS[i].logicalTextureUnit); - stream->writeInt(mSamplersVS[i].textureType); - } - - stream->writeInt(mUsedVertexSamplerRange); - stream->writeInt(mUsedPixelSamplerRange); - - stream->writeInt(mUniforms.size()); - for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); ++uniformIndex) - { - const gl::LinkedUniform &uniform = *mUniforms[uniformIndex]; - - stream->writeInt(uniform.type); - stream->writeInt(uniform.precision); - stream->writeString(uniform.name); - stream->writeInt(uniform.arraySize); - stream->writeInt(uniform.blockIndex); - - stream->writeInt(uniform.blockInfo.offset); - stream->writeInt(uniform.blockInfo.arrayStride); - stream->writeInt(uniform.blockInfo.matrixStride); - stream->writeInt(uniform.blockInfo.isRowMajorMatrix); - - stream->writeInt(uniform.psRegisterIndex); - stream->writeInt(uniform.vsRegisterIndex); - stream->writeInt(uniform.registerCount); - stream->writeInt(uniform.registerElement); - } - - stream->writeInt(mUniformIndex.size()); - for (size_t i = 0; i < mUniformIndex.size(); ++i) - { - stream->writeString(mUniformIndex[i].name); - stream->writeInt(mUniformIndex[i].element); - stream->writeInt(mUniformIndex[i].index); - } - - stream->writeInt(mUniformBlocks.size()); - for (size_t uniformBlockIndex = 0; uniformBlockIndex < mUniformBlocks.size(); ++uniformBlockIndex) - { - const gl::UniformBlock& uniformBlock = *mUniformBlocks[uniformBlockIndex]; - - stream->writeString(uniformBlock.name); - stream->writeInt(uniformBlock.elementIndex); - stream->writeInt(uniformBlock.dataSize); - - stream->writeInt(uniformBlock.memberUniformIndexes.size()); - for (unsigned int blockMemberIndex = 0; blockMemberIndex < uniformBlock.memberUniformIndexes.size(); blockMemberIndex++) - { - stream->writeInt(uniformBlock.memberUniformIndexes[blockMemberIndex]); - } - - stream->writeInt(uniformBlock.psRegisterIndex); - stream->writeInt(uniformBlock.vsRegisterIndex); - } - - stream->writeInt(mTransformFeedbackBufferMode); - stream->writeInt(mTransformFeedbackLinkedVaryings.size()); - for (size_t i = 0; i < mTransformFeedbackLinkedVaryings.size(); i++) - { - const gl::LinkedVarying &varying = mTransformFeedbackLinkedVaryings[i]; - - stream->writeString(varying.name); - stream->writeInt(varying.type); - stream->writeInt(varying.size); - stream->writeString(varying.semanticName); - stream->writeInt(varying.semanticIndex); - stream->writeInt(varying.semanticIndexCount); - } - - stream->writeString(mVertexHLSL); - stream->writeInt(mVertexWorkarounds); - stream->writeString(mPixelHLSL); - stream->writeInt(mPixelWorkarounds); - stream->writeInt(mUsesFragDepth); - stream->writeInt(mUsesPointSize); - - const std::vector &pixelShaderKey = mPixelShaderKey; - stream->writeInt(pixelShaderKey.size()); - for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKey.size(); pixelShaderKeyIndex++) - { - const PixelShaderOutputVariable &variable = pixelShaderKey[pixelShaderKeyIndex]; - stream->writeInt(variable.type); - stream->writeString(variable.name); - stream->writeString(variable.source); - stream->writeInt(variable.outputIndex); - } - - stream->writeInt(mVertexExecutables.size()); - for (size_t vertexExecutableIndex = 0; vertexExecutableIndex < mVertexExecutables.size(); vertexExecutableIndex++) - { - VertexExecutable *vertexExecutable = mVertexExecutables[vertexExecutableIndex]; - - for (size_t inputIndex = 0; inputIndex < gl::MAX_VERTEX_ATTRIBS; inputIndex++) - { - const gl::VertexFormat &vertexInput = vertexExecutable->inputs()[inputIndex]; - stream->writeInt(vertexInput.mType); - stream->writeInt(vertexInput.mNormalized); - stream->writeInt(vertexInput.mComponents); - stream->writeInt(vertexInput.mPureInteger); - } - - size_t vertexShaderSize = vertexExecutable->shaderExecutable()->getLength(); - stream->writeInt(vertexShaderSize); - - const uint8_t *vertexBlob = vertexExecutable->shaderExecutable()->getFunction(); - stream->writeBytes(vertexBlob, vertexShaderSize); - } - - stream->writeInt(mPixelExecutables.size()); - for (size_t pixelExecutableIndex = 0; pixelExecutableIndex < mPixelExecutables.size(); pixelExecutableIndex++) - { - PixelExecutable *pixelExecutable = mPixelExecutables[pixelExecutableIndex]; - - const std::vector outputs = pixelExecutable->outputSignature(); - stream->writeInt(outputs.size()); - for (size_t outputIndex = 0; outputIndex < outputs.size(); outputIndex++) - { - stream->writeInt(outputs[outputIndex]); - } - - size_t pixelShaderSize = pixelExecutable->shaderExecutable()->getLength(); - stream->writeInt(pixelShaderSize); - - const uint8_t *pixelBlob = pixelExecutable->shaderExecutable()->getFunction(); - stream->writeBytes(pixelBlob, pixelShaderSize); - } - - size_t geometryShaderSize = (mGeometryExecutable != NULL) ? mGeometryExecutable->getLength() : 0; - stream->writeInt(geometryShaderSize); - - if (mGeometryExecutable != NULL && geometryShaderSize > 0) - { - const uint8_t *geometryBlob = mGeometryExecutable->getFunction(); - stream->writeBytes(geometryBlob, geometryShaderSize); - } - - GUID binaryIdentifier = mRenderer->getAdapterIdentifier(); - stream->writeBytes(reinterpret_cast(&binaryIdentifier), sizeof(GUID)); - - return gl::Error(GL_NO_ERROR); -} - -gl::Error ProgramD3D::getPixelExecutableForFramebuffer(const gl::Framebuffer *fbo, ShaderExecutable **outExecutable) -{ - std::vector outputs; - - const gl::ColorbufferInfo &colorbuffers = fbo->getColorbuffersForRender(mRenderer->getWorkarounds()); - - for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment) - { - const gl::FramebufferAttachment *colorbuffer = colorbuffers[colorAttachment]; - - if (colorbuffer) - { - outputs.push_back(colorbuffer->getBinding() == GL_BACK ? GL_COLOR_ATTACHMENT0 : colorbuffer->getBinding()); - } - else - { - outputs.push_back(GL_NONE); - } - } - - return getPixelExecutableForOutputLayout(outputs, outExecutable); -} - -gl::Error ProgramD3D::getPixelExecutableForOutputLayout(const std::vector &outputSignature, ShaderExecutable **outExectuable) -{ - for (size_t executableIndex = 0; executableIndex < mPixelExecutables.size(); executableIndex++) - { - if (mPixelExecutables[executableIndex]->matchesSignature(outputSignature)) - { - *outExectuable = mPixelExecutables[executableIndex]->shaderExecutable(); - return gl::Error(GL_NO_ERROR); - } - } - - std::string finalPixelHLSL = mDynamicHLSL->generatePixelShaderForOutputSignature(mPixelHLSL, mPixelShaderKey, mUsesFragDepth, - outputSignature); - - // Generate new pixel executable - gl::InfoLog tempInfoLog; - ShaderExecutable *pixelExecutable = NULL; - gl::Error error = mRenderer->compileToExecutable(tempInfoLog, finalPixelHLSL, SHADER_PIXEL, - mTransformFeedbackLinkedVaryings, - (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS), - mPixelWorkarounds, &pixelExecutable); - if (error.isError()) - { - return error; - } - - if (!pixelExecutable) - { - std::vector tempCharBuffer(tempInfoLog.getLength() + 3); - tempInfoLog.getLog(tempInfoLog.getLength(), NULL, &tempCharBuffer[0]); - ERR("Error compiling dynamic pixel executable:\n%s\n", &tempCharBuffer[0]); - } - else - { - mPixelExecutables.push_back(new PixelExecutable(outputSignature, pixelExecutable)); - } - - *outExectuable = pixelExecutable; - return gl::Error(GL_NO_ERROR); -} - -gl::Error ProgramD3D::getVertexExecutableForInputLayout(const gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS], ShaderExecutable **outExectuable) -{ - GLenum signature[gl::MAX_VERTEX_ATTRIBS]; - getInputLayoutSignature(inputLayout, signature); - - for (size_t executableIndex = 0; executableIndex < mVertexExecutables.size(); executableIndex++) - { - if (mVertexExecutables[executableIndex]->matchesSignature(signature)) - { - *outExectuable = mVertexExecutables[executableIndex]->shaderExecutable(); - return gl::Error(GL_NO_ERROR); - } - } - - // Generate new dynamic layout with attribute conversions - std::string finalVertexHLSL = mDynamicHLSL->generateVertexShaderForInputLayout(mVertexHLSL, inputLayout, mShaderAttributes); - - // Generate new vertex executable - gl::InfoLog tempInfoLog; - ShaderExecutable *vertexExecutable = NULL; - gl::Error error = mRenderer->compileToExecutable(tempInfoLog, finalVertexHLSL, SHADER_VERTEX, - mTransformFeedbackLinkedVaryings, - (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS), - mVertexWorkarounds, &vertexExecutable); - if (error.isError()) - { - return error; - } - - if (!vertexExecutable) - { - std::vector tempCharBuffer(tempInfoLog.getLength()+3); - tempInfoLog.getLog(tempInfoLog.getLength(), NULL, &tempCharBuffer[0]); - ERR("Error compiling dynamic vertex executable:\n%s\n", &tempCharBuffer[0]); - } - else - { - mVertexExecutables.push_back(new VertexExecutable(inputLayout, signature, vertexExecutable)); - } - - *outExectuable = vertexExecutable; - return gl::Error(GL_NO_ERROR); -} - -gl::LinkResult ProgramD3D::compileProgramExecutables(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader, - int registers) -{ - ShaderD3D *vertexShaderD3D = ShaderD3D::makeShaderD3D(vertexShader->getImplementation()); - ShaderD3D *fragmentShaderD3D = ShaderD3D::makeShaderD3D(fragmentShader->getImplementation()); - - gl::VertexFormat defaultInputLayout[gl::MAX_VERTEX_ATTRIBS]; - GetDefaultInputLayoutFromShader(vertexShader->getActiveAttributes(), defaultInputLayout); - ShaderExecutable *defaultVertexExecutable = NULL; - gl::Error error = getVertexExecutableForInputLayout(defaultInputLayout, &defaultVertexExecutable); - if (error.isError()) - { - return gl::LinkResult(false, error); - } - - std::vector defaultPixelOutput = GetDefaultOutputLayoutFromShader(getPixelShaderKey()); - ShaderExecutable *defaultPixelExecutable = NULL; - error = getPixelExecutableForOutputLayout(defaultPixelOutput, &defaultPixelExecutable); - if (error.isError()) - { - return gl::LinkResult(false, error); - } - - if (usesGeometryShader()) - { - std::string geometryHLSL = mDynamicHLSL->generateGeometryShaderHLSL(registers, fragmentShaderD3D, vertexShaderD3D); - - - error = mRenderer->compileToExecutable(infoLog, geometryHLSL, SHADER_GEOMETRY, mTransformFeedbackLinkedVaryings, - (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS), - ANGLE_D3D_WORKAROUND_NONE, &mGeometryExecutable); - if (error.isError()) - { - return gl::LinkResult(false, error); - } - } - -#if ANGLE_SHADER_DEBUG_INFO == ANGLE_ENABLED - if (usesGeometryShader() && mGeometryExecutable) - { - // Geometry shaders are currently only used internally, so there is no corresponding shader object at the interface level - // For now the geometry shader debug info is pre-pended to the vertex shader, this is a bit of a clutch - vertexShaderD3D->appendDebugInfo("// GEOMETRY SHADER BEGIN\n\n"); - vertexShaderD3D->appendDebugInfo(mGeometryExecutable->getDebugInfo()); - vertexShaderD3D->appendDebugInfo("\nGEOMETRY SHADER END\n\n\n"); - } - - if (defaultVertexExecutable) - { - vertexShaderD3D->appendDebugInfo(defaultVertexExecutable->getDebugInfo()); - } - - if (defaultPixelExecutable) - { - fragmentShaderD3D->appendDebugInfo(defaultPixelExecutable->getDebugInfo()); - } -#endif - - bool linkSuccess = (defaultVertexExecutable && defaultPixelExecutable && (!usesGeometryShader() || mGeometryExecutable)); - return gl::LinkResult(linkSuccess, gl::Error(GL_NO_ERROR)); -} - -gl::LinkResult ProgramD3D::link(const gl::Data &data, gl::InfoLog &infoLog, - gl::Shader *fragmentShader, gl::Shader *vertexShader, - const std::vector &transformFeedbackVaryings, - GLenum transformFeedbackBufferMode, - int *registers, std::vector *linkedVaryings, - std::map *outputVariables) -{ - ShaderD3D *vertexShaderD3D = ShaderD3D::makeShaderD3D(vertexShader->getImplementation()); - ShaderD3D *fragmentShaderD3D = ShaderD3D::makeShaderD3D(fragmentShader->getImplementation()); - - mSamplersPS.resize(data.caps->maxTextureImageUnits); - mSamplersVS.resize(data.caps->maxVertexTextureImageUnits); - - mTransformFeedbackBufferMode = transformFeedbackBufferMode; - - mPixelHLSL = fragmentShaderD3D->getTranslatedSource(); - mPixelWorkarounds = fragmentShaderD3D->getD3DWorkarounds(); - - mVertexHLSL = vertexShaderD3D->getTranslatedSource(); - mVertexWorkarounds = vertexShaderD3D->getD3DWorkarounds(); - mShaderVersion = vertexShaderD3D->getShaderVersion(); - - // Map the varyings to the register file - VaryingPacking packing = { NULL }; - *registers = mDynamicHLSL->packVaryings(infoLog, packing, fragmentShaderD3D, vertexShaderD3D, transformFeedbackVaryings); - - if (*registers < 0) - { - return gl::LinkResult(false, gl::Error(GL_NO_ERROR)); - } - - if (!gl::ProgramBinary::linkVaryings(infoLog, fragmentShader, vertexShader)) - { - return gl::LinkResult(false, gl::Error(GL_NO_ERROR)); - } - - if (!mDynamicHLSL->generateShaderLinkHLSL(data, infoLog, *registers, packing, mPixelHLSL, mVertexHLSL, - fragmentShaderD3D, vertexShaderD3D, transformFeedbackVaryings, - linkedVaryings, outputVariables, &mPixelShaderKey, &mUsesFragDepth)) - { - return gl::LinkResult(false, gl::Error(GL_NO_ERROR)); - } - - mUsesPointSize = vertexShaderD3D->usesPointSize(); - - return gl::LinkResult(true, gl::Error(GL_NO_ERROR)); -} - -void ProgramD3D::getInputLayoutSignature(const gl::VertexFormat inputLayout[], GLenum signature[]) const -{ - mDynamicHLSL->getInputLayoutSignature(inputLayout, signature); -} - -void ProgramD3D::initializeUniformStorage() -{ - // Compute total default block size - unsigned int vertexRegisters = 0; - unsigned int fragmentRegisters = 0; - for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++) - { - const gl::LinkedUniform &uniform = *mUniforms[uniformIndex]; - - if (!gl::IsSampler(uniform.type)) - { - if (uniform.isReferencedByVertexShader()) - { - vertexRegisters = std::max(vertexRegisters, uniform.vsRegisterIndex + uniform.registerCount); - } - if (uniform.isReferencedByFragmentShader()) - { - fragmentRegisters = std::max(fragmentRegisters, uniform.psRegisterIndex + uniform.registerCount); - } - } - } - - mVertexUniformStorage = mRenderer->createUniformStorage(vertexRegisters * 16u); - mFragmentUniformStorage = mRenderer->createUniformStorage(fragmentRegisters * 16u); -} - -gl::Error ProgramD3D::applyUniforms() -{ - updateSamplerMapping(); - - gl::Error error = mRenderer->applyUniforms(*this, mUniforms); - if (error.isError()) - { - return error; - } - - for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++) - { - mUniforms[uniformIndex]->dirty = false; - } - - return gl::Error(GL_NO_ERROR); -} - -gl::Error ProgramD3D::applyUniformBuffers(const std::vector boundBuffers, const gl::Caps &caps) -{ - ASSERT(boundBuffers.size() == mUniformBlocks.size()); - - const gl::Buffer *vertexUniformBuffers[gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS] = {NULL}; - const gl::Buffer *fragmentUniformBuffers[gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS] = {NULL}; - - const unsigned int reservedBuffersInVS = mRenderer->getReservedVertexUniformBuffers(); - const unsigned int reservedBuffersInFS = mRenderer->getReservedFragmentUniformBuffers(); - - for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < mUniformBlocks.size(); uniformBlockIndex++) - { - gl::UniformBlock *uniformBlock = mUniformBlocks[uniformBlockIndex]; - gl::Buffer *uniformBuffer = boundBuffers[uniformBlockIndex]; - - ASSERT(uniformBlock && uniformBuffer); - - if (uniformBuffer->getSize() < uniformBlock->dataSize) - { - // undefined behaviour - return gl::Error(GL_INVALID_OPERATION, "It is undefined behaviour to use a uniform buffer that is too small."); - } - - // Unnecessary to apply an unreferenced standard or shared UBO - if (!uniformBlock->isReferencedByVertexShader() && !uniformBlock->isReferencedByFragmentShader()) - { - continue; - } - - if (uniformBlock->isReferencedByVertexShader()) - { - unsigned int registerIndex = uniformBlock->vsRegisterIndex - reservedBuffersInVS; - ASSERT(vertexUniformBuffers[registerIndex] == NULL); - ASSERT(registerIndex < caps.maxVertexUniformBlocks); - vertexUniformBuffers[registerIndex] = uniformBuffer; - } - - if (uniformBlock->isReferencedByFragmentShader()) - { - unsigned int registerIndex = uniformBlock->psRegisterIndex - reservedBuffersInFS; - ASSERT(fragmentUniformBuffers[registerIndex] == NULL); - ASSERT(registerIndex < caps.maxFragmentUniformBlocks); - fragmentUniformBuffers[registerIndex] = uniformBuffer; - } - } - - return mRenderer->setUniformBuffers(vertexUniformBuffers, fragmentUniformBuffers); -} - -bool ProgramD3D::assignUniformBlockRegister(gl::InfoLog &infoLog, gl::UniformBlock *uniformBlock, GLenum shader, - unsigned int registerIndex, const gl::Caps &caps) -{ - if (shader == GL_VERTEX_SHADER) - { - uniformBlock->vsRegisterIndex = registerIndex; - if (registerIndex - mRenderer->getReservedVertexUniformBuffers() >= caps.maxVertexUniformBlocks) - { - infoLog.append("Vertex shader uniform block count exceed GL_MAX_VERTEX_UNIFORM_BLOCKS (%u)", caps.maxVertexUniformBlocks); - return false; - } - } - else if (shader == GL_FRAGMENT_SHADER) - { - uniformBlock->psRegisterIndex = registerIndex; - if (registerIndex - mRenderer->getReservedFragmentUniformBuffers() >= caps.maxFragmentUniformBlocks) - { - infoLog.append("Fragment shader uniform block count exceed GL_MAX_FRAGMENT_UNIFORM_BLOCKS (%u)", caps.maxFragmentUniformBlocks); - return false; - } - } - else UNREACHABLE(); - - return true; -} - -void ProgramD3D::dirtyAllUniforms() -{ - unsigned int numUniforms = mUniforms.size(); - for (unsigned int index = 0; index < numUniforms; index++) - { - mUniforms[index]->dirty = true; - } -} - -void ProgramD3D::setUniform1fv(GLint location, GLsizei count, const GLfloat* v) -{ - setUniform(location, count, v, GL_FLOAT); -} - -void ProgramD3D::setUniform2fv(GLint location, GLsizei count, const GLfloat *v) -{ - setUniform(location, count, v, GL_FLOAT_VEC2); -} - -void ProgramD3D::setUniform3fv(GLint location, GLsizei count, const GLfloat *v) -{ - setUniform(location, count, v, GL_FLOAT_VEC3); -} - -void ProgramD3D::setUniform4fv(GLint location, GLsizei count, const GLfloat *v) -{ - setUniform(location, count, v, GL_FLOAT_VEC4); -} - -void ProgramD3D::setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) -{ - setUniformMatrixfv<2, 2>(location, count, transpose, value, GL_FLOAT_MAT2); -} - -void ProgramD3D::setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) -{ - setUniformMatrixfv<3, 3>(location, count, transpose, value, GL_FLOAT_MAT3); -} - -void ProgramD3D::setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) -{ - setUniformMatrixfv<4, 4>(location, count, transpose, value, GL_FLOAT_MAT4); -} - -void ProgramD3D::setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) -{ - setUniformMatrixfv<2, 3>(location, count, transpose, value, GL_FLOAT_MAT2x3); -} - -void ProgramD3D::setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) -{ - setUniformMatrixfv<3, 2>(location, count, transpose, value, GL_FLOAT_MAT3x2); -} - -void ProgramD3D::setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) -{ - setUniformMatrixfv<2, 4>(location, count, transpose, value, GL_FLOAT_MAT2x4); -} - -void ProgramD3D::setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) -{ - setUniformMatrixfv<4, 2>(location, count, transpose, value, GL_FLOAT_MAT4x2); -} - -void ProgramD3D::setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) -{ - setUniformMatrixfv<3, 4>(location, count, transpose, value, GL_FLOAT_MAT3x4); -} - -void ProgramD3D::setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) -{ - setUniformMatrixfv<4, 3>(location, count, transpose, value, GL_FLOAT_MAT4x3); -} - -void ProgramD3D::setUniform1iv(GLint location, GLsizei count, const GLint *v) -{ - setUniform(location, count, v, GL_INT); -} - -void ProgramD3D::setUniform2iv(GLint location, GLsizei count, const GLint *v) -{ - setUniform(location, count, v, GL_INT_VEC2); -} - -void ProgramD3D::setUniform3iv(GLint location, GLsizei count, const GLint *v) -{ - setUniform(location, count, v, GL_INT_VEC3); -} - -void ProgramD3D::setUniform4iv(GLint location, GLsizei count, const GLint *v) -{ - setUniform(location, count, v, GL_INT_VEC4); -} - -void ProgramD3D::setUniform1uiv(GLint location, GLsizei count, const GLuint *v) -{ - setUniform(location, count, v, GL_UNSIGNED_INT); -} - -void ProgramD3D::setUniform2uiv(GLint location, GLsizei count, const GLuint *v) -{ - setUniform(location, count, v, GL_UNSIGNED_INT_VEC2); -} - -void ProgramD3D::setUniform3uiv(GLint location, GLsizei count, const GLuint *v) -{ - setUniform(location, count, v, GL_UNSIGNED_INT_VEC3); -} - -void ProgramD3D::setUniform4uiv(GLint location, GLsizei count, const GLuint *v) -{ - setUniform(location, count, v, GL_UNSIGNED_INT_VEC4); -} - -void ProgramD3D::getUniformfv(GLint location, GLfloat *params) -{ - getUniformv(location, params, GL_FLOAT); -} - -void ProgramD3D::getUniformiv(GLint location, GLint *params) -{ - getUniformv(location, params, GL_INT); -} - -void ProgramD3D::getUniformuiv(GLint location, GLuint *params) -{ - getUniformv(location, params, GL_UNSIGNED_INT); -} - -bool ProgramD3D::linkUniforms(gl::InfoLog &infoLog, const gl::Shader &vertexShader, const gl::Shader &fragmentShader, - const gl::Caps &caps) -{ - const ShaderD3D *vertexShaderD3D = ShaderD3D::makeShaderD3D(vertexShader.getImplementation()); - const ShaderD3D *fragmentShaderD3D = ShaderD3D::makeShaderD3D(fragmentShader.getImplementation()); - - const std::vector &vertexUniforms = vertexShader.getUniforms(); - const std::vector &fragmentUniforms = fragmentShader.getUniforms(); - - // Check that uniforms defined in the vertex and fragment shaders are identical - typedef std::map UniformMap; - UniformMap linkedUniforms; - - for (unsigned int vertexUniformIndex = 0; vertexUniformIndex < vertexUniforms.size(); vertexUniformIndex++) - { - const sh::Uniform &vertexUniform = vertexUniforms[vertexUniformIndex]; - linkedUniforms[vertexUniform.name] = &vertexUniform; - } - - for (unsigned int fragmentUniformIndex = 0; fragmentUniformIndex < fragmentUniforms.size(); fragmentUniformIndex++) - { - const sh::Uniform &fragmentUniform = fragmentUniforms[fragmentUniformIndex]; - UniformMap::const_iterator entry = linkedUniforms.find(fragmentUniform.name); - if (entry != linkedUniforms.end()) - { - const sh::Uniform &vertexUniform = *entry->second; - const std::string &uniformName = "uniform '" + vertexUniform.name + "'"; - if (!gl::ProgramBinary::linkValidateUniforms(infoLog, uniformName, vertexUniform, fragmentUniform)) - { - return false; - } - } - } - - for (unsigned int uniformIndex = 0; uniformIndex < vertexUniforms.size(); uniformIndex++) - { - const sh::Uniform &uniform = vertexUniforms[uniformIndex]; - - if (uniform.staticUse) - { - defineUniformBase(GL_VERTEX_SHADER, uniform, vertexShaderD3D->getUniformRegister(uniform.name)); - } - } - - for (unsigned int uniformIndex = 0; uniformIndex < fragmentUniforms.size(); uniformIndex++) - { - const sh::Uniform &uniform = fragmentUniforms[uniformIndex]; - - if (uniform.staticUse) - { - defineUniformBase(GL_FRAGMENT_SHADER, uniform, fragmentShaderD3D->getUniformRegister(uniform.name)); - } - } - - if (!indexUniforms(infoLog, caps)) - { - return false; - } - - initializeUniformStorage(); - - // special case for gl_DepthRange, the only built-in uniform (also a struct) - if (vertexShaderD3D->usesDepthRange() || fragmentShaderD3D->usesDepthRange()) - { - const sh::BlockMemberInfo &defaultInfo = sh::BlockMemberInfo::getDefaultBlockInfo(); - - mUniforms.push_back(new gl::LinkedUniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.near", 0, -1, defaultInfo)); - mUniforms.push_back(new gl::LinkedUniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.far", 0, -1, defaultInfo)); - mUniforms.push_back(new gl::LinkedUniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.diff", 0, -1, defaultInfo)); - } - - return true; -} - -void ProgramD3D::defineUniformBase(GLenum shader, const sh::Uniform &uniform, unsigned int uniformRegister) -{ - ShShaderOutput outputType = ShaderD3D::getCompilerOutputType(shader); - sh::HLSLBlockEncoder encoder(sh::HLSLBlockEncoder::GetStrategyFor(outputType)); - encoder.skipRegisters(uniformRegister); - - defineUniform(shader, uniform, uniform.name, &encoder); -} - -void ProgramD3D::defineUniform(GLenum shader, const sh::ShaderVariable &uniform, - const std::string &fullName, sh::HLSLBlockEncoder *encoder) -{ - if (uniform.isStruct()) - { - for (unsigned int elementIndex = 0; elementIndex < uniform.elementCount(); elementIndex++) - { - const std::string &elementString = (uniform.isArray() ? ArrayString(elementIndex) : ""); - - encoder->enterAggregateType(); - - for (size_t fieldIndex = 0; fieldIndex < uniform.fields.size(); fieldIndex++) - { - const sh::ShaderVariable &field = uniform.fields[fieldIndex]; - const std::string &fieldFullName = (fullName + elementString + "." + field.name); - - defineUniform(shader, field, fieldFullName, encoder); - } - - encoder->exitAggregateType(); - } - } - else // Not a struct - { - // Arrays are treated as aggregate types - if (uniform.isArray()) - { - encoder->enterAggregateType(); - } - - gl::LinkedUniform *linkedUniform = getUniformByName(fullName); - - if (!linkedUniform) - { - linkedUniform = new gl::LinkedUniform(uniform.type, uniform.precision, fullName, uniform.arraySize, - -1, sh::BlockMemberInfo::getDefaultBlockInfo()); - ASSERT(linkedUniform); - linkedUniform->registerElement = encoder->getCurrentElement(); - mUniforms.push_back(linkedUniform); - } - - ASSERT(linkedUniform->registerElement == encoder->getCurrentElement()); - - if (shader == GL_FRAGMENT_SHADER) - { - linkedUniform->psRegisterIndex = encoder->getCurrentRegister(); - } - else if (shader == GL_VERTEX_SHADER) - { - linkedUniform->vsRegisterIndex = encoder->getCurrentRegister(); - } - else UNREACHABLE(); - - // Advance the uniform offset, to track registers allocation for structs - encoder->encodeType(uniform.type, uniform.arraySize, false); - - // Arrays are treated as aggregate types - if (uniform.isArray()) - { - encoder->exitAggregateType(); - } - } -} - -template -static inline void SetIfDirty(T *dest, const T& source, bool *dirtyFlag) -{ - ASSERT(dest != NULL); - ASSERT(dirtyFlag != NULL); - - *dirtyFlag = *dirtyFlag || (memcmp(dest, &source, sizeof(T)) != 0); - *dest = source; -} - -template -void ProgramD3D::setUniform(GLint location, GLsizei count, const T* v, GLenum targetUniformType) -{ - const int components = gl::VariableComponentCount(targetUniformType); - const GLenum targetBoolType = gl::VariableBoolVectorType(targetUniformType); - - gl::LinkedUniform *targetUniform = getUniformByLocation(location); - - int elementCount = targetUniform->elementCount(); - - count = std::min(elementCount - (int)mUniformIndex[location].element, count); - - if (targetUniform->type == targetUniformType) - { - T *target = reinterpret_cast(targetUniform->data) + mUniformIndex[location].element * 4; - - for (int i = 0; i < count; i++) - { - T *dest = target + (i * 4); - const T *source = v + (i * components); - - for (int c = 0; c < components; c++) - { - SetIfDirty(dest + c, source[c], &targetUniform->dirty); - } - for (int c = components; c < 4; c++) - { - SetIfDirty(dest + c, T(0), &targetUniform->dirty); - } - } - } - else if (targetUniform->type == targetBoolType) - { - GLint *boolParams = reinterpret_cast(targetUniform->data) + mUniformIndex[location].element * 4; - - for (int i = 0; i < count; i++) - { - GLint *dest = boolParams + (i * 4); - const T *source = v + (i * components); - - for (int c = 0; c < components; c++) - { - SetIfDirty(dest + c, (source[c] == static_cast(0)) ? GL_FALSE : GL_TRUE, &targetUniform->dirty); - } - for (int c = components; c < 4; c++) - { - SetIfDirty(dest + c, GL_FALSE, &targetUniform->dirty); - } - } - } - else if (gl::IsSampler(targetUniform->type)) - { - ASSERT(targetUniformType == GL_INT); - - GLint *target = reinterpret_cast(targetUniform->data) + mUniformIndex[location].element * 4; - - bool wasDirty = targetUniform->dirty; - - for (int i = 0; i < count; i++) - { - GLint *dest = target + (i * 4); - const GLint *source = reinterpret_cast(v) + (i * components); - - SetIfDirty(dest + 0, source[0], &targetUniform->dirty); - SetIfDirty(dest + 1, 0, &targetUniform->dirty); - SetIfDirty(dest + 2, 0, &targetUniform->dirty); - SetIfDirty(dest + 3, 0, &targetUniform->dirty); - } - - if (!wasDirty && targetUniform->dirty) - { - mDirtySamplerMapping = true; - } - } - else UNREACHABLE(); -} - -template -bool transposeMatrix(T *target, const GLfloat *value, int targetWidth, int targetHeight, int srcWidth, int srcHeight) -{ - bool dirty = false; - int copyWidth = std::min(targetHeight, srcWidth); - int copyHeight = std::min(targetWidth, srcHeight); - - for (int x = 0; x < copyWidth; x++) - { - for (int y = 0; y < copyHeight; y++) - { - SetIfDirty(target + (x * targetWidth + y), static_cast(value[y * srcWidth + x]), &dirty); - } - } - // clear unfilled right side - for (int y = 0; y < copyWidth; y++) - { - for (int x = copyHeight; x < targetWidth; x++) - { - SetIfDirty(target + (y * targetWidth + x), static_cast(0), &dirty); - } - } - // clear unfilled bottom. - for (int y = copyWidth; y < targetHeight; y++) - { - for (int x = 0; x < targetWidth; x++) - { - SetIfDirty(target + (y * targetWidth + x), static_cast(0), &dirty); - } - } - - return dirty; -} - -template -bool expandMatrix(T *target, const GLfloat *value, int targetWidth, int targetHeight, int srcWidth, int srcHeight) -{ - bool dirty = false; - int copyWidth = std::min(targetWidth, srcWidth); - int copyHeight = std::min(targetHeight, srcHeight); - - for (int y = 0; y < copyHeight; y++) - { - for (int x = 0; x < copyWidth; x++) - { - SetIfDirty(target + (y * targetWidth + x), static_cast(value[y * srcWidth + x]), &dirty); - } - } - // clear unfilled right side - for (int y = 0; y < copyHeight; y++) - { - for (int x = copyWidth; x < targetWidth; x++) - { - SetIfDirty(target + (y * targetWidth + x), static_cast(0), &dirty); - } - } - // clear unfilled bottom. - for (int y = copyHeight; y < targetHeight; y++) - { - for (int x = 0; x < targetWidth; x++) - { - SetIfDirty(target + (y * targetWidth + x), static_cast(0), &dirty); - } - } - - return dirty; -} - -template -void ProgramD3D::setUniformMatrixfv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value, GLenum targetUniformType) -{ - gl::LinkedUniform *targetUniform = getUniformByLocation(location); - - int elementCount = targetUniform->elementCount(); - - count = std::min(elementCount - (int)mUniformIndex[location].element, count); - const unsigned int targetMatrixStride = (4 * rows); - GLfloat *target = (GLfloat*)(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * targetMatrixStride); - - for (int i = 0; i < count; i++) - { - // Internally store matrices as transposed versions to accomodate HLSL matrix indexing - if (transpose == GL_FALSE) - { - targetUniform->dirty = transposeMatrix(target, value, 4, rows, rows, cols) || targetUniform->dirty; - } - else - { - targetUniform->dirty = expandMatrix(target, value, 4, rows, cols, rows) || targetUniform->dirty; - } - target += targetMatrixStride; - value += cols * rows; - } -} - -template -void ProgramD3D::getUniformv(GLint location, T *params, GLenum uniformType) -{ - gl::LinkedUniform *targetUniform = mUniforms[mUniformIndex[location].index]; - - if (gl::IsMatrixType(targetUniform->type)) - { - const int rows = gl::VariableRowCount(targetUniform->type); - const int cols = gl::VariableColumnCount(targetUniform->type); - transposeMatrix(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4 * rows, rows, cols, 4, rows); - } - else if (uniformType == gl::VariableComponentType(targetUniform->type)) - { - unsigned int size = gl::VariableComponentCount(targetUniform->type); - memcpy(params, targetUniform->data + mUniformIndex[location].element * 4 * sizeof(T), - size * sizeof(T)); - } - else - { - unsigned int size = gl::VariableComponentCount(targetUniform->type); - switch (gl::VariableComponentType(targetUniform->type)) - { - case GL_BOOL: - { - GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; - - for (unsigned int i = 0; i < size; i++) - { - params[i] = (boolParams[i] == GL_FALSE) ? static_cast(0) : static_cast(1); - } - } - break; - - case GL_FLOAT: - { - GLfloat *floatParams = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4; - - for (unsigned int i = 0; i < size; i++) - { - params[i] = static_cast(floatParams[i]); - } - } - break; - - case GL_INT: - { - GLint *intParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; - - for (unsigned int i = 0; i < size; i++) - { - params[i] = static_cast(intParams[i]); - } - } - break; - - case GL_UNSIGNED_INT: - { - GLuint *uintParams = (GLuint*)targetUniform->data + mUniformIndex[location].element * 4; - - for (unsigned int i = 0; i < size; i++) - { - params[i] = static_cast(uintParams[i]); - } - } - break; - - default: UNREACHABLE(); - } - } -} - -template -void ProgramD3D::defineUniformBlockMembers(const std::vector &fields, const std::string &prefix, int blockIndex, - sh::BlockLayoutEncoder *encoder, std::vector *blockUniformIndexes, - bool inRowMajorLayout) -{ - for (unsigned int uniformIndex = 0; uniformIndex < fields.size(); uniformIndex++) - { - const VarT &field = fields[uniformIndex]; - const std::string &fieldName = (prefix.empty() ? field.name : prefix + "." + field.name); - - if (field.isStruct()) - { - bool rowMajorLayout = (inRowMajorLayout || IsRowMajorLayout(field)); - - for (unsigned int arrayElement = 0; arrayElement < field.elementCount(); arrayElement++) - { - encoder->enterAggregateType(); - - const std::string uniformElementName = fieldName + (field.isArray() ? ArrayString(arrayElement) : ""); - defineUniformBlockMembers(field.fields, uniformElementName, blockIndex, encoder, blockUniformIndexes, rowMajorLayout); - - encoder->exitAggregateType(); - } - } - else - { - bool isRowMajorMatrix = (gl::IsMatrixType(field.type) && inRowMajorLayout); - - sh::BlockMemberInfo memberInfo = encoder->encodeType(field.type, field.arraySize, isRowMajorMatrix); - - gl::LinkedUniform *newUniform = new gl::LinkedUniform(field.type, field.precision, fieldName, field.arraySize, - blockIndex, memberInfo); - - // add to uniform list, but not index, since uniform block uniforms have no location - blockUniformIndexes->push_back(mUniforms.size()); - mUniforms.push_back(newUniform); - } - } -} - -bool ProgramD3D::defineUniformBlock(gl::InfoLog &infoLog, const gl::Shader &shader, const sh::InterfaceBlock &interfaceBlock, - const gl::Caps &caps) -{ - const ShaderD3D* shaderD3D = ShaderD3D::makeShaderD3D(shader.getImplementation()); - - // create uniform block entries if they do not exist - if (getUniformBlockIndex(interfaceBlock.name) == GL_INVALID_INDEX) - { - std::vector blockUniformIndexes; - const unsigned int blockIndex = mUniformBlocks.size(); - - // define member uniforms - sh::BlockLayoutEncoder *encoder = NULL; - - if (interfaceBlock.layout == sh::BLOCKLAYOUT_STANDARD) - { - encoder = new sh::Std140BlockEncoder; - } - else - { - encoder = new sh::HLSLBlockEncoder(sh::HLSLBlockEncoder::ENCODE_PACKED); - } - ASSERT(encoder); - - defineUniformBlockMembers(interfaceBlock.fields, "", blockIndex, encoder, &blockUniformIndexes, interfaceBlock.isRowMajorLayout); - - size_t dataSize = encoder->getBlockSize(); - - // create all the uniform blocks - if (interfaceBlock.arraySize > 0) - { - for (unsigned int uniformBlockElement = 0; uniformBlockElement < interfaceBlock.arraySize; uniformBlockElement++) - { - gl::UniformBlock *newUniformBlock = new gl::UniformBlock(interfaceBlock.name, uniformBlockElement, dataSize); - newUniformBlock->memberUniformIndexes = blockUniformIndexes; - mUniformBlocks.push_back(newUniformBlock); - } - } - else - { - gl::UniformBlock *newUniformBlock = new gl::UniformBlock(interfaceBlock.name, GL_INVALID_INDEX, dataSize); - newUniformBlock->memberUniformIndexes = blockUniformIndexes; - mUniformBlocks.push_back(newUniformBlock); - } - } - - if (interfaceBlock.staticUse) - { - // Assign registers to the uniform blocks - const GLuint blockIndex = getUniformBlockIndex(interfaceBlock.name); - const unsigned int elementCount = std::max(1u, interfaceBlock.arraySize); - ASSERT(blockIndex != GL_INVALID_INDEX); - ASSERT(blockIndex + elementCount <= mUniformBlocks.size()); - - unsigned int interfaceBlockRegister = shaderD3D->getInterfaceBlockRegister(interfaceBlock.name); - - for (unsigned int uniformBlockElement = 0; uniformBlockElement < elementCount; uniformBlockElement++) - { - gl::UniformBlock *uniformBlock = mUniformBlocks[blockIndex + uniformBlockElement]; - ASSERT(uniformBlock->name == interfaceBlock.name); - - if (!assignUniformBlockRegister(infoLog, uniformBlock, shader.getType(), - interfaceBlockRegister + uniformBlockElement, caps)) - { - return false; - } - } - } - - return true; -} - -bool ProgramD3D::assignSamplers(unsigned int startSamplerIndex, - GLenum samplerType, - unsigned int samplerCount, - std::vector &outSamplers, - GLuint *outUsedRange) -{ - unsigned int samplerIndex = startSamplerIndex; - - do - { - if (samplerIndex < outSamplers.size()) - { - Sampler& sampler = outSamplers[samplerIndex]; - sampler.active = true; - sampler.textureType = GetTextureType(samplerType); - sampler.logicalTextureUnit = 0; - *outUsedRange = std::max(samplerIndex + 1, *outUsedRange); - } - else - { - return false; - } - - samplerIndex++; - } while (samplerIndex < startSamplerIndex + samplerCount); - - return true; -} - -bool ProgramD3D::indexSamplerUniform(const gl::LinkedUniform &uniform, gl::InfoLog &infoLog, const gl::Caps &caps) -{ - ASSERT(gl::IsSampler(uniform.type)); - ASSERT(uniform.vsRegisterIndex != GL_INVALID_INDEX || uniform.psRegisterIndex != GL_INVALID_INDEX); - - if (uniform.vsRegisterIndex != GL_INVALID_INDEX) - { - if (!assignSamplers(uniform.vsRegisterIndex, uniform.type, uniform.arraySize, mSamplersVS, - &mUsedVertexSamplerRange)) - { - infoLog.append("Vertex shader sampler count exceeds the maximum vertex texture units (%d).", - mSamplersVS.size()); - return false; - } - - unsigned int maxVertexVectors = mRenderer->getReservedVertexUniformVectors() + caps.maxVertexUniformVectors; - if (uniform.vsRegisterIndex + uniform.registerCount > maxVertexVectors) - { - infoLog.append("Vertex shader active uniforms exceed GL_MAX_VERTEX_UNIFORM_VECTORS (%u)", - caps.maxVertexUniformVectors); - return false; - } - } - - if (uniform.psRegisterIndex != GL_INVALID_INDEX) - { - if (!assignSamplers(uniform.psRegisterIndex, uniform.type, uniform.arraySize, mSamplersPS, - &mUsedPixelSamplerRange)) - { - infoLog.append("Pixel shader sampler count exceeds MAX_TEXTURE_IMAGE_UNITS (%d).", - mSamplersPS.size()); - return false; - } - - unsigned int maxFragmentVectors = mRenderer->getReservedFragmentUniformVectors() + caps.maxFragmentUniformVectors; - if (uniform.psRegisterIndex + uniform.registerCount > maxFragmentVectors) - { - infoLog.append("Fragment shader active uniforms exceed GL_MAX_FRAGMENT_UNIFORM_VECTORS (%u)", - caps.maxFragmentUniformVectors); - return false; - } - } - - return true; -} - -bool ProgramD3D::indexUniforms(gl::InfoLog &infoLog, const gl::Caps &caps) -{ - for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++) - { - const gl::LinkedUniform &uniform = *mUniforms[uniformIndex]; - - if (gl::IsSampler(uniform.type)) - { - if (!indexSamplerUniform(uniform, infoLog, caps)) - { - return false; - } - } - - for (unsigned int arrayElementIndex = 0; arrayElementIndex < uniform.elementCount(); arrayElementIndex++) - { - mUniformIndex.push_back(gl::VariableLocation(uniform.name, arrayElementIndex, uniformIndex)); - } - } - - return true; -} - -void ProgramD3D::reset() -{ - ProgramImpl::reset(); - - SafeDeleteContainer(mVertexExecutables); - SafeDeleteContainer(mPixelExecutables); - SafeDelete(mGeometryExecutable); - - mTransformFeedbackBufferMode = GL_NONE; - - mVertexHLSL.clear(); - mVertexWorkarounds = ANGLE_D3D_WORKAROUND_NONE; - mShaderVersion = 100; - - mPixelHLSL.clear(); - mPixelWorkarounds = ANGLE_D3D_WORKAROUND_NONE; - mUsesFragDepth = false; - mPixelShaderKey.clear(); - mUsesPointSize = false; - - SafeDelete(mVertexUniformStorage); - SafeDelete(mFragmentUniformStorage); - - mSamplersPS.clear(); - mSamplersVS.clear(); - - mUsedVertexSamplerRange = 0; - mUsedPixelSamplerRange = 0; - mDirtySamplerMapping = true; -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ProgramD3D.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ProgramD3D.h deleted file mode 100644 index 4baab9aa19..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ProgramD3D.h +++ /dev/null @@ -1,219 +0,0 @@ -// -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// ProgramD3D.h: Defines the rx::ProgramD3D class which implements rx::ProgramImpl. - -#ifndef LIBGLESV2_RENDERER_PROGRAMD3D_H_ -#define LIBGLESV2_RENDERER_PROGRAMD3D_H_ - -#include "libGLESv2/renderer/ProgramImpl.h" -#include "libGLESv2/renderer/Workarounds.h" - -#include -#include - -namespace gl -{ -struct LinkedUniform; -struct VariableLocation; -struct VertexFormat; -} - -namespace rx -{ -class RendererD3D; -class UniformStorage; - -class ProgramD3D : public ProgramImpl -{ - public: - ProgramD3D(RendererD3D *renderer); - virtual ~ProgramD3D(); - - static ProgramD3D *makeProgramD3D(ProgramImpl *impl); - static const ProgramD3D *makeProgramD3D(const ProgramImpl *impl); - - const std::vector &getPixelShaderKey() { return mPixelShaderKey; } - int getShaderVersion() const { return mShaderVersion; } - GLenum getTransformFeedbackBufferMode() const { return mTransformFeedbackBufferMode; } - - GLint getSamplerMapping(gl::SamplerType type, unsigned int samplerIndex, const gl::Caps &caps) const; - GLenum getSamplerTextureType(gl::SamplerType type, unsigned int samplerIndex) const; - GLint getUsedSamplerRange(gl::SamplerType type) const; - void updateSamplerMapping(); - bool validateSamplers(gl::InfoLog *infoLog, const gl::Caps &caps); - - bool usesPointSize() const { return mUsesPointSize; } - bool usesPointSpriteEmulation() const; - bool usesGeometryShader() const; - - GLenum getBinaryFormat() { return GL_PROGRAM_BINARY_ANGLE; } - gl::LinkResult load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream); - gl::Error save(gl::BinaryOutputStream *stream); - - gl::Error getPixelExecutableForFramebuffer(const gl::Framebuffer *fbo, ShaderExecutable **outExectuable); - gl::Error getPixelExecutableForOutputLayout(const std::vector &outputLayout, ShaderExecutable **outExectuable); - gl::Error getVertexExecutableForInputLayout(const gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS], ShaderExecutable **outExectuable); - ShaderExecutable *getGeometryExecutable() const { return mGeometryExecutable; } - - gl::LinkResult compileProgramExecutables(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader, - int registers); - - gl::LinkResult link(const gl::Data &data, gl::InfoLog &infoLog, - gl::Shader *fragmentShader, gl::Shader *vertexShader, - const std::vector &transformFeedbackVaryings, - GLenum transformFeedbackBufferMode, - int *registers, std::vector *linkedVaryings, - std::map *outputVariables); - - void getInputLayoutSignature(const gl::VertexFormat inputLayout[], GLenum signature[]) const; - - void initializeUniformStorage(); - gl::Error applyUniforms(); - gl::Error applyUniformBuffers(const std::vector boundBuffers, const gl::Caps &caps); - bool assignUniformBlockRegister(gl::InfoLog &infoLog, gl::UniformBlock *uniformBlock, GLenum shader, - unsigned int registerIndex, const gl::Caps &caps); - void dirtyAllUniforms(); - - void setUniform1fv(GLint location, GLsizei count, const GLfloat *v); - void setUniform2fv(GLint location, GLsizei count, const GLfloat *v); - void setUniform3fv(GLint location, GLsizei count, const GLfloat *v); - void setUniform4fv(GLint location, GLsizei count, const GLfloat *v); - void setUniform1iv(GLint location, GLsizei count, const GLint *v); - void setUniform2iv(GLint location, GLsizei count, const GLint *v); - void setUniform3iv(GLint location, GLsizei count, const GLint *v); - void setUniform4iv(GLint location, GLsizei count, const GLint *v); - void setUniform1uiv(GLint location, GLsizei count, const GLuint *v); - void setUniform2uiv(GLint location, GLsizei count, const GLuint *v); - void setUniform3uiv(GLint location, GLsizei count, const GLuint *v); - void setUniform4uiv(GLint location, GLsizei count, const GLuint *v); - void setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); - void setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); - void setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); - void setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); - void setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); - void setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); - void setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); - void setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); - void setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); - - void getUniformfv(GLint location, GLfloat *params); - void getUniformiv(GLint location, GLint *params); - void getUniformuiv(GLint location, GLuint *params); - - const UniformStorage &getVertexUniformStorage() const { return *mVertexUniformStorage; } - const UniformStorage &getFragmentUniformStorage() const { return *mFragmentUniformStorage; } - - bool linkUniforms(gl::InfoLog &infoLog, const gl::Shader &vertexShader, const gl::Shader &fragmentShader, - const gl::Caps &caps); - bool defineUniformBlock(gl::InfoLog &infoLog, const gl::Shader &shader, const sh::InterfaceBlock &interfaceBlock, const gl::Caps &caps); - - void reset(); - - private: - DISALLOW_COPY_AND_ASSIGN(ProgramD3D); - - class VertexExecutable - { - public: - VertexExecutable(const gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS], - const GLenum signature[gl::MAX_VERTEX_ATTRIBS], - ShaderExecutable *shaderExecutable); - ~VertexExecutable(); - - bool matchesSignature(const GLenum convertedLayout[gl::MAX_VERTEX_ATTRIBS]) const; - - const gl::VertexFormat *inputs() const { return mInputs; } - const GLenum *signature() const { return mSignature; } - ShaderExecutable *shaderExecutable() const { return mShaderExecutable; } - - private: - gl::VertexFormat mInputs[gl::MAX_VERTEX_ATTRIBS]; - GLenum mSignature[gl::MAX_VERTEX_ATTRIBS]; - ShaderExecutable *mShaderExecutable; - }; - - class PixelExecutable - { - public: - PixelExecutable(const std::vector &outputSignature, ShaderExecutable *shaderExecutable); - ~PixelExecutable(); - - bool matchesSignature(const std::vector &signature) const { return mOutputSignature == signature; } - - const std::vector &outputSignature() const { return mOutputSignature; } - ShaderExecutable *shaderExecutable() const { return mShaderExecutable; } - - private: - std::vector mOutputSignature; - ShaderExecutable *mShaderExecutable; - }; - - struct Sampler - { - Sampler(); - - bool active; - GLint logicalTextureUnit; - GLenum textureType; - }; - - void defineUniformBase(GLenum shader, const sh::Uniform &uniform, unsigned int uniformRegister); - void defineUniform(GLenum shader, const sh::ShaderVariable &uniform, const std::string &fullName, - sh::HLSLBlockEncoder *encoder); - bool indexSamplerUniform(const gl::LinkedUniform &uniform, gl::InfoLog &infoLog, const gl::Caps &caps); - bool indexUniforms(gl::InfoLog &infoLog, const gl::Caps &caps); - static bool assignSamplers(unsigned int startSamplerIndex, GLenum samplerType, unsigned int samplerCount, - std::vector &outSamplers, GLuint *outUsedRange); - - template - void setUniform(GLint location, GLsizei count, const T* v, GLenum targetUniformType); - - template - void setUniformMatrixfv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value, GLenum targetUniformType); - - template - void getUniformv(GLint location, T *params, GLenum uniformType); - - template - void defineUniformBlockMembers(const std::vector &fields, const std::string &prefix, int blockIndex, - sh::BlockLayoutEncoder *encoder, std::vector *blockUniformIndexes, - bool inRowMajorLayout); - - RendererD3D *mRenderer; - DynamicHLSL *mDynamicHLSL; - - std::vector mVertexExecutables; - std::vector mPixelExecutables; - ShaderExecutable *mGeometryExecutable; - - std::string mVertexHLSL; - D3DWorkaroundType mVertexWorkarounds; - - std::string mPixelHLSL; - D3DWorkaroundType mPixelWorkarounds; - bool mUsesFragDepth; - std::vector mPixelShaderKey; - - bool mUsesPointSize; - - UniformStorage *mVertexUniformStorage; - UniformStorage *mFragmentUniformStorage; - - GLenum mTransformFeedbackBufferMode; - - std::vector mSamplersPS; - std::vector mSamplersVS; - GLuint mUsedVertexSamplerRange; - GLuint mUsedPixelSamplerRange; - bool mDirtySamplerMapping; - - int mShaderVersion; -}; - -} - -#endif // LIBGLESV2_RENDERER_PROGRAMD3D_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RenderbufferD3D.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RenderbufferD3D.cpp deleted file mode 100644 index cb4af367a2..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RenderbufferD3D.cpp +++ /dev/null @@ -1,108 +0,0 @@ -// -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// RenderbufferD3d.cpp: Implements the RenderbufferD3D class, a specialization of RenderbufferImpl - - -#include "libGLESv2/renderer/d3d/RenderbufferD3D.h" - -#include "libGLESv2/renderer/d3d/RendererD3D.h" -#include "libGLESv2/renderer/RenderTarget.h" - -namespace rx -{ -RenderbufferD3D::RenderbufferD3D(RendererD3D *renderer) : mRenderer(renderer) -{ - mRenderTarget = NULL; -} - -RenderbufferD3D::~RenderbufferD3D() -{ - SafeDelete(mRenderTarget); -} - -RenderbufferD3D *RenderbufferD3D::makeRenderbufferD3D(RenderbufferImpl *renderbuffer) -{ - ASSERT(HAS_DYNAMIC_TYPE(RenderbufferD3D*, renderbuffer)); - return static_cast(renderbuffer); -} - -gl::Error RenderbufferD3D::setStorage(GLsizei width, GLsizei height, GLenum internalformat, GLsizei samples) -{ - // If the renderbuffer parameters are queried, the calling function - // will expect one of the valid renderbuffer formats for use in - // glRenderbufferStorage, but we should create depth and stencil buffers - // as DEPTH24_STENCIL8 - GLenum creationFormat = internalformat; - if (internalformat == GL_DEPTH_COMPONENT16 || internalformat == GL_STENCIL_INDEX8) - { - creationFormat = GL_DEPTH24_STENCIL8_OES; - } - - RenderTarget *newRT = NULL; - gl::Error error = mRenderer->createRenderTarget(width, height, creationFormat, samples, &newRT); - if (error.isError()) - { - return error; - } - - SafeDelete(mRenderTarget); - mRenderTarget = newRT; - - return gl::Error(GL_NO_ERROR); -} - -gl::Error RenderbufferD3D::setStorage(SwapChain *swapChain, bool depth) -{ - RenderTarget *newRT = NULL; - gl::Error error = mRenderer->createRenderTarget(swapChain, depth, &newRT); - if (error.isError()) - { - return error; - } - - SafeDelete(mRenderTarget); - mRenderTarget = newRT; - - return gl::Error(GL_NO_ERROR); -} - -GLsizei RenderbufferD3D::getWidth() const -{ - return (mRenderTarget ? mRenderTarget->getWidth() : 0); -} - -GLsizei RenderbufferD3D::getHeight() const -{ - return (mRenderTarget ? mRenderTarget->getHeight() : 0); -} - -GLenum RenderbufferD3D::getInternalFormat() const -{ - return (mRenderTarget ? mRenderTarget->getInternalFormat() : GL_RGBA4); -} - -GLenum RenderbufferD3D::getActualFormat() const -{ - return (mRenderTarget ? mRenderTarget->getActualFormat() : GL_RGBA4); -} - -GLsizei RenderbufferD3D::getSamples() const -{ - return (mRenderTarget ? mRenderTarget->getSamples() : 0); -} - -RenderTarget *RenderbufferD3D::getRenderTarget() -{ - return mRenderTarget; -} - -unsigned int RenderbufferD3D::getRenderTargetSerial() const -{ - return (mRenderTarget ? mRenderTarget->getSerial() : 0); -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RenderbufferD3D.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RenderbufferD3D.h deleted file mode 100644 index 9440a449f2..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RenderbufferD3D.h +++ /dev/null @@ -1,51 +0,0 @@ -// -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// RenderbufferD3d.h: Defines the RenderbufferD3D class which implements RenderbufferImpl. - -#ifndef LIBGLESV2_RENDERER_RENDERBUFFERD3D_H_ -#define LIBGLESV2_RENDERER_RENDERBUFFERD3D_H_ - -#include "angle_gl.h" - -#include "common/angleutils.h" -#include "libGLESv2/renderer/RenderbufferImpl.h" - -namespace rx -{ -class RendererD3D; -class RenderTarget; -class SwapChain; - -class RenderbufferD3D : public RenderbufferImpl -{ - public: - RenderbufferD3D(RendererD3D *renderer); - virtual ~RenderbufferD3D(); - - static RenderbufferD3D *makeRenderbufferD3D(RenderbufferImpl *renderbuffer); - - virtual gl::Error setStorage(GLsizei width, GLsizei height, GLenum internalformat, GLsizei samples) override; - gl::Error setStorage(SwapChain *swapChain, bool depth); - - virtual GLsizei getWidth() const; - virtual GLsizei getHeight() const; - virtual GLenum getInternalFormat() const; - virtual GLenum getActualFormat() const; - virtual GLsizei getSamples() const; - - RenderTarget *getRenderTarget(); - unsigned int getRenderTargetSerial() const; - - private: - DISALLOW_COPY_AND_ASSIGN(RenderbufferD3D); - - RendererD3D *mRenderer; - RenderTarget *mRenderTarget; -}; -} - -#endif // LIBGLESV2_RENDERER_RENDERBUFFERD3D_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RendererD3D.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RendererD3D.cpp deleted file mode 100644 index 5cddd8ab5e..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RendererD3D.cpp +++ /dev/null @@ -1,801 +0,0 @@ -// -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// RendererD3D.cpp: Implementation of the base D3D Renderer. - -#include "libGLESv2/renderer/d3d/RendererD3D.h" - -#include "libGLESv2/renderer/d3d/IndexDataManager.h" -#include "libGLESv2/Framebuffer.h" -#include "libGLESv2/FramebufferAttachment.h" -#include "libGLESv2/ResourceManager.h" -#include "libGLESv2/State.h" -#include "libGLESv2/VertexArray.h" -#include "libGLESv2/formatutils.h" -#include "common/utilities.h" - -namespace rx -{ - -RendererD3D::RendererD3D(egl::Display *display) - : mDisplay(display) -{ -} - -RendererD3D::~RendererD3D() -{ - cleanup(); -} - -void RendererD3D::cleanup() -{ - for (gl::TextureMap::iterator i = mIncompleteTextures.begin(); i != mIncompleteTextures.end(); ++i) - { - i->second.set(NULL); - } - mIncompleteTextures.clear(); -} - -// static -RendererD3D *RendererD3D::makeRendererD3D(Renderer *renderer) -{ - ASSERT(HAS_DYNAMIC_TYPE(RendererD3D*, renderer)); - return static_cast(renderer); -} - -gl::Error RendererD3D::drawElements(const gl::Data &data, - GLenum mode, GLsizei count, GLenum type, - const GLvoid *indices, GLsizei instances, - const RangeUI &indexRange) -{ - ASSERT(data.state->getCurrentProgramId() != 0); - - gl::ProgramBinary *programBinary = data.state->getCurrentProgramBinary(); - programBinary->updateSamplerMapping(); - - gl::Error error = generateSwizzles(data); - if (error.isError()) - { - return error; - } - - if (!applyPrimitiveType(mode, count)) - { - return gl::Error(GL_NO_ERROR); - } - - error = applyRenderTarget(data, mode, false); - if (error.isError()) - { - return error; - } - - error = applyState(data, mode); - if (error.isError()) - { - return error; - } - - gl::VertexArray *vao = data.state->getVertexArray(); - TranslatedIndexData indexInfo; - indexInfo.indexRange = indexRange; - error = applyIndexBuffer(indices, vao->getElementArrayBuffer(), count, mode, type, &indexInfo); - if (error.isError()) - { - return error; - } - - GLsizei vertexCount = indexInfo.indexRange.length() + 1; - error = applyVertexBuffer(*data.state, indexInfo.indexRange.start, vertexCount, instances); - if (error.isError()) - { - return error; - } - - bool transformFeedbackActive = applyTransformFeedbackBuffers(data); - // Transform feedback is not allowed for DrawElements, this error should have been caught at the API validation - // layer. - ASSERT(!transformFeedbackActive); - - error = applyShaders(data, transformFeedbackActive); - if (error.isError()) - { - return error; - } - - error = applyTextures(data); - if (error.isError()) - { - return error; - } - - error = applyUniformBuffers(data); - if (error.isError()) - { - return error; - } - - if (!skipDraw(data, mode)) - { - error = drawElements(mode, count, type, indices, vao->getElementArrayBuffer(), indexInfo, instances); - if (error.isError()) - { - return error; - } - } - - return gl::Error(GL_NO_ERROR); -} - -gl::Error RendererD3D::drawArrays(const gl::Data &data, - GLenum mode, GLint first, - GLsizei count, GLsizei instances) -{ - ASSERT(data.state->getCurrentProgramId() != 0); - - gl::ProgramBinary *programBinary = data.state->getCurrentProgramBinary(); - programBinary->updateSamplerMapping(); - - gl::Error error = generateSwizzles(data); - if (error.isError()) - { - return error; - } - - if (!applyPrimitiveType(mode, count)) - { - return gl::Error(GL_NO_ERROR); - } - - error = applyRenderTarget(data, mode, false); - if (error.isError()) - { - return error; - } - - error = applyState(data, mode); - if (error.isError()) - { - return error; - } - - error = applyVertexBuffer(*data.state, first, count, instances); - if (error.isError()) - { - return error; - } - - bool transformFeedbackActive = applyTransformFeedbackBuffers(data); - - error = applyShaders(data, transformFeedbackActive); - if (error.isError()) - { - return error; - } - - error = applyTextures(data); - if (error.isError()) - { - return error; - } - - error = applyUniformBuffers(data); - if (error.isError()) - { - return error; - } - - if (!skipDraw(data, mode)) - { - error = drawArrays(mode, count, instances, transformFeedbackActive); - if (error.isError()) - { - return error; - } - - if (transformFeedbackActive) - { - markTransformFeedbackUsage(data); - } - } - - return gl::Error(GL_NO_ERROR); -} - -gl::Error RendererD3D::generateSwizzles(const gl::Data &data, gl::SamplerType type) -{ - gl::ProgramBinary *programBinary = data.state->getCurrentProgramBinary(); - - size_t samplerRange = programBinary->getUsedSamplerRange(type); - - for (size_t i = 0; i < samplerRange; i++) - { - GLenum textureType = programBinary->getSamplerTextureType(type, i); - GLint textureUnit = programBinary->getSamplerMapping(type, i, *data.caps); - if (textureUnit != -1) - { - gl::Texture *texture = data.state->getSamplerTexture(textureUnit, textureType); - ASSERT(texture); - if (texture->getSamplerState().swizzleRequired()) - { - gl::Error error = generateSwizzle(texture); - if (error.isError()) - { - return error; - } - } - } - } - - return gl::Error(GL_NO_ERROR); -} - -gl::Error RendererD3D::generateSwizzles(const gl::Data &data) -{ - gl::Error error = generateSwizzles(data, gl::SAMPLER_VERTEX); - if (error.isError()) - { - return error; - } - - error = generateSwizzles(data, gl::SAMPLER_PIXEL); - if (error.isError()) - { - return error; - } - - return gl::Error(GL_NO_ERROR); -} - -// Applies the render target surface, depth stencil surface, viewport rectangle and -// scissor rectangle to the renderer -gl::Error RendererD3D::applyRenderTarget(const gl::Data &data, GLenum drawMode, bool ignoreViewport) -{ - const gl::Framebuffer *framebufferObject = data.state->getDrawFramebuffer(); - ASSERT(framebufferObject && framebufferObject->completeness(data) == GL_FRAMEBUFFER_COMPLETE); - - gl::Error error = applyRenderTarget(framebufferObject); - if (error.isError()) - { - return error; - } - - float nearZ, farZ; - data.state->getDepthRange(&nearZ, &farZ); - setViewport(data.state->getViewport(), nearZ, farZ, drawMode, - data.state->getRasterizerState().frontFace, ignoreViewport); - - setScissorRectangle(data.state->getScissor(), data.state->isScissorTestEnabled()); - - return gl::Error(GL_NO_ERROR); -} - -// Applies the fixed-function state (culling, depth test, alpha blending, stenciling, etc) to the Direct3D device -gl::Error RendererD3D::applyState(const gl::Data &data, GLenum drawMode) -{ - const gl::Framebuffer *framebufferObject = data.state->getDrawFramebuffer(); - int samples = framebufferObject->getSamples(data); - - gl::RasterizerState rasterizer = data.state->getRasterizerState(); - rasterizer.pointDrawMode = (drawMode == GL_POINTS); - rasterizer.multiSample = (samples != 0); - - gl::Error error = setRasterizerState(rasterizer); - if (error.isError()) - { - return error; - } - - unsigned int mask = 0; - if (data.state->isSampleCoverageEnabled()) - { - GLclampf coverageValue; - bool coverageInvert = false; - data.state->getSampleCoverageParams(&coverageValue, &coverageInvert); - if (coverageValue != 0) - { - float threshold = 0.5f; - - for (int i = 0; i < samples; ++i) - { - mask <<= 1; - - if ((i + 1) * coverageValue >= threshold) - { - threshold += 1.0f; - mask |= 1; - } - } - } - - if (coverageInvert) - { - mask = ~mask; - } - } - else - { - mask = 0xFFFFFFFF; - } - error = setBlendState(framebufferObject, data.state->getBlendState(), data.state->getBlendColor(), mask); - if (error.isError()) - { - return error; - } - - error = setDepthStencilState(data.state->getDepthStencilState(), data.state->getStencilRef(), - data.state->getStencilBackRef(), rasterizer.frontFace == GL_CCW); - if (error.isError()) - { - return error; - } - - return gl::Error(GL_NO_ERROR); -} - -bool RendererD3D::applyTransformFeedbackBuffers(const gl::Data &data) -{ - gl::TransformFeedback *curTransformFeedback = data.state->getCurrentTransformFeedback(); - if (curTransformFeedback && curTransformFeedback->isStarted() && !curTransformFeedback->isPaused()) - { - applyTransformFeedbackBuffers(*data.state); - return true; - } - else - { - return false; - } -} - -// Applies the shaders and shader constants to the Direct3D device -gl::Error RendererD3D::applyShaders(const gl::Data &data, bool transformFeedbackActive) -{ - gl::ProgramBinary *programBinary = data.state->getCurrentProgramBinary(); - - gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS]; - gl::VertexFormat::GetInputLayout(inputLayout, programBinary, *data.state); - - const gl::Framebuffer *fbo = data.state->getDrawFramebuffer(); - - gl::Error error = applyShaders(programBinary, inputLayout, fbo, data.state->getRasterizerState().rasterizerDiscard, transformFeedbackActive); - if (error.isError()) - { - return error; - } - - return programBinary->applyUniforms(); -} - -// For each Direct3D 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). -gl::Error RendererD3D::applyTextures(const gl::Data &data, gl::SamplerType shaderType, - const FramebufferTextureSerialArray &framebufferSerials, size_t framebufferSerialCount) -{ - gl::ProgramBinary *programBinary = data.state->getCurrentProgramBinary(); - - size_t samplerRange = programBinary->getUsedSamplerRange(shaderType); - for (size_t samplerIndex = 0; samplerIndex < samplerRange; samplerIndex++) - { - GLenum textureType = programBinary->getSamplerTextureType(shaderType, samplerIndex); - GLint textureUnit = programBinary->getSamplerMapping(shaderType, samplerIndex, *data.caps); - if (textureUnit != -1) - { - gl::Texture *texture = data.state->getSamplerTexture(textureUnit, textureType); - ASSERT(texture); - gl::SamplerState sampler = texture->getSamplerState(); - - gl::Sampler *samplerObject = data.state->getSampler(textureUnit); - if (samplerObject) - { - samplerObject->getState(&sampler); - } - - // TODO: std::binary_search may become unavailable using older versions of GCC - if (texture->isSamplerComplete(sampler, *data.textureCaps, *data.extensions, data.clientVersion) && - !std::binary_search(framebufferSerials.begin(), framebufferSerials.begin() + framebufferSerialCount, texture->getTextureSerial())) - { - gl::Error error = setSamplerState(shaderType, samplerIndex, texture, sampler); - if (error.isError()) - { - return error; - } - - error = setTexture(shaderType, samplerIndex, texture); - if (error.isError()) - { - return error; - } - } - else - { - // Texture is not sampler complete or it is in use by the framebuffer. Bind the incomplete texture. - gl::Texture *incompleteTexture = getIncompleteTexture(textureType); - gl::Error error = setTexture(shaderType, samplerIndex, incompleteTexture); - if (error.isError()) - { - return error; - } - } - } - else - { - // No texture bound to this slot even though it is used by the shader, bind a NULL texture - gl::Error error = setTexture(shaderType, samplerIndex, NULL); - if (error.isError()) - { - return error; - } - } - } - - // Set all the remaining textures to NULL - size_t samplerCount = (shaderType == gl::SAMPLER_PIXEL) ? data.caps->maxTextureImageUnits - : data.caps->maxVertexTextureImageUnits; - for (size_t samplerIndex = samplerRange; samplerIndex < samplerCount; samplerIndex++) - { - gl::Error error = setTexture(shaderType, samplerIndex, NULL); - if (error.isError()) - { - return error; - } - } - - return gl::Error(GL_NO_ERROR); -} - -gl::Error RendererD3D::applyTextures(const gl::Data &data) -{ - FramebufferTextureSerialArray framebufferSerials; - size_t framebufferSerialCount = getBoundFramebufferTextureSerials(data, &framebufferSerials); - - gl::Error error = applyTextures(data, gl::SAMPLER_VERTEX, framebufferSerials, framebufferSerialCount); - if (error.isError()) - { - return error; - } - - error = applyTextures(data, gl::SAMPLER_PIXEL, framebufferSerials, framebufferSerialCount); - if (error.isError()) - { - return error; - } - - return gl::Error(GL_NO_ERROR); -} - -gl::Error RendererD3D::applyUniformBuffers(const gl::Data &data) -{ - gl::Program *programObject = data.resourceManager->getProgram(data.state->getCurrentProgramId()); - gl::ProgramBinary *programBinary = programObject->getProgramBinary(); - - std::vector boundBuffers; - - for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < programBinary->getActiveUniformBlockCount(); uniformBlockIndex++) - { - GLuint blockBinding = programObject->getUniformBlockBinding(uniformBlockIndex); - - if (data.state->getIndexedUniformBuffer(blockBinding)->id() == 0) - { - // undefined behaviour - return gl::Error(GL_INVALID_OPERATION, "It is undefined behaviour to have a used but unbound uniform buffer."); - } - else - { - gl::Buffer *uniformBuffer = data.state->getIndexedUniformBuffer(blockBinding); - ASSERT(uniformBuffer); - boundBuffers.push_back(uniformBuffer); - } - } - - return programBinary->applyUniformBuffers(boundBuffers, *data.caps); -} - -bool RendererD3D::skipDraw(const gl::Data &data, GLenum drawMode) -{ - if (drawMode == GL_POINTS) - { - // ProgramBinary assumes non-point rendering if gl_PointSize isn't written, - // which affects varying interpolation. Since the value of gl_PointSize is - // undefined when not written, just skip drawing to avoid unexpected results. - if (!data.state->getCurrentProgramBinary()->usesPointSize()) - { - // This is stictly speaking not an error, but developers should be - // notified of risking undefined behavior. - ERR("Point rendering without writing to gl_PointSize."); - - return true; - } - } - else if (gl::IsTriangleMode(drawMode)) - { - if (data.state->getRasterizerState().cullFace && data.state->getRasterizerState().cullMode == GL_FRONT_AND_BACK) - { - return true; - } - } - - return false; -} - -void RendererD3D::markTransformFeedbackUsage(const gl::Data &data) -{ - for (size_t i = 0; i < data.caps->maxTransformFeedbackSeparateAttributes; i++) - { - gl::Buffer *buffer = data.state->getIndexedTransformFeedbackBuffer(i); - if (buffer) - { - buffer->markTransformFeedbackUsage(); - } - } -} - -size_t RendererD3D::getBoundFramebufferTextureSerials(const gl::Data &data, - FramebufferTextureSerialArray *outSerialArray) -{ - size_t serialCount = 0; - - const gl::Framebuffer *drawFramebuffer = data.state->getDrawFramebuffer(); - for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; i++) - { - gl::FramebufferAttachment *attachment = drawFramebuffer->getColorbuffer(i); - if (attachment && attachment->isTexture()) - { - gl::Texture *texture = attachment->getTexture(); - (*outSerialArray)[serialCount++] = texture->getTextureSerial(); - } - } - - gl::FramebufferAttachment *depthStencilAttachment = drawFramebuffer->getDepthOrStencilbuffer(); - if (depthStencilAttachment && depthStencilAttachment->isTexture()) - { - gl::Texture *depthStencilTexture = depthStencilAttachment->getTexture(); - (*outSerialArray)[serialCount++] = depthStencilTexture->getTextureSerial(); - } - - std::sort(outSerialArray->begin(), outSerialArray->begin() + serialCount); - - return serialCount; -} - -gl::Texture *RendererD3D::getIncompleteTexture(GLenum type) -{ - if (mIncompleteTextures.find(type) == mIncompleteTextures.end()) - { - const GLubyte color[] = { 0, 0, 0, 255 }; - const gl::PixelUnpackState incompleteUnpackState(1); - - gl::Texture* t = NULL; - switch (type) - { - default: - UNREACHABLE(); - // default falls through to TEXTURE_2D - - case GL_TEXTURE_2D: - { - gl::Texture2D *incomplete2d = new gl::Texture2D(createTexture(GL_TEXTURE_2D), gl::Texture::INCOMPLETE_TEXTURE_ID); - incomplete2d->setImage(0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); - t = incomplete2d; - } - break; - - case GL_TEXTURE_CUBE_MAP: - { - gl::TextureCubeMap *incompleteCube = new gl::TextureCubeMap(createTexture(GL_TEXTURE_CUBE_MAP), gl::Texture::INCOMPLETE_TEXTURE_ID); - - incompleteCube->setImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); - incompleteCube->setImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); - incompleteCube->setImage(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); - incompleteCube->setImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); - incompleteCube->setImage(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); - incompleteCube->setImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); - - t = incompleteCube; - } - break; - - case GL_TEXTURE_3D: - { - gl::Texture3D *incomplete3d = new gl::Texture3D(createTexture(GL_TEXTURE_3D), gl::Texture::INCOMPLETE_TEXTURE_ID); - incomplete3d->setImage(0, 1, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); - - t = incomplete3d; - } - break; - - case GL_TEXTURE_2D_ARRAY: - { - gl::Texture2DArray *incomplete2darray = new gl::Texture2DArray(createTexture(GL_TEXTURE_2D_ARRAY), gl::Texture::INCOMPLETE_TEXTURE_ID); - incomplete2darray->setImage(0, 1, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); - - t = incomplete2darray; - } - break; - } - - mIncompleteTextures[type].set(t); - } - - return mIncompleteTextures[type].get(); -} - -gl::Error RendererD3D::clear(const gl::Data &data, GLbitfield mask) -{ - gl::ClearParameters clearParams = data.state->getClearParameters(mask); - - // Clips the clear to the scissor rectangle but not the viewport - gl::Error error = applyRenderTarget(data, GL_TRIANGLES, true); - if (error.isError()) - { - return error; - } - - return clear(clearParams, data.state->getDrawFramebuffer()); -} - -gl::Error RendererD3D::clearBufferfv(const gl::Data &data, GLenum buffer, GLint drawbuffer, const GLfloat *values) -{ - // glClearBufferfv can be called to clear the color buffer or depth buffer - gl::ClearParameters clearParams = data.state->getClearParameters(0); - - if (buffer == GL_COLOR) - { - for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++) - { - clearParams.clearColor[i] = (drawbuffer == static_cast(i)); - } - clearParams.colorFClearValue = gl::ColorF(values[0], values[1], values[2], values[3]); - clearParams.colorClearType = GL_FLOAT; - } - - if (buffer == GL_DEPTH) - { - clearParams.clearDepth = true; - clearParams.depthClearValue = values[0]; - } - - // Clips the clear to the scissor rectangle but not the viewport - gl::Error error = applyRenderTarget(data, GL_TRIANGLES, true); - if (error.isError()) - { - return error; - } - - return clear(clearParams, data.state->getDrawFramebuffer()); -} - -gl::Error RendererD3D::clearBufferuiv(const gl::Data &data, GLenum buffer, GLint drawbuffer, const GLuint *values) -{ - // glClearBufferuiv can only be called to clear a color buffer - gl::ClearParameters clearParams = data.state->getClearParameters(0); - for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++) - { - clearParams.clearColor[i] = (drawbuffer == static_cast(i)); - } - clearParams.colorUIClearValue = gl::ColorUI(values[0], values[1], values[2], values[3]); - clearParams.colorClearType = GL_UNSIGNED_INT; - - // Clips the clear to the scissor rectangle but not the viewport - gl::Error error = applyRenderTarget(data, GL_TRIANGLES, true); - if (error.isError()) - { - return error; - } - - return clear(clearParams, data.state->getDrawFramebuffer()); -} - -gl::Error RendererD3D::clearBufferiv(const gl::Data &data, GLenum buffer, GLint drawbuffer, const GLint *values) -{ - // glClearBufferiv can be called to clear the color buffer or stencil buffer - gl::ClearParameters clearParams = data.state->getClearParameters(0); - - if (buffer == GL_COLOR) - { - for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++) - { - clearParams.clearColor[i] = (drawbuffer == static_cast(i)); - } - clearParams.colorIClearValue = gl::ColorI(values[0], values[1], values[2], values[3]); - clearParams.colorClearType = GL_INT; - } - - if (buffer == GL_STENCIL) - { - clearParams.clearStencil = true; - clearParams.stencilClearValue = values[1]; - } - - // Clips the clear to the scissor rectangle but not the viewport - gl::Error error = applyRenderTarget(data, GL_TRIANGLES, true); - if (error.isError()) - { - return error; - } - - return clear(clearParams, data.state->getDrawFramebuffer()); -} - -gl::Error RendererD3D::clearBufferfi(const gl::Data &data, GLenum buffer, GLint drawbuffer, - GLfloat depth, GLint stencil) -{ - if (data.state->isRasterizerDiscardEnabled()) - { - return gl::Error(GL_NO_ERROR); - } - - // glClearBufferfi can only be called to clear a depth stencil buffer - gl::ClearParameters clearParams = data.state->getClearParameters(0); - clearParams.clearDepth = true; - clearParams.depthClearValue = depth; - clearParams.clearStencil = true; - clearParams.stencilClearValue = stencil; - - // Clips the clear to the scissor rectangle but not the viewport - gl::Error error = applyRenderTarget(data, GL_TRIANGLES, true); - if (error.isError()) - { - return error; - } - - return clear(clearParams, data.state->getDrawFramebuffer()); -} - -gl::Error RendererD3D::blitFramebuffer(const gl::Data &data, - GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, - GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, - GLbitfield mask, GLenum filter) -{ - const gl::Framebuffer *readFramebuffer = data.state->getReadFramebuffer(); - const gl::Framebuffer *drawFramebuffer = data.state->getDrawFramebuffer(); - - bool blitRenderTarget = false; - bool blitDepth = false; - bool blitStencil = false; - if ((mask & GL_COLOR_BUFFER_BIT) && readFramebuffer->getReadColorbuffer() && drawFramebuffer->getFirstColorbuffer()) - { - blitRenderTarget = true; - } - if ((mask & GL_STENCIL_BUFFER_BIT) && readFramebuffer->getStencilbuffer() && drawFramebuffer->getStencilbuffer()) - { - blitStencil = true; - } - if ((mask & GL_DEPTH_BUFFER_BIT) && readFramebuffer->getDepthbuffer() && drawFramebuffer->getDepthbuffer()) - { - blitDepth = true; - } - - gl::Rectangle srcRect(srcX0, srcY0, srcX1 - srcX0, srcY1 - srcY0); - gl::Rectangle dstRect(dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0); - if (blitRenderTarget || blitDepth || blitStencil) - { - const gl::Rectangle *scissor = data.state->isScissorTestEnabled() ? &data.state->getScissor() : NULL; - gl::Error error = blitRect(readFramebuffer, srcRect, drawFramebuffer, dstRect, scissor, - blitRenderTarget, blitDepth, blitStencil, filter); - if (error.isError()) - { - return error; - } - } - - return gl::Error(GL_NO_ERROR); -} - -gl::Error RendererD3D::readPixels(const gl::Data &data, GLint x, GLint y, GLsizei width, GLsizei height, - GLenum format, GLenum type, GLsizei *bufSize, void* pixels) -{ - const gl::Framebuffer *framebuffer = data.state->getReadFramebuffer(); - - GLenum sizedInternalFormat = gl::GetSizedInternalFormat(format, type); - const gl::InternalFormat &sizedFormatInfo = gl::GetInternalFormatInfo(sizedInternalFormat); - GLuint outputPitch = sizedFormatInfo.computeRowPitch(type, width, data.state->getPackAlignment()); - - return readPixels(framebuffer, x, y, width, height, format, type, outputPitch, data.state->getPackState(), - reinterpret_cast(pixels)); -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RendererD3D.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RendererD3D.h deleted file mode 100644 index a2f778763c..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RendererD3D.h +++ /dev/null @@ -1,197 +0,0 @@ - -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// RendererD3D.h: Defines a back-end specific class for the DirectX renderer. - -#ifndef LIBGLESV2_RENDERER_RENDERERD3D_H_ -#define LIBGLESV2_RENDERER_RENDERERD3D_H_ - -#include "libGLESv2/renderer/Renderer.h" -#include "libGLESv2/Data.h" - -//FIXME(jmadill): std::array is currently prohibited by Chromium style guide -#include - -namespace gl -{ -class InfoLog; -struct LinkedVarying; -class Texture; -} - -namespace rx -{ -class TextureStorage; -class VertexBuffer; -class IndexBuffer; -class ShaderExecutable; -class SwapChain; -class RenderTarget; -class Image; -class TextureStorage; -class UniformStorage; - -class RendererD3D : public Renderer -{ - public: - explicit RendererD3D(egl::Display *display); - virtual ~RendererD3D(); - - static RendererD3D *makeRendererD3D(Renderer *renderer); - - gl::Error drawArrays(const gl::Data &data, - GLenum mode, GLint first, - GLsizei count, GLsizei instances) override; - - gl::Error drawElements(const gl::Data &data, - GLenum mode, GLsizei count, GLenum type, - const GLvoid *indices, GLsizei instances, - const RangeUI &indexRange) override; - - gl::Error clear(const gl::Data &data, GLbitfield mask) override; - gl::Error clearBufferfv(const gl::Data &data, GLenum buffer, int drawbuffer, const GLfloat *values) override; - gl::Error clearBufferuiv(const gl::Data &data, GLenum buffer, int drawbuffer, const GLuint *values) override; - gl::Error clearBufferiv(const gl::Data &data, GLenum buffer, int drawbuffer, const GLint *values) override; - gl::Error clearBufferfi(const gl::Data &data, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) override; - - gl::Error readPixels(const gl::Data &data, GLint x, GLint y, GLsizei width, GLsizei height, - GLenum format, GLenum type, GLsizei *bufSize, void* pixels) override; - - gl::Error blitFramebuffer(const gl::Data &data, - GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, - GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, - GLbitfield mask, GLenum filter) override; - - // Direct3D Specific methods - virtual SwapChain *createSwapChain(NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) = 0; - - virtual gl::Error generateSwizzle(gl::Texture *texture) = 0; - virtual gl::Error setSamplerState(gl::SamplerType type, int index, gl::Texture *texture, const gl::SamplerState &sampler) = 0; - virtual gl::Error setTexture(gl::SamplerType type, int index, gl::Texture *texture) = 0; - - virtual gl::Error setUniformBuffers(const gl::Buffer *vertexUniformBuffers[], const gl::Buffer *fragmentUniformBuffers[]) = 0; - - virtual gl::Error setRasterizerState(const gl::RasterizerState &rasterState) = 0; - virtual gl::Error setBlendState(const gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::ColorF &blendColor, - unsigned int sampleMask) = 0; - virtual gl::Error setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef, - int stencilBackRef, bool frontFaceCCW) = 0; - - virtual void setScissorRectangle(const gl::Rectangle &scissor, bool enabled) = 0; - virtual void setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace, - bool ignoreViewport) = 0; - - virtual gl::Error applyRenderTarget(const gl::Framebuffer *frameBuffer) = 0; - virtual gl::Error applyShaders(gl::ProgramBinary *programBinary, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer, - bool rasterizerDiscard, bool transformFeedbackActive) = 0; - virtual gl::Error applyUniforms(const ProgramImpl &program, const std::vector &uniformArray) = 0; - virtual bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount) = 0; - virtual gl::Error applyVertexBuffer(const gl::State &state, GLint first, GLsizei count, GLsizei instances) = 0; - virtual gl::Error applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo) = 0; - virtual void applyTransformFeedbackBuffers(const gl::State& state) = 0; - - virtual void markAllStateDirty() = 0; - - virtual unsigned int getReservedVertexUniformVectors() const = 0; - virtual unsigned int getReservedFragmentUniformVectors() const = 0; - virtual unsigned int getReservedVertexUniformBuffers() const = 0; - virtual unsigned int getReservedFragmentUniformBuffers() const = 0; - virtual bool getShareHandleSupport() const = 0; - virtual bool getPostSubBufferSupport() const = 0; - - // Pixel operations - virtual gl::Error copyImage2D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, TextureStorage *storage, GLint level) = 0; - virtual gl::Error copyImageCube(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, TextureStorage *storage, GLenum target, GLint level) = 0; - virtual gl::Error copyImage3D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level) = 0; - virtual gl::Error copyImage2DArray(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level) = 0; - - virtual gl::Error readPixels(const gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, - GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, uint8_t *pixels) = 0; - - // RenderTarget creation - virtual gl::Error createRenderTarget(SwapChain *swapChain, bool depth, RenderTarget **outRT) = 0; - virtual gl::Error createRenderTarget(int width, int height, GLenum format, GLsizei samples, RenderTarget **outRT) = 0; - - // Shader operations - virtual void releaseShaderCompiler() = 0; - virtual gl::Error loadExecutable(const void *function, size_t length, ShaderType type, - const std::vector &transformFeedbackVaryings, - bool separatedOutputBuffers, ShaderExecutable **outExecutable) = 0; - virtual gl::Error compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, ShaderType type, - const std::vector &transformFeedbackVaryings, - bool separatedOutputBuffers, D3DWorkaroundType workaround, - ShaderExecutable **outExectuable) = 0; - virtual UniformStorage *createUniformStorage(size_t storageSize) = 0; - - // Image operations - virtual Image *createImage() = 0; - virtual gl::Error generateMipmap(Image *dest, Image *source) = 0; - virtual TextureStorage *createTextureStorage2D(SwapChain *swapChain) = 0; - virtual TextureStorage *createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels) = 0; - virtual TextureStorage *createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels) = 0; - virtual TextureStorage *createTextureStorage3D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) = 0; - virtual TextureStorage *createTextureStorage2DArray(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) = 0; - - // Buffer-to-texture and Texture-to-buffer copies - virtual bool supportsFastCopyBufferToTexture(GLenum internalFormat) const = 0; - virtual gl::Error fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget, - GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea) = 0; - - virtual VertexConversionType getVertexConversionType(const gl::VertexFormat &vertexFormat) const = 0; - virtual GLenum getVertexComponentType(const gl::VertexFormat &vertexFormat) const = 0; - - virtual VertexBuffer *createVertexBuffer() = 0; - virtual IndexBuffer *createIndexBuffer() = 0; - - protected: - virtual gl::Error drawArrays(GLenum mode, GLsizei count, GLsizei instances, bool transformFeedbackActive) = 0; - virtual gl::Error drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, - gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances) = 0; - virtual gl::Error clear(const gl::ClearParameters &clearParams, const gl::Framebuffer *frameBuffer) = 0; - virtual gl::Error blitRect(const gl::Framebuffer *readTarget, const gl::Rectangle &readRect, - const gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect, - const gl::Rectangle *scissor, bool blitRenderTarget, - bool blitDepth, bool blitStencil, GLenum filter) = 0; - - void cleanup(); - - egl::Display *mDisplay; - - private: - DISALLOW_COPY_AND_ASSIGN(RendererD3D); - - //FIXME(jmadill): std::array is currently prohibited by Chromium style guide - typedef std::array FramebufferTextureSerialArray; - - gl::Error generateSwizzles(const gl::Data &data, gl::SamplerType type); - gl::Error generateSwizzles(const gl::Data &data); - - gl::Error applyRenderTarget(const gl::Data &data, GLenum drawMode, bool ignoreViewport); - gl::Error applyState(const gl::Data &data, GLenum drawMode); - bool applyTransformFeedbackBuffers(const gl::Data &data); - gl::Error applyShaders(const gl::Data &data, bool transformFeedbackActive); - gl::Error applyTextures(const gl::Data &data, gl::SamplerType shaderType, - const FramebufferTextureSerialArray &framebufferSerials, size_t framebufferSerialCount); - gl::Error applyTextures(const gl::Data &data); - gl::Error applyUniformBuffers(const gl::Data &data); - - bool skipDraw(const gl::Data &data, GLenum drawMode); - void markTransformFeedbackUsage(const gl::Data &data); - - size_t getBoundFramebufferTextureSerials(const gl::Data &data, - FramebufferTextureSerialArray *outSerialArray); - gl::Texture *getIncompleteTexture(GLenum type); - - gl::TextureMap mIncompleteTextures; -}; - -} - -#endif // LIBGLESV2_RENDERER_RENDERERD3D_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ShaderD3D.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ShaderD3D.cpp deleted file mode 100644 index 8a97579e16..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ShaderD3D.cpp +++ /dev/null @@ -1,481 +0,0 @@ -// -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// ShaderD3D.cpp: Defines the rx::ShaderD3D class which implements rx::ShaderImpl. - -#include "libGLESv2/Shader.h" -#include "libGLESv2/main.h" -#include "libGLESv2/renderer/d3d/RendererD3D.h" -#include "libGLESv2/renderer/d3d/ShaderD3D.h" - -#include "common/features.h" -#include "common/utilities.h" - -// Definitions local to the translation unit -namespace -{ - -const char *GetShaderTypeString(GLenum type) -{ - switch (type) - { - case GL_VERTEX_SHADER: - return "VERTEX"; - - case GL_FRAGMENT_SHADER: - return "FRAGMENT"; - - default: - UNREACHABLE(); - return ""; - } -} - -} - -namespace rx -{ - -template -void FilterInactiveVariables(std::vector *variableList) -{ - ASSERT(variableList); - - for (size_t varIndex = 0; varIndex < variableList->size();) - { - if (!(*variableList)[varIndex].staticUse) - { - variableList->erase(variableList->begin() + varIndex); - } - else - { - varIndex++; - } - } -} - -void *ShaderD3D::mFragmentCompiler = NULL; -void *ShaderD3D::mVertexCompiler = NULL; - -template -const std::vector *GetShaderVariables(const std::vector *variableList) -{ - ASSERT(variableList); - return variableList; -} - -ShaderD3D::ShaderD3D(const gl::Data &data, GLenum type, RendererD3D *renderer) - : mType(type), - mRenderer(renderer), - mShaderVersion(100) -{ - uncompile(); - initializeCompiler(data); -} - -ShaderD3D::~ShaderD3D() -{ -} - -ShaderD3D *ShaderD3D::makeShaderD3D(ShaderImpl *impl) -{ - ASSERT(HAS_DYNAMIC_TYPE(ShaderD3D*, impl)); - return static_cast(impl); -} - -const ShaderD3D *ShaderD3D::makeShaderD3D(const ShaderImpl *impl) -{ - ASSERT(HAS_DYNAMIC_TYPE(const ShaderD3D*, impl)); - return static_cast(impl); -} - -std::string ShaderD3D::getDebugInfo() const -{ - return mDebugInfo + std::string("\n// ") + GetShaderTypeString(mType) + " SHADER END\n"; -} - -// Perform a one-time initialization of the shader compiler (or after being destructed by releaseCompiler) -void ShaderD3D::initializeCompiler(const gl::Data &data) -{ - if (!mFragmentCompiler) - { - bool result = ShInitialize(); - - if (result) - { - ShShaderSpec specVersion = (data.clientVersion >= 3) ? SH_GLES3_SPEC : SH_GLES2_SPEC; - ShShaderOutput hlslVersion = (mRenderer->getMajorShaderModel() >= 4) ? SH_HLSL11_OUTPUT : SH_HLSL9_OUTPUT; - - ShBuiltInResources resources; - ShInitBuiltInResources(&resources); - - const gl::Caps &caps = *data.caps; - const gl::Extensions &extensions = *data.extensions; - - resources.MaxVertexAttribs = caps.maxVertexAttributes; - resources.MaxVertexUniformVectors = caps.maxVertexUniformVectors; - resources.MaxVaryingVectors = caps.maxVaryingVectors; - resources.MaxVertexTextureImageUnits = caps.maxVertexTextureImageUnits; - resources.MaxCombinedTextureImageUnits = caps.maxCombinedTextureImageUnits; - resources.MaxTextureImageUnits = caps.maxTextureImageUnits; - resources.MaxFragmentUniformVectors = caps.maxFragmentUniformVectors; - resources.MaxDrawBuffers = caps.maxDrawBuffers; - resources.OES_standard_derivatives = extensions.standardDerivatives; - resources.EXT_draw_buffers = extensions.drawBuffers; - resources.EXT_shader_texture_lod = 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 - resources.EXT_frag_depth = 1; // Shader Model 2+ always supports explicit depth output - // GLSL ES 3.0 constants - resources.MaxVertexOutputVectors = caps.maxVertexOutputComponents / 4; - resources.MaxFragmentInputVectors = caps.maxFragmentInputComponents / 4; - resources.MinProgramTexelOffset = caps.minProgramTexelOffset; - resources.MaxProgramTexelOffset = caps.maxProgramTexelOffset; - - mFragmentCompiler = ShConstructCompiler(GL_FRAGMENT_SHADER, specVersion, hlslVersion, &resources); - mVertexCompiler = ShConstructCompiler(GL_VERTEX_SHADER, specVersion, hlslVersion, &resources); - } - } -} - -void ShaderD3D::releaseCompiler() -{ - ShDestruct(mFragmentCompiler); - ShDestruct(mVertexCompiler); - - mFragmentCompiler = NULL; - mVertexCompiler = NULL; - - ShFinalize(); -} - -void ShaderD3D::parseVaryings(void *compiler) -{ - if (!mHlsl.empty()) - { - const std::vector *varyings = ShGetVaryings(compiler); - ASSERT(varyings); - - for (size_t varyingIndex = 0; varyingIndex < varyings->size(); varyingIndex++) - { - mVaryings.push_back(gl::PackedVarying((*varyings)[varyingIndex])); - } - - mUsesMultipleRenderTargets = mHlsl.find("GL_USES_MRT") != std::string::npos; - mUsesFragColor = mHlsl.find("GL_USES_FRAG_COLOR") != std::string::npos; - mUsesFragData = mHlsl.find("GL_USES_FRAG_DATA") != std::string::npos; - mUsesFragCoord = mHlsl.find("GL_USES_FRAG_COORD") != std::string::npos; - mUsesFrontFacing = mHlsl.find("GL_USES_FRONT_FACING") != std::string::npos; - mUsesPointSize = mHlsl.find("GL_USES_POINT_SIZE") != std::string::npos; - mUsesPointCoord = mHlsl.find("GL_USES_POINT_COORD") != std::string::npos; - mUsesDepthRange = mHlsl.find("GL_USES_DEPTH_RANGE") != std::string::npos; - mUsesFragDepth = mHlsl.find("GL_USES_FRAG_DEPTH") != std::string::npos; - mUsesDiscardRewriting = mHlsl.find("ANGLE_USES_DISCARD_REWRITING") != std::string::npos; - mUsesNestedBreak = mHlsl.find("ANGLE_USES_NESTED_BREAK") != std::string::npos; - } -} - -void ShaderD3D::resetVaryingsRegisterAssignment() -{ - for (size_t varyingIndex = 0; varyingIndex < mVaryings.size(); varyingIndex++) - { - mVaryings[varyingIndex].resetRegisterAssignment(); - } -} - -// initialize/clean up previous state -void ShaderD3D::uncompile() -{ - // set by compileToHLSL - mHlsl.clear(); - mInfoLog.clear(); - - mUsesMultipleRenderTargets = false; - mUsesFragColor = false; - mUsesFragData = false; - mUsesFragCoord = false; - mUsesFrontFacing = false; - mUsesPointSize = false; - mUsesPointCoord = false; - mUsesDepthRange = false; - mUsesFragDepth = false; - mShaderVersion = 100; - mUsesDiscardRewriting = false; - mUsesNestedBreak = false; - - mVaryings.clear(); - mUniforms.clear(); - mInterfaceBlocks.clear(); - mActiveAttributes.clear(); - mActiveOutputVariables.clear(); - mDebugInfo.clear(); -} - -void ShaderD3D::compileToHLSL(const gl::Data &data, void *compiler, const std::string &source) -{ - // ensure the compiler is loaded - initializeCompiler(data); - - int compileOptions = (SH_OBJECT_CODE | SH_VARIABLES); - std::string sourcePath; - -#if !defined (ANGLE_ENABLE_WINDOWS_STORE) - if (gl::perfActive()) - { - sourcePath = getTempPath(); - writeFile(sourcePath.c_str(), source.c_str(), source.length()); - compileOptions |= SH_LINE_DIRECTIVES; - } -#endif - - int result; - if (sourcePath.empty()) - { - const char* sourceStrings[] = - { - source.c_str(), - }; - - result = ShCompile(compiler, sourceStrings, ArraySize(sourceStrings), compileOptions); - } - else - { - const char* sourceStrings[] = - { - sourcePath.c_str(), - source.c_str(), - }; - - result = ShCompile(compiler, sourceStrings, ArraySize(sourceStrings), compileOptions | SH_SOURCE_PATH); - } - - mShaderVersion = ShGetShaderVersion(compiler); - - if (mShaderVersion == 300 && data.clientVersion < 3) - { - mInfoLog = "GLSL ES 3.00 is not supported by OpenGL ES 2.0 contexts"; - TRACE("\n%s", mInfoLog.c_str()); - } - else if (result) - { - mHlsl = ShGetObjectCode(compiler); - -#ifdef _DEBUG - // Prefix hlsl shader with commented out glsl shader - // Useful in diagnostics tools like pix which capture the hlsl shaders - std::ostringstream hlslStream; - hlslStream << "// GLSL\n"; - hlslStream << "//\n"; - - size_t curPos = 0; - while (curPos != std::string::npos) - { - size_t nextLine = source.find("\n", curPos); - size_t len = (nextLine == std::string::npos) ? std::string::npos : (nextLine - curPos + 1); - - hlslStream << "// " << source.substr(curPos, len); - - curPos = (nextLine == std::string::npos) ? std::string::npos : (nextLine + 1); - } - hlslStream << "\n\n"; - hlslStream << mHlsl; - mHlsl = hlslStream.str(); -#endif - - mUniforms = *GetShaderVariables(ShGetUniforms(compiler)); - - for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++) - { - const sh::Uniform &uniform = mUniforms[uniformIndex]; - - if (uniform.staticUse) - { - unsigned int index = -1; - bool result = ShGetUniformRegister(compiler, uniform.name, &index); - UNUSED_ASSERTION_VARIABLE(result); - ASSERT(result); - - mUniformRegisterMap[uniform.name] = index; - } - } - - mInterfaceBlocks = *GetShaderVariables(ShGetInterfaceBlocks(compiler)); - - for (size_t blockIndex = 0; blockIndex < mInterfaceBlocks.size(); blockIndex++) - { - const sh::InterfaceBlock &interfaceBlock = mInterfaceBlocks[blockIndex]; - - if (interfaceBlock.staticUse) - { - unsigned int index = -1; - bool result = ShGetInterfaceBlockRegister(compiler, interfaceBlock.name, &index); - UNUSED_ASSERTION_VARIABLE(result); - ASSERT(result); - - mInterfaceBlockRegisterMap[interfaceBlock.name] = index; - } - } - } - else - { - mInfoLog = ShGetInfoLog(compiler); - - TRACE("\n%s", mInfoLog.c_str()); - } -} - -D3DWorkaroundType ShaderD3D::getD3DWorkarounds() const -{ - if (mUsesDiscardRewriting) - { - // ANGLE issue 486: - // Work-around a D3D9 compiler bug that presents itself when using conditional discard, by disabling optimization - return ANGLE_D3D_WORKAROUND_SKIP_OPTIMIZATION; - } - - if (mUsesNestedBreak) - { - // ANGLE issue 603: - // Work-around a D3D9 compiler bug that presents itself when using break in a nested loop, by maximizing optimization - // We want to keep the use of ANGLE_D3D_WORKAROUND_MAX_OPTIMIZATION minimal to prevent hangs, so usesDiscard takes precedence - return ANGLE_D3D_WORKAROUND_MAX_OPTIMIZATION; - } - - return ANGLE_D3D_WORKAROUND_NONE; -} - -// true if varying x has a higher priority in packing than y -bool ShaderD3D::compareVarying(const gl::PackedVarying &x, const gl::PackedVarying &y) -{ - if (x.type == y.type) - { - return x.arraySize > y.arraySize; - } - - // Special case for handling structs: we sort these to the end of the list - if (x.type == GL_STRUCT_ANGLEX) - { - return false; - } - - if (y.type == GL_STRUCT_ANGLEX) - { - return true; - } - - return gl::VariableSortOrder(x.type) < gl::VariableSortOrder(y.type); -} - -unsigned int ShaderD3D::getUniformRegister(const std::string &uniformName) const -{ - ASSERT(mUniformRegisterMap.count(uniformName) > 0); - return mUniformRegisterMap.find(uniformName)->second; -} - -unsigned int ShaderD3D::getInterfaceBlockRegister(const std::string &blockName) const -{ - ASSERT(mInterfaceBlockRegisterMap.count(blockName) > 0); - return mInterfaceBlockRegisterMap.find(blockName)->second; -} - -void *ShaderD3D::getCompiler() -{ - if (mType == GL_VERTEX_SHADER) - { - return mVertexCompiler; - } - else - { - ASSERT(mType == GL_FRAGMENT_SHADER); - return mFragmentCompiler; - } -} - -ShShaderOutput ShaderD3D::getCompilerOutputType(GLenum shader) -{ - void *compiler = NULL; - - switch (shader) - { - case GL_VERTEX_SHADER: compiler = mVertexCompiler; break; - case GL_FRAGMENT_SHADER: compiler = mFragmentCompiler; break; - default: UNREACHABLE(); return SH_HLSL9_OUTPUT; - } - - return ShGetShaderOutputType(compiler); -} - -bool ShaderD3D::compile(const gl::Data &data, const std::string &source) -{ - uncompile(); - - void *compiler = getCompiler(); - - compileToHLSL(data, compiler, source); - - if (mType == GL_VERTEX_SHADER) - { - parseAttributes(compiler); - } - - parseVaryings(compiler); - - if (mType == GL_FRAGMENT_SHADER) - { - std::sort(mVaryings.begin(), mVaryings.end(), compareVarying); - - const std::string &hlsl = getTranslatedSource(); - if (!hlsl.empty()) - { - mActiveOutputVariables = *GetShaderVariables(ShGetOutputVariables(compiler)); - FilterInactiveVariables(&mActiveOutputVariables); - } - } - -#if ANGLE_SHADER_DEBUG_INFO == ANGLE_ENABLED - mDebugInfo += std::string("// ") + GetShaderTypeString(mType) + " SHADER BEGIN\n"; - mDebugInfo += "\n// GLSL BEGIN\n\n" + source + "\n\n// GLSL END\n\n\n"; - mDebugInfo += "// INITIAL HLSL BEGIN\n\n" + getTranslatedSource() + "\n// INITIAL HLSL END\n\n\n"; - // Successive steps will append more info -#else - mDebugInfo += getTranslatedSource(); -#endif - - return !getTranslatedSource().empty(); -} - -void ShaderD3D::parseAttributes(void *compiler) -{ - const std::string &hlsl = getTranslatedSource(); - if (!hlsl.empty()) - { - mActiveAttributes = *GetShaderVariables(ShGetAttributes(compiler)); - FilterInactiveVariables(&mActiveAttributes); - } -} - -int ShaderD3D::getSemanticIndex(const std::string &attributeName) const -{ - if (!attributeName.empty()) - { - int semanticIndex = 0; - for (size_t attributeIndex = 0; attributeIndex < mActiveAttributes.size(); attributeIndex++) - { - const sh::ShaderVariable &attribute = mActiveAttributes[attributeIndex]; - - if (attribute.name == attributeName) - { - return semanticIndex; - } - - semanticIndex += gl::VariableRegisterCount(attribute.type); - } - } - - return -1; -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ShaderD3D.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ShaderD3D.h deleted file mode 100644 index 3c9aac2c12..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ShaderD3D.h +++ /dev/null @@ -1,98 +0,0 @@ -// -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// ShaderD3D.h: Defines the rx::ShaderD3D class which implements rx::ShaderImpl. - -#ifndef LIBGLESV2_RENDERER_SHADERD3D_H_ -#define LIBGLESV2_RENDERER_SHADERD3D_H_ - -#include "libGLESv2/renderer/ShaderImpl.h" -#include "libGLESv2/renderer/Workarounds.h" -#include "libGLESv2/Shader.h" - -#include - -namespace rx -{ -class DynamicHLSL; -class RendererD3D; - -class ShaderD3D : public ShaderImpl -{ - friend class DynamicHLSL; - - public: - ShaderD3D(const gl::Data &data, GLenum type, RendererD3D *renderer); - virtual ~ShaderD3D(); - - static ShaderD3D *makeShaderD3D(ShaderImpl *impl); - static const ShaderD3D *makeShaderD3D(const ShaderImpl *impl); - - // ShaderImpl implementation - virtual const std::string &getInfoLog() const { return mInfoLog; } - virtual const std::string &getTranslatedSource() const { return mHlsl; } - virtual std::string getDebugInfo() const; - - // D3D-specific methods - virtual void uncompile(); - void resetVaryingsRegisterAssignment(); - unsigned int getUniformRegister(const std::string &uniformName) const; - unsigned int getInterfaceBlockRegister(const std::string &blockName) const; - int getSemanticIndex(const std::string &attributeName) const; - void appendDebugInfo(const std::string &info) { mDebugInfo += info; } - - D3DWorkaroundType getD3DWorkarounds() const; - int getShaderVersion() const { return mShaderVersion; } - bool usesDepthRange() const { return mUsesDepthRange; } - bool usesPointSize() const { return mUsesPointSize; } - - static void releaseCompiler(); - static ShShaderOutput getCompilerOutputType(GLenum shader); - - virtual bool compile(const gl::Data &data, const std::string &source); - - private: - DISALLOW_COPY_AND_ASSIGN(ShaderD3D); - - void compileToHLSL(const gl::Data &data, void *compiler, const std::string &source); - void parseVaryings(void *compiler); - - void initializeCompiler(const gl::Data &data); - void parseAttributes(void *compiler); - void *getCompiler(); - - static bool compareVarying(const gl::PackedVarying &x, const gl::PackedVarying &y); - - static void *mFragmentCompiler; - static void *mVertexCompiler; - - GLenum mType; - RendererD3D *mRenderer; - - int mShaderVersion; - - bool mUsesMultipleRenderTargets; - bool mUsesFragColor; - bool mUsesFragData; - bool mUsesFragCoord; - bool mUsesFrontFacing; - bool mUsesPointSize; - bool mUsesPointCoord; - bool mUsesDepthRange; - bool mUsesFragDepth; - bool mUsesDiscardRewriting; - bool mUsesNestedBreak; - - std::string mHlsl; - std::string mInfoLog; - std::string mDebugInfo; - std::map mUniformRegisterMap; - std::map mInterfaceBlockRegisterMap; -}; - -} - -#endif // LIBGLESV2_RENDERER_SHADERD3D_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureD3D.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureD3D.cpp deleted file mode 100644 index 4a67701fdf..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureD3D.cpp +++ /dev/null @@ -1,2813 +0,0 @@ -// -// Copyright 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// TextureD3D.cpp: Implementations of the Texture interfaces shared betweeen the D3D backends. - -#include "libGLESv2/Buffer.h" -#include "libGLESv2/Framebuffer.h" -#include "libGLESv2/Texture.h" -#include "libGLESv2/main.h" -#include "libGLESv2/formatutils.h" -#include "libGLESv2/renderer/BufferImpl.h" -#include "libGLESv2/renderer/RenderTarget.h" -#include "libGLESv2/renderer/d3d/BufferD3D.h" -#include "libGLESv2/renderer/d3d/TextureD3D.h" -#include "libGLESv2/renderer/d3d/TextureStorage.h" -#include "libGLESv2/renderer/d3d/ImageD3D.h" -#include "libGLESv2/renderer/d3d/RendererD3D.h" - -#include "libEGL/Surface.h" - -#include "common/mathutil.h" -#include "common/utilities.h" - -namespace rx -{ - -namespace -{ - -gl::Error GetUnpackPointer(const gl::PixelUnpackState &unpack, const void *pixels, const uint8_t **pointerOut) -{ - if (unpack.pixelBuffer.id() != 0) - { - // Do a CPU readback here, if we have an unpack buffer bound and the fast GPU path is not supported - gl::Buffer *pixelBuffer = unpack.pixelBuffer.get(); - ptrdiff_t offset = reinterpret_cast(pixels); - - // TODO: this is the only place outside of renderer that asks for a buffers raw data. - // This functionality should be moved into renderer and the getData method of BufferImpl removed. - BufferD3D *bufferD3D = BufferD3D::makeBufferD3D(pixelBuffer->getImplementation()); - ASSERT(bufferD3D); - const uint8_t *bufferData = NULL; - gl::Error error = bufferD3D->getData(&bufferData); - if (error.isError()) - { - return error; - } - - *pointerOut = bufferData + offset; - } - else - { - *pointerOut = static_cast(pixels); - } - - return gl::Error(GL_NO_ERROR); -} - -bool IsRenderTargetUsage(GLenum usage) -{ - return (usage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE); -} - -} - -TextureD3D::TextureD3D(RendererD3D *renderer) - : mRenderer(renderer), - mUsage(GL_NONE), - mDirtyImages(true), - mImmutable(false), - mTexStorage(NULL) -{ -} - -TextureD3D::~TextureD3D() -{ -} - -TextureD3D *TextureD3D::makeTextureD3D(TextureImpl *texture) -{ - ASSERT(HAS_DYNAMIC_TYPE(TextureD3D*, texture)); - return static_cast(texture); -} - -TextureStorage *TextureD3D::getNativeTexture() -{ - // ensure the underlying texture is created - initializeStorage(false); - - if (mTexStorage) - { - updateStorage(); - } - - return mTexStorage; -} - -GLint TextureD3D::getBaseLevelWidth() const -{ - const Image *baseImage = getBaseLevelImage(); - return (baseImage ? baseImage->getWidth() : 0); -} - -GLint TextureD3D::getBaseLevelHeight() const -{ - const Image *baseImage = getBaseLevelImage(); - return (baseImage ? baseImage->getHeight() : 0); -} - -GLint TextureD3D::getBaseLevelDepth() const -{ - const Image *baseImage = getBaseLevelImage(); - return (baseImage ? baseImage->getDepth() : 0); -} - -// Note: "base level image" is loosely defined to be any image from the base level, -// where in the base of 2D array textures and cube maps there are several. Don't use -// the base level image for anything except querying texture format and size. -GLenum TextureD3D::getBaseLevelInternalFormat() const -{ - const Image *baseImage = getBaseLevelImage(); - return (baseImage ? baseImage->getInternalFormat() : GL_NONE); -} - -bool TextureD3D::shouldUseSetData(const Image *image) const -{ - if (!mRenderer->getWorkarounds().setDataFasterThanImageUpload) - { - return false; - } - - gl::InternalFormat internalFormat = gl::GetInternalFormatInfo(image->getInternalFormat()); - - // We can only handle full updates for depth-stencil textures, so to avoid complications - // disable them entirely. - if (internalFormat.depthBits > 0 || internalFormat.stencilBits > 0) - { - return false; - } - - // TODO(jmadill): Handle compressed internal formats - return (mTexStorage && !internalFormat.compressed); -} - -gl::Error TextureD3D::setImage(const gl::PixelUnpackState &unpack, GLenum type, const void *pixels, const gl::ImageIndex &index) -{ - Image *image = getImage(index); - ASSERT(image); - - // No-op - if (image->getWidth() == 0 || image->getHeight() == 0 || image->getDepth() == 0) - { - return gl::Error(GL_NO_ERROR); - } - - // We no longer need the "GLenum format" parameter to TexImage to determine what data format "pixels" contains. - // From our image internal format we know how many channels to expect, and "type" gives the format of pixel's components. - const uint8_t *pixelData = NULL; - gl::Error error = GetUnpackPointer(unpack, pixels, &pixelData); - if (error.isError()) - { - return error; - } - - if (pixelData != NULL) - { - gl::Error error(GL_NO_ERROR); - - if (shouldUseSetData(image)) - { - error = mTexStorage->setData(index, image, NULL, type, unpack, pixelData); - } - else - { - error = image->loadData(0, 0, 0, image->getWidth(), image->getHeight(), image->getDepth(), unpack.alignment, type, pixelData); - } - - if (error.isError()) - { - return error; - } - - mDirtyImages = true; - } - - return gl::Error(GL_NO_ERROR); -} - -gl::Error TextureD3D::subImage(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, - GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels, const gl::ImageIndex &index) -{ - // CPU readback & copy where direct GPU copy is not supported - const uint8_t *pixelData = NULL; - gl::Error error = GetUnpackPointer(unpack, pixels, &pixelData); - if (error.isError()) - { - return error; - } - - if (pixelData != NULL) - { - Image *image = getImage(index); - ASSERT(image); - - gl::Box region(xoffset, yoffset, zoffset, width, height, depth); - if (shouldUseSetData(image)) - { - return mTexStorage->setData(index, image, ®ion, type, unpack, pixelData); - } - - gl::Error error = image->loadData(xoffset, yoffset, zoffset, width, height, depth, unpack.alignment, - type, pixelData); - if (error.isError()) - { - return error; - } - - error = commitRegion(index, region); - if (error.isError()) - { - return error; - } - - mDirtyImages = true; - } - - return gl::Error(GL_NO_ERROR); -} - -gl::Error TextureD3D::setCompressedImage(const gl::PixelUnpackState &unpack, GLsizei imageSize, const void *pixels, Image *image) -{ - // We no longer need the "GLenum format" parameter to TexImage to determine what data format "pixels" contains. - // From our image internal format we know how many channels to expect, and "type" gives the format of pixel's components. - const uint8_t *pixelData = NULL; - gl::Error error = GetUnpackPointer(unpack, pixels, &pixelData); - if (error.isError()) - { - return error; - } - - if (pixelData != NULL) - { - gl::Error error = image->loadCompressedData(0, 0, 0, image->getWidth(), image->getHeight(), image->getDepth(), pixelData); - if (error.isError()) - { - return error; - } - - mDirtyImages = true; - } - - return gl::Error(GL_NO_ERROR); -} - -gl::Error TextureD3D::subImageCompressed(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, - GLenum format, GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels, Image *image) -{ - const uint8_t *pixelData = NULL; - gl::Error error = GetUnpackPointer(unpack, pixels, &pixelData); - if (error.isError()) - { - return error; - } - - if (pixelData != NULL) - { - gl::Error error = image->loadCompressedData(xoffset, yoffset, zoffset, width, height, depth, pixelData); - if (error.isError()) - { - return error; - } - - mDirtyImages = true; - } - - return gl::Error(GL_NO_ERROR); -} - -bool TextureD3D::isFastUnpackable(const gl::PixelUnpackState &unpack, GLenum sizedInternalFormat) -{ - return unpack.pixelBuffer.id() != 0 && mRenderer->supportsFastCopyBufferToTexture(sizedInternalFormat); -} - -gl::Error TextureD3D::fastUnpackPixels(const gl::PixelUnpackState &unpack, const void *pixels, const gl::Box &destArea, - GLenum sizedInternalFormat, GLenum type, RenderTarget *destRenderTarget) -{ - // No-op - if (destArea.width <= 0 && destArea.height <= 0 && destArea.depth <= 0) - { - return gl::Error(GL_NO_ERROR); - } - - // In order to perform the fast copy through the shader, we must have the right format, and be able - // to create a render target. - ASSERT(mRenderer->supportsFastCopyBufferToTexture(sizedInternalFormat)); - - uintptr_t offset = reinterpret_cast(pixels); - - gl::Error error = mRenderer->fastCopyBufferToTexture(unpack, offset, destRenderTarget, sizedInternalFormat, type, destArea); - if (error.isError()) - { - return error; - } - - return gl::Error(GL_NO_ERROR); -} - -GLint TextureD3D::creationLevels(GLsizei width, GLsizei height, GLsizei depth) const -{ - if ((gl::isPow2(width) && gl::isPow2(height) && gl::isPow2(depth)) || mRenderer->getRendererExtensions().textureNPOT) - { - // Maximum number of levels - return gl::log2(std::max(std::max(width, height), depth)) + 1; - } - else - { - // OpenGL ES 2.0 without GL_OES_texture_npot does not permit NPOT mipmaps. - return 1; - } -} - -int TextureD3D::mipLevels() const -{ - return gl::log2(std::max(std::max(getBaseLevelWidth(), getBaseLevelHeight()), getBaseLevelDepth())) + 1; -} - -TextureStorage *TextureD3D::getStorage() -{ - ASSERT(mTexStorage); - return mTexStorage; -} - -Image *TextureD3D::getBaseLevelImage() const -{ - return getImage(getImageIndex(0, 0)); -} - -gl::Error TextureD3D::generateMipmaps() -{ - GLint mipCount = mipLevels(); - - if (mipCount == 1) - { - return gl::Error(GL_NO_ERROR); // no-op - } - - // Set up proper mipmap chain in our Image array. - initMipmapsImages(); - - // We know that all layers have the same dimension, for the texture to be complete - GLint layerCount = static_cast(getLayerCount(0)); - - // When making mipmaps with the setData workaround enabled, the texture storage has - // the image data already. For non-render-target storage, we have to pull it out into - // an image layer. - if (mRenderer->getWorkarounds().setDataFasterThanImageUpload && mTexStorage) - { - if (!mTexStorage->isRenderTarget()) - { - // Copy from the storage mip 0 to Image mip 0 - for (GLint layer = 0; layer < layerCount; ++layer) - { - gl::ImageIndex srcIndex = getImageIndex(0, layer); - - Image *image = getImage(srcIndex); - gl::Rectangle area(0, 0, image->getWidth(), image->getHeight()); - gl::Error error = image->copy(0, 0, 0, area, srcIndex, mTexStorage); - if (error.isError()) - { - return error; - } - } - } - else - { - gl::Error error = updateStorage(); - if (error.isError()) - { - return error; - } - } - } - - bool renderableStorage = (mTexStorage && mTexStorage->isRenderTarget()); - - for (GLint layer = 0; layer < layerCount; ++layer) - { - for (GLint mip = 1; mip < mipCount; ++mip) - { - ASSERT(getLayerCount(mip) == layerCount); - - gl::ImageIndex sourceIndex = getImageIndex(mip - 1, layer); - gl::ImageIndex destIndex = getImageIndex(mip, layer); - - if (renderableStorage) - { - // GPU-side mipmapping - gl::Error error = mTexStorage->generateMipmap(sourceIndex, destIndex); - if (error.isError()) - { - return error; - } - } - else - { - // CPU-side mipmapping - gl::Error error = mRenderer->generateMipmap(getImage(destIndex), getImage(sourceIndex)); - if (error.isError()) - { - return error; - } - } - } - } - - return gl::Error(GL_NO_ERROR); -} - -bool TextureD3D::isBaseImageZeroSize() const -{ - Image *baseImage = getBaseLevelImage(); - - if (!baseImage || baseImage->getWidth() <= 0) - { - return true; - } - - if (!gl::IsCubemapTextureTarget(baseImage->getTarget()) && baseImage->getHeight() <= 0) - { - return true; - } - - if (baseImage->getTarget() == GL_TEXTURE_3D && baseImage->getDepth() <= 0) - { - return true; - } - - if (baseImage->getTarget() == GL_TEXTURE_2D_ARRAY && getLayerCount(0) <= 0) - { - return true; - } - - return false; -} - -gl::Error TextureD3D::ensureRenderTarget() -{ - gl::Error error = initializeStorage(true); - if (error.isError()) - { - return error; - } - - if (!isBaseImageZeroSize()) - { - ASSERT(mTexStorage); - if (!mTexStorage->isRenderTarget()) - { - TextureStorage *newRenderTargetStorage = NULL; - error = createCompleteStorage(true, &newRenderTargetStorage); - if (error.isError()) - { - return error; - } - - error = mTexStorage->copyToStorage(newRenderTargetStorage); - if (error.isError()) - { - SafeDelete(newRenderTargetStorage); - return error; - } - - error = setCompleteTexStorage(newRenderTargetStorage); - if (error.isError()) - { - SafeDelete(newRenderTargetStorage); - return error; - } - } - } - - return gl::Error(GL_NO_ERROR); -} - -bool TextureD3D::canCreateRenderTargetForImage(const gl::ImageIndex &index) const -{ - Image *image = getImage(index); - bool levelsComplete = (isImageComplete(index) && isImageComplete(getImageIndex(0, 0))); - return (image->isRenderableFormat() && levelsComplete); -} - -gl::Error TextureD3D::commitRegion(const gl::ImageIndex &index, const gl::Box ®ion) -{ - if (mTexStorage) - { - ASSERT(isValidIndex(index)); - Image *image = getImage(index); - ImageD3D *imageD3D = ImageD3D::makeImageD3D(image); - gl::Error error = imageD3D->copyToStorage(mTexStorage, index, region); - if (error.isError()) - { - return error; - } - - image->markClean(); - } - - return gl::Error(GL_NO_ERROR); -} - -TextureD3D_2D::TextureD3D_2D(RendererD3D *renderer) - : TextureD3D(renderer) -{ - for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i) - { - mImageArray[i] = ImageD3D::makeImageD3D(renderer->createImage()); - } -} - -TextureD3D_2D::~TextureD3D_2D() -{ - // Delete the Images before the TextureStorage. - // Images might be relying on the TextureStorage for some of their data. - // If TextureStorage is deleted before the Images, then their data will be wastefully copied back from the GPU before we delete the Images. - for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i) - { - delete mImageArray[i]; - } - - SafeDelete(mTexStorage); -} - -Image *TextureD3D_2D::getImage(int level, int layer) const -{ - ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); - ASSERT(layer == 0); - return mImageArray[level]; -} - -Image *TextureD3D_2D::getImage(const gl::ImageIndex &index) const -{ - ASSERT(index.mipIndex < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); - ASSERT(!index.hasLayer()); - ASSERT(index.type == GL_TEXTURE_2D); - return mImageArray[index.mipIndex]; -} - -GLsizei TextureD3D_2D::getLayerCount(int level) const -{ - ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); - return 1; -} - -GLsizei TextureD3D_2D::getWidth(GLint level) const -{ - if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) - return mImageArray[level]->getWidth(); - else - return 0; -} - -GLsizei TextureD3D_2D::getHeight(GLint level) const -{ - if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) - return mImageArray[level]->getHeight(); - else - return 0; -} - -GLenum TextureD3D_2D::getInternalFormat(GLint level) const -{ - if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) - return mImageArray[level]->getInternalFormat(); - else - return GL_NONE; -} - -GLenum TextureD3D_2D::getActualFormat(GLint level) const -{ - if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) - return mImageArray[level]->getActualFormat(); - else - return GL_NONE; -} - -bool TextureD3D_2D::isDepth(GLint level) const -{ - return gl::GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0; -} - -gl::Error TextureD3D_2D::setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, - GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, - const void *pixels) -{ - ASSERT(target == GL_TEXTURE_2D && depth == 1); - - GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, type); - - bool fastUnpacked = false; - - redefineImage(level, sizedInternalFormat, width, height); - - gl::ImageIndex index = gl::ImageIndex::Make2D(level); - - // Attempt a fast gpu copy of the pixel data to the surface - if (isFastUnpackable(unpack, sizedInternalFormat) && isLevelComplete(level)) - { - // Will try to create RT storage if it does not exist - RenderTarget *destRenderTarget = NULL; - gl::Error error = getRenderTarget(index, &destRenderTarget); - if (error.isError()) - { - return error; - } - - gl::Box destArea(0, 0, 0, getWidth(level), getHeight(level), 1); - - error = fastUnpackPixels(unpack, pixels, destArea, sizedInternalFormat, type, destRenderTarget); - if (error.isError()) - { - return error; - } - - // Ensure we don't overwrite our newly initialized data - mImageArray[level]->markClean(); - - fastUnpacked = true; - } - - if (!fastUnpacked) - { - gl::Error error = TextureD3D::setImage(unpack, type, pixels, index); - if (error.isError()) - { - return error; - } - } - - return gl::Error(GL_NO_ERROR); -} - -gl::Error TextureD3D_2D::setCompressedImage(GLenum target, GLint level, GLenum format, - GLsizei width, GLsizei height, GLsizei depth, - GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels) -{ - ASSERT(target == GL_TEXTURE_2D && depth == 1); - - // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly - redefineImage(level, format, width, height); - - return TextureD3D::setCompressedImage(unpack, imageSize, pixels, mImageArray[level]); -} - -gl::Error TextureD3D_2D::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, - GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, - const gl::PixelUnpackState &unpack, const void *pixels) -{ - ASSERT(target == GL_TEXTURE_2D && depth == 1 && zoffset == 0); - - bool fastUnpacked = false; - - gl::ImageIndex index = gl::ImageIndex::Make2D(level); - gl::Box destArea(xoffset, yoffset, 0, width, height, 1); - if (isFastUnpackable(unpack, getInternalFormat(level)) && isLevelComplete(level)) - { - RenderTarget *renderTarget = NULL; - gl::Error error = getRenderTarget(index, &renderTarget); - if (error.isError()) - { - return error; - } - - error = fastUnpackPixels(unpack, pixels, destArea, getInternalFormat(level), type, renderTarget); - if (error.isError()) - { - return error; - } - - // Ensure we don't overwrite our newly initialized data - mImageArray[level]->markClean(); - - fastUnpacked = true; - } - - if (!fastUnpacked) - { - return TextureD3D::subImage(xoffset, yoffset, 0, width, height, 1, format, type, - unpack, pixels, index); - } - - return gl::Error(GL_NO_ERROR); -} - -gl::Error TextureD3D_2D::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, - GLsizei width, GLsizei height, GLsizei depth, GLenum format, - GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels) -{ - ASSERT(target == GL_TEXTURE_2D && depth == 1 && zoffset == 0); - - gl::Error error = TextureD3D::subImageCompressed(xoffset, yoffset, 0, width, height, 1, format, imageSize, unpack, pixels, mImageArray[level]); - if (error.isError()) - { - return error; - } - - gl::ImageIndex index = gl::ImageIndex::Make2D(level); - gl::Box region(xoffset, yoffset, 0, width, height, 1); - return commitRegion(index, region); -} - -gl::Error TextureD3D_2D::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, - gl::Framebuffer *source) -{ - ASSERT(target == GL_TEXTURE_2D); - - GLenum sizedInternalFormat = gl::GetSizedInternalFormat(format, GL_UNSIGNED_BYTE); - redefineImage(level, sizedInternalFormat, width, height); - - gl::Rectangle sourceRect(x, y, width, height); - gl::ImageIndex index = gl::ImageIndex::Make2D(level); - - if (!canCreateRenderTargetForImage(index)) - { - gl::Error error = mImageArray[level]->copy(0, 0, 0, sourceRect, source); - if (error.isError()) - { - return error; - } - - mDirtyImages = true; - } - else - { - gl::Error error = ensureRenderTarget(); - if (error.isError()) - { - return error; - } - - mImageArray[level]->markClean(); - - if (width != 0 && height != 0 && isValidLevel(level)) - { - gl::Error error = mRenderer->copyImage2D(source, sourceRect, format, 0, 0, mTexStorage, level); - if (error.isError()) - { - return error; - } - } - } - - return gl::Error(GL_NO_ERROR); -} - -gl::Error TextureD3D_2D::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, - GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) -{ - ASSERT(target == GL_TEXTURE_2D && zoffset == 0); - - // can only make our texture storage to a render target if level 0 is defined (with a width & height) and - // the current level we're copying to is defined (with appropriate format, width & height) - - gl::Rectangle sourceRect(x, y, width, height); - gl::ImageIndex index = gl::ImageIndex::Make2D(level); - - if (!canCreateRenderTargetForImage(index)) - { - gl::Error error = mImageArray[level]->copy(xoffset, yoffset, 0, sourceRect, source); - if (error.isError()) - { - return error; - } - - mDirtyImages = true; - } - else - { - gl::Error error = ensureRenderTarget(); - if (error.isError()) - { - return error; - } - - if (isValidLevel(level)) - { - error = updateStorageLevel(level); - if (error.isError()) - { - return error; - } - - error = mRenderer->copyImage2D(source, sourceRect, - gl::GetInternalFormatInfo(getBaseLevelInternalFormat()).format, - xoffset, yoffset, mTexStorage, level); - if (error.isError()) - { - return error; - } - } - } - - return gl::Error(GL_NO_ERROR); -} - -gl::Error TextureD3D_2D::storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) -{ - ASSERT(target == GL_TEXTURE_2D && depth == 1); - - for (int level = 0; level < levels; level++) - { - GLsizei levelWidth = std::max(1, width >> level); - GLsizei levelHeight = std::max(1, height >> level); - mImageArray[level]->redefine(mRenderer, GL_TEXTURE_2D, internalformat, levelWidth, levelHeight, 1, true); - } - - for (int level = levels; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) - { - mImageArray[level]->redefine(mRenderer, GL_TEXTURE_2D, GL_NONE, 0, 0, 0, true); - } - - // TODO(geofflang): Verify storage creation had no errors - bool renderTarget = IsRenderTargetUsage(mUsage); - TextureStorage *storage = mRenderer->createTextureStorage2D(internalformat, renderTarget, width, height, levels); - - gl::Error error = setCompleteTexStorage(storage); - if (error.isError()) - { - SafeDelete(storage); - return error; - } - - mImmutable = true; - - return gl::Error(GL_NO_ERROR); -} - -void TextureD3D_2D::bindTexImage(egl::Surface *surface) -{ - GLenum internalformat = surface->getFormat(); - - mImageArray[0]->redefine(mRenderer, GL_TEXTURE_2D, internalformat, surface->getWidth(), surface->getHeight(), 1, true); - - if (mTexStorage) - { - SafeDelete(mTexStorage); - } - - mTexStorage = mRenderer->createTextureStorage2D(surface->getSwapChain()); - - mDirtyImages = true; -} - -void TextureD3D_2D::releaseTexImage() -{ - if (mTexStorage) - { - SafeDelete(mTexStorage); - } - - for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) - { - mImageArray[i]->redefine(mRenderer, GL_TEXTURE_2D, GL_NONE, 0, 0, 0, true); - } -} - -void TextureD3D_2D::initMipmapsImages() -{ - // Purge array levels 1 through q and reset them to represent the generated mipmap levels. - int levelCount = mipLevels(); - for (int level = 1; level < levelCount; level++) - { - redefineImage(level, getBaseLevelInternalFormat(), - std::max(getBaseLevelWidth() >> level, 1), - std::max(getBaseLevelHeight() >> level, 1)); - } -} - -unsigned int TextureD3D_2D::getRenderTargetSerial(const gl::ImageIndex &index) -{ - ASSERT(!index.hasLayer()); - return (!ensureRenderTarget().isError() ? mTexStorage->getRenderTargetSerial(index) : 0); -} - -gl::Error TextureD3D_2D::getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT) -{ - ASSERT(!index.hasLayer()); - - // ensure the underlying texture is created - gl::Error error = ensureRenderTarget(); - if (error.isError()) - { - return error; - } - - error = updateStorageLevel(index.mipIndex); - if (error.isError()) - { - return error; - } - - return mTexStorage->getRenderTarget(index, outRT); -} - -bool TextureD3D_2D::isValidLevel(int level) const -{ - return (mTexStorage ? (level >= 0 && level < mTexStorage->getLevelCount()) : false); -} - -bool TextureD3D_2D::isLevelComplete(int level) const -{ - if (isImmutable()) - { - return true; - } - - const Image *baseImage = getBaseLevelImage(); - - GLsizei width = baseImage->getWidth(); - GLsizei height = baseImage->getHeight(); - - if (width <= 0 || height <= 0) - { - return false; - } - - // The base image level is complete if the width and height are positive - if (level == 0) - { - return true; - } - - ASSERT(level >= 1 && level <= (int)ArraySize(mImageArray) && mImageArray[level] != NULL); - ImageD3D *image = mImageArray[level]; - - if (image->getInternalFormat() != baseImage->getInternalFormat()) - { - return false; - } - - if (image->getWidth() != std::max(1, width >> level)) - { - return false; - } - - if (image->getHeight() != std::max(1, height >> level)) - { - return false; - } - - return true; -} - -bool TextureD3D_2D::isImageComplete(const gl::ImageIndex &index) const -{ - return isLevelComplete(index.mipIndex); -} - -// Constructs a native texture resource from the texture images -gl::Error TextureD3D_2D::initializeStorage(bool renderTarget) -{ - // Only initialize the first time this texture is used as a render target or shader resource - if (mTexStorage) - { - return gl::Error(GL_NO_ERROR); - } - - // do not attempt to create storage for nonexistant data - if (!isLevelComplete(0)) - { - return gl::Error(GL_NO_ERROR); - } - - bool createRenderTarget = (renderTarget || IsRenderTargetUsage(mUsage)); - - TextureStorage *storage = NULL; - gl::Error error = createCompleteStorage(createRenderTarget, &storage); - if (error.isError()) - { - return error; - } - - error = setCompleteTexStorage(storage); - if (error.isError()) - { - SafeDelete(storage); - return error; - } - - ASSERT(mTexStorage); - - // flush image data to the storage - error = updateStorage(); - if (error.isError()) - { - return error; - } - - return gl::Error(GL_NO_ERROR); -} - -gl::Error TextureD3D_2D::createCompleteStorage(bool renderTarget, TextureStorage **outTexStorage) const -{ - GLsizei width = getBaseLevelWidth(); - GLsizei height = getBaseLevelHeight(); - GLenum internalFormat = getBaseLevelInternalFormat(); - - ASSERT(width > 0 && height > 0); - - // use existing storage level count, when previously specified by TexStorage*D - GLint levels = (mTexStorage ? mTexStorage->getLevelCount() : creationLevels(width, height, 1)); - - // TODO(geofflang): Determine if the texture creation succeeded - *outTexStorage = mRenderer->createTextureStorage2D(internalFormat, renderTarget, width, height, levels); - - return gl::Error(GL_NO_ERROR); -} - -gl::Error TextureD3D_2D::setCompleteTexStorage(TextureStorage *newCompleteTexStorage) -{ - if (newCompleteTexStorage && newCompleteTexStorage->isManaged()) - { - for (int level = 0; level < newCompleteTexStorage->getLevelCount(); level++) - { - gl::Error error = mImageArray[level]->setManagedSurface2D(newCompleteTexStorage, level); - if (error.isError()) - { - return error; - } - } - } - - SafeDelete(mTexStorage); - mTexStorage = newCompleteTexStorage; - - mDirtyImages = true; - - return gl::Error(GL_NO_ERROR); -} - -gl::Error TextureD3D_2D::updateStorage() -{ - ASSERT(mTexStorage != NULL); - GLint storageLevels = mTexStorage->getLevelCount(); - for (int level = 0; level < storageLevels; level++) - { - if (mImageArray[level]->isDirty() && isLevelComplete(level)) - { - gl::Error error = updateStorageLevel(level); - if (error.isError()) - { - return error; - } - } - } - - return gl::Error(GL_NO_ERROR); -} - -gl::Error TextureD3D_2D::updateStorageLevel(int level) -{ - ASSERT(level <= (int)ArraySize(mImageArray) && mImageArray[level] != NULL); - ASSERT(isLevelComplete(level)); - - if (mImageArray[level]->isDirty()) - { - gl::ImageIndex index = gl::ImageIndex::Make2D(level); - gl::Box region(0, 0, 0, getWidth(level), getHeight(level), 1); - gl::Error error = commitRegion(index, region); - if (error.isError()) - { - return error; - } - } - - return gl::Error(GL_NO_ERROR); -} - -void TextureD3D_2D::redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height) -{ - // If there currently is a corresponding storage texture image, it has these parameters - const int storageWidth = std::max(1, getBaseLevelWidth() >> level); - const int storageHeight = std::max(1, getBaseLevelHeight() >> level); - const GLenum storageFormat = getBaseLevelInternalFormat(); - - mImageArray[level]->redefine(mRenderer, GL_TEXTURE_2D, internalformat, width, height, 1, false); - - if (mTexStorage) - { - const int storageLevels = mTexStorage->getLevelCount(); - - if ((level >= storageLevels && storageLevels != 0) || - width != storageWidth || - height != storageHeight || - internalformat != storageFormat) // Discard mismatched storage - { - for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) - { - mImageArray[i]->markDirty(); - } - - SafeDelete(mTexStorage); - mDirtyImages = true; - } - } -} - -gl::ImageIndexIterator TextureD3D_2D::imageIterator() const -{ - return gl::ImageIndexIterator::Make2D(0, mTexStorage->getLevelCount()); -} - -gl::ImageIndex TextureD3D_2D::getImageIndex(GLint mip, GLint /*layer*/) const -{ - // "layer" does not apply to 2D Textures. - return gl::ImageIndex::Make2D(mip); -} - -bool TextureD3D_2D::isValidIndex(const gl::ImageIndex &index) const -{ - return (mTexStorage && index.type == GL_TEXTURE_2D && - index.mipIndex >= 0 && index.mipIndex < mTexStorage->getLevelCount()); -} - -TextureD3D_Cube::TextureD3D_Cube(RendererD3D *renderer) - : TextureD3D(renderer) -{ - for (int i = 0; i < 6; i++) - { - for (int j = 0; j < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++j) - { - mImageArray[i][j] = ImageD3D::makeImageD3D(renderer->createImage()); - } - } -} - -TextureD3D_Cube::~TextureD3D_Cube() -{ - // Delete the Images before the TextureStorage. - // Images might be relying on the TextureStorage for some of their data. - // If TextureStorage is deleted before the Images, then their data will be wastefully copied back from the GPU before we delete the Images. - for (int i = 0; i < 6; i++) - { - for (int j = 0; j < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++j) - { - SafeDelete(mImageArray[i][j]); - } - } - - SafeDelete(mTexStorage); -} - -Image *TextureD3D_Cube::getImage(int level, int layer) const -{ - ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); - ASSERT(layer < 6); - return mImageArray[layer][level]; -} - -Image *TextureD3D_Cube::getImage(const gl::ImageIndex &index) const -{ - ASSERT(index.mipIndex < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); - ASSERT(index.layerIndex < 6); - return mImageArray[index.layerIndex][index.mipIndex]; -} - -GLsizei TextureD3D_Cube::getLayerCount(int level) const -{ - ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); - return 6; -} - -GLenum TextureD3D_Cube::getInternalFormat(GLint level, GLint layer) const -{ - if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) - return mImageArray[layer][level]->getInternalFormat(); - else - return GL_NONE; -} - -bool TextureD3D_Cube::isDepth(GLint level, GLint layer) const -{ - return gl::GetInternalFormatInfo(getInternalFormat(level, layer)).depthBits > 0; -} - -gl::Error TextureD3D_Cube::setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, - GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, - const void *pixels) -{ - ASSERT(depth == 1); - - GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, type); - gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level); - - redefineImage(index.layerIndex, level, sizedInternalFormat, width, height); - - return TextureD3D::setImage(unpack, type, pixels, index); -} - -gl::Error TextureD3D_Cube::setCompressedImage(GLenum target, GLint level, GLenum format, - GLsizei width, GLsizei height, GLsizei depth, - GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels) -{ - ASSERT(depth == 1); - - // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly - int faceIndex = gl::TextureCubeMap::targetToLayerIndex(target); - - redefineImage(faceIndex, level, format, width, height); - - return TextureD3D::setCompressedImage(unpack, imageSize, pixels, mImageArray[faceIndex][level]); -} - -gl::Error TextureD3D_Cube::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, - GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, - const gl::PixelUnpackState &unpack, const void *pixels) -{ - ASSERT(depth == 1 && zoffset == 0); - gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level); - return TextureD3D::subImage(xoffset, yoffset, 0, width, height, 1, format, type, unpack, pixels, index); -} - -gl::Error TextureD3D_Cube::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, - GLsizei width, GLsizei height, GLsizei depth, GLenum format, - GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels) -{ - ASSERT(depth == 1 && zoffset == 0); - - gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level); - - gl::Error error = TextureD3D::subImageCompressed(xoffset, yoffset, 0, width, height, 1, format, imageSize, unpack, pixels, mImageArray[index.layerIndex][level]); - if (error.isError()) - { - return error; - } - - gl::Box region(xoffset, yoffset, 0, width, height, 1); - return commitRegion(index, region); -} - -gl::Error TextureD3D_Cube::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, - GLsizei width, GLsizei height, gl::Framebuffer *source) -{ - int faceIndex = gl::TextureCubeMap::targetToLayerIndex(target); - GLenum sizedInternalFormat = gl::GetSizedInternalFormat(format, GL_UNSIGNED_BYTE); - - redefineImage(faceIndex, level, sizedInternalFormat, width, height); - - gl::Rectangle sourceRect(x, y, width, height); - gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level); - - if (!canCreateRenderTargetForImage(index)) - { - gl::Error error = mImageArray[faceIndex][level]->copy(0, 0, 0, sourceRect, source); - if (error.isError()) - { - return error; - } - - mDirtyImages = true; - } - else - { - gl::Error error = ensureRenderTarget(); - if (error.isError()) - { - return error; - } - - mImageArray[faceIndex][level]->markClean(); - - ASSERT(width == height); - - if (width > 0 && isValidFaceLevel(faceIndex, level)) - { - error = mRenderer->copyImageCube(source, sourceRect, format, 0, 0, mTexStorage, target, level); - if (error.isError()) - { - return error; - } - } - } - - return gl::Error(GL_NO_ERROR); -} - -gl::Error TextureD3D_Cube::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, - GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) -{ - int faceIndex = gl::TextureCubeMap::targetToLayerIndex(target); - - gl::Rectangle sourceRect(x, y, width, height); - gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level); - - if (!canCreateRenderTargetForImage(index)) - { - gl::Error error =mImageArray[faceIndex][level]->copy(0, 0, 0, sourceRect, source); - if (error.isError()) - { - return error; - } - - mDirtyImages = true; - } - else - { - gl::Error error = ensureRenderTarget(); - if (error.isError()) - { - return error; - } - - if (isValidFaceLevel(faceIndex, level)) - { - error = updateStorageFaceLevel(faceIndex, level); - if (error.isError()) - { - return error; - } - - error = mRenderer->copyImageCube(source, sourceRect, gl::GetInternalFormatInfo(getBaseLevelInternalFormat()).format, - xoffset, yoffset, mTexStorage, target, level); - if (error.isError()) - { - return error; - } - } - } - - return gl::Error(GL_NO_ERROR); -} - -gl::Error TextureD3D_Cube::storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) -{ - ASSERT(width == height); - ASSERT(depth == 1); - - for (int level = 0; level < levels; level++) - { - GLsizei mipSize = std::max(1, width >> level); - for (int faceIndex = 0; faceIndex < 6; faceIndex++) - { - mImageArray[faceIndex][level]->redefine(mRenderer, GL_TEXTURE_CUBE_MAP, internalformat, mipSize, mipSize, 1, true); - } - } - - for (int level = levels; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) - { - for (int faceIndex = 0; faceIndex < 6; faceIndex++) - { - mImageArray[faceIndex][level]->redefine(mRenderer, GL_TEXTURE_CUBE_MAP, GL_NONE, 0, 0, 0, true); - } - } - - // TODO(geofflang): Verify storage creation had no errors - bool renderTarget = IsRenderTargetUsage(mUsage); - TextureStorage *storage = mRenderer->createTextureStorageCube(internalformat, renderTarget, width, levels); - - gl::Error error = setCompleteTexStorage(storage); - if (error.isError()) - { - SafeDelete(storage); - return error; - } - - mImmutable = true; - - return gl::Error(GL_NO_ERROR); -} - -// Tests for cube texture completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81. -bool TextureD3D_Cube::isCubeComplete() const -{ - int baseWidth = getBaseLevelWidth(); - int baseHeight = getBaseLevelHeight(); - GLenum baseFormat = getBaseLevelInternalFormat(); - - if (baseWidth <= 0 || baseWidth != baseHeight) - { - return false; - } - - for (int faceIndex = 1; faceIndex < 6; faceIndex++) - { - const ImageD3D &faceBaseImage = *mImageArray[faceIndex][0]; - - if (faceBaseImage.getWidth() != baseWidth || - faceBaseImage.getHeight() != baseHeight || - faceBaseImage.getInternalFormat() != baseFormat ) - { - return false; - } - } - - return true; -} - -void TextureD3D_Cube::bindTexImage(egl::Surface *surface) -{ - UNREACHABLE(); -} - -void TextureD3D_Cube::releaseTexImage() -{ - UNREACHABLE(); -} - - -void TextureD3D_Cube::initMipmapsImages() -{ - // Purge array levels 1 through q and reset them to represent the generated mipmap levels. - int levelCount = mipLevels(); - for (int faceIndex = 0; faceIndex < 6; faceIndex++) - { - for (int level = 1; level < levelCount; level++) - { - int faceLevelSize = (std::max(mImageArray[faceIndex][0]->getWidth() >> level, 1)); - redefineImage(faceIndex, level, mImageArray[faceIndex][0]->getInternalFormat(), faceLevelSize, faceLevelSize); - } - } -} - -unsigned int TextureD3D_Cube::getRenderTargetSerial(const gl::ImageIndex &index) -{ - return (ensureRenderTarget().isError() ? mTexStorage->getRenderTargetSerial(index) : 0); -} - -gl::Error TextureD3D_Cube::getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT) -{ - ASSERT(gl::IsCubemapTextureTarget(index.type)); - - // ensure the underlying texture is created - gl::Error error = ensureRenderTarget(); - if (error.isError()) - { - return error; - } - - error = updateStorageFaceLevel(index.layerIndex, index.mipIndex); - if (error.isError()) - { - return error; - } - - return mTexStorage->getRenderTarget(index, outRT); -} - -gl::Error TextureD3D_Cube::initializeStorage(bool renderTarget) -{ - // Only initialize the first time this texture is used as a render target or shader resource - if (mTexStorage) - { - return gl::Error(GL_NO_ERROR); - } - - // do not attempt to create storage for nonexistant data - if (!isFaceLevelComplete(0, 0)) - { - return gl::Error(GL_NO_ERROR); - } - - bool createRenderTarget = (renderTarget || IsRenderTargetUsage(mUsage)); - - TextureStorage *storage = NULL; - gl::Error error = createCompleteStorage(createRenderTarget, &storage); - if (error.isError()) - { - return error; - } - - error = setCompleteTexStorage(storage); - if (error.isError()) - { - SafeDelete(storage); - return error; - } - - ASSERT(mTexStorage); - - // flush image data to the storage - error = updateStorage(); - if (error.isError()) - { - return error; - } - - return gl::Error(GL_NO_ERROR); -} - -gl::Error TextureD3D_Cube::createCompleteStorage(bool renderTarget, TextureStorage **outTexStorage) const -{ - GLsizei size = getBaseLevelWidth(); - - ASSERT(size > 0); - - // use existing storage level count, when previously specified by TexStorage*D - GLint levels = (mTexStorage ? mTexStorage->getLevelCount() : creationLevels(size, size, 1)); - - // TODO (geofflang): detect if storage creation succeeded - *outTexStorage = mRenderer->createTextureStorageCube(getBaseLevelInternalFormat(), renderTarget, size, levels); - - return gl::Error(GL_NO_ERROR); -} - -gl::Error TextureD3D_Cube::setCompleteTexStorage(TextureStorage *newCompleteTexStorage) -{ - if (newCompleteTexStorage && newCompleteTexStorage->isManaged()) - { - for (int faceIndex = 0; faceIndex < 6; faceIndex++) - { - for (int level = 0; level < newCompleteTexStorage->getLevelCount(); level++) - { - gl::Error error = mImageArray[faceIndex][level]->setManagedSurfaceCube(newCompleteTexStorage, faceIndex, level); - if (error.isError()) - { - return error; - } - } - } - } - - SafeDelete(mTexStorage); - mTexStorage = newCompleteTexStorage; - - mDirtyImages = true; - return gl::Error(GL_NO_ERROR); -} - -gl::Error TextureD3D_Cube::updateStorage() -{ - ASSERT(mTexStorage != NULL); - GLint storageLevels = mTexStorage->getLevelCount(); - for (int face = 0; face < 6; face++) - { - for (int level = 0; level < storageLevels; level++) - { - if (mImageArray[face][level]->isDirty() && isFaceLevelComplete(face, level)) - { - gl::Error error = updateStorageFaceLevel(face, level); - if (error.isError()) - { - return error; - } - } - } - } - - return gl::Error(GL_NO_ERROR); -} - -bool TextureD3D_Cube::isValidFaceLevel(int faceIndex, int level) const -{ - return (mTexStorage ? (level >= 0 && level < mTexStorage->getLevelCount()) : 0); -} - -bool TextureD3D_Cube::isFaceLevelComplete(int faceIndex, int level) const -{ - ASSERT(level >= 0 && faceIndex < 6 && level < (int)ArraySize(mImageArray[faceIndex]) && mImageArray[faceIndex][level] != NULL); - - if (isImmutable()) - { - return true; - } - - int baseSize = getBaseLevelWidth(); - - if (baseSize <= 0) - { - return false; - } - - // "isCubeComplete" checks for base level completeness and we must call that - // to determine if any face at level 0 is complete. We omit that check here - // to avoid re-checking cube-completeness for every face at level 0. - if (level == 0) - { - return true; - } - - // Check that non-zero levels are consistent with the base level. - const ImageD3D *faceLevelImage = mImageArray[faceIndex][level]; - - if (faceLevelImage->getInternalFormat() != getBaseLevelInternalFormat()) - { - return false; - } - - if (faceLevelImage->getWidth() != std::max(1, baseSize >> level)) - { - return false; - } - - return true; -} - -bool TextureD3D_Cube::isImageComplete(const gl::ImageIndex &index) const -{ - return isFaceLevelComplete(index.layerIndex, index.mipIndex); -} - -gl::Error TextureD3D_Cube::updateStorageFaceLevel(int faceIndex, int level) -{ - ASSERT(level >= 0 && faceIndex < 6 && level < (int)ArraySize(mImageArray[faceIndex]) && mImageArray[faceIndex][level] != NULL); - ImageD3D *image = mImageArray[faceIndex][level]; - - if (image->isDirty()) - { - GLenum faceTarget = gl::TextureCubeMap::layerIndexToTarget(faceIndex); - gl::ImageIndex index = gl::ImageIndex::MakeCube(faceTarget, level); - gl::Box region(0, 0, 0, image->getWidth(), image->getHeight(), 1); - gl::Error error = commitRegion(index, region); - if (error.isError()) - { - return error; - } - } - - return gl::Error(GL_NO_ERROR); -} - -void TextureD3D_Cube::redefineImage(int faceIndex, GLint level, GLenum internalformat, GLsizei width, GLsizei height) -{ - // If there currently is a corresponding storage texture image, it has these parameters - const int storageWidth = std::max(1, getBaseLevelWidth() >> level); - const int storageHeight = std::max(1, getBaseLevelHeight() >> level); - const GLenum storageFormat = getBaseLevelInternalFormat(); - - mImageArray[faceIndex][level]->redefine(mRenderer, GL_TEXTURE_CUBE_MAP, internalformat, width, height, 1, false); - - if (mTexStorage) - { - const int storageLevels = mTexStorage->getLevelCount(); - - if ((level >= storageLevels && storageLevels != 0) || - width != storageWidth || - height != storageHeight || - internalformat != storageFormat) // Discard mismatched storage - { - for (int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) - { - for (int faceIndex = 0; faceIndex < 6; faceIndex++) - { - mImageArray[faceIndex][level]->markDirty(); - } - } - - SafeDelete(mTexStorage); - - mDirtyImages = true; - } - } -} - -gl::ImageIndexIterator TextureD3D_Cube::imageIterator() const -{ - return gl::ImageIndexIterator::MakeCube(0, mTexStorage->getLevelCount()); -} - -gl::ImageIndex TextureD3D_Cube::getImageIndex(GLint mip, GLint layer) const -{ - // The "layer" of the image index corresponds to the cube face - return gl::ImageIndex::MakeCube(gl::TextureCubeMap::layerIndexToTarget(layer), mip); -} - -bool TextureD3D_Cube::isValidIndex(const gl::ImageIndex &index) const -{ - return (mTexStorage && gl::IsCubemapTextureTarget(index.type) && - index.mipIndex >= 0 && index.mipIndex < mTexStorage->getLevelCount()); -} - -TextureD3D_3D::TextureD3D_3D(RendererD3D *renderer) - : TextureD3D(renderer) -{ - for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i) - { - mImageArray[i] = ImageD3D::makeImageD3D(renderer->createImage()); - } -} - -TextureD3D_3D::~TextureD3D_3D() -{ - // Delete the Images before the TextureStorage. - // Images might be relying on the TextureStorage for some of their data. - // If TextureStorage is deleted before the Images, then their data will be wastefully copied back from the GPU before we delete the Images. - for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i) - { - delete mImageArray[i]; - } - - SafeDelete(mTexStorage); -} - -Image *TextureD3D_3D::getImage(int level, int layer) const -{ - ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); - ASSERT(layer == 0); - return mImageArray[level]; -} - -Image *TextureD3D_3D::getImage(const gl::ImageIndex &index) const -{ - ASSERT(index.mipIndex < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); - ASSERT(!index.hasLayer()); - ASSERT(index.type == GL_TEXTURE_3D); - return mImageArray[index.mipIndex]; -} - -GLsizei TextureD3D_3D::getLayerCount(int level) const -{ - ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); - return 1; -} - -GLsizei TextureD3D_3D::getWidth(GLint level) const -{ - if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) - return mImageArray[level]->getWidth(); - else - return 0; -} - -GLsizei TextureD3D_3D::getHeight(GLint level) const -{ - if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) - return mImageArray[level]->getHeight(); - else - return 0; -} - -GLsizei TextureD3D_3D::getDepth(GLint level) const -{ - if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) - return mImageArray[level]->getDepth(); - else - return 0; -} - -GLenum TextureD3D_3D::getInternalFormat(GLint level) const -{ - if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) - return mImageArray[level]->getInternalFormat(); - else - return GL_NONE; -} - -bool TextureD3D_3D::isDepth(GLint level) const -{ - return gl::GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0; -} - -gl::Error TextureD3D_3D::setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, - GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, - const void *pixels) -{ - ASSERT(target == GL_TEXTURE_3D); - GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, type); - - redefineImage(level, sizedInternalFormat, width, height, depth); - - bool fastUnpacked = false; - - gl::ImageIndex index = gl::ImageIndex::Make3D(level); - - // Attempt a fast gpu copy of the pixel data to the surface if the app bound an unpack buffer - if (isFastUnpackable(unpack, sizedInternalFormat)) - { - // Will try to create RT storage if it does not exist - RenderTarget *destRenderTarget = NULL; - gl::Error error = getRenderTarget(index, &destRenderTarget); - if (error.isError()) - { - return error; - } - - gl::Box destArea(0, 0, 0, getWidth(level), getHeight(level), getDepth(level)); - - error = fastUnpackPixels(unpack, pixels, destArea, sizedInternalFormat, type, destRenderTarget); - if (error.isError()) - { - return error; - } - - // Ensure we don't overwrite our newly initialized data - mImageArray[level]->markClean(); - - fastUnpacked = true; - } - - if (!fastUnpacked) - { - gl::Error error = TextureD3D::setImage(unpack, type, pixels, index); - if (error.isError()) - { - return error; - } - } - - return gl::Error(GL_NO_ERROR); -} - -gl::Error TextureD3D_3D::setCompressedImage(GLenum target, GLint level, GLenum format, - GLsizei width, GLsizei height,GLsizei depth, - GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels) -{ - ASSERT(target == GL_TEXTURE_3D); - - // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly - redefineImage(level, format, width, height, depth); - - return TextureD3D::setCompressedImage(unpack, imageSize, pixels, mImageArray[level]); -} - -gl::Error TextureD3D_3D::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, - GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, - const gl::PixelUnpackState &unpack, const void *pixels) -{ - ASSERT(target == GL_TEXTURE_3D); - - bool fastUnpacked = false; - - gl::ImageIndex index = gl::ImageIndex::Make3D(level); - - // Attempt a fast gpu copy of the pixel data to the surface if the app bound an unpack buffer - if (isFastUnpackable(unpack, getInternalFormat(level))) - { - RenderTarget *destRenderTarget = NULL; - gl::Error error = getRenderTarget(index, &destRenderTarget); - if (error.isError()) - { - return error; - } - - gl::Box destArea(xoffset, yoffset, zoffset, width, height, depth); - error = fastUnpackPixels(unpack, pixels, destArea, getInternalFormat(level), type, destRenderTarget); - if (error.isError()) - { - return error; - } - - // Ensure we don't overwrite our newly initialized data - mImageArray[level]->markClean(); - - fastUnpacked = true; - } - - if (!fastUnpacked) - { - return TextureD3D::subImage(xoffset, yoffset, zoffset, width, height, depth, format, type, - unpack, pixels, index); - } - - return gl::Error(GL_NO_ERROR); -} - -gl::Error TextureD3D_3D::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, - GLsizei width, GLsizei height, GLsizei depth, GLenum format, - GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels) -{ - ASSERT(target == GL_TEXTURE_3D); - - gl::Error error = TextureD3D::subImageCompressed(xoffset, yoffset, zoffset, width, height, depth, - format, imageSize, unpack, pixels, mImageArray[level]); - if (error.isError()) - { - return error; - } - - gl::ImageIndex index = gl::ImageIndex::Make3D(level); - gl::Box region(xoffset, yoffset, zoffset, width, height, depth); - return commitRegion(index, region); -} - -gl::Error TextureD3D_3D::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, - GLsizei width, GLsizei height, gl::Framebuffer *source) -{ - UNIMPLEMENTED(); - return gl::Error(GL_INVALID_OPERATION, "Copying 3D textures is unimplemented."); -} - -gl::Error TextureD3D_3D::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, - GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) -{ - ASSERT(target == GL_TEXTURE_3D); - - gl::Rectangle sourceRect(x, y, width, height); - gl::ImageIndex index = gl::ImageIndex::Make3D(level); - - if (canCreateRenderTargetForImage(index)) - { - gl::Error error = mImageArray[level]->copy(xoffset, yoffset, zoffset, sourceRect, source); - if (error.isError()) - { - return error; - } - - mDirtyImages = true; - } - else - { - gl::Error error = ensureRenderTarget(); - if (error.isError()) - { - return error; - } - - if (isValidLevel(level)) - { - error = updateStorageLevel(level); - if (error.isError()) - { - return error; - } - - error = mRenderer->copyImage3D(source, sourceRect, - gl::GetInternalFormatInfo(getBaseLevelInternalFormat()).format, - xoffset, yoffset, zoffset, mTexStorage, level); - if (error.isError()) - { - return error; - } - } - } - - return gl::Error(GL_NO_ERROR); -} - -gl::Error TextureD3D_3D::storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) -{ - ASSERT(target == GL_TEXTURE_3D); - - for (int level = 0; level < levels; level++) - { - GLsizei levelWidth = std::max(1, width >> level); - GLsizei levelHeight = std::max(1, height >> level); - GLsizei levelDepth = std::max(1, depth >> level); - mImageArray[level]->redefine(mRenderer, GL_TEXTURE_3D, internalformat, levelWidth, levelHeight, levelDepth, true); - } - - for (int level = levels; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) - { - mImageArray[level]->redefine(mRenderer, GL_TEXTURE_3D, GL_NONE, 0, 0, 0, true); - } - - // TODO(geofflang): Verify storage creation had no errors - bool renderTarget = IsRenderTargetUsage(mUsage); - TextureStorage *storage = mRenderer->createTextureStorage3D(internalformat, renderTarget, width, height, depth, levels); - - gl::Error error = setCompleteTexStorage(storage); - if (error.isError()) - { - SafeDelete(storage); - return error; - } - - mImmutable = true; - - return gl::Error(GL_NO_ERROR); -} - -void TextureD3D_3D::bindTexImage(egl::Surface *surface) -{ - UNREACHABLE(); -} - -void TextureD3D_3D::releaseTexImage() -{ - UNREACHABLE(); -} - - -void TextureD3D_3D::initMipmapsImages() -{ - // Purge array levels 1 through q and reset them to represent the generated mipmap levels. - int levelCount = mipLevels(); - for (int level = 1; level < levelCount; level++) - { - redefineImage(level, getBaseLevelInternalFormat(), - std::max(getBaseLevelWidth() >> level, 1), - std::max(getBaseLevelHeight() >> level, 1), - std::max(getBaseLevelDepth() >> level, 1)); - } -} - -unsigned int TextureD3D_3D::getRenderTargetSerial(const gl::ImageIndex &index) -{ - return (!ensureRenderTarget().isError() ? mTexStorage->getRenderTargetSerial(index) : 0); -} - -gl::Error TextureD3D_3D::getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT) -{ - // ensure the underlying texture is created - gl::Error error = ensureRenderTarget(); - if (error.isError()) - { - return error; - } - - if (index.hasLayer()) - { - error = updateStorage(); - if (error.isError()) - { - return error; - } - } - else - { - error = updateStorageLevel(index.mipIndex); - if (error.isError()) - { - return error; - } - } - - return mTexStorage->getRenderTarget(index, outRT); -} - -gl::Error TextureD3D_3D::initializeStorage(bool renderTarget) -{ - // Only initialize the first time this texture is used as a render target or shader resource - if (mTexStorage) - { - return gl::Error(GL_NO_ERROR); - } - - // do not attempt to create storage for nonexistant data - if (!isLevelComplete(0)) - { - return gl::Error(GL_NO_ERROR); - } - - bool createRenderTarget = (renderTarget || mUsage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE); - - TextureStorage *storage = NULL; - gl::Error error = createCompleteStorage(createRenderTarget, &storage); - if (error.isError()) - { - return error; - } - - error = setCompleteTexStorage(storage); - if (error.isError()) - { - SafeDelete(storage); - return error; - } - - ASSERT(mTexStorage); - - // flush image data to the storage - error = updateStorage(); - if (error.isError()) - { - return error; - } - - return gl::Error(GL_NO_ERROR); -} - -gl::Error TextureD3D_3D::createCompleteStorage(bool renderTarget, TextureStorage **outStorage) const -{ - GLsizei width = getBaseLevelWidth(); - GLsizei height = getBaseLevelHeight(); - GLsizei depth = getBaseLevelDepth(); - GLenum internalFormat = getBaseLevelInternalFormat(); - - ASSERT(width > 0 && height > 0 && depth > 0); - - // use existing storage level count, when previously specified by TexStorage*D - GLint levels = (mTexStorage ? mTexStorage->getLevelCount() : creationLevels(width, height, depth)); - - // TODO: Verify creation of the storage succeeded - *outStorage = mRenderer->createTextureStorage3D(internalFormat, renderTarget, width, height, depth, levels); - - return gl::Error(GL_NO_ERROR); -} - -gl::Error TextureD3D_3D::setCompleteTexStorage(TextureStorage *newCompleteTexStorage) -{ - SafeDelete(mTexStorage); - mTexStorage = newCompleteTexStorage; - mDirtyImages = true; - - // We do not support managed 3D storage, as that is D3D9/ES2-only - ASSERT(!mTexStorage->isManaged()); - - return gl::Error(GL_NO_ERROR); -} - -gl::Error TextureD3D_3D::updateStorage() -{ - ASSERT(mTexStorage != NULL); - GLint storageLevels = mTexStorage->getLevelCount(); - for (int level = 0; level < storageLevels; level++) - { - if (mImageArray[level]->isDirty() && isLevelComplete(level)) - { - gl::Error error = updateStorageLevel(level); - if (error.isError()) - { - return error; - } - } - } - - return gl::Error(GL_NO_ERROR); -} - -bool TextureD3D_3D::isValidLevel(int level) const -{ - return (mTexStorage ? (level >= 0 && level < mTexStorage->getLevelCount()) : 0); -} - -bool TextureD3D_3D::isLevelComplete(int level) const -{ - ASSERT(level >= 0 && level < (int)ArraySize(mImageArray) && mImageArray[level] != NULL); - - if (isImmutable()) - { - return true; - } - - GLsizei width = getBaseLevelWidth(); - GLsizei height = getBaseLevelHeight(); - GLsizei depth = getBaseLevelDepth(); - - if (width <= 0 || height <= 0 || depth <= 0) - { - return false; - } - - if (level == 0) - { - return true; - } - - ImageD3D *levelImage = mImageArray[level]; - - if (levelImage->getInternalFormat() != getBaseLevelInternalFormat()) - { - return false; - } - - if (levelImage->getWidth() != std::max(1, width >> level)) - { - return false; - } - - if (levelImage->getHeight() != std::max(1, height >> level)) - { - return false; - } - - if (levelImage->getDepth() != std::max(1, depth >> level)) - { - return false; - } - - return true; -} - -bool TextureD3D_3D::isImageComplete(const gl::ImageIndex &index) const -{ - return isLevelComplete(index.mipIndex); -} - -gl::Error TextureD3D_3D::updateStorageLevel(int level) -{ - ASSERT(level >= 0 && level < (int)ArraySize(mImageArray) && mImageArray[level] != NULL); - ASSERT(isLevelComplete(level)); - - if (mImageArray[level]->isDirty()) - { - gl::ImageIndex index = gl::ImageIndex::Make3D(level); - gl::Box region(0, 0, 0, getWidth(level), getHeight(level), getDepth(level)); - gl::Error error = commitRegion(index, region); - if (error.isError()) - { - return error; - } - } - - return gl::Error(GL_NO_ERROR); -} - -void TextureD3D_3D::redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) -{ - // If there currently is a corresponding storage texture image, it has these parameters - const int storageWidth = std::max(1, getBaseLevelWidth() >> level); - const int storageHeight = std::max(1, getBaseLevelHeight() >> level); - const int storageDepth = std::max(1, getBaseLevelDepth() >> level); - const GLenum storageFormat = getBaseLevelInternalFormat(); - - mImageArray[level]->redefine(mRenderer, GL_TEXTURE_3D, internalformat, width, height, depth, false); - - if (mTexStorage) - { - const int storageLevels = mTexStorage->getLevelCount(); - - if ((level >= storageLevels && storageLevels != 0) || - width != storageWidth || - height != storageHeight || - depth != storageDepth || - internalformat != storageFormat) // Discard mismatched storage - { - for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) - { - mImageArray[i]->markDirty(); - } - - SafeDelete(mTexStorage); - mDirtyImages = true; - } - } -} - -gl::ImageIndexIterator TextureD3D_3D::imageIterator() const -{ - return gl::ImageIndexIterator::Make3D(0, mTexStorage->getLevelCount(), - gl::ImageIndex::ENTIRE_LEVEL, gl::ImageIndex::ENTIRE_LEVEL); -} - -gl::ImageIndex TextureD3D_3D::getImageIndex(GLint mip, GLint /*layer*/) const -{ - // The "layer" here does not apply to 3D images. We use one Image per mip. - return gl::ImageIndex::Make3D(mip); -} - -bool TextureD3D_3D::isValidIndex(const gl::ImageIndex &index) const -{ - return (mTexStorage && index.type == GL_TEXTURE_3D && - index.mipIndex >= 0 && index.mipIndex < mTexStorage->getLevelCount()); -} - -TextureD3D_2DArray::TextureD3D_2DArray(RendererD3D *renderer) - : TextureD3D(renderer) -{ - for (int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++level) - { - mLayerCounts[level] = 0; - mImageArray[level] = NULL; - } -} - -TextureD3D_2DArray::~TextureD3D_2DArray() -{ - // Delete the Images before the TextureStorage. - // Images might be relying on the TextureStorage for some of their data. - // If TextureStorage is deleted before the Images, then their data will be wastefully copied back from the GPU before we delete the Images. - deleteImages(); - SafeDelete(mTexStorage); -} - -Image *TextureD3D_2DArray::getImage(int level, int layer) const -{ - ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); - ASSERT(layer < mLayerCounts[level]); - return mImageArray[level][layer]; -} - -Image *TextureD3D_2DArray::getImage(const gl::ImageIndex &index) const -{ - ASSERT(index.mipIndex < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); - ASSERT(index.layerIndex < mLayerCounts[index.mipIndex]); - ASSERT(index.type == GL_TEXTURE_2D_ARRAY); - return mImageArray[index.mipIndex][index.layerIndex]; -} - -GLsizei TextureD3D_2DArray::getLayerCount(int level) const -{ - ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); - return mLayerCounts[level]; -} - -GLsizei TextureD3D_2DArray::getWidth(GLint level) const -{ - return (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS && mLayerCounts[level] > 0) ? mImageArray[level][0]->getWidth() : 0; -} - -GLsizei TextureD3D_2DArray::getHeight(GLint level) const -{ - return (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS && mLayerCounts[level] > 0) ? mImageArray[level][0]->getHeight() : 0; -} - -GLenum TextureD3D_2DArray::getInternalFormat(GLint level) const -{ - return (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS && mLayerCounts[level] > 0) ? mImageArray[level][0]->getInternalFormat() : GL_NONE; -} - -bool TextureD3D_2DArray::isDepth(GLint level) const -{ - return gl::GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0; -} - -gl::Error TextureD3D_2DArray::setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, - GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, - const void *pixels) -{ - ASSERT(target == GL_TEXTURE_2D_ARRAY); - - GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, type); - - redefineImage(level, sizedInternalFormat, width, height, depth); - - const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedInternalFormat); - GLsizei inputDepthPitch = formatInfo.computeDepthPitch(type, width, height, unpack.alignment); - - for (int i = 0; i < depth; i++) - { - const void *layerPixels = pixels ? (reinterpret_cast(pixels) + (inputDepthPitch * i)) : NULL; - gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, i); - gl::Error error = TextureD3D::setImage(unpack, type, layerPixels, index); - if (error.isError()) - { - return error; - } - } - - return gl::Error(GL_NO_ERROR); -} - -gl::Error TextureD3D_2DArray::setCompressedImage(GLenum target, GLint level, GLenum format, - GLsizei width, GLsizei height, GLsizei depth, - GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels) -{ - ASSERT(target == GL_TEXTURE_2D_ARRAY); - - // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly - redefineImage(level, format, width, height, depth); - - const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format); - GLsizei inputDepthPitch = formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, width, height, 1); - - for (int i = 0; i < depth; i++) - { - const void *layerPixels = pixels ? (reinterpret_cast(pixels) + (inputDepthPitch * i)) : NULL; - gl::Error error = TextureD3D::setCompressedImage(unpack, imageSize, layerPixels, mImageArray[level][i]); - if (error.isError()) - { - return error; - } - } - - return gl::Error(GL_NO_ERROR); -} - -gl::Error TextureD3D_2DArray::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, - GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, - const gl::PixelUnpackState &unpack, const void *pixels) -{ - ASSERT(target == GL_TEXTURE_2D_ARRAY); - - const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(getInternalFormat(level)); - GLsizei inputDepthPitch = formatInfo.computeDepthPitch(type, width, height, unpack.alignment); - - for (int i = 0; i < depth; i++) - { - int layer = zoffset + i; - const void *layerPixels = pixels ? (reinterpret_cast(pixels) + (inputDepthPitch * i)) : NULL; - - gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, layer); - gl::Error error = TextureD3D::subImage(xoffset, yoffset, zoffset, width, height, 1, format, type, - unpack, layerPixels, index); - if (error.isError()) - { - return error; - } - } - - return gl::Error(GL_NO_ERROR); -} - -gl::Error TextureD3D_2DArray::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, - GLsizei width, GLsizei height, GLsizei depth, GLenum format, - GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels) -{ - ASSERT(target == GL_TEXTURE_2D_ARRAY); - - const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format); - GLsizei inputDepthPitch = formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, width, height, 1); - - for (int i = 0; i < depth; i++) - { - int layer = zoffset + i; - const void *layerPixels = pixels ? (reinterpret_cast(pixels) + (inputDepthPitch * i)) : NULL; - - gl::Error error = TextureD3D::subImageCompressed(xoffset, yoffset, zoffset, width, height, 1, format, imageSize, unpack, layerPixels, mImageArray[level][layer]); - if (error.isError()) - { - return error; - } - - gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, layer); - gl::Box region(xoffset, yoffset, 0, width, height, 1); - error = commitRegion(index, region); - if (error.isError()) - { - return error; - } - } - - return gl::Error(GL_NO_ERROR); -} - -gl::Error TextureD3D_2DArray::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) -{ - UNIMPLEMENTED(); - return gl::Error(GL_INVALID_OPERATION, "Copying 2D array textures is unimplemented."); -} - -gl::Error TextureD3D_2DArray::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) -{ - ASSERT(target == GL_TEXTURE_2D_ARRAY); - - gl::Rectangle sourceRect(x, y, width, height); - gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, zoffset); - - if (canCreateRenderTargetForImage(index)) - { - gl::Error error = mImageArray[level][zoffset]->copy(xoffset, yoffset, 0, sourceRect, source); - if (error.isError()) - { - return error; - } - - mDirtyImages = true; - } - else - { - gl::Error error = ensureRenderTarget(); - if (error.isError()) - { - return error; - } - - if (isValidLevel(level)) - { - error = updateStorageLevel(level); - if (error.isError()) - { - return error; - } - - error = mRenderer->copyImage2DArray(source, sourceRect, gl::GetInternalFormatInfo(getInternalFormat(0)).format, - xoffset, yoffset, zoffset, mTexStorage, level); - if (error.isError()) - { - return error; - } - } - } - return gl::Error(GL_NO_ERROR); -} - -gl::Error TextureD3D_2DArray::storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) -{ - ASSERT(target == GL_TEXTURE_2D_ARRAY); - - deleteImages(); - - for (int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) - { - GLsizei levelWidth = std::max(1, width >> level); - GLsizei levelHeight = std::max(1, height >> level); - - mLayerCounts[level] = (level < levels ? depth : 0); - - if (mLayerCounts[level] > 0) - { - // Create new images for this level - mImageArray[level] = new ImageD3D*[mLayerCounts[level]]; - - for (int layer = 0; layer < mLayerCounts[level]; layer++) - { - mImageArray[level][layer] = ImageD3D::makeImageD3D(mRenderer->createImage()); - mImageArray[level][layer]->redefine(mRenderer, GL_TEXTURE_2D_ARRAY, internalformat, levelWidth, - levelHeight, 1, true); - } - } - } - - // TODO(geofflang): Verify storage creation had no errors - bool renderTarget = IsRenderTargetUsage(mUsage); - TextureStorage *storage = mRenderer->createTextureStorage2DArray(internalformat, renderTarget, width, height, depth, levels); - - gl::Error error = setCompleteTexStorage(storage); - if (error.isError()) - { - SafeDelete(storage); - return error; - } - - mImmutable = true; - - return gl::Error(GL_NO_ERROR); -} - -void TextureD3D_2DArray::bindTexImage(egl::Surface *surface) -{ - UNREACHABLE(); -} - -void TextureD3D_2DArray::releaseTexImage() -{ - UNREACHABLE(); -} - - -void TextureD3D_2DArray::initMipmapsImages() -{ - int baseWidth = getBaseLevelWidth(); - int baseHeight = getBaseLevelHeight(); - int baseDepth = getBaseLevelDepth(); - GLenum baseFormat = getBaseLevelInternalFormat(); - - // Purge array levels 1 through q and reset them to represent the generated mipmap levels. - int levelCount = mipLevels(); - for (int level = 1; level < levelCount; level++) - { - redefineImage(level, baseFormat, std::max(baseWidth >> level, 1), std::max(baseHeight >> level, 1), baseDepth); - } -} - -unsigned int TextureD3D_2DArray::getRenderTargetSerial(const gl::ImageIndex &index) -{ - return (!ensureRenderTarget().isError() ? mTexStorage->getRenderTargetSerial(index) : 0); -} - -gl::Error TextureD3D_2DArray::getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT) -{ - // ensure the underlying texture is created - gl::Error error = ensureRenderTarget(); - if (error.isError()) - { - return error; - } - - error = updateStorageLevel(index.mipIndex); - if (error.isError()) - { - return error; - } - - return mTexStorage->getRenderTarget(index, outRT); -} - -gl::Error TextureD3D_2DArray::initializeStorage(bool renderTarget) -{ - // Only initialize the first time this texture is used as a render target or shader resource - if (mTexStorage) - { - return gl::Error(GL_NO_ERROR); - } - - // do not attempt to create storage for nonexistant data - if (!isLevelComplete(0)) - { - return gl::Error(GL_NO_ERROR); - } - - bool createRenderTarget = (renderTarget || mUsage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE); - - TextureStorage *storage = NULL; - gl::Error error = createCompleteStorage(createRenderTarget, &storage); - if (error.isError()) - { - return error; - } - - error = setCompleteTexStorage(storage); - if (error.isError()) - { - SafeDelete(storage); - return error; - } - - ASSERT(mTexStorage); - - // flush image data to the storage - error = updateStorage(); - if (error.isError()) - { - return error; - } - - return gl::Error(GL_NO_ERROR); -} - -gl::Error TextureD3D_2DArray::createCompleteStorage(bool renderTarget, TextureStorage **outStorage) const -{ - GLsizei width = getBaseLevelWidth(); - GLsizei height = getBaseLevelHeight(); - GLsizei depth = getLayerCount(0); - GLenum internalFormat = getBaseLevelInternalFormat(); - - ASSERT(width > 0 && height > 0 && depth > 0); - - // use existing storage level count, when previously specified by TexStorage*D - GLint levels = (mTexStorage ? mTexStorage->getLevelCount() : creationLevels(width, height, 1)); - - // TODO(geofflang): Verify storage creation succeeds - *outStorage = mRenderer->createTextureStorage2DArray(internalFormat, renderTarget, width, height, depth, levels); - - return gl::Error(GL_NO_ERROR); -} - -gl::Error TextureD3D_2DArray::setCompleteTexStorage(TextureStorage *newCompleteTexStorage) -{ - SafeDelete(mTexStorage); - mTexStorage = newCompleteTexStorage; - mDirtyImages = true; - - // We do not support managed 2D array storage, as managed storage is ES2/D3D9 only - ASSERT(!mTexStorage->isManaged()); - - return gl::Error(GL_NO_ERROR); -} - -gl::Error TextureD3D_2DArray::updateStorage() -{ - ASSERT(mTexStorage != NULL); - GLint storageLevels = mTexStorage->getLevelCount(); - for (int level = 0; level < storageLevels; level++) - { - if (isLevelComplete(level)) - { - gl::Error error = updateStorageLevel(level); - if (error.isError()) - { - return error; - } - } - } - - return gl::Error(GL_NO_ERROR); -} - -bool TextureD3D_2DArray::isValidLevel(int level) const -{ - return (mTexStorage ? (level >= 0 && level < mTexStorage->getLevelCount()) : 0); -} - -bool TextureD3D_2DArray::isLevelComplete(int level) const -{ - ASSERT(level >= 0 && level < (int)ArraySize(mImageArray)); - - if (isImmutable()) - { - return true; - } - - GLsizei width = getBaseLevelWidth(); - GLsizei height = getBaseLevelHeight(); - GLsizei layers = getLayerCount(0); - - if (width <= 0 || height <= 0 || layers <= 0) - { - return false; - } - - if (level == 0) - { - return true; - } - - if (getInternalFormat(level) != getInternalFormat(0)) - { - return false; - } - - if (getWidth(level) != std::max(1, width >> level)) - { - return false; - } - - if (getHeight(level) != std::max(1, height >> level)) - { - return false; - } - - if (getLayerCount(level) != layers) - { - return false; - } - - return true; -} - -bool TextureD3D_2DArray::isImageComplete(const gl::ImageIndex &index) const -{ - return isLevelComplete(index.mipIndex); -} - -gl::Error TextureD3D_2DArray::updateStorageLevel(int level) -{ - ASSERT(level >= 0 && level < (int)ArraySize(mLayerCounts)); - ASSERT(isLevelComplete(level)); - - for (int layer = 0; layer < mLayerCounts[level]; layer++) - { - ASSERT(mImageArray[level] != NULL && mImageArray[level][layer] != NULL); - if (mImageArray[level][layer]->isDirty()) - { - gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, layer); - gl::Box region(0, 0, 0, getWidth(level), getHeight(level), 1); - gl::Error error = commitRegion(index, region); - if (error.isError()) - { - return error; - } - } - } - - return gl::Error(GL_NO_ERROR); -} - -void TextureD3D_2DArray::deleteImages() -{ - for (int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++level) - { - for (int layer = 0; layer < mLayerCounts[level]; ++layer) - { - delete mImageArray[level][layer]; - } - delete[] mImageArray[level]; - mImageArray[level] = NULL; - mLayerCounts[level] = 0; - } -} - -void TextureD3D_2DArray::redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) -{ - // If there currently is a corresponding storage texture image, it has these parameters - const int storageWidth = std::max(1, getBaseLevelWidth() >> level); - const int storageHeight = std::max(1, getBaseLevelHeight() >> level); - const int storageDepth = getLayerCount(0); - const GLenum storageFormat = getBaseLevelInternalFormat(); - - for (int layer = 0; layer < mLayerCounts[level]; layer++) - { - delete mImageArray[level][layer]; - } - delete[] mImageArray[level]; - mImageArray[level] = NULL; - mLayerCounts[level] = depth; - - if (depth > 0) - { - mImageArray[level] = new ImageD3D*[depth](); - - for (int layer = 0; layer < mLayerCounts[level]; layer++) - { - mImageArray[level][layer] = ImageD3D::makeImageD3D(mRenderer->createImage()); - mImageArray[level][layer]->redefine(mRenderer, GL_TEXTURE_2D_ARRAY, internalformat, width, height, 1, false); - } - } - - if (mTexStorage) - { - const int storageLevels = mTexStorage->getLevelCount(); - - if ((level >= storageLevels && storageLevels != 0) || - width != storageWidth || - height != storageHeight || - depth != storageDepth || - internalformat != storageFormat) // Discard mismatched storage - { - for (int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) - { - for (int layer = 0; layer < mLayerCounts[level]; layer++) - { - mImageArray[level][layer]->markDirty(); - } - } - - delete mTexStorage; - mTexStorage = NULL; - mDirtyImages = true; - } - } -} - -gl::ImageIndexIterator TextureD3D_2DArray::imageIterator() const -{ - return gl::ImageIndexIterator::Make2DArray(0, mTexStorage->getLevelCount(), mLayerCounts); -} - -gl::ImageIndex TextureD3D_2DArray::getImageIndex(GLint mip, GLint layer) const -{ - return gl::ImageIndex::Make2DArray(mip, layer); -} - -bool TextureD3D_2DArray::isValidIndex(const gl::ImageIndex &index) const -{ - // Check for having a storage and the right type of index - if (!mTexStorage || index.type != GL_TEXTURE_2D_ARRAY) - { - return false; - } - - // Check the mip index - if (index.mipIndex < 0 || index.mipIndex >= mTexStorage->getLevelCount()) - { - return false; - } - - // Check the layer index - return (!index.hasLayer() || (index.layerIndex >= 0 && index.layerIndex < mLayerCounts[index.mipIndex])); -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureD3D.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureD3D.h deleted file mode 100644 index 083a6335b9..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureD3D.h +++ /dev/null @@ -1,335 +0,0 @@ -// -// Copyright 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// TextureD3D.h: Implementations of the Texture interfaces shared betweeen the D3D backends. - -#ifndef LIBGLESV2_RENDERER_TEXTURED3D_H_ -#define LIBGLESV2_RENDERER_TEXTURED3D_H_ - -#include "libGLESv2/renderer/TextureImpl.h" -#include "libGLESv2/angletypes.h" -#include "libGLESv2/Constants.h" - -namespace gl -{ -class Framebuffer; -} - -namespace rx -{ - -class Image; -class ImageD3D; -class RendererD3D; -class RenderTarget; -class TextureStorage; - -class TextureD3D : public TextureImpl -{ - public: - TextureD3D(RendererD3D *renderer); - virtual ~TextureD3D(); - - static TextureD3D *makeTextureD3D(TextureImpl *texture); - - TextureStorage *getNativeTexture(); - - virtual void setUsage(GLenum usage) { mUsage = usage; } - bool hasDirtyImages() const { return mDirtyImages; } - void resetDirty() { mDirtyImages = false; } - - GLint getBaseLevelWidth() const; - GLint getBaseLevelHeight() const; - GLint getBaseLevelDepth() const; - GLenum getBaseLevelInternalFormat() const; - - bool isImmutable() const { return mImmutable; } - - virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT) = 0; - virtual unsigned int getRenderTargetSerial(const gl::ImageIndex &index) = 0; - - // Returns an iterator over all "Images" for this particular Texture. - virtual gl::ImageIndexIterator imageIterator() const = 0; - - // Returns an ImageIndex for a particular "Image". 3D Textures do not have images for - // slices of their depth texures, so 3D textures ignore the layer parameter. - virtual gl::ImageIndex getImageIndex(GLint mip, GLint layer) const = 0; - virtual bool isValidIndex(const gl::ImageIndex &index) const = 0; - - virtual gl::Error generateMipmaps(); - TextureStorage *getStorage(); - Image *getBaseLevelImage() const; - - protected: - gl::Error setImage(const gl::PixelUnpackState &unpack, GLenum type, const void *pixels, const gl::ImageIndex &index); - gl::Error subImage(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, - GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels, const gl::ImageIndex &index); - gl::Error setCompressedImage(const gl::PixelUnpackState &unpack, GLsizei imageSize, const void *pixels, Image *image); - gl::Error subImageCompressed(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, - GLenum format, GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels, Image *image); - bool isFastUnpackable(const gl::PixelUnpackState &unpack, GLenum sizedInternalFormat); - gl::Error fastUnpackPixels(const gl::PixelUnpackState &unpack, const void *pixels, const gl::Box &destArea, - GLenum sizedInternalFormat, GLenum type, RenderTarget *destRenderTarget); - - GLint creationLevels(GLsizei width, GLsizei height, GLsizei depth) const; - int mipLevels() const; - virtual void initMipmapsImages() = 0; - bool isBaseImageZeroSize() const; - virtual bool isImageComplete(const gl::ImageIndex &index) const = 0; - - bool canCreateRenderTargetForImage(const gl::ImageIndex &index) const; - virtual gl::Error ensureRenderTarget(); - - virtual gl::Error createCompleteStorage(bool renderTarget, TextureStorage **outTexStorage) const = 0; - virtual gl::Error setCompleteTexStorage(TextureStorage *newCompleteTexStorage) = 0; - gl::Error commitRegion(const gl::ImageIndex &index, const gl::Box ®ion); - - RendererD3D *mRenderer; - - GLenum mUsage; - - bool mDirtyImages; - - bool mImmutable; - TextureStorage *mTexStorage; - - private: - DISALLOW_COPY_AND_ASSIGN(TextureD3D); - - virtual gl::Error initializeStorage(bool renderTarget) = 0; - - virtual gl::Error updateStorage() = 0; - - bool shouldUseSetData(const Image *image) const; -}; - -class TextureD3D_2D : public TextureD3D -{ - public: - TextureD3D_2D(RendererD3D *renderer); - virtual ~TextureD3D_2D(); - - virtual Image *getImage(int level, int layer) const; - virtual Image *getImage(const gl::ImageIndex &index) const; - virtual GLsizei getLayerCount(int level) const; - - GLsizei getWidth(GLint level) const; - GLsizei getHeight(GLint level) const; - GLenum getInternalFormat(GLint level) const; - GLenum getActualFormat(GLint level) const; - bool isDepth(GLint level) const; - - virtual gl::Error setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels); - virtual gl::Error setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels); - virtual gl::Error subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels); - virtual gl::Error subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels); - virtual gl::Error copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source); - virtual gl::Error copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source); - virtual gl::Error storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); - - virtual void bindTexImage(egl::Surface *surface); - virtual void releaseTexImage(); - - virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT); - virtual unsigned int getRenderTargetSerial(const gl::ImageIndex &index); - - virtual gl::ImageIndexIterator imageIterator() const; - virtual gl::ImageIndex getImageIndex(GLint mip, GLint layer) const; - virtual bool isValidIndex(const gl::ImageIndex &index) const; - - private: - DISALLOW_COPY_AND_ASSIGN(TextureD3D_2D); - - virtual gl::Error initializeStorage(bool renderTarget); - virtual gl::Error createCompleteStorage(bool renderTarget, TextureStorage **outTexStorage) const; - virtual gl::Error setCompleteTexStorage(TextureStorage *newCompleteTexStorage); - - virtual gl::Error updateStorage(); - virtual void initMipmapsImages(); - - bool isValidLevel(int level) const; - bool isLevelComplete(int level) const; - virtual bool isImageComplete(const gl::ImageIndex &index) const; - - gl::Error updateStorageLevel(int level); - - void redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height); - - ImageD3D *mImageArray[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; -}; - -class TextureD3D_Cube : public TextureD3D -{ - public: - TextureD3D_Cube(RendererD3D *renderer); - virtual ~TextureD3D_Cube(); - - virtual Image *getImage(int level, int layer) const; - virtual Image *getImage(const gl::ImageIndex &index) const; - virtual GLsizei getLayerCount(int level) const; - - virtual bool hasDirtyImages() const { return mDirtyImages; } - virtual void resetDirty() { mDirtyImages = false; } - virtual void setUsage(GLenum usage) { mUsage = usage; } - - GLenum getInternalFormat(GLint level, GLint layer) const; - bool isDepth(GLint level, GLint layer) const; - - virtual gl::Error setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels); - virtual gl::Error setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels); - virtual gl::Error subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels); - virtual gl::Error subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels); - virtual gl::Error copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source); - virtual gl::Error copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source); - virtual gl::Error storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); - - virtual void bindTexImage(egl::Surface *surface); - virtual void releaseTexImage(); - - virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT); - virtual unsigned int getRenderTargetSerial(const gl::ImageIndex &index); - - virtual gl::ImageIndexIterator imageIterator() const; - virtual gl::ImageIndex getImageIndex(GLint mip, GLint layer) const; - virtual bool isValidIndex(const gl::ImageIndex &index) const; - - private: - DISALLOW_COPY_AND_ASSIGN(TextureD3D_Cube); - - virtual gl::Error initializeStorage(bool renderTarget); - virtual gl::Error createCompleteStorage(bool renderTarget, TextureStorage **outTexStorage) const; - virtual gl::Error setCompleteTexStorage(TextureStorage *newCompleteTexStorage); - - virtual gl::Error updateStorage(); - virtual void initMipmapsImages(); - - bool isValidFaceLevel(int faceIndex, int level) const; - bool isFaceLevelComplete(int faceIndex, int level) const; - bool isCubeComplete() const; - virtual bool isImageComplete(const gl::ImageIndex &index) const; - gl::Error updateStorageFaceLevel(int faceIndex, int level); - - void redefineImage(int faceIndex, GLint level, GLenum internalformat, GLsizei width, GLsizei height); - - ImageD3D *mImageArray[6][gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; -}; - -class TextureD3D_3D : public TextureD3D -{ - public: - TextureD3D_3D(RendererD3D *renderer); - virtual ~TextureD3D_3D(); - - virtual Image *getImage(int level, int layer) const; - virtual Image *getImage(const gl::ImageIndex &index) const; - virtual GLsizei getLayerCount(int level) const; - - GLsizei getWidth(GLint level) const; - GLsizei getHeight(GLint level) const; - GLsizei getDepth(GLint level) const; - GLenum getInternalFormat(GLint level) const; - bool isDepth(GLint level) const; - - virtual gl::Error setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels); - virtual gl::Error setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels); - virtual gl::Error subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels); - virtual gl::Error subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels); - virtual gl::Error copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source); - virtual gl::Error copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source); - virtual gl::Error storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); - - virtual void bindTexImage(egl::Surface *surface); - virtual void releaseTexImage(); - - virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT); - virtual unsigned int getRenderTargetSerial(const gl::ImageIndex &index); - - virtual gl::ImageIndexIterator imageIterator() const; - virtual gl::ImageIndex getImageIndex(GLint mip, GLint layer) const; - virtual bool isValidIndex(const gl::ImageIndex &index) const; - - private: - DISALLOW_COPY_AND_ASSIGN(TextureD3D_3D); - - virtual gl::Error initializeStorage(bool renderTarget); - virtual gl::Error createCompleteStorage(bool renderTarget, TextureStorage **outStorage) const; - virtual gl::Error setCompleteTexStorage(TextureStorage *newCompleteTexStorage); - - virtual gl::Error updateStorage(); - virtual void initMipmapsImages(); - - bool isValidLevel(int level) const; - bool isLevelComplete(int level) const; - virtual bool isImageComplete(const gl::ImageIndex &index) const; - gl::Error updateStorageLevel(int level); - - void redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); - - ImageD3D *mImageArray[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; -}; - -class TextureD3D_2DArray : public TextureD3D -{ - public: - TextureD3D_2DArray(RendererD3D *renderer); - virtual ~TextureD3D_2DArray(); - - virtual Image *getImage(int level, int layer) const; - virtual Image *getImage(const gl::ImageIndex &index) const; - virtual GLsizei getLayerCount(int level) const; - - GLsizei getWidth(GLint level) const; - GLsizei getHeight(GLint level) const; - GLenum getInternalFormat(GLint level) const; - bool isDepth(GLint level) const; - - virtual gl::Error setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels); - virtual gl::Error setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels); - virtual gl::Error subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels); - virtual gl::Error subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels); - virtual gl::Error copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source); - virtual gl::Error copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source); - virtual gl::Error storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); - - virtual void bindTexImage(egl::Surface *surface); - virtual void releaseTexImage(); - - virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT); - virtual unsigned int getRenderTargetSerial(const gl::ImageIndex &index); - - virtual gl::ImageIndexIterator imageIterator() const; - virtual gl::ImageIndex getImageIndex(GLint mip, GLint layer) const; - virtual bool isValidIndex(const gl::ImageIndex &index) const; - - private: - DISALLOW_COPY_AND_ASSIGN(TextureD3D_2DArray); - - virtual gl::Error initializeStorage(bool renderTarget); - virtual gl::Error createCompleteStorage(bool renderTarget, TextureStorage **outStorage) const; - virtual gl::Error setCompleteTexStorage(TextureStorage *newCompleteTexStorage); - - virtual gl::Error updateStorage(); - virtual void initMipmapsImages(); - - bool isValidLevel(int level) const; - bool isLevelComplete(int level) const; - virtual bool isImageComplete(const gl::ImageIndex &index) const; - gl::Error updateStorageLevel(int level); - - void deleteImages(); - void redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); - - // Storing images as an array of single depth textures since D3D11 treats each array level of a - // Texture2D object as a separate subresource. Each layer would have to be looped over - // to update all the texture layers since they cannot all be updated at once and it makes the most - // sense for the Image class to not have to worry about layer subresource as well as mip subresources. - GLsizei mLayerCounts[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; - ImageD3D **mImageArray[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; -}; - -} - -#endif // LIBGLESV2_RENDERER_TEXTURED3D_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureStorage.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureStorage.cpp deleted file mode 100644 index 320b74b8ed..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureStorage.cpp +++ /dev/null @@ -1,39 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// TextureStorage.cpp: Shared members of abstract rx::TextureStorage class. - -#include "libGLESv2/renderer/d3d/TextureStorage.h" -#include "libGLESv2/renderer/d3d/TextureD3D.h" -#include "libGLESv2/renderer/RenderTarget.h" -#include "libGLESv2/renderer/Renderer.h" -#include "libGLESv2/Renderbuffer.h" -#include "libGLESv2/Texture.h" - -#include "common/debug.h" -#include "common/mathutil.h" - -namespace rx -{ - -TextureStorage::TextureStorage() - : mFirstRenderTargetSerial(0), - mRenderTargetSerialsLayerStride(0) -{} - -void TextureStorage::initializeSerials(unsigned int rtSerialsToReserve, unsigned int rtSerialsLayerStride) -{ - mFirstRenderTargetSerial = RenderTarget::issueSerials(rtSerialsToReserve); - mRenderTargetSerialsLayerStride = rtSerialsLayerStride; -} - -unsigned int TextureStorage::getRenderTargetSerial(const gl::ImageIndex &index) const -{ - unsigned int layerOffset = (index.hasLayer() ? (static_cast(index.layerIndex) * mRenderTargetSerialsLayerStride) : 0); - return mFirstRenderTargetSerial + static_cast(index.mipIndex) + layerOffset; -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureStorage.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureStorage.h deleted file mode 100644 index da92be3c74..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureStorage.h +++ /dev/null @@ -1,66 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// TextureStorage.h: Defines the abstract rx::TextureStorage class. - -#ifndef LIBGLESV2_RENDERER_TEXTURESTORAGE_H_ -#define LIBGLESV2_RENDERER_TEXTURESTORAGE_H_ - -#include "libGLESv2/Error.h" - -#include "common/debug.h" -#include "libGLESv2/Error.h" - -#include -#include - -namespace gl -{ -struct ImageIndex; -struct Box; -struct PixelUnpackState; -} - -namespace rx -{ -class SwapChain; -class RenderTarget; -class Image; - -class TextureStorage -{ - public: - TextureStorage(); - virtual ~TextureStorage() {}; - - virtual int getTopLevel() const = 0; - virtual bool isRenderTarget() const = 0; - virtual bool isManaged() const = 0; - virtual int getLevelCount() const = 0; - - virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT) = 0; - virtual gl::Error generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex) = 0; - - virtual gl::Error copyToStorage(TextureStorage *destStorage) = 0; - virtual gl::Error setData(const gl::ImageIndex &index, Image *image, const gl::Box *destBox, GLenum type, - const gl::PixelUnpackState &unpack, const uint8_t *pixelData) = 0; - - unsigned int getRenderTargetSerial(const gl::ImageIndex &index) const; - unsigned int getTextureSerial() const; - - protected: - void initializeSerials(unsigned int rtSerialsToReserve, unsigned int rtSerialsLayerStride); - - private: - DISALLOW_COPY_AND_ASSIGN(TextureStorage); - - unsigned int mFirstRenderTargetSerial; - unsigned int mRenderTargetSerialsLayerStride; -}; - -} - -#endif // LIBGLESV2_RENDERER_TEXTURESTORAGE_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TransformFeedbackD3D.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TransformFeedbackD3D.cpp deleted file mode 100644 index 11596006d0..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TransformFeedbackD3D.cpp +++ /dev/null @@ -1,38 +0,0 @@ -// -// Copyright 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// TransformFeedbackD3D.cpp is a no-op implementation for both the D3D9 and D3D11 renderers. - -#include "libGLESv2/renderer/d3d/TransformFeedbackD3D.h" - -namespace rx -{ - -TransformFeedbackD3D::TransformFeedbackD3D() -{ -} - -TransformFeedbackD3D::~TransformFeedbackD3D() -{ -} - -void TransformFeedbackD3D::begin(GLenum primitiveMode) -{ -} - -void TransformFeedbackD3D::end() -{ -} - -void TransformFeedbackD3D::pause() -{ -} - -void TransformFeedbackD3D::resume() -{ -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TransformFeedbackD3D.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TransformFeedbackD3D.h deleted file mode 100644 index 7c367aba1d..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TransformFeedbackD3D.h +++ /dev/null @@ -1,32 +0,0 @@ -// -// Copyright 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// TransformFeedbackD3D.h: Implements the abstract rx::TransformFeedbackImpl class. - -#ifndef LIBGLESV2_RENDERER_D3D_TRANSFORMFEEDBACKD3D_H_ -#define LIBGLESV2_RENDERER_D3D_TRANSFORMFEEDBACKD3D_H_ - -#include "libGLESv2/renderer/TransformFeedbackImpl.h" -#include "libGLESv2/angletypes.h" - -namespace rx -{ - -class TransformFeedbackD3D : public TransformFeedbackImpl -{ - public: - TransformFeedbackD3D(); - virtual ~TransformFeedbackD3D(); - - virtual void begin(GLenum primitiveMode); - virtual void end(); - virtual void pause(); - virtual void resume(); -}; - -} - -#endif // LIBGLESV2_RENDERER_D3D_TRANSFORMFEEDBACKD3D_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexBuffer.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexBuffer.cpp deleted file mode 100644 index 73f0c79e19..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexBuffer.cpp +++ /dev/null @@ -1,307 +0,0 @@ -// -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// VertexBuffer.cpp: Defines the abstract VertexBuffer class and VertexBufferInterface -// class with derivations, classes that perform graphics API agnostic vertex buffer operations. - -#include "libGLESv2/renderer/d3d/VertexBuffer.h" -#include "libGLESv2/renderer/d3d/BufferD3D.h" -#include "libGLESv2/renderer/d3d/RendererD3D.h" -#include "libGLESv2/VertexAttribute.h" - -#include "common/mathutil.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(RendererD3D *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(); -} - -gl::Error 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; -} - -gl::Error VertexBufferInterface::discard() -{ - return mVertexBuffer->discard(); -} - -gl::Error VertexBufferInterface::storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData ¤tValue, - GLint start, GLsizei count, GLsizei instances, unsigned int *outStreamOffset) -{ - gl::Error error(GL_NO_ERROR); - - unsigned int spaceRequired; - error = mVertexBuffer->getSpaceRequired(attrib, count, instances, &spaceRequired); - if (error.isError()) - { - return error; - } - - if (mWritePosition + spaceRequired < mWritePosition) - { - return gl::Error(GL_OUT_OF_MEMORY, "Internal error, new vertex buffer write position would overflow."); - } - - error = reserveSpace(mReservedSpace); - if (error.isError()) - { - return error; - } - mReservedSpace = 0; - - error = mVertexBuffer->storeVertexAttributes(attrib, currentValue, start, count, instances, mWritePosition); - if (error.isError()) - { - return error; - } - - if (outStreamOffset) - { - *outStreamOffset = mWritePosition; - } - - mWritePosition += spaceRequired; - - // Align to 16-byte boundary - mWritePosition = roundUp(mWritePosition, 16u); - - return gl::Error(GL_NO_ERROR); -} - -gl::Error VertexBufferInterface::reserveVertexSpace(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances) -{ - gl::Error error(GL_NO_ERROR); - - unsigned int requiredSpace; - error = mVertexBuffer->getSpaceRequired(attrib, count, instances, &requiredSpace); - if (error.isError()) - { - return error; - } - - // Protect against integer overflow - if (mReservedSpace + requiredSpace < mReservedSpace) - { - return gl::Error(GL_OUT_OF_MEMORY, "Unable to reserve %u extra bytes in internal vertex buffer, " - "it would result in an overflow.", requiredSpace); - } - - mReservedSpace += requiredSpace; - - // Align to 16-byte boundary - mReservedSpace = roundUp(mReservedSpace, 16u); - - return gl::Error(GL_NO_ERROR); -} - -VertexBuffer* VertexBufferInterface::getVertexBuffer() const -{ - return mVertexBuffer; -} - -bool VertexBufferInterface::directStoragePossible(const gl::VertexAttribute &attrib, - const gl::VertexAttribCurrentValueData ¤tValue) const -{ - gl::Buffer *buffer = attrib.buffer.get(); - BufferD3D *storage = buffer ? BufferD3D::makeBufferD3D(buffer->getImplementation()) : NULL; - - if (!storage || !storage->supportsDirectBinding()) - { - return false; - } - - // Alignment restrictions: In D3D, vertex data must be aligned to - // the format stride, or to a 4-byte boundary, whichever is smaller. - // (Undocumented, and experimentally confirmed) - size_t alignment = 4; - bool requiresConversion = false; - - if (attrib.type != GL_FLOAT) - { - gl::VertexFormat vertexFormat(attrib, currentValue.Type); - - unsigned int outputElementSize; - getVertexBuffer()->getSpaceRequired(attrib, 1, 0, &outputElementSize); - alignment = std::min(outputElementSize, 4); - - requiresConversion = (mRenderer->getVertexConversionType(vertexFormat) & VERTEX_CONVERT_CPU) != 0; - } - - bool isAligned = (static_cast(ComputeVertexAttributeStride(attrib)) % alignment == 0) && - (static_cast(attrib.offset) % alignment == 0); - - return !requiresConversion && isAligned; -} - -StreamingVertexBufferInterface::StreamingVertexBufferInterface(RendererD3D *renderer, std::size_t initialSize) : VertexBufferInterface(renderer, true) -{ - setBufferSize(initialSize); -} - -StreamingVertexBufferInterface::~StreamingVertexBufferInterface() -{ -} - -gl::Error StreamingVertexBufferInterface::reserveSpace(unsigned int size) -{ - unsigned int curBufferSize = getBufferSize(); - if (size > curBufferSize) - { - gl::Error error = setBufferSize(std::max(size, 3 * curBufferSize / 2)); - if (error.isError()) - { - return error; - } - setWritePosition(0); - } - else if (getWritePosition() + size > curBufferSize) - { - gl::Error error = discard(); - if (error.isError()) - { - return error; - } - setWritePosition(0); - } - - return gl::Error(GL_NO_ERROR); -} - -StaticVertexBufferInterface::StaticVertexBufferInterface(RendererD3D *renderer) : VertexBufferInterface(renderer, false) -{ -} - -StaticVertexBufferInterface::~StaticVertexBufferInterface() -{ -} - -bool StaticVertexBufferInterface::lookupAttribute(const gl::VertexAttribute &attrib, unsigned int *outStreamOffset) -{ - for (unsigned int element = 0; element < mCache.size(); element++) - { - if (mCache[element].type == attrib.type && - mCache[element].size == attrib.size && - mCache[element].stride == ComputeVertexAttributeStride(attrib) && - mCache[element].normalized == attrib.normalized && - mCache[element].pureInteger == attrib.pureInteger) - { - size_t offset = (static_cast(attrib.offset) % ComputeVertexAttributeStride(attrib)); - if (mCache[element].attributeOffset == offset) - { - if (outStreamOffset) - { - *outStreamOffset = mCache[element].streamOffset; - } - return true; - } - } - } - - return false; -} - -gl::Error StaticVertexBufferInterface::reserveSpace(unsigned int size) -{ - unsigned int curSize = getBufferSize(); - if (curSize == 0) - { - return setBufferSize(size); - } - else if (curSize >= size) - { - return gl::Error(GL_NO_ERROR); - } - else - { - UNREACHABLE(); - return gl::Error(GL_INVALID_OPERATION, "Internal error, Static vertex buffers can't be resized."); - } -} - -gl::Error StaticVertexBufferInterface::storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData ¤tValue, - GLint start, GLsizei count, GLsizei instances, unsigned int *outStreamOffset) -{ - unsigned int streamOffset; - gl::Error error = VertexBufferInterface::storeVertexAttributes(attrib, currentValue, start, count, instances, &streamOffset); - if (error.isError()) - { - return error; - } - - size_t attributeOffset = static_cast(attrib.offset) % ComputeVertexAttributeStride(attrib); - VertexElement element = { attrib.type, attrib.size, ComputeVertexAttributeStride(attrib), attrib.normalized, attrib.pureInteger, attributeOffset, streamOffset }; - mCache.push_back(element); - - if (outStreamOffset) - { - *outStreamOffset = streamOffset; - } - - return gl::Error(GL_NO_ERROR); -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexBuffer.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexBuffer.h deleted file mode 100644 index 4b40818f8e..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexBuffer.h +++ /dev/null @@ -1,144 +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. -// - -// 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" -#include "libGLESv2/Error.h" - -#include - -#include -#include - -namespace gl -{ -struct VertexAttribute; -struct VertexAttribCurrentValueData; -} - -namespace rx -{ -class RendererD3D; - -class VertexBuffer -{ - public: - VertexBuffer(); - virtual ~VertexBuffer(); - - virtual gl::Error initialize(unsigned int size, bool dynamicUsage) = 0; - - virtual gl::Error storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData ¤tValue, - GLint start, GLsizei count, GLsizei instances, unsigned int offset) = 0; - virtual gl::Error getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances, - unsigned int *outSpaceRequired) const = 0; - - virtual unsigned int getBufferSize() const = 0; - virtual gl::Error setBufferSize(unsigned int size) = 0; - virtual gl::Error 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(RendererD3D *renderer, bool dynamic); - virtual ~VertexBufferInterface(); - - gl::Error reserveVertexSpace(const gl::VertexAttribute &attribute, GLsizei count, GLsizei instances); - - unsigned int getBufferSize() const; - - unsigned int getSerial() const; - - virtual gl::Error storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData ¤tValue, - GLint start, GLsizei count, GLsizei instances, unsigned int *outStreamOffset); - - bool directStoragePossible(const gl::VertexAttribute &attrib, - const gl::VertexAttribCurrentValueData ¤tValue) const; - - VertexBuffer* getVertexBuffer() const; - - protected: - virtual gl::Error reserveSpace(unsigned int size) = 0; - - unsigned int getWritePosition() const; - void setWritePosition(unsigned int writePosition); - - gl::Error discard(); - - gl::Error setBufferSize(unsigned int size); - - private: - DISALLOW_COPY_AND_ASSIGN(VertexBufferInterface); - - RendererD3D *const mRenderer; - - VertexBuffer* mVertexBuffer; - - unsigned int mWritePosition; - unsigned int mReservedSpace; - bool mDynamic; -}; - -class StreamingVertexBufferInterface : public VertexBufferInterface -{ - public: - StreamingVertexBufferInterface(RendererD3D *renderer, std::size_t initialSize); - ~StreamingVertexBufferInterface(); - - protected: - gl::Error reserveSpace(unsigned int size); -}; - -class StaticVertexBufferInterface : public VertexBufferInterface -{ - public: - explicit StaticVertexBufferInterface(RendererD3D *renderer); - ~StaticVertexBufferInterface(); - - gl::Error storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData ¤tValue, - GLint start, GLsizei count, GLsizei instances, unsigned int *outStreamOffset); - - bool lookupAttribute(const gl::VertexAttribute &attribute, unsigned int* outStreamFffset); - - protected: - gl::Error reserveSpace(unsigned int size); - - private: - struct VertexElement - { - GLenum type; - GLuint size; - GLuint stride; - bool normalized; - bool pureInteger; - size_t 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/d3d/VertexDataManager.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexDataManager.cpp deleted file mode 100644 index 8d3df31c8b..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexDataManager.cpp +++ /dev/null @@ -1,354 +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/renderer/d3d/VertexDataManager.h" -#include "libGLESv2/renderer/d3d/BufferD3D.h" -#include "libGLESv2/renderer/d3d/VertexBuffer.h" -#include "libGLESv2/renderer/Renderer.h" -#include "libGLESv2/Buffer.h" -#include "libGLESv2/ProgramBinary.h" -#include "libGLESv2/VertexAttribute.h" -#include "libGLESv2/State.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 &attrib, unsigned int size) -{ - // Size cannot be larger than a GLsizei - if (size > static_cast(std::numeric_limits::max())) - { - size = static_cast(std::numeric_limits::max()); - } - - GLsizei stride = ComputeVertexAttributeStride(attrib); - return (size - attrib.offset % stride + (stride - ComputeVertexAttributeTypeSize(attrib))) / stride; -} - -static int StreamingBufferElementCount(const gl::VertexAttribute &attrib, int vertexDrawCount, int instanceDrawCount) -{ - // For instanced rendering, we draw "instanceDrawCount" sets of "vertexDrawCount" vertices. - // - // A vertex attribute with a positive divisor loads one instanced vertex for every set of - // non-instanced vertices, and the instanced vertex index advances once every "mDivisor" instances. - if (instanceDrawCount > 0 && attrib.divisor > 0) - { - return instanceDrawCount / attrib.divisor; - } - - return vertexDrawCount; -} - -VertexDataManager::VertexDataManager(RendererD3D *renderer) : mRenderer(renderer) -{ - for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) - { - mCurrentValue[i].FloatValues[0] = std::numeric_limits::quiet_NaN(); - mCurrentValue[i].FloatValues[1] = std::numeric_limits::quiet_NaN(); - mCurrentValue[i].FloatValues[2] = std::numeric_limits::quiet_NaN(); - mCurrentValue[i].FloatValues[3] = std::numeric_limits::quiet_NaN(); - mCurrentValue[i].Type = GL_FLOAT; - 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]; - } -} - -gl::Error VertexDataManager::prepareVertexData(const gl::State &state, GLint start, GLsizei count, - TranslatedAttribute *translated, GLsizei instances) -{ - if (!mStreamingBuffer) - { - return gl::Error(GL_OUT_OF_MEMORY, "Internal streaming vertex buffer is unexpectedly NULL."); - } - - // Invalidate static buffers that don't contain matching attributes - for (int attributeIndex = 0; attributeIndex < gl::MAX_VERTEX_ATTRIBS; attributeIndex++) - { - translated[attributeIndex].active = (state.getCurrentProgramBinary()->getSemanticIndex(attributeIndex) != -1); - const gl::VertexAttribute &curAttrib = state.getVertexAttribState(attributeIndex); - - if (translated[attributeIndex].active && curAttrib.enabled) - { - invalidateMatchingStaticData(curAttrib, state.getVertexAttribCurrentValue(attributeIndex)); - } - } - - // Reserve the required space in the buffers - for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) - { - const gl::VertexAttribute &curAttrib = state.getVertexAttribState(i); - if (translated[i].active && curAttrib.enabled) - { - gl::Error error = reserveSpaceForAttrib(curAttrib, state.getVertexAttribCurrentValue(i), count, instances); - if (error.isError()) - { - return error; - } - } - } - - // Perform the vertex data translations - for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) - { - const gl::VertexAttribute &curAttrib = state.getVertexAttribState(i); - if (translated[i].active) - { - if (curAttrib.enabled) - { - gl::Error error = storeAttribute(curAttrib, state.getVertexAttribCurrentValue(i), - &translated[i], start, count, instances); - - if (error.isError()) - { - return error; - } - } - else - { - if (!mCurrentValueBuffer[i]) - { - mCurrentValueBuffer[i] = new StreamingVertexBufferInterface(mRenderer, CONSTANT_VERTEX_BUFFER_SIZE); - } - - gl::Error error = storeCurrentValue(curAttrib, state.getVertexAttribCurrentValue(i), &translated[i], - &mCurrentValue[i], &mCurrentValueOffsets[i], - mCurrentValueBuffer[i]); - if (error.isError()) - { - return error; - } - } - } - } - - for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) - { - const gl::VertexAttribute &curAttrib = state.getVertexAttribState(i); - if (translated[i].active && curAttrib.enabled) - { - gl::Buffer *buffer = curAttrib.buffer.get(); - - if (buffer) - { - BufferD3D *bufferImpl = BufferD3D::makeBufferD3D(buffer->getImplementation()); - bufferImpl->promoteStaticUsage(count * ComputeVertexAttributeTypeSize(curAttrib)); - } - } - } - - return gl::Error(GL_NO_ERROR); -} - -void VertexDataManager::invalidateMatchingStaticData(const gl::VertexAttribute &attrib, - const gl::VertexAttribCurrentValueData ¤tValue) const -{ - gl::Buffer *buffer = attrib.buffer.get(); - - if (buffer) - { - BufferD3D *bufferImpl = BufferD3D::makeBufferD3D(buffer->getImplementation()); - StaticVertexBufferInterface *staticBuffer = bufferImpl->getStaticVertexBuffer(); - - if (staticBuffer && - staticBuffer->getBufferSize() > 0 && - !staticBuffer->lookupAttribute(attrib, NULL) && - !staticBuffer->directStoragePossible(attrib, currentValue)) - { - bufferImpl->invalidateStaticData(); - } - } -} - -gl::Error VertexDataManager::reserveSpaceForAttrib(const gl::VertexAttribute &attrib, - const gl::VertexAttribCurrentValueData ¤tValue, - GLsizei count, - GLsizei instances) const -{ - gl::Buffer *buffer = attrib.buffer.get(); - BufferD3D *bufferImpl = buffer ? BufferD3D::makeBufferD3D(buffer->getImplementation()) : NULL; - StaticVertexBufferInterface *staticBuffer = bufferImpl ? bufferImpl->getStaticVertexBuffer() : NULL; - VertexBufferInterface *vertexBuffer = staticBuffer ? staticBuffer : static_cast(mStreamingBuffer); - - if (!vertexBuffer->directStoragePossible(attrib, currentValue)) - { - if (staticBuffer) - { - if (staticBuffer->getBufferSize() == 0) - { - int totalCount = ElementsInBuffer(attrib, bufferImpl->getSize()); - gl::Error error = staticBuffer->reserveVertexSpace(attrib, totalCount, 0); - if (error.isError()) - { - return error; - } - } - } - else - { - int totalCount = StreamingBufferElementCount(attrib, count, instances); - ASSERT(!bufferImpl || ElementsInBuffer(attrib, bufferImpl->getSize()) >= totalCount); - - gl::Error error = mStreamingBuffer->reserveVertexSpace(attrib, totalCount, instances); - if (error.isError()) - { - return error; - } - } - } - - return gl::Error(GL_NO_ERROR); -} - -gl::Error VertexDataManager::storeAttribute(const gl::VertexAttribute &attrib, - const gl::VertexAttribCurrentValueData ¤tValue, - TranslatedAttribute *translated, - GLint start, - GLsizei count, - GLsizei instances) -{ - gl::Buffer *buffer = attrib.buffer.get(); - ASSERT(buffer || attrib.pointer); - - BufferD3D *storage = buffer ? BufferD3D::makeBufferD3D(buffer->getImplementation()) : NULL; - StaticVertexBufferInterface *staticBuffer = storage ? storage->getStaticVertexBuffer() : NULL; - VertexBufferInterface *vertexBuffer = staticBuffer ? staticBuffer : static_cast(mStreamingBuffer); - bool directStorage = vertexBuffer->directStoragePossible(attrib, currentValue); - - unsigned int streamOffset = 0; - unsigned int outputElementSize = 0; - - if (directStorage) - { - outputElementSize = ComputeVertexAttributeStride(attrib); - streamOffset = attrib.offset + outputElementSize * start; - } - else if (staticBuffer) - { - gl::Error error = staticBuffer->getVertexBuffer()->getSpaceRequired(attrib, 1, 0, &outputElementSize); - if (error.isError()) - { - return error; - } - - if (!staticBuffer->lookupAttribute(attrib, &streamOffset)) - { - // Convert the entire buffer - int totalCount = ElementsInBuffer(attrib, storage->getSize()); - int startIndex = attrib.offset / ComputeVertexAttributeStride(attrib); - - gl::Error error = staticBuffer->storeVertexAttributes(attrib, currentValue, -startIndex, totalCount, - 0, &streamOffset); - if (error.isError()) - { - return error; - } - } - - unsigned int firstElementOffset = (attrib.offset / ComputeVertexAttributeStride(attrib)) * outputElementSize; - unsigned int startOffset = (instances == 0 || attrib.divisor == 0) ? start * outputElementSize : 0; - if (streamOffset + firstElementOffset + startOffset < streamOffset) - { - return gl::Error(GL_OUT_OF_MEMORY); - } - - streamOffset += firstElementOffset + startOffset; - } - else - { - int totalCount = StreamingBufferElementCount(attrib, count, instances); - gl::Error error = mStreamingBuffer->getVertexBuffer()->getSpaceRequired(attrib, 1, 0, &outputElementSize); - if (error.isError()) - { - return error; - } - - error = mStreamingBuffer->storeVertexAttributes(attrib, currentValue, start, totalCount, instances, &streamOffset); - if (error.isError()) - { - return error; - } - } - - translated->storage = directStorage ? storage : NULL; - translated->vertexBuffer = vertexBuffer->getVertexBuffer(); - translated->serial = directStorage ? storage->getSerial() : vertexBuffer->getSerial(); - translated->divisor = attrib.divisor; - - translated->attribute = &attrib; - translated->currentValueType = currentValue.Type; - translated->stride = outputElementSize; - translated->offset = streamOffset; - - return gl::Error(GL_NO_ERROR); -} - -gl::Error VertexDataManager::storeCurrentValue(const gl::VertexAttribute &attrib, - const gl::VertexAttribCurrentValueData ¤tValue, - TranslatedAttribute *translated, - gl::VertexAttribCurrentValueData *cachedValue, - size_t *cachedOffset, - StreamingVertexBufferInterface *buffer) -{ - if (*cachedValue != currentValue) - { - gl::Error error = buffer->reserveVertexSpace(attrib, 1, 0); - if (error.isError()) - { - return error; - } - - unsigned int streamOffset; - error = buffer->storeVertexAttributes(attrib, currentValue, 0, 1, 0, &streamOffset); - if (error.isError()) - { - return error; - } - - *cachedValue = currentValue; - *cachedOffset = streamOffset; - } - - translated->storage = NULL; - translated->vertexBuffer = buffer->getVertexBuffer(); - translated->serial = buffer->getSerial(); - translated->divisor = 0; - - translated->attribute = &attrib; - translated->currentValueType = currentValue.Type; - translated->stride = 0; - translated->offset = *cachedOffset; - - return gl::Error(GL_NO_ERROR); -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexDataManager.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexDataManager.h deleted file mode 100644 index 64ef653221..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexDataManager.h +++ /dev/null @@ -1,96 +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_RENDERER_VERTEXDATAMANAGER_H_ -#define LIBGLESV2_RENDERER_VERTEXDATAMANAGER_H_ - -#include "libGLESv2/Constants.h" -#include "libGLESv2/VertexAttribute.h" -#include "common/angleutils.h" - -namespace gl -{ -class ProgramBinary; -class State; -struct VertexAttribute; -struct VertexAttribCurrentValueData; -} - -namespace rx -{ -class BufferD3D; -class StreamingVertexBufferInterface; -class VertexBuffer; -class RendererD3D; - -struct TranslatedAttribute -{ - TranslatedAttribute() : active(false), attribute(NULL), currentValueType(GL_NONE), - offset(0), stride(0), vertexBuffer(NULL), storage(NULL), - serial(0), divisor(0) {}; - bool active; - - const gl::VertexAttribute *attribute; - GLenum currentValueType; - unsigned int offset; - unsigned int stride; // 0 means not to advance the read pointer at all - - VertexBuffer *vertexBuffer; - BufferD3D *storage; - unsigned int serial; - unsigned int divisor; -}; - -class VertexDataManager -{ - public: - VertexDataManager(RendererD3D *renderer); - virtual ~VertexDataManager(); - - gl::Error prepareVertexData(const gl::State &state, GLint start, GLsizei count, - TranslatedAttribute *outAttribs, GLsizei instances); - - private: - DISALLOW_COPY_AND_ASSIGN(VertexDataManager); - - gl::Error reserveSpaceForAttrib(const gl::VertexAttribute &attrib, - const gl::VertexAttribCurrentValueData ¤tValue, - GLsizei count, - GLsizei instances) const; - - void invalidateMatchingStaticData(const gl::VertexAttribute &attrib, - const gl::VertexAttribCurrentValueData ¤tValue) const; - - gl::Error storeAttribute(const gl::VertexAttribute &attrib, - const gl::VertexAttribCurrentValueData ¤tValue, - TranslatedAttribute *translated, - GLint start, - GLsizei count, - GLsizei instances); - - gl::Error storeCurrentValue(const gl::VertexAttribute &attrib, - const gl::VertexAttribCurrentValueData ¤tValue, - TranslatedAttribute *translated, - gl::VertexAttribCurrentValueData *cachedValue, - size_t *cachedOffset, - StreamingVertexBufferInterface *buffer); - - RendererD3D *const mRenderer; - - StreamingVertexBufferInterface *mStreamingBuffer; - - gl::VertexAttribCurrentValueData mCurrentValue[gl::MAX_VERTEX_ATTRIBS]; - - 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/d3d/d3d11/Blit11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp deleted file mode 100644 index 06aea9befe..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp +++ /dev/null @@ -1,1047 +0,0 @@ -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Blit11.cpp: Texture copy utility class. - -#include "libGLESv2/renderer/d3d/d3d11/Blit11.h" -#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" -#include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h" -#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" -#include "libGLESv2/main.h" -#include "libGLESv2/formatutils.h" - -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthrough2dvs.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughdepth2dps.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dps.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2duips.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dips.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2dps.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2duips.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2dips.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg2dps.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg2duips.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg2dips.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr2dps.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr2duips.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr2dips.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughlum2dps.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha2dps.h" - -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthrough3dvs.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthrough3dgs.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3dps.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3duips.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3dips.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3dps.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3duips.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3dips.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg3dps.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg3duips.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg3dips.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr3dps.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr3duips.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr3dips.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughlum3dps.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha3dps.h" - -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzlef2dps.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzlei2dps.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzleui2dps.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzlef3dps.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzlei3dps.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzleui3dps.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzlef2darrayps.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzlei2darrayps.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzleui2darrayps.h" - -namespace rx -{ - -static DXGI_FORMAT GetTextureFormat(ID3D11Resource *resource) -{ - ID3D11Texture2D *texture = d3d11::DynamicCastComObject(resource); - if (!texture) - { - return DXGI_FORMAT_UNKNOWN; - } - - D3D11_TEXTURE2D_DESC desc; - texture->GetDesc(&desc); - - SafeRelease(texture); - - return desc.Format; -} - -static ID3D11Resource *CreateStagingTexture(ID3D11Device *device, ID3D11DeviceContext *context, - ID3D11Resource *source, unsigned int subresource, - const gl::Extents &size, unsigned int cpuAccessFlags) -{ - D3D11_TEXTURE2D_DESC stagingDesc; - stagingDesc.Width = size.width; - stagingDesc.Height = size.height; - stagingDesc.MipLevels = 1; - stagingDesc.ArraySize = 1; - stagingDesc.Format = GetTextureFormat(source); - stagingDesc.SampleDesc.Count = 1; - stagingDesc.SampleDesc.Quality = 0; - stagingDesc.Usage = D3D11_USAGE_STAGING; - stagingDesc.CPUAccessFlags = cpuAccessFlags; - stagingDesc.MiscFlags = 0; - stagingDesc.BindFlags = 0; - - ID3D11Texture2D *stagingTexture = NULL; - HRESULT result = device->CreateTexture2D(&stagingDesc, NULL, &stagingTexture); - if (FAILED(result)) - { - ERR("Failed to create staging texture for depth stencil blit. HRESULT: 0x%X.", result); - return NULL; - } - - context->CopySubresourceRegion(stagingTexture, 0, 0, 0, 0, source, subresource, NULL); - - return stagingTexture; -} - -inline static void GenerateVertexCoords(const gl::Box &sourceArea, const gl::Extents &sourceSize, - const gl::Box &destArea, const gl::Extents &destSize, - float *x1, float *y1, float *x2, float *y2, - float *u1, float *v1, float *u2, float *v2) -{ - *x1 = (destArea.x / float(destSize.width)) * 2.0f - 1.0f; - *y1 = ((destSize.height - destArea.y - destArea.height) / float(destSize.height)) * 2.0f - 1.0f; - *x2 = ((destArea.x + destArea.width) / float(destSize.width)) * 2.0f - 1.0f; - *y2 = ((destSize.height - destArea.y) / float(destSize.height)) * 2.0f - 1.0f; - - *u1 = sourceArea.x / float(sourceSize.width); - *v1 = sourceArea.y / float(sourceSize.height); - *u2 = (sourceArea.x + sourceArea.width) / float(sourceSize.width); - *v2 = (sourceArea.y + sourceArea.height) / float(sourceSize.height); -} - -static void Write2DVertices(const gl::Box &sourceArea, const gl::Extents &sourceSize, - const gl::Box &destArea, const gl::Extents &destSize, - void *outVertices, unsigned int *outStride, unsigned int *outVertexCount, - D3D11_PRIMITIVE_TOPOLOGY *outTopology) -{ - float x1, y1, x2, y2, u1, v1, u2, v2; - GenerateVertexCoords(sourceArea, sourceSize, destArea, destSize, &x1, &y1, &x2, &y2, &u1, &v1, &u2, &v2); - - d3d11::PositionTexCoordVertex *vertices = static_cast(outVertices); - - 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); - - *outStride = sizeof(d3d11::PositionTexCoordVertex); - *outVertexCount = 4; - *outTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP; -} - -static void Write3DVertices(const gl::Box &sourceArea, const gl::Extents &sourceSize, - const gl::Box &destArea, const gl::Extents &destSize, - void *outVertices, unsigned int *outStride, unsigned int *outVertexCount, - D3D11_PRIMITIVE_TOPOLOGY *outTopology) -{ - ASSERT(sourceSize.depth > 0 && destSize.depth > 0); - - float x1, y1, x2, y2, u1, v1, u2, v2; - GenerateVertexCoords(sourceArea, sourceSize, destArea, destSize, &x1, &y1, &x2, &y2, &u1, &v1, &u2, &v2); - - d3d11::PositionLayerTexCoord3DVertex *vertices = static_cast(outVertices); - - for (int i = 0; i < destSize.depth; i++) - { - float readDepth = (float)i / std::max(destSize.depth - 1, 1); - - d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 0], x1, y1, i, u1, v2, readDepth); - d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 1], x1, y2, i, u1, v1, readDepth); - d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 2], x2, y1, i, u2, v2, readDepth); - - d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 3], x1, y2, i, u1, v1, readDepth); - d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 4], x2, y2, i, u2, v1, readDepth); - d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 5], x2, y1, i, u2, v2, readDepth); - } - - *outStride = sizeof(d3d11::PositionLayerTexCoord3DVertex); - *outVertexCount = destSize.depth * 6; - *outTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; -} - -Blit11::Blit11(Renderer11 *renderer) - : mRenderer(renderer), mBlitShaderMap(compareBlitParameters), mSwizzleShaderMap(compareSwizzleParameters), - mVertexBuffer(NULL), mPointSampler(NULL), mLinearSampler(NULL), mScissorEnabledRasterizerState(NULL), - mScissorDisabledRasterizerState(NULL), mDepthStencilState(NULL), - mQuad2DIL(NULL), mQuad2DVS(NULL), mDepthPS(NULL), - mQuad3DIL(NULL), mQuad3DVS(NULL), mQuad3DGS(NULL), - mSwizzleCB(NULL) -{ - HRESULT result; - ID3D11Device *device = mRenderer->getDevice(); - - D3D11_BUFFER_DESC vbDesc; - vbDesc.ByteWidth = std::max(sizeof(d3d11::PositionLayerTexCoord3DVertex), sizeof(d3d11::PositionTexCoordVertex)) * - 6 * renderer->getRendererCaps().max3DTextureSize; - vbDesc.Usage = D3D11_USAGE_DYNAMIC; - vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; - vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - vbDesc.MiscFlags = 0; - vbDesc.StructureByteStride = 0; - - result = device->CreateBuffer(&vbDesc, NULL, &mVertexBuffer); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mVertexBuffer, "Blit11 vertex buffer"); - - D3D11_SAMPLER_DESC pointSamplerDesc; - pointSamplerDesc.Filter = D3D11_FILTER_MIN_MAG_POINT_MIP_LINEAR; - pointSamplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP; - pointSamplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; - pointSamplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; - pointSamplerDesc.MipLODBias = 0.0f; - pointSamplerDesc.MaxAnisotropy = 0; - pointSamplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER; - pointSamplerDesc.BorderColor[0] = 0.0f; - pointSamplerDesc.BorderColor[1] = 0.0f; - pointSamplerDesc.BorderColor[2] = 0.0f; - pointSamplerDesc.BorderColor[3] = 0.0f; - pointSamplerDesc.MinLOD = 0.0f; - pointSamplerDesc.MaxLOD = mRenderer->isLevel9() ? D3D11_FLOAT32_MAX : 0.0f; - - result = device->CreateSamplerState(&pointSamplerDesc, &mPointSampler); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mPointSampler, "Blit11 point sampler"); - - D3D11_SAMPLER_DESC linearSamplerDesc; - linearSamplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; - linearSamplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP; - linearSamplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; - linearSamplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; - linearSamplerDesc.MipLODBias = 0.0f; - linearSamplerDesc.MaxAnisotropy = 0; - linearSamplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER; - linearSamplerDesc.BorderColor[0] = 0.0f; - linearSamplerDesc.BorderColor[1] = 0.0f; - linearSamplerDesc.BorderColor[2] = 0.0f; - linearSamplerDesc.BorderColor[3] = 0.0f; - linearSamplerDesc.MinLOD = 0.0f; - linearSamplerDesc.MaxLOD = mRenderer->isLevel9() ? D3D11_FLOAT32_MAX : 0.0f; - - result = device->CreateSamplerState(&linearSamplerDesc, &mLinearSampler); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mLinearSampler, "Blit11 linear sampler"); - - // Use a rasterizer state that will not cull so that inverted quads will not be culled - D3D11_RASTERIZER_DESC rasterDesc; - rasterDesc.FillMode = D3D11_FILL_SOLID; - rasterDesc.CullMode = D3D11_CULL_NONE; - rasterDesc.FrontCounterClockwise = FALSE; - rasterDesc.DepthBias = 0; - rasterDesc.SlopeScaledDepthBias = 0.0f; - rasterDesc.DepthBiasClamp = 0.0f; - rasterDesc.DepthClipEnable = TRUE; - rasterDesc.MultisampleEnable = FALSE; - rasterDesc.AntialiasedLineEnable = FALSE; - - rasterDesc.ScissorEnable = TRUE; - result = device->CreateRasterizerState(&rasterDesc, &mScissorEnabledRasterizerState); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mScissorEnabledRasterizerState, "Blit11 scissoring rasterizer state"); - - rasterDesc.ScissorEnable = FALSE; - result = device->CreateRasterizerState(&rasterDesc, &mScissorDisabledRasterizerState); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mScissorDisabledRasterizerState, "Blit11 no scissoring rasterizer state"); - - D3D11_DEPTH_STENCIL_DESC depthStencilDesc; - depthStencilDesc.DepthEnable = true; - depthStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; - depthStencilDesc.DepthFunc = D3D11_COMPARISON_ALWAYS; - depthStencilDesc.StencilEnable = FALSE; - depthStencilDesc.StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK; - depthStencilDesc.StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK; - depthStencilDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; - depthStencilDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP; - depthStencilDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; - depthStencilDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS; - depthStencilDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; - depthStencilDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP; - depthStencilDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; - depthStencilDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS; - - result = device->CreateDepthStencilState(&depthStencilDesc, &mDepthStencilState); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mDepthStencilState, "Blit11 depth stencil state"); - - D3D11_INPUT_ELEMENT_DESC quad2DLayout[] = - { - { "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(quad2DLayout, ArraySize(quad2DLayout), g_VS_Passthrough2D, ArraySize(g_VS_Passthrough2D), &mQuad2DIL); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mQuad2DIL, "Blit11 2D input layout"); - - result = device->CreateVertexShader(g_VS_Passthrough2D, ArraySize(g_VS_Passthrough2D), NULL, &mQuad2DVS); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mQuad2DVS, "Blit11 2D vertex shader"); - - if (!renderer->isLevel9()) - { - result = device->CreatePixelShader(g_PS_PassthroughDepth2D, ArraySize(g_PS_PassthroughDepth2D), NULL, &mDepthPS); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mDepthPS, "Blit11 2D depth pixel shader"); - - D3D11_INPUT_ELEMENT_DESC quad3DLayout[] = - { - { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, - { "LAYER", 0, DXGI_FORMAT_R32_UINT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0 }, - { "TEXCOORD", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, - }; - - result = device->CreateInputLayout(quad3DLayout, ArraySize(quad3DLayout), g_VS_Passthrough3D, ArraySize(g_VS_Passthrough3D), &mQuad3DIL); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mQuad3DIL, "Blit11 3D input layout"); - - result = device->CreateVertexShader(g_VS_Passthrough3D, ArraySize(g_VS_Passthrough3D), NULL, &mQuad3DVS); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mQuad3DVS, "Blit11 3D vertex shader"); - - result = device->CreateGeometryShader(g_GS_Passthrough3D, ArraySize(g_GS_Passthrough3D), NULL, &mQuad3DGS); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mQuad3DGS, "Renderer11 copy 3D texture geometry shader"); - } - - buildShaderMap(); - - D3D11_BUFFER_DESC swizzleBufferDesc; - swizzleBufferDesc.ByteWidth = sizeof(unsigned int) * 4; - swizzleBufferDesc.Usage = D3D11_USAGE_DYNAMIC; - swizzleBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; - swizzleBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - swizzleBufferDesc.MiscFlags = 0; - swizzleBufferDesc.StructureByteStride = 0; - - result = device->CreateBuffer(&swizzleBufferDesc, NULL, &mSwizzleCB); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mSwizzleCB, "Blit11 swizzle constant buffer"); -} - -Blit11::~Blit11() -{ - SafeRelease(mVertexBuffer); - SafeRelease(mPointSampler); - SafeRelease(mLinearSampler); - SafeRelease(mScissorEnabledRasterizerState); - SafeRelease(mScissorDisabledRasterizerState); - SafeRelease(mDepthStencilState); - - SafeRelease(mQuad2DIL); - SafeRelease(mQuad2DVS); - SafeRelease(mDepthPS); - - SafeRelease(mQuad3DIL); - SafeRelease(mQuad3DVS); - SafeRelease(mQuad3DGS); - - SafeRelease(mSwizzleCB); - - clearShaderMap(); -} - -static inline unsigned int GetSwizzleIndex(GLenum swizzle) -{ - unsigned int colorIndex = 0; - - switch (swizzle) - { - case GL_RED: colorIndex = 0; break; - case GL_GREEN: colorIndex = 1; break; - case GL_BLUE: colorIndex = 2; break; - case GL_ALPHA: colorIndex = 3; break; - case GL_ZERO: colorIndex = 4; break; - case GL_ONE: colorIndex = 5; break; - default: UNREACHABLE(); break; - } - - return colorIndex; -} - -gl::Error Blit11::swizzleTexture(ID3D11ShaderResourceView *source, ID3D11RenderTargetView *dest, const gl::Extents &size, - GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha) -{ - HRESULT result; - ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); - - D3D11_SHADER_RESOURCE_VIEW_DESC sourceSRVDesc; - source->GetDesc(&sourceSRVDesc); - - const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(sourceSRVDesc.Format); - const gl::InternalFormat &sourceFormatInfo = gl::GetInternalFormatInfo(dxgiFormatInfo.internalFormat); - - GLenum shaderType = GL_NONE; - switch (sourceFormatInfo.componentType) - { - case GL_UNSIGNED_NORMALIZED: - case GL_SIGNED_NORMALIZED: - case GL_FLOAT: - shaderType = GL_FLOAT; - break; - case GL_INT: - shaderType = GL_INT; - break; - case GL_UNSIGNED_INT: - shaderType = GL_UNSIGNED_INT; - break; - default: - UNREACHABLE(); - break; - } - - SwizzleParameters parameters = { 0 }; - parameters.mDestinationType = shaderType; - parameters.mViewDimension = sourceSRVDesc.ViewDimension; - - SwizzleShaderMap::const_iterator i = mSwizzleShaderMap.find(parameters); - if (i == mSwizzleShaderMap.end()) - { - UNREACHABLE(); - return gl::Error(GL_INVALID_OPERATION, "Internal error, missing swizzle shader."); - } - - const Shader &shader = i->second; - - // Set vertices - D3D11_MAPPED_SUBRESOURCE mappedResource; - result = deviceContext->Map(mVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal vertex buffer for swizzle, HRESULT: 0x%X.", result); - } - - UINT stride = 0; - UINT startIdx = 0; - UINT drawCount = 0; - D3D11_PRIMITIVE_TOPOLOGY topology; - - gl::Box area(0, 0, 0, size.width, size.height, size.depth); - shader.mVertexWriteFunction(area, size, area, size, mappedResource.pData, &stride, &drawCount, &topology); - - deviceContext->Unmap(mVertexBuffer, 0); - - // Set constant buffer - result = deviceContext->Map(mSwizzleCB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal constant buffer for swizzle, HRESULT: 0x%X.", result); - } - - unsigned int *swizzleIndices = reinterpret_cast(mappedResource.pData); - swizzleIndices[0] = GetSwizzleIndex(swizzleRed); - swizzleIndices[1] = GetSwizzleIndex(swizzleGreen); - swizzleIndices[2] = GetSwizzleIndex(swizzleBlue); - swizzleIndices[3] = GetSwizzleIndex(swizzleAlpha); - - deviceContext->Unmap(mSwizzleCB, 0); - - // Apply vertex buffer - deviceContext->IASetVertexBuffers(0, 1, &mVertexBuffer, &stride, &startIdx); - - // Apply constant buffer - deviceContext->PSSetConstantBuffers(0, 1, &mSwizzleCB); - - // Apply state - deviceContext->OMSetBlendState(NULL, NULL, 0xFFFFFFF); - deviceContext->OMSetDepthStencilState(NULL, 0xFFFFFFFF); - deviceContext->RSSetState(mScissorDisabledRasterizerState); - - // Apply shaders - deviceContext->IASetInputLayout(shader.mInputLayout); - deviceContext->IASetPrimitiveTopology(topology); - deviceContext->VSSetShader(shader.mVertexShader, NULL, 0); - - deviceContext->PSSetShader(shader.mPixelShader, NULL, 0); - deviceContext->GSSetShader(shader.mGeometryShader, NULL, 0); - - // Unset the currently bound shader resource to avoid conflicts - mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, NULL); - - // Apply render target - mRenderer->setOneTimeRenderTarget(dest); - - // Set the viewport - D3D11_VIEWPORT viewport; - viewport.TopLeftX = 0; - viewport.TopLeftY = 0; - viewport.Width = size.width; - viewport.Height = size.height; - viewport.MinDepth = 0.0f; - viewport.MaxDepth = 1.0f; - deviceContext->RSSetViewports(1, &viewport); - - // Apply textures - mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, source); - - // Apply samplers - deviceContext->PSSetSamplers(0, 1, &mPointSampler); - - // Draw the quad - deviceContext->Draw(drawCount, 0); - - // Unbind textures and render targets and vertex buffer - mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, NULL); - - mRenderer->unapplyRenderTargets(); - - UINT zero = 0; - ID3D11Buffer *const nullBuffer = NULL; - deviceContext->IASetVertexBuffers(0, 1, &nullBuffer, &zero, &zero); - - mRenderer->markAllStateDirty(); - - return gl::Error(GL_NO_ERROR); -} - -gl::Error Blit11::copyTexture(ID3D11ShaderResourceView *source, const gl::Box &sourceArea, const gl::Extents &sourceSize, - ID3D11RenderTargetView *dest, const gl::Box &destArea, const gl::Extents &destSize, - const gl::Rectangle *scissor, GLenum destFormat, GLenum filter) -{ - HRESULT result; - ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); - - // Determine if the source format is a signed integer format, the destFormat will already - // be GL_XXXX_INTEGER but it does not tell us if it is signed or unsigned. - D3D11_SHADER_RESOURCE_VIEW_DESC sourceSRVDesc; - source->GetDesc(&sourceSRVDesc); - - const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(sourceSRVDesc.Format); - const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(dxgiFormatInfo.internalFormat); - - BlitParameters parameters = { 0 }; - parameters.mDestinationFormat = destFormat; - parameters.mSignedInteger = (internalFormatInfo.componentType == GL_INT); - parameters.m3DBlit = sourceArea.depth > 1; - - BlitShaderMap::const_iterator i = mBlitShaderMap.find(parameters); - if (i == mBlitShaderMap.end()) - { - UNREACHABLE(); - return gl::Error(GL_OUT_OF_MEMORY, "Could not find appropriate shader for internal texture blit."); - } - - const Shader& shader = i->second; - - // Set vertices - D3D11_MAPPED_SUBRESOURCE mappedResource; - result = deviceContext->Map(mVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal vertex buffer for texture copy, HRESULT: 0x%X.", result); - } - - UINT stride = 0; - UINT startIdx = 0; - UINT drawCount = 0; - D3D11_PRIMITIVE_TOPOLOGY topology; - - shader.mVertexWriteFunction(sourceArea, sourceSize, destArea, destSize, mappedResource.pData, - &stride, &drawCount, &topology); - - deviceContext->Unmap(mVertexBuffer, 0); - - // Apply vertex buffer - deviceContext->IASetVertexBuffers(0, 1, &mVertexBuffer, &stride, &startIdx); - - // Apply state - deviceContext->OMSetBlendState(NULL, NULL, 0xFFFFFFF); - deviceContext->OMSetDepthStencilState(NULL, 0xFFFFFFFF); - - if (scissor) - { - D3D11_RECT scissorRect; - scissorRect.left = scissor->x; - scissorRect.right = scissor->x + scissor->width; - scissorRect.top = scissor->y; - scissorRect.bottom = scissor->y + scissor->height; - - deviceContext->RSSetScissorRects(1, &scissorRect); - deviceContext->RSSetState(mScissorEnabledRasterizerState); - } - else - { - deviceContext->RSSetState(mScissorDisabledRasterizerState); - } - - // Apply shaders - deviceContext->IASetInputLayout(shader.mInputLayout); - deviceContext->IASetPrimitiveTopology(topology); - deviceContext->VSSetShader(shader.mVertexShader, NULL, 0); - - deviceContext->PSSetShader(shader.mPixelShader, NULL, 0); - deviceContext->GSSetShader(shader.mGeometryShader, NULL, 0); - - // Unset the currently bound shader resource to avoid conflicts - mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, NULL); - - // Apply render target - mRenderer->setOneTimeRenderTarget(dest); - - // Set the viewport - D3D11_VIEWPORT viewport; - viewport.TopLeftX = 0; - viewport.TopLeftY = 0; - viewport.Width = destSize.width; - viewport.Height = destSize.height; - viewport.MinDepth = 0.0f; - viewport.MaxDepth = 1.0f; - deviceContext->RSSetViewports(1, &viewport); - - // Apply textures - mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, source); - - // Apply samplers - ID3D11SamplerState *sampler = NULL; - switch (filter) - { - case GL_NEAREST: sampler = mPointSampler; break; - case GL_LINEAR: sampler = mLinearSampler; break; - - default: - UNREACHABLE(); - return gl::Error(GL_OUT_OF_MEMORY, "Internal error, unknown blit filter mode."); - } - deviceContext->PSSetSamplers(0, 1, &sampler); - - // Draw the quad - deviceContext->Draw(drawCount, 0); - - // Unbind textures and render targets and vertex buffer - mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, NULL); - - mRenderer->unapplyRenderTargets(); - - UINT zero = 0; - ID3D11Buffer *const nullBuffer = NULL; - deviceContext->IASetVertexBuffers(0, 1, &nullBuffer, &zero, &zero); - - mRenderer->markAllStateDirty(); - - return gl::Error(GL_NO_ERROR); -} - -gl::Error Blit11::copyStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize, - ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize, - const gl::Rectangle *scissor) -{ - return copyDepthStencil(source, sourceSubresource, sourceArea, sourceSize, - dest, destSubresource, destArea, destSize, - scissor, true); -} - -gl::Error Blit11::copyDepth(ID3D11ShaderResourceView *source, const gl::Box &sourceArea, const gl::Extents &sourceSize, - ID3D11DepthStencilView *dest, const gl::Box &destArea, const gl::Extents &destSize, - const gl::Rectangle *scissor) -{ - HRESULT result; - ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); - - // Set vertices - D3D11_MAPPED_SUBRESOURCE mappedResource; - result = deviceContext->Map(mVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal vertex buffer for texture copy, HRESULT: 0x%X.", result); - } - - UINT stride = 0; - UINT startIdx = 0; - UINT drawCount = 0; - D3D11_PRIMITIVE_TOPOLOGY topology; - - Write2DVertices(sourceArea, sourceSize, destArea, destSize, mappedResource.pData, - &stride, &drawCount, &topology); - - deviceContext->Unmap(mVertexBuffer, 0); - - // Apply vertex buffer - deviceContext->IASetVertexBuffers(0, 1, &mVertexBuffer, &stride, &startIdx); - - // Apply state - deviceContext->OMSetBlendState(NULL, NULL, 0xFFFFFFF); - deviceContext->OMSetDepthStencilState(mDepthStencilState, 0xFFFFFFFF); - - if (scissor) - { - D3D11_RECT scissorRect; - scissorRect.left = scissor->x; - scissorRect.right = scissor->x + scissor->width; - scissorRect.top = scissor->y; - scissorRect.bottom = scissor->y + scissor->height; - - deviceContext->RSSetScissorRects(1, &scissorRect); - deviceContext->RSSetState(mScissorEnabledRasterizerState); - } - else - { - deviceContext->RSSetState(mScissorDisabledRasterizerState); - } - - // Apply shaders - deviceContext->IASetInputLayout(mQuad2DIL); - deviceContext->IASetPrimitiveTopology(topology); - deviceContext->VSSetShader(mQuad2DVS, NULL, 0); - - deviceContext->PSSetShader(mDepthPS, NULL, 0); - deviceContext->GSSetShader(NULL, NULL, 0); - - // Unset the currently bound shader resource to avoid conflicts - mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, NULL); - - // Apply render target - deviceContext->OMSetRenderTargets(0, NULL, dest); - - // Set the viewport - D3D11_VIEWPORT viewport; - viewport.TopLeftX = 0; - viewport.TopLeftY = 0; - viewport.Width = destSize.width; - viewport.Height = destSize.height; - viewport.MinDepth = 0.0f; - viewport.MaxDepth = 1.0f; - deviceContext->RSSetViewports(1, &viewport); - - // Apply textures - mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, source); - - // Apply samplers - deviceContext->PSSetSamplers(0, 1, &mPointSampler); - - // Draw the quad - deviceContext->Draw(drawCount, 0); - - // Unbind textures and render targets and vertex buffer - mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, NULL); - - mRenderer->unapplyRenderTargets(); - - UINT zero = 0; - ID3D11Buffer *const nullBuffer = NULL; - deviceContext->IASetVertexBuffers(0, 1, &nullBuffer, &zero, &zero); - - mRenderer->markAllStateDirty(); - - return gl::Error(GL_NO_ERROR); -} - -gl::Error Blit11::copyDepthStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize, - ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize, - const gl::Rectangle *scissor) -{ - return copyDepthStencil(source, sourceSubresource, sourceArea, sourceSize, - dest, destSubresource, destArea, destSize, - scissor, false); -} - -gl::Error Blit11::copyDepthStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize, - ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize, - const gl::Rectangle *scissor, bool stencilOnly) -{ - ID3D11Device *device = mRenderer->getDevice(); - ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); - - ID3D11Resource *sourceStaging = CreateStagingTexture(device, deviceContext, source, sourceSubresource, sourceSize, D3D11_CPU_ACCESS_READ); - // HACK: Create the destination staging buffer as a read/write texture so ID3D11DevicContext::UpdateSubresource can be called - // using it's mapped data as a source - ID3D11Resource *destStaging = CreateStagingTexture(device, deviceContext, dest, destSubresource, destSize, D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE); - - if (!sourceStaging || !destStaging) - { - SafeRelease(sourceStaging); - SafeRelease(destStaging); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal staging textures for depth stencil blit."); - } - - DXGI_FORMAT format = GetTextureFormat(source); - ASSERT(format == GetTextureFormat(dest)); - - const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(format); - unsigned int pixelSize = dxgiFormatInfo.pixelBytes; - unsigned int copyOffset = 0; - unsigned int copySize = pixelSize; - if (stencilOnly) - { - copyOffset = dxgiFormatInfo.depthBits / 8; - copySize = dxgiFormatInfo.stencilBits / 8; - - // It would be expensive to have non-byte sized stencil sizes since it would - // require reading from the destination, currently there aren't any though. - ASSERT(dxgiFormatInfo.stencilBits % 8 == 0 && - dxgiFormatInfo.depthBits % 8 == 0); - } - - D3D11_MAPPED_SUBRESOURCE sourceMapping; - HRESULT result = deviceContext->Map(sourceStaging, 0, D3D11_MAP_READ, 0, &sourceMapping); - if (FAILED(result)) - { - SafeRelease(sourceStaging); - SafeRelease(destStaging); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal source staging texture for depth stencil blit, HRESULT: 0x%X.", result); - } - - D3D11_MAPPED_SUBRESOURCE destMapping; - result = deviceContext->Map(destStaging, 0, D3D11_MAP_WRITE, 0, &destMapping); - if (FAILED(result)) - { - deviceContext->Unmap(sourceStaging, 0); - SafeRelease(sourceStaging); - SafeRelease(destStaging); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal destination staging texture for depth stencil blit, HRESULT: 0x%X.", result); - } - - gl::Rectangle clippedDestArea(destArea.x, destArea.y, destArea.width, destArea.height); - - // Clip dest area to the destination size - gl::ClipRectangle(clippedDestArea, gl::Rectangle(0, 0, destSize.width, destSize.height), &clippedDestArea); - - // Clip dest area to the scissor - if (scissor) - { - gl::ClipRectangle(clippedDestArea, *scissor, &clippedDestArea); - } - - // Determine if entire rows can be copied at once instead of each individual pixel, requires that there is - // no out of bounds lookups required, the entire pixel is copied and no stretching - bool wholeRowCopy = sourceArea.width == clippedDestArea.width && - sourceArea.x >= 0 && sourceArea.x + sourceArea.width <= sourceSize.width && - copySize == pixelSize; - - for (int y = clippedDestArea.y; y < clippedDestArea.y + clippedDestArea.height; y++) - { - float yPerc = static_cast(y - destArea.y) / (destArea.height - 1); - - // Interpolate using the original source rectangle to determine which row to sample from while clamping to the edges - unsigned int readRow = gl::clamp(sourceArea.y + floor(yPerc * (sourceArea.height - 1) + 0.5f), 0, sourceSize.height - 1); - unsigned int writeRow = y; - - if (wholeRowCopy) - { - void *sourceRow = reinterpret_cast(sourceMapping.pData) + - readRow * sourceMapping.RowPitch + - sourceArea.x * pixelSize; - - void *destRow = reinterpret_cast(destMapping.pData) + - writeRow * destMapping.RowPitch + - destArea.x * pixelSize; - - memcpy(destRow, sourceRow, pixelSize * destArea.width); - } - else - { - for (int x = clippedDestArea.x; x < clippedDestArea.x + clippedDestArea.width; x++) - { - float xPerc = static_cast(x - destArea.x) / (destArea.width - 1); - - // Interpolate the original source rectangle to determine which column to sample from while clamping to the edges - unsigned int readColumn = gl::clamp(sourceArea.x + floor(xPerc * (sourceArea.width - 1) + 0.5f), 0, sourceSize.width - 1); - unsigned int writeColumn = x; - - void *sourcePixel = reinterpret_cast(sourceMapping.pData) + - readRow * sourceMapping.RowPitch + - readColumn * pixelSize + - copyOffset; - - void *destPixel = reinterpret_cast(destMapping.pData) + - writeRow * destMapping.RowPitch + - writeColumn * pixelSize + - copyOffset; - - memcpy(destPixel, sourcePixel, copySize); - } - } - } - - // HACK: Use ID3D11DevicContext::UpdateSubresource which causes an extra copy compared to ID3D11DevicContext::CopySubresourceRegion - // according to MSDN. - deviceContext->UpdateSubresource(dest, destSubresource, NULL, destMapping.pData, destMapping.RowPitch, destMapping.DepthPitch); - - deviceContext->Unmap(sourceStaging, 0); - deviceContext->Unmap(destStaging, 0); - - // TODO: Determine why this call to ID3D11DevicContext::CopySubresourceRegion causes a TDR timeout on some - // systems when called repeatedly. - // deviceContext->CopySubresourceRegion(dest, destSubresource, 0, 0, 0, destStaging, 0, NULL); - - SafeRelease(sourceStaging); - SafeRelease(destStaging); - - return gl::Error(GL_NO_ERROR); -} - -bool Blit11::compareBlitParameters(const Blit11::BlitParameters &a, const Blit11::BlitParameters &b) -{ - return memcmp(&a, &b, sizeof(Blit11::BlitParameters)) < 0; -} - -bool Blit11::compareSwizzleParameters(const SwizzleParameters &a, const SwizzleParameters &b) -{ - return memcmp(&a, &b, sizeof(Blit11::SwizzleParameters)) < 0; -} - -void Blit11::add2DBlitShaderToMap(GLenum destFormat, bool signedInteger, ID3D11PixelShader *ps) -{ - BlitParameters params = { 0 }; - params.mDestinationFormat = destFormat; - params.mSignedInteger = signedInteger; - params.m3DBlit = false; - - ASSERT(mBlitShaderMap.find(params) == mBlitShaderMap.end()); - ASSERT(ps); - - Shader shader; - shader.mVertexWriteFunction = Write2DVertices; - shader.mInputLayout = mQuad2DIL; - shader.mVertexShader = mQuad2DVS; - shader.mGeometryShader = NULL; - shader.mPixelShader = ps; - - mBlitShaderMap[params] = shader; -} - -void Blit11::add3DBlitShaderToMap(GLenum destFormat, bool signedInteger, ID3D11PixelShader *ps) -{ - BlitParameters params = { 0 }; - params.mDestinationFormat = destFormat; - params.mSignedInteger = signedInteger; - params.m3DBlit = true; - - ASSERT(mBlitShaderMap.find(params) == mBlitShaderMap.end()); - ASSERT(ps); - - Shader shader; - shader.mVertexWriteFunction = Write3DVertices; - shader.mInputLayout = mQuad3DIL; - shader.mVertexShader = mQuad3DVS; - shader.mGeometryShader = mQuad3DGS; - shader.mPixelShader = ps; - - mBlitShaderMap[params] = shader; -} - -void Blit11::addSwizzleShaderToMap(GLenum destType, D3D11_SRV_DIMENSION viewDimension, ID3D11PixelShader *ps) -{ - SwizzleParameters params = { 0 }; - params.mDestinationType = destType; - params.mViewDimension = viewDimension; - - ASSERT(mSwizzleShaderMap.find(params) == mSwizzleShaderMap.end()); - ASSERT(ps); - - Shader shader; - switch (viewDimension) - { - case D3D_SRV_DIMENSION_TEXTURE2D: - shader.mVertexWriteFunction = Write2DVertices; - shader.mInputLayout = mQuad2DIL; - shader.mVertexShader = mQuad2DVS; - shader.mGeometryShader = NULL; - break; - - case D3D_SRV_DIMENSION_TEXTURE3D: - case D3D_SRV_DIMENSION_TEXTURE2DARRAY: - case D3D_SRV_DIMENSION_TEXTURECUBE: - shader.mVertexWriteFunction = Write3DVertices; - shader.mInputLayout = mQuad3DIL; - shader.mVertexShader = mQuad3DVS; - shader.mGeometryShader = mQuad3DGS; - break; - - default: - UNREACHABLE(); - break; - } - shader.mPixelShader = ps; - - mSwizzleShaderMap[params] = shader; -} - -void Blit11::buildShaderMap() -{ - ID3D11Device *device = mRenderer->getDevice(); - - add2DBlitShaderToMap(GL_RGBA, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA2D, "Blit11 2D RGBA pixel shader" )); - add2DBlitShaderToMap(GL_BGRA_EXT, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA2D, "Blit11 2D BGRA pixel shader" )); - add2DBlitShaderToMap(GL_RGB, false, d3d11::CompilePS(device, g_PS_PassthroughRGB2D, "Blit11 2D RGB pixel shader" )); - add2DBlitShaderToMap(GL_RG, false, d3d11::CompilePS(device, g_PS_PassthroughRG2D, "Blit11 2D RG pixel shader" )); - add2DBlitShaderToMap(GL_RED, false, d3d11::CompilePS(device, g_PS_PassthroughR2D, "Blit11 2D R pixel shader" )); - add2DBlitShaderToMap(GL_ALPHA, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA2D, "Blit11 2D alpha pixel shader" )); - add2DBlitShaderToMap(GL_LUMINANCE, false, d3d11::CompilePS(device, g_PS_PassthroughLum2D, "Blit11 2D lum pixel shader" )); - add2DBlitShaderToMap(GL_LUMINANCE_ALPHA, false, d3d11::CompilePS(device, g_PS_PassthroughLumAlpha2D, "Blit11 2D luminance alpha pixel shader")); - - addSwizzleShaderToMap(GL_FLOAT, D3D_SRV_DIMENSION_TEXTURE2D, d3d11::CompilePS(device, g_PS_SwizzleF2D, "Blit11 2D F swizzle pixel shader" )); - - if (mRenderer->isLevel9()) - return; - - add2DBlitShaderToMap(GL_RGBA_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA2DUI, "Blit11 2D RGBA UI pixel shader" )); - add2DBlitShaderToMap(GL_RGBA_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughRGBA2DI, "Blit11 2D RGBA I pixel shader" )); - add2DBlitShaderToMap(GL_RGB_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughRGB2DUI, "Blit11 2D RGB UI pixel shader" )); - add2DBlitShaderToMap(GL_RGB_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughRGB2DI, "Blit11 2D RGB I pixel shader" )); - add2DBlitShaderToMap(GL_RG_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughRG2DUI, "Blit11 2D RG UI pixel shader" )); - add2DBlitShaderToMap(GL_RG_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughRG2DI, "Blit11 2D RG I pixel shader" )); - add2DBlitShaderToMap(GL_RED_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughR2DUI, "Blit11 2D R UI pixel shader" )); - add2DBlitShaderToMap(GL_RED_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughR2DI, "Blit11 2D R I pixel shader" )); - add3DBlitShaderToMap(GL_RGBA, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA3D, "Blit11 3D RGBA pixel shader" )); - add3DBlitShaderToMap(GL_RGBA_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA3DUI, "Blit11 3D UI RGBA pixel shader" )); - add3DBlitShaderToMap(GL_RGBA_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughRGBA3DI, "Blit11 3D I RGBA pixel shader" )); - add3DBlitShaderToMap(GL_BGRA_EXT, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA3D, "Blit11 3D BGRA pixel shader" )); - add3DBlitShaderToMap(GL_RGB, false, d3d11::CompilePS(device, g_PS_PassthroughRGB3D, "Blit11 3D RGB pixel shader" )); - add3DBlitShaderToMap(GL_RGB_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughRGB3DUI, "Blit11 3D RGB UI pixel shader" )); - add3DBlitShaderToMap(GL_RGB_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughRGB3DI, "Blit11 3D RGB I pixel shader" )); - add3DBlitShaderToMap(GL_RG, false, d3d11::CompilePS(device, g_PS_PassthroughRG3D, "Blit11 3D RG pixel shader" )); - add3DBlitShaderToMap(GL_RG_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughRG3DUI, "Blit11 3D RG UI pixel shader" )); - add3DBlitShaderToMap(GL_RG_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughRG3DI, "Blit11 3D RG I pixel shader" )); - add3DBlitShaderToMap(GL_RED, false, d3d11::CompilePS(device, g_PS_PassthroughR3D, "Blit11 3D R pixel shader" )); - add3DBlitShaderToMap(GL_RED_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughR3DUI, "Blit11 3D R UI pixel shader" )); - add3DBlitShaderToMap(GL_RED_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughR3DI, "Blit11 3D R I pixel shader" )); - add3DBlitShaderToMap(GL_ALPHA, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA3D, "Blit11 3D alpha pixel shader" )); - add3DBlitShaderToMap(GL_LUMINANCE, false, d3d11::CompilePS(device, g_PS_PassthroughLum3D, "Blit11 3D luminance pixel shader" )); - add3DBlitShaderToMap(GL_LUMINANCE_ALPHA, false, d3d11::CompilePS(device, g_PS_PassthroughLumAlpha3D, "Blit11 3D luminance alpha pixel shader")); - - addSwizzleShaderToMap(GL_UNSIGNED_INT, D3D_SRV_DIMENSION_TEXTURE2D, d3d11::CompilePS(device, g_PS_SwizzleUI2D, "Blit11 2D UI swizzle pixel shader")); - addSwizzleShaderToMap(GL_INT, D3D_SRV_DIMENSION_TEXTURE2D, d3d11::CompilePS(device, g_PS_SwizzleI2D, "Blit11 2D I swizzle pixel shader" )); - - addSwizzleShaderToMap(GL_FLOAT, D3D_SRV_DIMENSION_TEXTURECUBE, d3d11::CompilePS(device, g_PS_SwizzleF2DArray, "Blit11 2D Cube F swizzle pixel shader" )); - addSwizzleShaderToMap(GL_UNSIGNED_INT, D3D_SRV_DIMENSION_TEXTURECUBE, d3d11::CompilePS(device, g_PS_SwizzleUI2DArray, "Blit11 2D Cube UI swizzle pixel shader")); - addSwizzleShaderToMap(GL_INT, D3D_SRV_DIMENSION_TEXTURECUBE, d3d11::CompilePS(device, g_PS_SwizzleI2DArray, "Blit11 2D Cube I swizzle pixel shader" )); - - addSwizzleShaderToMap(GL_FLOAT, D3D_SRV_DIMENSION_TEXTURE3D, d3d11::CompilePS(device, g_PS_SwizzleF3D, "Blit11 3D F swizzle pixel shader" )); - addSwizzleShaderToMap(GL_UNSIGNED_INT, D3D_SRV_DIMENSION_TEXTURE3D, d3d11::CompilePS(device, g_PS_SwizzleUI3D, "Blit11 3D UI swizzle pixel shader")); - addSwizzleShaderToMap(GL_INT, D3D_SRV_DIMENSION_TEXTURE3D, d3d11::CompilePS(device, g_PS_SwizzleI3D, "Blit11 3D I swizzle pixel shader" )); - - addSwizzleShaderToMap(GL_FLOAT, D3D_SRV_DIMENSION_TEXTURE2DARRAY, d3d11::CompilePS(device, g_PS_SwizzleF2DArray, "Blit11 2D Array F swizzle pixel shader" )); - addSwizzleShaderToMap(GL_UNSIGNED_INT, D3D_SRV_DIMENSION_TEXTURE2DARRAY, d3d11::CompilePS(device, g_PS_SwizzleUI2DArray, "Blit11 2D Array UI swizzle pixel shader")); - addSwizzleShaderToMap(GL_INT, D3D_SRV_DIMENSION_TEXTURE2DARRAY, d3d11::CompilePS(device, g_PS_SwizzleI2DArray, "Blit11 2D Array I swizzle pixel shader" )); -} - -void Blit11::clearShaderMap() -{ - for (BlitShaderMap::iterator i = mBlitShaderMap.begin(); i != mBlitShaderMap.end(); ++i) - { - Shader &shader = i->second; - SafeRelease(shader.mPixelShader); - } - mBlitShaderMap.clear(); - - for (SwizzleShaderMap::iterator i = mSwizzleShaderMap.begin(); i != mSwizzleShaderMap.end(); ++i) - { - Shader &shader = i->second; - SafeRelease(shader.mPixelShader); - } - mSwizzleShaderMap.clear(); -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.h deleted file mode 100644 index 821fa9d0cc..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.h +++ /dev/null @@ -1,123 +0,0 @@ -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Blit11.cpp: Texture copy utility class. - -#ifndef LIBGLESV2_BLIT11_H_ -#define LIBGLESV2_BLIT11_H_ - -#include "common/angleutils.h" -#include "libGLESv2/angletypes.h" -#include "libGLESv2/Error.h" - -#include - -namespace rx -{ -class Renderer11; - -class Blit11 -{ - public: - explicit Blit11(Renderer11 *renderer); - ~Blit11(); - - gl::Error swizzleTexture(ID3D11ShaderResourceView *source, ID3D11RenderTargetView *dest, const gl::Extents &size, - GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha); - - gl::Error copyTexture(ID3D11ShaderResourceView *source, const gl::Box &sourceArea, const gl::Extents &sourceSize, - ID3D11RenderTargetView *dest, const gl::Box &destArea, const gl::Extents &destSize, - const gl::Rectangle *scissor, GLenum destFormat, GLenum filter); - - gl::Error copyStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize, - ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize, - const gl::Rectangle *scissor); - - gl::Error copyDepth(ID3D11ShaderResourceView *source, const gl::Box &sourceArea, const gl::Extents &sourceSize, - ID3D11DepthStencilView *dest, const gl::Box &destArea, const gl::Extents &destSize, - const gl::Rectangle *scissor); - - gl::Error copyDepthStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize, - ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize, - const gl::Rectangle *scissor); - - private: - Renderer11 *mRenderer; - - struct BlitParameters - { - GLenum mDestinationFormat; - bool mSignedInteger; - bool m3DBlit; - }; - - gl::Error copyDepthStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize, - ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize, - const gl::Rectangle *scissor, bool stencilOnly); - - static bool compareBlitParameters(const BlitParameters &a, const BlitParameters &b); - - typedef void (*WriteVertexFunction)(const gl::Box &sourceArea, const gl::Extents &sourceSize, - const gl::Box &destArea, const gl::Extents &destSize, - void *outVertices, unsigned int *outStride, unsigned int *outVertexCount, - D3D11_PRIMITIVE_TOPOLOGY *outTopology); - - struct Shader - { - WriteVertexFunction mVertexWriteFunction; - ID3D11InputLayout *mInputLayout; - ID3D11VertexShader *mVertexShader; - ID3D11GeometryShader *mGeometryShader; - ID3D11PixelShader *mPixelShader; - }; - - typedef bool (*BlitParametersComparisonFunction)(const BlitParameters&, const BlitParameters &); - typedef std::map BlitShaderMap; - BlitShaderMap mBlitShaderMap; - - void add2DBlitShaderToMap(GLenum destFormat, bool signedInteger, ID3D11PixelShader *ps); - void add3DBlitShaderToMap(GLenum destFormat, bool signedInteger, ID3D11PixelShader *ps); - - struct SwizzleParameters - { - GLenum mDestinationType; - D3D11_SRV_DIMENSION mViewDimension; - }; - - static bool compareSwizzleParameters(const SwizzleParameters &a, const SwizzleParameters &b); - - typedef bool (*SwizzleParametersComparisonFunction)(const SwizzleParameters&, const SwizzleParameters &); - typedef std::map SwizzleShaderMap; - SwizzleShaderMap mSwizzleShaderMap; - - void addSwizzleShaderToMap(GLenum destType, D3D11_SRV_DIMENSION viewDimension, ID3D11PixelShader *ps); - - void buildShaderMap(); - void clearShaderMap(); - - ID3D11Buffer *mVertexBuffer; - ID3D11SamplerState *mPointSampler; - ID3D11SamplerState *mLinearSampler; - ID3D11RasterizerState *mScissorEnabledRasterizerState; - ID3D11RasterizerState *mScissorDisabledRasterizerState; - ID3D11DepthStencilState *mDepthStencilState; - - ID3D11InputLayout *mQuad2DIL; - ID3D11VertexShader *mQuad2DVS; - ID3D11PixelShader *mDepthPS; - - ID3D11InputLayout *mQuad3DIL; - ID3D11VertexShader *mQuad3DVS; - ID3D11GeometryShader *mQuad3DGS; - - ID3D11Buffer *mSwizzleCB; - - DISALLOW_COPY_AND_ASSIGN(Blit11); -}; - -} - -#endif // LIBGLESV2_BLIT11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.cpp deleted file mode 100644 index 5aab37938f..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.cpp +++ /dev/null @@ -1,983 +0,0 @@ -// -// Copyright 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Buffer11.cpp Defines the Buffer11 class. - -#include "libGLESv2/renderer/d3d/d3d11/Buffer11.h" -#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" -#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" -#include "libGLESv2/main.h" - -namespace rx -{ - -PackPixelsParams::PackPixelsParams() - : format(GL_NONE), - type(GL_NONE), - outputPitch(0), - packBuffer(NULL), - offset(0) -{} - -PackPixelsParams::PackPixelsParams(const gl::Rectangle &areaIn, GLenum formatIn, GLenum typeIn, GLuint outputPitchIn, - const gl::PixelPackState &packIn, ptrdiff_t offsetIn) - : area(areaIn), - format(formatIn), - type(typeIn), - outputPitch(outputPitchIn), - packBuffer(packIn.pixelBuffer.get()), - pack(packIn.alignment, packIn.reverseRowOrder), - offset(offsetIn) -{} - -namespace gl_d3d11 -{ - -D3D11_MAP GetD3DMapTypeFromBits(GLbitfield access) -{ - bool readBit = ((access & GL_MAP_READ_BIT) != 0); - bool writeBit = ((access & GL_MAP_WRITE_BIT) != 0); - - ASSERT(readBit || writeBit); - - // Note : we ignore the discard bit, because in D3D11, staging buffers - // don't accept the map-discard flag (discard only works for DYNAMIC usage) - - if (readBit && !writeBit) - { - return D3D11_MAP_READ; - } - else if (writeBit && !readBit) - { - return D3D11_MAP_WRITE; - } - else if (writeBit && readBit) - { - return D3D11_MAP_READ_WRITE; - } - else - { - UNREACHABLE(); - return D3D11_MAP_READ; - } -} - -} - -// Each instance of Buffer11::BufferStorage11 is specialized for a class of D3D binding points -// - vertex/transform feedback buffers -// - index buffers -// - pixel unpack buffers -// - uniform buffers -class Buffer11::BufferStorage11 -{ - public: - virtual ~BufferStorage11() {} - - DataRevision getDataRevision() const { return mRevision; } - BufferUsage getUsage() const { return mUsage; } - size_t getSize() const { return mBufferSize; } - bool isMappable() const { return (mUsage == BUFFER_USAGE_STAGING || mUsage == BUFFER_USAGE_PIXEL_PACK); } - - void setDataRevision(DataRevision rev) { mRevision = rev; } - - virtual bool copyFromStorage(BufferStorage11 *source, size_t sourceOffset, - size_t size, size_t destOffset) = 0; - virtual gl::Error resize(size_t size, bool preserveData) = 0; - - virtual void *map(size_t offset, size_t length, GLbitfield access) = 0; - virtual void unmap() = 0; - - protected: - BufferStorage11(Renderer11 *renderer, BufferUsage usage); - - Renderer11 *mRenderer; - DataRevision mRevision; - const BufferUsage mUsage; - size_t mBufferSize; -}; - -// A native buffer storage represents an underlying D3D11 buffer for a particular -// type of storage. -class Buffer11::NativeBuffer11 : public Buffer11::BufferStorage11 -{ - public: - NativeBuffer11(Renderer11 *renderer, BufferUsage usage); - ~NativeBuffer11(); - - ID3D11Buffer *getNativeBuffer() const { return mNativeBuffer; } - - virtual bool copyFromStorage(BufferStorage11 *source, size_t sourceOffset, - size_t size, size_t destOffset); - virtual gl::Error resize(size_t size, bool preserveData); - - virtual void *map(size_t offset, size_t length, GLbitfield access); - virtual void unmap(); - - gl::Error setData(D3D11_MAP mapMode, const uint8_t *data, size_t size, size_t offset); - - private: - ID3D11Buffer *mNativeBuffer; - - static void fillBufferDesc(D3D11_BUFFER_DESC* bufferDesc, Renderer11 *renderer, BufferUsage usage, unsigned int bufferSize); -}; - -// Pack storage represents internal storage for pack buffers. We implement pack buffers -// as CPU memory, tied to a staging texture, for asynchronous texture readback. -class Buffer11::PackStorage11 : public Buffer11::BufferStorage11 -{ - public: - PackStorage11(Renderer11 *renderer); - ~PackStorage11(); - - virtual bool copyFromStorage(BufferStorage11 *source, size_t sourceOffset, - size_t size, size_t destOffset); - virtual gl::Error resize(size_t size, bool preserveData); - - virtual void *map(size_t offset, size_t length, GLbitfield access); - virtual void unmap(); - - gl::Error packPixels(ID3D11Texture2D *srcTexure, UINT srcSubresource, const PackPixelsParams ¶ms); - - private: - - gl::Error flushQueuedPackCommand(); - - ID3D11Texture2D *mStagingTexture; - DXGI_FORMAT mTextureFormat; - gl::Extents mTextureSize; - MemoryBuffer mMemoryBuffer; - PackPixelsParams *mQueuedPackCommand; - PackPixelsParams mPackParams; - bool mDataModified; -}; - - -Buffer11::Buffer11(Renderer11 *renderer) - : BufferD3D(), - mRenderer(renderer), - mSize(0), - mMappedStorage(NULL), - mResolvedDataRevision(0), - mReadUsageCount(0) -{} - -Buffer11::~Buffer11() -{ - for (auto it = mBufferStorages.begin(); it != mBufferStorages.end(); it++) - { - SafeDelete(it->second); - } -} - -Buffer11 *Buffer11::makeBuffer11(BufferImpl *buffer) -{ - ASSERT(HAS_DYNAMIC_TYPE(Buffer11*, buffer)); - return static_cast(buffer); -} - -gl::Error Buffer11::setData(const void *data, size_t size, GLenum usage) -{ - gl::Error error = setSubData(data, size, 0); - if (error.isError()) - { - return error; - } - - if (usage == GL_STATIC_DRAW) - { - initializeStaticData(); - } - - return error; -} - -gl::Error Buffer11::getData(const uint8_t **outData) -{ - NativeBuffer11 *stagingBuffer = getStagingBuffer(); - - if (!stagingBuffer) - { - // Out-of-memory - return gl::Error(GL_OUT_OF_MEMORY, "Failed to get internal staging buffer."); - } - - if (stagingBuffer->getDataRevision() > mResolvedDataRevision) - { - if (stagingBuffer->getSize() > mResolvedData.size()) - { - if (!mResolvedData.resize(stagingBuffer->getSize())) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to resize data resolve buffer."); - } - } - - ID3D11DeviceContext *context = mRenderer->getDeviceContext(); - - D3D11_MAPPED_SUBRESOURCE mappedResource; - HRESULT result = context->Map(stagingBuffer->getNativeBuffer(), 0, D3D11_MAP_READ, 0, &mappedResource); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal buffer, result: 0x%X.", result); - } - - memcpy(mResolvedData.data(), mappedResource.pData, stagingBuffer->getSize()); - - context->Unmap(stagingBuffer->getNativeBuffer(), 0); - - mResolvedDataRevision = stagingBuffer->getDataRevision(); - } - - mReadUsageCount = 0; - - // Only happens if we initialized the buffer with no data (NULL) - if (mResolvedData.empty()) - { - if (!mResolvedData.resize(mSize)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to resize data resolve buffer."); - } - } - - ASSERT(mResolvedData.size() >= mSize); - - *outData = mResolvedData.data(); - return gl::Error(GL_NO_ERROR); -} - -gl::Error Buffer11::setSubData(const void *data, size_t size, size_t offset) -{ - size_t requiredSize = size + offset; - - if (data && size > 0) - { - NativeBuffer11 *stagingBuffer = getStagingBuffer(); - - if (!stagingBuffer) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal staging buffer."); - } - - // Explicitly resize the staging buffer, preserving data if the new data will not - // completely fill the buffer - if (stagingBuffer->getSize() < requiredSize) - { - bool preserveData = (offset > 0); - gl::Error error = stagingBuffer->resize(requiredSize, preserveData); - if (error.isError()) - { - return error; - } - } - - gl::Error error = stagingBuffer->setData(D3D11_MAP_WRITE, reinterpret_cast(data), size, offset); - if (error.isError()) - { - return error; - } - - stagingBuffer->setDataRevision(stagingBuffer->getDataRevision() + 1); - } - - mSize = std::max(mSize, requiredSize); - invalidateStaticData(); - - return gl::Error(GL_NO_ERROR); -} - -gl::Error Buffer11::copySubData(BufferImpl* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size) -{ - Buffer11 *sourceBuffer = makeBuffer11(source); - ASSERT(sourceBuffer != NULL); - - BufferStorage11 *copyDest = getLatestBufferStorage(); - if (!copyDest) - { - copyDest = getStagingBuffer(); - } - - BufferStorage11 *copySource = sourceBuffer->getLatestBufferStorage(); - - if (!copySource || !copyDest) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal staging buffer."); - } - - // If copying to/from a pixel pack buffer, we must have a staging or - // pack buffer partner, because other native buffers can't be mapped - if (copyDest->getUsage() == BUFFER_USAGE_PIXEL_PACK && !copySource->isMappable()) - { - copySource = sourceBuffer->getStagingBuffer(); - } - else if (copySource->getUsage() == BUFFER_USAGE_PIXEL_PACK && !copyDest->isMappable()) - { - copyDest = getStagingBuffer(); - } - - // D3D11 does not allow overlapped copies until 11.1, and only if the - // device supports D3D11_FEATURE_DATA_D3D11_OPTIONS::CopyWithOverlap - // Get around this via a different source buffer - if (copySource == copyDest) - { - if (copySource->getUsage() == BUFFER_USAGE_STAGING) - { - copySource = getBufferStorage(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK); - } - else - { - copySource = getStagingBuffer(); - } - } - - copyDest->copyFromStorage(copySource, sourceOffset, size, destOffset); - copyDest->setDataRevision(copyDest->getDataRevision() + 1); - - mSize = std::max(mSize, destOffset + size); - invalidateStaticData(); - - return gl::Error(GL_NO_ERROR); -} - -gl::Error Buffer11::map(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr) -{ - ASSERT(!mMappedStorage); - - BufferStorage11 *latestStorage = getLatestBufferStorage(); - if (latestStorage && - (latestStorage->getUsage() == BUFFER_USAGE_PIXEL_PACK || - latestStorage->getUsage() == BUFFER_USAGE_STAGING)) - { - // Latest storage is mappable. - mMappedStorage = latestStorage; - } - else - { - // Fall back to using the staging buffer if the latest storage does - // not exist or is not CPU-accessible. - mMappedStorage = getStagingBuffer(); - } - - if (!mMappedStorage) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate mappable internal buffer."); - } - - if ((access & GL_MAP_WRITE_BIT) > 0) - { - // Update the data revision immediately, since the data might be changed at any time - mMappedStorage->setDataRevision(mMappedStorage->getDataRevision() + 1); - } - - void *mappedBuffer = mMappedStorage->map(offset, length, access); - if (!mappedBuffer) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal buffer."); - } - - *mapPtr = mappedBuffer; - return gl::Error(GL_NO_ERROR); -} - -gl::Error Buffer11::unmap() -{ - ASSERT(mMappedStorage); - mMappedStorage->unmap(); - mMappedStorage = NULL; - return gl::Error(GL_NO_ERROR); -} - -void Buffer11::markTransformFeedbackUsage() -{ - BufferStorage11 *transformFeedbackStorage = getBufferStorage(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK); - - if (transformFeedbackStorage) - { - transformFeedbackStorage->setDataRevision(transformFeedbackStorage->getDataRevision() + 1); - } - - invalidateStaticData(); -} - -void Buffer11::markBufferUsage() -{ - mReadUsageCount++; - - const unsigned int usageLimit = 5; - - if (mReadUsageCount > usageLimit && mResolvedData.size() > 0) - { - mResolvedData.resize(0); - mResolvedDataRevision = 0; - } -} - -RendererD3D* Buffer11::getRenderer() -{ - return mRenderer; -} - -ID3D11Buffer *Buffer11::getBuffer(BufferUsage usage) -{ - markBufferUsage(); - - BufferStorage11 *bufferStorage = getBufferStorage(usage); - - if (!bufferStorage) - { - // Storage out-of-memory - return NULL; - } - - ASSERT(HAS_DYNAMIC_TYPE(NativeBuffer11*, bufferStorage)); - - return static_cast(bufferStorage)->getNativeBuffer(); -} - -ID3D11ShaderResourceView *Buffer11::getSRV(DXGI_FORMAT srvFormat) -{ - BufferStorage11 *storage = getBufferStorage(BUFFER_USAGE_PIXEL_UNPACK); - - if (!storage) - { - // Storage out-of-memory - return NULL; - } - - ASSERT(HAS_DYNAMIC_TYPE(NativeBuffer11*, storage)); - ID3D11Buffer *buffer = static_cast(storage)->getNativeBuffer(); - - auto bufferSRVIt = mBufferResourceViews.find(srvFormat); - - if (bufferSRVIt != mBufferResourceViews.end()) - { - if (bufferSRVIt->second.first == buffer) - { - return bufferSRVIt->second.second; - } - else - { - // The underlying buffer has changed since the SRV was created: recreate the SRV. - SafeRelease(bufferSRVIt->second.second); - } - } - - ID3D11Device *device = mRenderer->getDevice(); - ID3D11ShaderResourceView *bufferSRV = NULL; - - const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(srvFormat); - - D3D11_SHADER_RESOURCE_VIEW_DESC bufferSRVDesc; - bufferSRVDesc.Buffer.ElementOffset = 0; - bufferSRVDesc.Buffer.ElementWidth = mSize / dxgiFormatInfo.pixelBytes; - bufferSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER; - bufferSRVDesc.Format = srvFormat; - - HRESULT result = device->CreateShaderResourceView(buffer, &bufferSRVDesc, &bufferSRV); - UNUSED_ASSERTION_VARIABLE(result); - ASSERT(SUCCEEDED(result)); - - mBufferResourceViews[srvFormat] = BufferSRVPair(buffer, bufferSRV); - - return bufferSRV; -} - -gl::Error Buffer11::packPixels(ID3D11Texture2D *srcTexture, UINT srcSubresource, const PackPixelsParams ¶ms) -{ - PackStorage11 *packStorage = getPackStorage(); - - BufferStorage11 *latestStorage = getLatestBufferStorage(); - - if (packStorage) - { - gl::Error error = packStorage->packPixels(srcTexture, srcSubresource, params); - if (error.isError()) - { - return error; - } - packStorage->setDataRevision(latestStorage ? latestStorage->getDataRevision() + 1 : 1); - } - - return gl::Error(GL_NO_ERROR); -} - -Buffer11::BufferStorage11 *Buffer11::getBufferStorage(BufferUsage usage) -{ - BufferStorage11 *directBuffer = NULL; - auto directBufferIt = mBufferStorages.find(usage); - if (directBufferIt != mBufferStorages.end()) - { - directBuffer = directBufferIt->second; - } - - if (!directBuffer) - { - if (usage == BUFFER_USAGE_PIXEL_PACK) - { - directBuffer = new PackStorage11(mRenderer); - } - else - { - // buffer is not allocated, create it - directBuffer = new NativeBuffer11(mRenderer, usage); - } - - mBufferStorages.insert(std::make_pair(usage, directBuffer)); - } - - // resize buffer - if (directBuffer->getSize() < mSize) - { - if (directBuffer->resize(mSize, true).isError()) - { - // Out of memory error - return NULL; - } - } - - BufferStorage11 *latestBuffer = getLatestBufferStorage(); - if (latestBuffer && latestBuffer->getDataRevision() > directBuffer->getDataRevision()) - { - // if copying from a pack buffer to a non-staging native buffer, we must first - // copy through the staging buffer, because other native buffers can't be mapped - if (latestBuffer->getUsage() == BUFFER_USAGE_PIXEL_PACK && !directBuffer->isMappable()) - { - NativeBuffer11 *stagingBuffer = getStagingBuffer(); - - stagingBuffer->copyFromStorage(latestBuffer, 0, latestBuffer->getSize(), 0); - directBuffer->setDataRevision(latestBuffer->getDataRevision()); - - latestBuffer = stagingBuffer; - } - - // if copyFromStorage returns true, the D3D buffer has been recreated - // and we should update our serial - if (directBuffer->copyFromStorage(latestBuffer, 0, latestBuffer->getSize(), 0)) - { - updateSerial(); - } - directBuffer->setDataRevision(latestBuffer->getDataRevision()); - } - - return directBuffer; -} - -Buffer11::BufferStorage11 *Buffer11::getLatestBufferStorage() const -{ - // Even though we iterate over all the direct buffers, it is expected that only - // 1 or 2 will be present. - BufferStorage11 *latestStorage = NULL; - DataRevision latestRevision = 0; - for (auto it = mBufferStorages.begin(); it != mBufferStorages.end(); it++) - { - BufferStorage11 *storage = it->second; - if (!latestStorage || storage->getDataRevision() > latestRevision) - { - latestStorage = storage; - latestRevision = storage->getDataRevision(); - } - } - - return latestStorage; -} - -Buffer11::NativeBuffer11 *Buffer11::getStagingBuffer() -{ - BufferStorage11 *stagingStorage = getBufferStorage(BUFFER_USAGE_STAGING); - - if (!stagingStorage) - { - // Out-of-memory - return NULL; - } - - ASSERT(HAS_DYNAMIC_TYPE(NativeBuffer11*, stagingStorage)); - return static_cast(stagingStorage); -} - -Buffer11::PackStorage11 *Buffer11::getPackStorage() -{ - BufferStorage11 *packStorage = getBufferStorage(BUFFER_USAGE_PIXEL_PACK); - - if (!packStorage) - { - // Out-of-memory - return NULL; - } - - ASSERT(HAS_DYNAMIC_TYPE(PackStorage11*, packStorage)); - return static_cast(packStorage); -} - -bool Buffer11::supportsDirectBinding() const -{ - // Do not support direct buffers for dynamic data. The streaming buffer - // offers better performance for data which changes every frame. - // Check for absence of static buffer interfaces to detect dynamic data. - return (mStaticVertexBuffer && mStaticIndexBuffer); -} - -Buffer11::BufferStorage11::BufferStorage11(Renderer11 *renderer, BufferUsage usage) - : mRenderer(renderer), - mUsage(usage), - mRevision(0), - mBufferSize(0) -{ -} - -Buffer11::NativeBuffer11::NativeBuffer11(Renderer11 *renderer, BufferUsage usage) - : BufferStorage11(renderer, usage), - mNativeBuffer(NULL) -{ -} - -Buffer11::NativeBuffer11::~NativeBuffer11() -{ - SafeRelease(mNativeBuffer); -} - -// Returns true if it recreates the direct buffer -bool Buffer11::NativeBuffer11::copyFromStorage(BufferStorage11 *source, size_t sourceOffset, - size_t size, size_t destOffset) -{ - ID3D11DeviceContext *context = mRenderer->getDeviceContext(); - - size_t requiredSize = sourceOffset + size; - bool createBuffer = !mNativeBuffer || mBufferSize < requiredSize; - - // (Re)initialize D3D buffer if needed - if (createBuffer) - { - bool preserveData = (destOffset > 0); - resize(source->getSize(), preserveData); - } - - if (source->getUsage() == BUFFER_USAGE_PIXEL_PACK) - { - ASSERT(HAS_DYNAMIC_TYPE(PackStorage11*, source)); - - void *sourcePointer = source->map(sourceOffset, size, GL_MAP_READ_BIT); - - D3D11_MAPPED_SUBRESOURCE mappedResource; - HRESULT hr = context->Map(mNativeBuffer, 0, D3D11_MAP_WRITE, 0, &mappedResource); - UNUSED_ASSERTION_VARIABLE(hr); - ASSERT(SUCCEEDED(hr)); - - unsigned char *destPointer = static_cast(mappedResource.pData) + destOffset; - - // Offset bounds are validated at the API layer - ASSERT(sourceOffset + size <= destOffset + mBufferSize); - memcpy(destPointer, sourcePointer, size); - - context->Unmap(mNativeBuffer, 0); - source->unmap(); - } - else - { - ASSERT(HAS_DYNAMIC_TYPE(NativeBuffer11*, source)); - - D3D11_BOX srcBox; - srcBox.left = sourceOffset; - srcBox.right = sourceOffset + size; - srcBox.top = 0; - srcBox.bottom = 1; - srcBox.front = 0; - srcBox.back = 1; - - ASSERT(HAS_DYNAMIC_TYPE(NativeBuffer11*, source)); - ID3D11Buffer *sourceBuffer = static_cast(source)->getNativeBuffer(); - - context->CopySubresourceRegion(mNativeBuffer, 0, destOffset, 0, 0, sourceBuffer, 0, &srcBox); - } - - return createBuffer; -} - -gl::Error Buffer11::NativeBuffer11::resize(size_t size, bool preserveData) -{ - ID3D11Device *device = mRenderer->getDevice(); - ID3D11DeviceContext *context = mRenderer->getDeviceContext(); - - D3D11_BUFFER_DESC bufferDesc; - fillBufferDesc(&bufferDesc, mRenderer, mUsage, size); - - ID3D11Buffer *newBuffer; - HRESULT result = device->CreateBuffer(&bufferDesc, NULL, &newBuffer); - - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal buffer, result: 0x%X.", result); - } - - if (mNativeBuffer && preserveData) - { - // We don't call resize if the buffer is big enough already. - ASSERT(mBufferSize <= size); - - D3D11_BOX srcBox; - srcBox.left = 0; - srcBox.right = mBufferSize; - srcBox.top = 0; - srcBox.bottom = 1; - srcBox.front = 0; - srcBox.back = 1; - - context->CopySubresourceRegion(newBuffer, 0, 0, 0, 0, mNativeBuffer, 0, &srcBox); - } - - // No longer need the old buffer - SafeRelease(mNativeBuffer); - mNativeBuffer = newBuffer; - - mBufferSize = bufferDesc.ByteWidth; - - return gl::Error(GL_NO_ERROR); -} - -void Buffer11::NativeBuffer11::fillBufferDesc(D3D11_BUFFER_DESC* bufferDesc, Renderer11 *renderer, - BufferUsage usage, unsigned int bufferSize) -{ - bufferDesc->ByteWidth = bufferSize; - bufferDesc->MiscFlags = 0; - bufferDesc->StructureByteStride = 0; - - switch (usage) - { - case BUFFER_USAGE_STAGING: - bufferDesc->Usage = D3D11_USAGE_STAGING; - bufferDesc->BindFlags = 0; - bufferDesc->CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; - break; - - case BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK: - bufferDesc->Usage = D3D11_USAGE_DEFAULT; - bufferDesc->BindFlags = D3D11_BIND_VERTEX_BUFFER; - if (!renderer->isLevel9()) - bufferDesc->BindFlags |= D3D11_BIND_STREAM_OUTPUT; - bufferDesc->CPUAccessFlags = 0; - break; - - case BUFFER_USAGE_INDEX: - bufferDesc->Usage = D3D11_USAGE_DEFAULT; - bufferDesc->BindFlags = D3D11_BIND_INDEX_BUFFER; - bufferDesc->CPUAccessFlags = 0; - break; - - case BUFFER_USAGE_PIXEL_UNPACK: - bufferDesc->Usage = D3D11_USAGE_DEFAULT; - bufferDesc->BindFlags = D3D11_BIND_SHADER_RESOURCE; - bufferDesc->CPUAccessFlags = 0; - break; - - case BUFFER_USAGE_UNIFORM: - bufferDesc->Usage = D3D11_USAGE_DYNAMIC; - bufferDesc->BindFlags = D3D11_BIND_CONSTANT_BUFFER; - bufferDesc->CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - - // Constant buffers must be of a limited size, and aligned to 16 byte boundaries - // For our purposes we ignore any buffer data past the maximum constant buffer size - bufferDesc->ByteWidth = roundUp(bufferDesc->ByteWidth, 16u); - bufferDesc->ByteWidth = std::min(bufferDesc->ByteWidth, renderer->getRendererCaps().maxUniformBlockSize); - break; - - default: - UNREACHABLE(); - } -} - -void *Buffer11::NativeBuffer11::map(size_t offset, size_t length, GLbitfield access) -{ - ASSERT(mUsage == BUFFER_USAGE_STAGING); - - D3D11_MAPPED_SUBRESOURCE mappedResource; - ID3D11DeviceContext *context = mRenderer->getDeviceContext(); - D3D11_MAP d3dMapType = gl_d3d11::GetD3DMapTypeFromBits(access); - UINT d3dMapFlag = ((access & GL_MAP_UNSYNCHRONIZED_BIT) != 0 ? D3D11_MAP_FLAG_DO_NOT_WAIT : 0); - - HRESULT result = context->Map(mNativeBuffer, 0, d3dMapType, d3dMapFlag, &mappedResource); - UNUSED_ASSERTION_VARIABLE(result); - ASSERT(SUCCEEDED(result)); - - return static_cast(mappedResource.pData) + offset; -} - -gl::Error Buffer11::NativeBuffer11::setData(D3D11_MAP mapMode, const uint8_t *data, size_t size, size_t offset) -{ - ID3D11DeviceContext *context = mRenderer->getDeviceContext(); - - D3D11_MAPPED_SUBRESOURCE mappedResource; - HRESULT result = context->Map(mNativeBuffer, 0, mapMode, 0, &mappedResource); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal buffer, result: 0x%X.", result); - } - - uint8_t *offsetBufferPointer = reinterpret_cast(mappedResource.pData) + offset; - memcpy(offsetBufferPointer, data, size); - - context->Unmap(mNativeBuffer, 0); - - return gl::Error(GL_NO_ERROR); -} - -void Buffer11::NativeBuffer11::unmap() -{ - ASSERT(mUsage == BUFFER_USAGE_STAGING); - ID3D11DeviceContext *context = mRenderer->getDeviceContext(); - context->Unmap(mNativeBuffer, 0); -} - -Buffer11::PackStorage11::PackStorage11(Renderer11 *renderer) - : BufferStorage11(renderer, BUFFER_USAGE_PIXEL_PACK), - mStagingTexture(NULL), - mTextureFormat(DXGI_FORMAT_UNKNOWN), - mQueuedPackCommand(NULL), - mDataModified(false) -{ -} - -Buffer11::PackStorage11::~PackStorage11() -{ - SafeRelease(mStagingTexture); - SafeDelete(mQueuedPackCommand); -} - -bool Buffer11::PackStorage11::copyFromStorage(BufferStorage11 *source, size_t sourceOffset, - size_t size, size_t destOffset) -{ - // We copy through a staging buffer when drawing with a pack buffer, - // or for other cases where we access the pack buffer - UNREACHABLE(); - return false; -} - -gl::Error Buffer11::PackStorage11::resize(size_t size, bool preserveData) -{ - if (size != mBufferSize) - { - if (!mMemoryBuffer.resize(size)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to resize internal buffer storage."); - } - mBufferSize = size; - } - - return gl::Error(GL_NO_ERROR); -} - -void *Buffer11::PackStorage11::map(size_t offset, size_t length, GLbitfield access) -{ - ASSERT(offset + length <= getSize()); - // TODO: fast path - // We might be able to optimize out one or more memcpy calls by detecting when - // and if D3D packs the staging texture memory identically to how we would fill - // the pack buffer according to the current pack state. - - gl::Error error = flushQueuedPackCommand(); - if (error.isError()) - { - return NULL; - } - - mDataModified = (mDataModified || (access & GL_MAP_WRITE_BIT) != 0); - - return mMemoryBuffer.data() + offset; -} - -void Buffer11::PackStorage11::unmap() -{ - // No-op -} - -gl::Error Buffer11::PackStorage11::packPixels(ID3D11Texture2D *srcTexure, UINT srcSubresource, const PackPixelsParams ¶ms) -{ - gl::Error error = flushQueuedPackCommand(); - if (error.isError()) - { - return error; - } - - mQueuedPackCommand = new PackPixelsParams(params); - - D3D11_TEXTURE2D_DESC textureDesc; - srcTexure->GetDesc(&textureDesc); - - if (mStagingTexture != NULL && - (mTextureFormat != textureDesc.Format || - mTextureSize.width != params.area.width || - mTextureSize.height != params.area.height)) - { - SafeRelease(mStagingTexture); - mTextureSize.width = 0; - mTextureSize.height = 0; - mTextureFormat = DXGI_FORMAT_UNKNOWN; - } - - if (mStagingTexture == NULL) - { - ID3D11Device *device = mRenderer->getDevice(); - HRESULT hr; - - mTextureSize.width = params.area.width; - mTextureSize.height = params.area.height; - mTextureFormat = textureDesc.Format; - - D3D11_TEXTURE2D_DESC stagingDesc; - stagingDesc.Width = params.area.width; - stagingDesc.Height = params.area.height; - stagingDesc.MipLevels = 1; - stagingDesc.ArraySize = 1; - stagingDesc.Format = mTextureFormat; - 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; - - hr = device->CreateTexture2D(&stagingDesc, NULL, &mStagingTexture); - if (FAILED(hr)) - { - ASSERT(hr == E_OUTOFMEMORY); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal staging texture."); - } - } - - // ReadPixels from multisampled FBOs isn't supported in current GL - ASSERT(textureDesc.SampleDesc.Count <= 1); - - ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext(); - D3D11_BOX srcBox; - srcBox.left = params.area.x; - srcBox.right = params.area.x + params.area.width; - srcBox.top = params.area.y; - srcBox.bottom = params.area.y + params.area.height; - srcBox.front = 0; - srcBox.back = 1; - - // Asynchronous copy - immediateContext->CopySubresourceRegion(mStagingTexture, 0, 0, 0, 0, srcTexure, srcSubresource, &srcBox); - - return gl::Error(GL_NO_ERROR); -} - -gl::Error Buffer11::PackStorage11::flushQueuedPackCommand() -{ - ASSERT(mMemoryBuffer.size() > 0); - - if (mQueuedPackCommand) - { - gl::Error error = mRenderer->packPixels(mStagingTexture, *mQueuedPackCommand, mMemoryBuffer.data()); - SafeDelete(mQueuedPackCommand); - if (error.isError()) - { - return error; - } - } - - return gl::Error(GL_NO_ERROR); -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.h deleted file mode 100644 index 1c06bbf88a..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.h +++ /dev/null @@ -1,105 +0,0 @@ -// -// Copyright 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Buffer11.h: Defines the rx::Buffer11 class which implements rx::BufferImpl via rx::BufferD3D. - -#ifndef LIBGLESV2_RENDERER_BUFFER11_H_ -#define LIBGLESV2_RENDERER_BUFFER11_H_ - -#include "libGLESv2/renderer/d3d/BufferD3D.h" -#include "libGLESv2/renderer/d3d/MemoryBuffer.h" -#include "libGLESv2/angletypes.h" - -namespace rx -{ -class Renderer11; - -enum BufferUsage -{ - BUFFER_USAGE_STAGING, - BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK, - BUFFER_USAGE_INDEX, - BUFFER_USAGE_PIXEL_UNPACK, - BUFFER_USAGE_PIXEL_PACK, - BUFFER_USAGE_UNIFORM, -}; - -struct PackPixelsParams -{ - PackPixelsParams(); - PackPixelsParams(const gl::Rectangle &area, GLenum format, GLenum type, GLuint outputPitch, - const gl::PixelPackState &pack, ptrdiff_t offset); - - gl::Rectangle area; - GLenum format; - GLenum type; - GLuint outputPitch; - gl::Buffer *packBuffer; - gl::PixelPackState pack; - ptrdiff_t offset; -}; - -typedef size_t DataRevision; - -class Buffer11 : public BufferD3D -{ - public: - Buffer11(Renderer11 *renderer); - virtual ~Buffer11(); - - static Buffer11 *makeBuffer11(BufferImpl *buffer); - - ID3D11Buffer *getBuffer(BufferUsage usage); - ID3D11ShaderResourceView *getSRV(DXGI_FORMAT srvFormat); - bool isMapped() const { return mMappedStorage != NULL; } - gl::Error packPixels(ID3D11Texture2D *srcTexure, UINT srcSubresource, const PackPixelsParams ¶ms); - - // BufferD3D implementation - virtual size_t getSize() const { return mSize; } - virtual bool supportsDirectBinding() const; - RendererD3D *getRenderer() override; - - // BufferImpl implementation - virtual gl::Error setData(const void* data, size_t size, GLenum usage); - gl::Error getData(const uint8_t **outData) override; - virtual gl::Error setSubData(const void* data, size_t size, size_t offset); - virtual gl::Error copySubData(BufferImpl* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size); - virtual gl::Error map(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr); - virtual gl::Error unmap(); - virtual void markTransformFeedbackUsage(); - - private: - DISALLOW_COPY_AND_ASSIGN(Buffer11); - - class BufferStorage11; - class NativeBuffer11; - class PackStorage11; - - Renderer11 *mRenderer; - size_t mSize; - - BufferStorage11 *mMappedStorage; - - std::map mBufferStorages; - - typedef std::pair BufferSRVPair; - std::map mBufferResourceViews; - - MemoryBuffer mResolvedData; - DataRevision mResolvedDataRevision; - unsigned int mReadUsageCount; - - void markBufferUsage(); - NativeBuffer11 *getStagingBuffer(); - PackStorage11 *getPackStorage(); - - BufferStorage11 *getBufferStorage(BufferUsage usage); - BufferStorage11 *getLatestBufferStorage() const; -}; - -} - -#endif // LIBGLESV2_RENDERER_BUFFER11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp deleted file mode 100644 index 7185a05506..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp +++ /dev/null @@ -1,556 +0,0 @@ -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Clear11.cpp: Framebuffer clear utility class. - -#include "libGLESv2/renderer/d3d/d3d11/Clear11.h" -#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" -#include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h" -#include "libGLESv2/renderer/d3d/d3d11/RenderTarget11.h" -#include "libGLESv2/formatutils.h" -#include "libGLESv2/Framebuffer.h" -#include "libGLESv2/FramebufferAttachment.h" - -// Precompiled shaders -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearfloatvs.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearfloatps.h" - -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearuintvs.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearuintps.h" - -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearsintvs.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearsintps.h" - -namespace rx -{ - -template -static void ApplyVertices(const gl::Extents &framebufferSize, const gl::Rectangle *scissor, const gl::Color &color, float depth, void *buffer) -{ - d3d11::PositionDepthColorVertex *vertices = reinterpret_cast*>(buffer); - - float depthClear = gl::clamp01(depth); - float left = -1.0f; - float right = 1.0f; - float top = -1.0f; - float bottom = 1.0f; - - // Clip the quad coordinates to the scissor if needed - if (scissor != NULL) - { - left = std::max(left, (scissor->x / float(framebufferSize.width)) * 2.0f - 1.0f); - right = std::min(right, ((scissor->x + scissor->width) / float(framebufferSize.width)) * 2.0f - 1.0f); - top = std::max(top, ((framebufferSize.height - scissor->y - scissor->height) / float(framebufferSize.height)) * 2.0f - 1.0f); - bottom = std::min(bottom, ((framebufferSize.height - scissor->y) / float(framebufferSize.height)) * 2.0f - 1.0f); - } - - d3d11::SetPositionDepthColorVertex(vertices + 0, left, bottom, depthClear, color); - d3d11::SetPositionDepthColorVertex(vertices + 1, left, top, depthClear, color); - d3d11::SetPositionDepthColorVertex(vertices + 2, right, bottom, depthClear, color); - d3d11::SetPositionDepthColorVertex(vertices + 3, right, top, depthClear, color); -} - -template -Clear11::ClearShader Clear11::CreateClearShader(ID3D11Device *device, DXGI_FORMAT colorType, const BYTE (&vsByteCode)[vsSize], const BYTE (&psByteCode)[psSize]) -{ - HRESULT result; - - ClearShader shader = { 0 }; - - D3D11_INPUT_ELEMENT_DESC quadLayout[] = - { - { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, - { "COLOR", 0, colorType, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, - }; - - result = device->CreateInputLayout(quadLayout, ArraySize(quadLayout), vsByteCode, vsSize, &shader.inputLayout); - ASSERT(SUCCEEDED(result)); - - result = device->CreateVertexShader(vsByteCode, vsSize, NULL, &shader.vertexShader); - ASSERT(SUCCEEDED(result)); - - result = device->CreatePixelShader(psByteCode, psSize, NULL, &shader.pixelShader); - ASSERT(SUCCEEDED(result)); - - return shader; -} - -Clear11::Clear11(Renderer11 *renderer) - : mRenderer(renderer), mClearBlendStates(StructLessThan), mClearDepthStencilStates(StructLessThan), - mVertexBuffer(NULL), mRasterizerState(NULL) -{ - HRESULT result; - ID3D11Device *device = renderer->getDevice(); - - 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 = device->CreateBuffer(&vbDesc, NULL, &mVertexBuffer); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mVertexBuffer, "Clear11 masked clear vertex buffer"); - - D3D11_RASTERIZER_DESC rsDesc; - rsDesc.FillMode = D3D11_FILL_SOLID; - rsDesc.CullMode = D3D11_CULL_NONE; - rsDesc.FrontCounterClockwise = FALSE; - rsDesc.DepthBias = 0; - rsDesc.DepthBiasClamp = 0.0f; - rsDesc.SlopeScaledDepthBias = 0.0f; - rsDesc.DepthClipEnable = renderer->isLevel9(); - rsDesc.ScissorEnable = FALSE; - rsDesc.MultisampleEnable = FALSE; - rsDesc.AntialiasedLineEnable = FALSE; - - result = device->CreateRasterizerState(&rsDesc, &mRasterizerState); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mRasterizerState, "Clear11 masked clear rasterizer state"); - - mFloatClearShader = CreateClearShader(device, DXGI_FORMAT_R32G32B32A32_FLOAT, g_VS_ClearFloat, g_PS_ClearFloat); - if (mRenderer->isLevel9()) { - memset(&mUintClearShader, 0, sizeof(ClearShader)); - memset(&mIntClearShader, 0, sizeof(ClearShader)); - return; - } - mUintClearShader = CreateClearShader(device, DXGI_FORMAT_R32G32B32A32_UINT, g_VS_ClearUint, g_PS_ClearUint ); - mIntClearShader = CreateClearShader(device, DXGI_FORMAT_R32G32B32A32_SINT, g_VS_ClearSint, g_PS_ClearSint ); -} - -Clear11::~Clear11() -{ - for (ClearBlendStateMap::iterator i = mClearBlendStates.begin(); i != mClearBlendStates.end(); i++) - { - SafeRelease(i->second); - } - mClearBlendStates.clear(); - - SafeRelease(mFloatClearShader.inputLayout); - SafeRelease(mFloatClearShader.vertexShader); - SafeRelease(mFloatClearShader.pixelShader); - - SafeRelease(mUintClearShader.inputLayout); - SafeRelease(mUintClearShader.vertexShader); - SafeRelease(mUintClearShader.pixelShader); - - SafeRelease(mIntClearShader.inputLayout); - SafeRelease(mIntClearShader.vertexShader); - SafeRelease(mIntClearShader.pixelShader); - - for (ClearDepthStencilStateMap::iterator i = mClearDepthStencilStates.begin(); i != mClearDepthStencilStates.end(); i++) - { - SafeRelease(i->second); - } - mClearDepthStencilStates.clear(); - - SafeRelease(mVertexBuffer); - SafeRelease(mRasterizerState); -} - -gl::Error Clear11::clearFramebuffer(const gl::ClearParameters &clearParams, const gl::Framebuffer *frameBuffer) -{ - // First determine if a scissored clear is needed, this will always require drawing a quad. - // - // Otherwise, iterate over the color buffers which require clearing and determine if they can be - // cleared with ID3D11DeviceContext::ClearRenderTargetView... This requires: - // 1) The render target is being cleared to a float value (will be cast to integer when clearing integer - // render targets as expected but does not work the other way around) - // 2) The format of the render target has no color channels that are currently masked out. - // Clear the easy-to-clear buffers on the spot and accumulate the ones that require special work. - // - // Also determine if the depth stencil can be cleared with ID3D11DeviceContext::ClearDepthStencilView - // by checking if the stencil write mask covers the entire stencil. - // - // To clear the remaining buffers, quads must be drawn containing an int, uint or float vertex color - // attribute. - - gl::Extents framebufferSize; - if (frameBuffer->getFirstColorbuffer() != NULL) - { - gl::FramebufferAttachment *attachment = frameBuffer->getFirstColorbuffer(); - framebufferSize.width = attachment->getWidth(); - framebufferSize.height = attachment->getHeight(); - framebufferSize.depth = 1; - } - else if (frameBuffer->getDepthOrStencilbuffer() != NULL) - { - gl::FramebufferAttachment *attachment = frameBuffer->getDepthOrStencilbuffer(); - framebufferSize.width = attachment->getWidth(); - framebufferSize.height = attachment->getHeight(); - framebufferSize.depth = 1; - } - else - { - UNREACHABLE(); - return gl::Error(GL_INVALID_OPERATION); - } - - if (clearParams.scissorEnabled && (clearParams.scissor.x >= framebufferSize.width || - clearParams.scissor.y >= framebufferSize.height || - clearParams.scissor.x + clearParams.scissor.width <= 0 || - clearParams.scissor.y + clearParams.scissor.height <= 0)) - { - // Scissor is enabled and the scissor rectangle is outside the renderbuffer - return gl::Error(GL_NO_ERROR); - } - - bool needScissoredClear = clearParams.scissorEnabled && (clearParams.scissor.x > 0 || clearParams.scissor.y > 0 || - clearParams.scissor.x + clearParams.scissor.width < framebufferSize.width || - clearParams.scissor.y + clearParams.scissor.height < framebufferSize.height); - - std::vector maskedClearRenderTargets; - RenderTarget11* maskedClearDepthStencil = NULL; - - ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); - - for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) - { - if (clearParams.clearColor[colorAttachment] && frameBuffer->isEnabledColorAttachment(colorAttachment)) - { - gl::FramebufferAttachment *attachment = frameBuffer->getColorbuffer(colorAttachment); - if (attachment) - { - RenderTarget11 *renderTarget = NULL; - gl::Error error = d3d11::GetAttachmentRenderTarget(attachment, &renderTarget); - if (error.isError()) - { - return error; - } - - const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(attachment->getInternalFormat()); - - if (clearParams.colorClearType == GL_FLOAT && - !(formatInfo.componentType == GL_FLOAT || formatInfo.componentType == GL_UNSIGNED_NORMALIZED || formatInfo.componentType == GL_SIGNED_NORMALIZED)) - { - ERR("It is undefined behaviour to clear a render buffer which is not normalized fixed point or floating-" - "point to floating point values (color attachment %u has internal format 0x%X).", colorAttachment, - attachment->getInternalFormat()); - } - - if ((formatInfo.redBits == 0 || !clearParams.colorMaskRed) && - (formatInfo.greenBits == 0 || !clearParams.colorMaskGreen) && - (formatInfo.blueBits == 0 || !clearParams.colorMaskBlue) && - (formatInfo.alphaBits == 0 || !clearParams.colorMaskAlpha)) - { - // Every channel either does not exist in the render target or is masked out - continue; - } - else if (needScissoredClear || clearParams.colorClearType != GL_FLOAT || - (formatInfo.redBits > 0 && !clearParams.colorMaskRed) || - (formatInfo.greenBits > 0 && !clearParams.colorMaskGreen) || - (formatInfo.blueBits > 0 && !clearParams.colorMaskBlue) || - (formatInfo.alphaBits > 0 && !clearParams.colorMaskAlpha)) - { - // A scissored or masked clear is required - MaskedRenderTarget maskAndRt; - bool clearColor = clearParams.clearColor[colorAttachment]; - maskAndRt.colorMask[0] = (clearColor && clearParams.colorMaskRed); - maskAndRt.colorMask[1] = (clearColor && clearParams.colorMaskGreen); - maskAndRt.colorMask[2] = (clearColor && clearParams.colorMaskBlue); - maskAndRt.colorMask[3] = (clearColor && clearParams.colorMaskAlpha); - maskAndRt.renderTarget = renderTarget; - maskedClearRenderTargets.push_back(maskAndRt); - } - else - { - // ID3D11DeviceContext::ClearRenderTargetView is possible - - ID3D11RenderTargetView *framebufferRTV = renderTarget->getRenderTargetView(); - if (!framebufferRTV) - { - return gl::Error(GL_OUT_OF_MEMORY, "Internal render target view pointer unexpectedly null."); - } - - const gl::InternalFormat &actualFormatInfo = gl::GetInternalFormatInfo(attachment->getActualFormat()); - - // Check if the actual format has a channel that the internal format does not and set them to the - // default values - const float clearValues[4] = - { - ((formatInfo.redBits == 0 && actualFormatInfo.redBits > 0) ? 0.0f : clearParams.colorFClearValue.red), - ((formatInfo.greenBits == 0 && actualFormatInfo.greenBits > 0) ? 0.0f : clearParams.colorFClearValue.green), - ((formatInfo.blueBits == 0 && actualFormatInfo.blueBits > 0) ? 0.0f : clearParams.colorFClearValue.blue), - ((formatInfo.alphaBits == 0 && actualFormatInfo.alphaBits > 0) ? 1.0f : clearParams.colorFClearValue.alpha), - }; - - deviceContext->ClearRenderTargetView(framebufferRTV, clearValues); - } - } - } - } - - if (clearParams.clearDepth || clearParams.clearStencil) - { - gl::FramebufferAttachment *attachment = frameBuffer->getDepthOrStencilbuffer(); - if (attachment) - { - RenderTarget11 *renderTarget = NULL; - gl::Error error = d3d11::GetAttachmentRenderTarget(attachment, &renderTarget); - if (error.isError()) - { - return error; - } - - const gl::InternalFormat &actualFormatInfo = gl::GetInternalFormatInfo(attachment->getActualFormat()); - - unsigned int stencilUnmasked = frameBuffer->hasStencil() ? (1 << actualFormatInfo.stencilBits) - 1 : 0; - bool needMaskedStencilClear = clearParams.clearStencil && (clearParams.stencilWriteMask & stencilUnmasked) != stencilUnmasked; - - if (needScissoredClear || needMaskedStencilClear) - { - maskedClearDepthStencil = renderTarget; - } - else - { - ID3D11DepthStencilView *framebufferDSV = renderTarget->getDepthStencilView(); - if (!framebufferDSV) - { - return gl::Error(GL_OUT_OF_MEMORY, "Internal depth stencil view pointer unexpectedly null."); - } - - UINT clearFlags = (clearParams.clearDepth ? D3D11_CLEAR_DEPTH : 0) | - (clearParams.clearStencil ? D3D11_CLEAR_STENCIL : 0); - FLOAT depthClear = gl::clamp01(clearParams.depthClearValue); - UINT8 stencilClear = clearParams.stencilClearValue & 0xFF; - - deviceContext->ClearDepthStencilView(framebufferDSV, clearFlags, depthClear, stencilClear); - } - } - } - - if (maskedClearRenderTargets.size() > 0 || maskedClearDepthStencil) - { - // To clear the render targets and depth stencil in one pass: - // - // Render a quad clipped to the scissor rectangle which draws the clear color and a blend - // state that will perform the required color masking. - // - // The quad's depth is equal to the depth clear value with a depth stencil state that - // will enable or disable depth test/writes if the depth buffer should be cleared or not. - // - // The rasterizer state's stencil is set to always pass or fail based on if the stencil - // should be cleared or not with a stencil write mask of the stencil clear value. - // - // ====================================================================================== - // - // Luckily, the gl spec (ES 3.0.2 pg 183) states that the results of clearing a render- - // buffer that is not normalized fixed point or floating point with floating point values - // are undefined so we can just write floats to them and D3D11 will bit cast them to - // integers. - // - // Also, we don't have to worry about attempting to clear a normalized fixed/floating point - // buffer with integer values because there is no gl API call which would allow it, - // glClearBuffer* calls only clear a single renderbuffer at a time which is verified to - // be a compatible clear type. - - // Bind all the render targets which need clearing - ASSERT(maskedClearRenderTargets.size() <= mRenderer->getRendererCaps().maxDrawBuffers); - std::vector rtvs(maskedClearRenderTargets.size()); - for (unsigned int i = 0; i < maskedClearRenderTargets.size(); i++) - { - RenderTarget11 *renderTarget = maskedClearRenderTargets[i].renderTarget; - ID3D11RenderTargetView *rtv = renderTarget->getRenderTargetView(); - if (!rtv) - { - return gl::Error(GL_OUT_OF_MEMORY, "Internal render target view pointer unexpectedly null."); - } - - rtvs[i] = rtv; - } - ID3D11DepthStencilView *dsv = maskedClearDepthStencil ? maskedClearDepthStencil->getDepthStencilView() : NULL; - - ID3D11BlendState *blendState = getBlendState(maskedClearRenderTargets); - const FLOAT blendFactors[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; - const UINT sampleMask = 0xFFFFFFFF; - - ID3D11DepthStencilState *dsState = getDepthStencilState(clearParams); - const UINT stencilClear = clearParams.stencilClearValue & 0xFF; - - // Set the vertices - UINT vertexStride = 0; - const UINT startIdx = 0; - const ClearShader* shader = NULL; - D3D11_MAPPED_SUBRESOURCE mappedResource; - HRESULT result = deviceContext->Map(mVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal masked clear vertex buffer, HRESULT: 0x%X.", result); - } - - const gl::Rectangle *scissorPtr = clearParams.scissorEnabled ? &clearParams.scissor : NULL; - switch (clearParams.colorClearType) - { - case GL_FLOAT: - ApplyVertices(framebufferSize, scissorPtr, clearParams.colorFClearValue, clearParams.depthClearValue, mappedResource.pData); - vertexStride = sizeof(d3d11::PositionDepthColorVertex); - shader = &mFloatClearShader; - break; - - case GL_UNSIGNED_INT: - ApplyVertices(framebufferSize, scissorPtr, clearParams.colorUIClearValue, clearParams.depthClearValue, mappedResource.pData); - vertexStride = sizeof(d3d11::PositionDepthColorVertex); - shader = &mUintClearShader; - break; - - case GL_INT: - ApplyVertices(framebufferSize, scissorPtr, clearParams.colorIClearValue, clearParams.depthClearValue, mappedResource.pData); - vertexStride = sizeof(d3d11::PositionDepthColorVertex); - shader = &mIntClearShader; - break; - - default: - UNREACHABLE(); - break; - } - - deviceContext->Unmap(mVertexBuffer, 0); - - // Set the viewport to be the same size as the framebuffer - D3D11_VIEWPORT viewport; - viewport.TopLeftX = 0; - viewport.TopLeftY = 0; - viewport.Width = framebufferSize.width; - viewport.Height = framebufferSize.height; - viewport.MinDepth = 0; - viewport.MaxDepth = 1; - deviceContext->RSSetViewports(1, &viewport); - - // Apply state - deviceContext->OMSetBlendState(blendState, blendFactors, sampleMask); - deviceContext->OMSetDepthStencilState(dsState, stencilClear); - deviceContext->RSSetState(mRasterizerState); - - // Apply shaders - deviceContext->IASetInputLayout(shader->inputLayout); - deviceContext->VSSetShader(shader->vertexShader, NULL, 0); - deviceContext->PSSetShader(shader->pixelShader, NULL, 0); - deviceContext->GSSetShader(NULL, NULL, 0); - - // Apply vertex buffer - deviceContext->IASetVertexBuffers(0, 1, &mVertexBuffer, &vertexStride, &startIdx); - deviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); - - // Apply render targets - deviceContext->OMSetRenderTargets(rtvs.size(), (rtvs.empty() ? NULL : &rtvs[0]), dsv); - - // Draw the clear quad - deviceContext->Draw(4, 0); - - // Clean up - mRenderer->markAllStateDirty(); - } - - return gl::Error(GL_NO_ERROR); -} - -ID3D11BlendState *Clear11::getBlendState(const std::vector& rts) -{ - ClearBlendInfo blendKey = { 0 }; - for (unsigned int i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++) - { - if (i < rts.size()) - { - RenderTarget11 *rt = rts[i].renderTarget; - const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(rt->getInternalFormat()); - - blendKey.maskChannels[i][0] = (rts[i].colorMask[0] && formatInfo.redBits > 0); - blendKey.maskChannels[i][1] = (rts[i].colorMask[1] && formatInfo.greenBits > 0); - blendKey.maskChannels[i][2] = (rts[i].colorMask[2] && formatInfo.blueBits > 0); - blendKey.maskChannels[i][3] = (rts[i].colorMask[3] && formatInfo.alphaBits > 0); - } - else - { - blendKey.maskChannels[i][0] = false; - blendKey.maskChannels[i][1] = false; - blendKey.maskChannels[i][2] = false; - blendKey.maskChannels[i][3] = false; - } - } - - ClearBlendStateMap::const_iterator i = mClearBlendStates.find(blendKey); - if (i != mClearBlendStates.end()) - { - return i->second; - } - else - { - D3D11_BLEND_DESC blendDesc = { 0 }; - blendDesc.AlphaToCoverageEnable = FALSE; - blendDesc.IndependentBlendEnable = (rts.size() > 1) ? TRUE : FALSE; - - for (unsigned int i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++) - { - blendDesc.RenderTarget[i].BlendEnable = FALSE; - blendDesc.RenderTarget[i].RenderTargetWriteMask = gl_d3d11::ConvertColorMask(blendKey.maskChannels[i][0], - blendKey.maskChannels[i][1], - blendKey.maskChannels[i][2], - blendKey.maskChannels[i][3]); - } - - ID3D11Device *device = mRenderer->getDevice(); - ID3D11BlendState* blendState = NULL; - HRESULT result = device->CreateBlendState(&blendDesc, &blendState); - if (FAILED(result) || !blendState) - { - ERR("Unable to create a ID3D11BlendState, HRESULT: 0x%X.", result); - return NULL; - } - - mClearBlendStates[blendKey] = blendState; - - return blendState; - } -} - -ID3D11DepthStencilState *Clear11::getDepthStencilState(const gl::ClearParameters &clearParams) -{ - ClearDepthStencilInfo dsKey = { 0 }; - dsKey.clearDepth = clearParams.clearDepth; - dsKey.clearStencil = clearParams.clearStencil; - dsKey.stencilWriteMask = clearParams.stencilWriteMask & 0xFF; - - ClearDepthStencilStateMap::const_iterator i = mClearDepthStencilStates.find(dsKey); - if (i != mClearDepthStencilStates.end()) - { - return i->second; - } - else - { - D3D11_DEPTH_STENCIL_DESC dsDesc = { 0 }; - dsDesc.DepthEnable = dsKey.clearDepth ? TRUE : FALSE; - dsDesc.DepthWriteMask = dsKey.clearDepth ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO; - dsDesc.DepthFunc = D3D11_COMPARISON_ALWAYS; - dsDesc.StencilEnable = dsKey.clearStencil ? TRUE : FALSE; - dsDesc.StencilReadMask = 0; - dsDesc.StencilWriteMask = dsKey.stencilWriteMask; - dsDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_REPLACE; - dsDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_REPLACE; - dsDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_REPLACE; - dsDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS; - dsDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_REPLACE; - dsDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_REPLACE; - dsDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_REPLACE; - dsDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS; - - ID3D11Device *device = mRenderer->getDevice(); - ID3D11DepthStencilState* dsState = NULL; - HRESULT result = device->CreateDepthStencilState(&dsDesc, &dsState); - if (FAILED(result) || !dsState) - { - ERR("Unable to create a ID3D11DepthStencilState, HRESULT: 0x%X.", result); - return NULL; - } - - mClearDepthStencilStates[dsKey] = dsState; - - return dsState; - } -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.h deleted file mode 100644 index a7e8fea56a..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.h +++ /dev/null @@ -1,87 +0,0 @@ -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Clear11.h: Framebuffer clear utility class. - -#ifndef LIBGLESV2_RENDERER_CLEAR11_H_ -#define LIBGLESV2_RENDERER_CLEAR11_H_ - -#include "libGLESv2/angletypes.h" -#include "libGLESv2/Error.h" - -#include -#include - -namespace gl -{ -class Framebuffer; -} - -namespace rx -{ -class Renderer11; -class RenderTarget11; - -class Clear11 -{ - public: - explicit Clear11(Renderer11 *renderer); - ~Clear11(); - - // Clears the framebuffer with the supplied clear parameters, assumes that the framebuffer is currently applied. - gl::Error clearFramebuffer(const gl::ClearParameters &clearParams, const gl::Framebuffer *frameBuffer); - - private: - Renderer11 *mRenderer; - - struct ClearBlendInfo - { - bool maskChannels[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT][4]; - }; - typedef bool (*ClearBlendInfoComparisonFunction)(const ClearBlendInfo&, const ClearBlendInfo &); - typedef std::map ClearBlendStateMap; - ClearBlendStateMap mClearBlendStates; - - struct MaskedRenderTarget - { - bool colorMask[4]; - RenderTarget11 *renderTarget; - }; - - ID3D11BlendState *getBlendState(const std::vector &rts); - - struct ClearShader - { - ID3D11InputLayout *inputLayout; - ID3D11VertexShader *vertexShader; - ID3D11PixelShader *pixelShader; - }; - ClearShader mFloatClearShader; - ClearShader mUintClearShader; - ClearShader mIntClearShader; - - template - static ClearShader CreateClearShader(ID3D11Device *device, DXGI_FORMAT colorType, const BYTE (&vsByteCode)[vsSize], const BYTE (&psByteCode)[psSize]); - - struct ClearDepthStencilInfo - { - bool clearDepth; - bool clearStencil; - UINT8 stencilWriteMask; - }; - typedef bool (*ClearDepthStencilInfoComparisonFunction)(const ClearDepthStencilInfo&, const ClearDepthStencilInfo &); - typedef std::map ClearDepthStencilStateMap; - ClearDepthStencilStateMap mClearDepthStencilStates; - - ID3D11DepthStencilState *getDepthStencilState(const gl::ClearParameters &clearParams); - - ID3D11Buffer *mVertexBuffer; - ID3D11RasterizerState *mRasterizerState; -}; - -} - -#endif // LIBGLESV2_RENDERER_CLEAR11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Fence11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Fence11.cpp deleted file mode 100644 index f44d934056..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Fence11.cpp +++ /dev/null @@ -1,232 +0,0 @@ -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Fence11.cpp: Defines the rx::FenceNV11 and rx::FenceSync11 classes which implement rx::FenceNVImpl and rx::FenceSyncImpl. - -#include "libGLESv2/renderer/d3d/d3d11/Fence11.h" -#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" -#include "libGLESv2/main.h" - -#include "common/utilities.h" - -namespace rx -{ - -// -// Template helpers for set and test operations. -// - -template -gl::Error FenceSetHelper(FenceClass *fence) -{ - if (!fence->mQuery) - { - D3D11_QUERY_DESC queryDesc; - queryDesc.Query = D3D11_QUERY_EVENT; - queryDesc.MiscFlags = 0; - - HRESULT result = fence->mRenderer->getDevice()->CreateQuery(&queryDesc, &fence->mQuery); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create event query, result: 0x%X.", result); - } - } - - fence->mRenderer->getDeviceContext()->End(fence->mQuery); - return gl::Error(GL_NO_ERROR); -} - -template -gl::Error FenceTestHelper(FenceClass *fence, bool flushCommandBuffer, GLboolean *outFinished) -{ - ASSERT(fence->mQuery); - - UINT getDataFlags = (flushCommandBuffer ? 0 : D3D11_ASYNC_GETDATA_DONOTFLUSH); - HRESULT result = fence->mRenderer->getDeviceContext()->GetData(fence->mQuery, NULL, 0, getDataFlags); - - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to get query data, result: 0x%X.", result); - } - else if (fence->mRenderer->isDeviceLost()) - { - return gl::Error(GL_OUT_OF_MEMORY, "Device was lost while querying result of an event query."); - } - - ASSERT(result == S_OK || result == S_FALSE); - *outFinished = ((result == S_OK) ? GL_TRUE : GL_FALSE); - return gl::Error(GL_NO_ERROR); -} - -// -// FenceNV11 -// - -FenceNV11::FenceNV11(Renderer11 *renderer) - : FenceNVImpl(), - mRenderer(renderer), - mQuery(NULL) -{ -} - -FenceNV11::~FenceNV11() -{ - SafeRelease(mQuery); -} - -gl::Error FenceNV11::set() -{ - return FenceSetHelper(this); -} - -gl::Error FenceNV11::test(bool flushCommandBuffer, GLboolean *outFinished) -{ - return FenceTestHelper(this, flushCommandBuffer, outFinished); -} - -gl::Error FenceNV11::finishFence(GLboolean *outFinished) -{ - ASSERT(outFinished); - - while (*outFinished != GL_TRUE) - { - gl::Error error = test(true, outFinished); - if (error.isError()) - { - return error; - } - - Sleep(0); - } - - return gl::Error(GL_NO_ERROR); -} - -// -// FenceSync11 -// - -// Important note on accurate timers in Windows: -// -// QueryPerformanceCounter has a few major issues, including being 10x as expensive to call -// as timeGetTime on laptops and "jumping" during certain hardware events. -// -// See the comments at the top of the Chromium source file "chromium/src/base/time/time_win.cc" -// https://code.google.com/p/chromium/codesearch#chromium/src/base/time/time_win.cc -// -// We still opt to use QPC. In the present and moving forward, most newer systems will not suffer -// from buggy implementations. - -FenceSync11::FenceSync11(Renderer11 *renderer) - : FenceSyncImpl(), - mRenderer(renderer), - mQuery(NULL) -{ - LARGE_INTEGER counterFreqency = { 0 }; - BOOL success = QueryPerformanceFrequency(&counterFreqency); - UNUSED_ASSERTION_VARIABLE(success); - ASSERT(success); - - mCounterFrequency = counterFreqency.QuadPart; -} - -FenceSync11::~FenceSync11() -{ - SafeRelease(mQuery); -} - -gl::Error FenceSync11::set() -{ - return FenceSetHelper(this); -} - -gl::Error FenceSync11::clientWait(GLbitfield flags, GLuint64 timeout, GLenum *outResult) -{ - ASSERT(outResult); - - bool flushCommandBuffer = ((flags & GL_SYNC_FLUSH_COMMANDS_BIT) != 0); - - GLboolean result = GL_FALSE; - gl::Error error = FenceTestHelper(this, flushCommandBuffer, &result); - if (error.isError()) - { - *outResult = GL_WAIT_FAILED; - return error; - } - - if (result == GL_TRUE) - { - *outResult = GL_ALREADY_SIGNALED; - return gl::Error(GL_NO_ERROR); - } - - if (timeout == 0) - { - *outResult = GL_TIMEOUT_EXPIRED; - return gl::Error(GL_NO_ERROR); - } - - LARGE_INTEGER currentCounter = { 0 }; - BOOL success = QueryPerformanceCounter(¤tCounter); - UNUSED_ASSERTION_VARIABLE(success); - ASSERT(success); - - LONGLONG timeoutInSeconds = static_cast(timeout) * static_cast(1000000ll); - LONGLONG endCounter = currentCounter.QuadPart + mCounterFrequency * timeoutInSeconds; - - while (currentCounter.QuadPart < endCounter && !result) - { - Sleep(0); - BOOL success = QueryPerformanceCounter(¤tCounter); - UNUSED_ASSERTION_VARIABLE(success); - ASSERT(success); - - error = FenceTestHelper(this, flushCommandBuffer, &result); - if (error.isError()) - { - *outResult = GL_WAIT_FAILED; - return error; - } - } - - if (currentCounter.QuadPart >= endCounter) - { - *outResult = GL_TIMEOUT_EXPIRED; - } - else - { - *outResult = GL_CONDITION_SATISFIED; - } - - return gl::Error(GL_NO_ERROR); -} - -gl::Error FenceSync11::serverWait(GLbitfield flags, GLuint64 timeout) -{ - // Because our API is currently designed to be called from a single thread, we don't need to do - // extra work for a server-side fence. GPU commands issued after the fence is created will always - // be processed after the fence is signaled. - return gl::Error(GL_NO_ERROR); -} - -gl::Error FenceSync11::getStatus(GLint *outResult) -{ - GLboolean result = GL_FALSE; - gl::Error error = FenceTestHelper(this, false, &result); - if (error.isError()) - { - // The spec does not specify any way to report errors during the status test (e.g. device lost) - // so we report the fence is unblocked in case of error or signaled. - *outResult = GL_SIGNALED; - - return error; - } - - *outResult = (result ? GL_SIGNALED : GL_UNSIGNALED); - return gl::Error(GL_NO_ERROR); -} - -} // namespace rx diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Fence11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Fence11.h deleted file mode 100644 index 1223a53b90..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Fence11.h +++ /dev/null @@ -1,62 +0,0 @@ -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Fence11.h: Defines the rx::FenceNV11 and rx::FenceSync11 classes which implement rx::FenceNVImpl and rx::FenceSyncImpl. - -#ifndef LIBGLESV2_RENDERER_FENCE11_H_ -#define LIBGLESV2_RENDERER_FENCE11_H_ - -#include "libGLESv2/renderer/FenceImpl.h" - -namespace rx -{ -class Renderer11; - -class FenceNV11 : public FenceNVImpl -{ - public: - explicit FenceNV11(Renderer11 *renderer); - virtual ~FenceNV11(); - - gl::Error set(); - gl::Error test(bool flushCommandBuffer, GLboolean *outFinished); - gl::Error finishFence(GLboolean *outFinished); - - private: - DISALLOW_COPY_AND_ASSIGN(FenceNV11); - - template friend gl::Error FenceSetHelper(T *fence); - template friend gl::Error FenceTestHelper(T *fence, bool flushCommandBuffer, GLboolean *outFinished); - - Renderer11 *mRenderer; - ID3D11Query *mQuery; -}; - -class FenceSync11 : public FenceSyncImpl -{ - public: - explicit FenceSync11(Renderer11 *renderer); - virtual ~FenceSync11(); - - gl::Error set(); - gl::Error clientWait(GLbitfield flags, GLuint64 timeout, GLenum *outResult); - gl::Error serverWait(GLbitfield flags, GLuint64 timeout); - gl::Error getStatus(GLint *outResult); - - private: - DISALLOW_COPY_AND_ASSIGN(FenceSync11); - - template friend gl::Error FenceSetHelper(T *fence); - template friend gl::Error FenceTestHelper(T *fence, bool flushCommandBuffer, GLboolean *outFinished); - - Renderer11 *mRenderer; - ID3D11Query *mQuery; - LONGLONG mCounterFrequency; -}; - -} - -#endif // LIBGLESV2_RENDERER_FENCE11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Image11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Image11.cpp deleted file mode 100644 index e6f3e90683..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Image11.cpp +++ /dev/null @@ -1,634 +0,0 @@ -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Image11.h: Implements the rx::Image11 class, which acts as the interface to -// the actual underlying resources of a Texture - -#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" -#include "libGLESv2/renderer/d3d/d3d11/Image11.h" -#include "libGLESv2/renderer/d3d/d3d11/RenderTarget11.h" -#include "libGLESv2/renderer/d3d/d3d11/TextureStorage11.h" -#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" -#include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h" -#include "libGLESv2/Framebuffer.h" -#include "libGLESv2/FramebufferAttachment.h" -#include "libGLESv2/main.h" - -#include "common/utilities.h" - -namespace rx -{ - -Image11::Image11() - : mRenderer(NULL), - mDXGIFormat(DXGI_FORMAT_UNKNOWN), - mStagingTexture(NULL), - mStagingSubresource(0), - mRecoverFromStorage(false), - mAssociatedStorage(NULL), - mAssociatedImageIndex(gl::ImageIndex::MakeInvalid()), - mRecoveredFromStorageCount(0) - -{ -} - -Image11::~Image11() -{ - disassociateStorage(); - releaseStagingTexture(); -} - -Image11 *Image11::makeImage11(Image *img) -{ - ASSERT(HAS_DYNAMIC_TYPE(Image11*, img)); - return static_cast(img); -} - -gl::Error 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()); - - const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(src->getDXGIFormat()); - ASSERT(dxgiFormatInfo.mipGenerationFunction != NULL); - - D3D11_MAPPED_SUBRESOURCE destMapped; - gl::Error error = dest->map(D3D11_MAP_WRITE, &destMapped); - if (error.isError()) - { - return error; - } - - D3D11_MAPPED_SUBRESOURCE srcMapped; - error = src->map(D3D11_MAP_READ, &srcMapped); - if (error.isError()) - { - dest->unmap(); - return error; - } - - const uint8_t *sourceData = reinterpret_cast(srcMapped.pData); - uint8_t *destData = reinterpret_cast(destMapped.pData); - - dxgiFormatInfo.mipGenerationFunction(src->getWidth(), src->getHeight(), src->getDepth(), - sourceData, srcMapped.RowPitch, srcMapped.DepthPitch, - destData, destMapped.RowPitch, destMapped.DepthPitch); - - dest->unmap(); - src->unmap(); - - dest->markDirty(); - - return gl::Error(GL_NO_ERROR); -} - -bool Image11::isDirty() const -{ - // If mDirty is true - // AND mStagingTexture doesn't exist AND mStagingTexture doesn't need to be recovered from TextureStorage - // AND the texture doesn't require init data (i.e. a blank new texture will suffice) - // then isDirty should still return false. - if (mDirty && !mStagingTexture && !mRecoverFromStorage && !(d3d11::GetTextureFormatInfo(mInternalFormat).dataInitializerFunction != NULL)) - { - return false; - } - - return mDirty; -} - -gl::Error Image11::copyToStorage(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box ®ion) -{ - TextureStorage11 *storage11 = TextureStorage11::makeTextureStorage11(storage); - - // If an app's behavior results in an Image11 copying its data to/from to a TextureStorage multiple times, - // then we should just keep the staging texture around to prevent the copying from impacting perf. - // We allow the Image11 to copy its data to/from TextureStorage once. - // This accounts for an app making a late call to glGenerateMipmap. - bool attemptToReleaseStagingTexture = (mRecoveredFromStorageCount < 2); - - if (attemptToReleaseStagingTexture) - { - // If another image is relying on this Storage for its data, then we must let it recover its data before we overwrite it. - gl::Error error = storage11->releaseAssociatedImage(index, this); - if (error.isError()) - { - return error; - } - } - - ID3D11Resource *stagingTexture = NULL; - unsigned int stagingSubresourceIndex = 0; - gl::Error error = getStagingTexture(&stagingTexture, &stagingSubresourceIndex); - if (error.isError()) - { - return error; - } - - error = storage11->updateSubresourceLevel(stagingTexture, stagingSubresourceIndex, index, region); - if (error.isError()) - { - return error; - } - - // Once the image data has been copied into the Storage, we can release it locally. - if (attemptToReleaseStagingTexture) - { - storage11->associateImage(this, index); - releaseStagingTexture(); - mRecoverFromStorage = true; - mAssociatedStorage = storage11; - mAssociatedImageIndex = index; - } - - return gl::Error(GL_NO_ERROR); -} - -bool Image11::isAssociatedStorageValid(TextureStorage11* textureStorage) const -{ - return (mAssociatedStorage == textureStorage); -} - -gl::Error Image11::recoverFromAssociatedStorage() -{ - if (mRecoverFromStorage) - { - gl::Error error = createStagingTexture(); - if (error.isError()) - { - return error; - } - - bool textureStorageCorrect = mAssociatedStorage->isAssociatedImageValid(mAssociatedImageIndex, this); - - // This means that the cached TextureStorage has been modified after this Image11 released its copy of its data. - // This should not have happened. The TextureStorage should have told this Image11 to recover its data before it was overwritten. - ASSERT(textureStorageCorrect); - - if (textureStorageCorrect) - { - // CopySubResource from the Storage to the Staging texture - gl::Box region(0, 0, 0, mWidth, mHeight, mDepth); - error = mAssociatedStorage->copySubresourceLevel(mStagingTexture, mStagingSubresource, mAssociatedImageIndex, region); - if (error.isError()) - { - return error; - } - - mRecoveredFromStorageCount += 1; - } - - // Reset all the recovery parameters, even if the texture storage association is broken. - disassociateStorage(); - } - - return gl::Error(GL_NO_ERROR); -} - -void Image11::disassociateStorage() -{ - if (mRecoverFromStorage) - { - // Make the texturestorage release the Image11 too - mAssociatedStorage->disassociateImage(mAssociatedImageIndex, this); - - mRecoverFromStorage = false; - mAssociatedStorage = NULL; - mAssociatedImageIndex = gl::ImageIndex::MakeInvalid(); - } -} - -bool Image11::redefine(RendererD3D *renderer, GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, bool forceRelease) -{ - if (mWidth != width || - mHeight != height || - mInternalFormat != internalformat || - forceRelease) - { - // End the association with the TextureStorage, since that data will be out of date. - // Also reset mRecoveredFromStorageCount since this Image is getting completely redefined. - disassociateStorage(); - mRecoveredFromStorageCount = 0; - - mRenderer = Renderer11::makeRenderer11(renderer); - - mWidth = width; - mHeight = height; - mDepth = depth; - mInternalFormat = internalformat; - mTarget = target; - - // compute the d3d format that will be used - const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat); - const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(formatInfo.texFormat); - mDXGIFormat = formatInfo.texFormat; - mActualFormat = dxgiFormatInfo.internalFormat; - mRenderable = (formatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN); - - releaseStagingTexture(); - mDirty = (formatInfo.dataInitializerFunction != NULL); - - return true; - } - - return false; -} - -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. -gl::Error Image11::loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, - GLint unpackAlignment, GLenum type, const void *input) -{ - const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat); - GLsizei inputRowPitch = formatInfo.computeRowPitch(type, width, unpackAlignment); - GLsizei inputDepthPitch = formatInfo.computeDepthPitch(type, width, height, unpackAlignment); - - const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mDXGIFormat); - GLuint outputPixelSize = dxgiFormatInfo.pixelBytes; - - const d3d11::TextureFormat &d3dFormatInfo = d3d11::GetTextureFormatInfo(mInternalFormat); - LoadImageFunction loadFunction = d3dFormatInfo.loadFunctions.at(type); - - D3D11_MAPPED_SUBRESOURCE mappedImage; - gl::Error error = map(D3D11_MAP_WRITE, &mappedImage); - if (error.isError()) - { - return error; - } - - uint8_t* offsetMappedData = (reinterpret_cast(mappedImage.pData) + (yoffset * mappedImage.RowPitch + xoffset * outputPixelSize + zoffset * mappedImage.DepthPitch)); - loadFunction(width, height, depth, - reinterpret_cast(input), inputRowPitch, inputDepthPitch, - offsetMappedData, mappedImage.RowPitch, mappedImage.DepthPitch); - - unmap(); - - return gl::Error(GL_NO_ERROR); -} - -gl::Error Image11::loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, - const void *input) -{ - const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat); - GLsizei inputRowPitch = formatInfo.computeRowPitch(GL_UNSIGNED_BYTE, width, 1); - GLsizei inputDepthPitch = formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, width, height, 1); - - const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mDXGIFormat); - GLuint outputPixelSize = dxgiFormatInfo.pixelBytes; - GLuint outputBlockWidth = dxgiFormatInfo.blockWidth; - GLuint outputBlockHeight = dxgiFormatInfo.blockHeight; - - ASSERT(xoffset % outputBlockWidth == 0); - ASSERT(yoffset % outputBlockHeight == 0); - - const d3d11::TextureFormat &d3dFormatInfo = d3d11::GetTextureFormatInfo(mInternalFormat); - LoadImageFunction loadFunction = d3dFormatInfo.loadFunctions.at(GL_UNSIGNED_BYTE); - - D3D11_MAPPED_SUBRESOURCE mappedImage; - gl::Error error = map(D3D11_MAP_WRITE, &mappedImage); - if (error.isError()) - { - return error; - } - - uint8_t* offsetMappedData = reinterpret_cast(mappedImage.pData) + ((yoffset / outputBlockHeight) * mappedImage.RowPitch + - (xoffset / outputBlockWidth) * outputPixelSize + - zoffset * mappedImage.DepthPitch); - - loadFunction(width, height, depth, - reinterpret_cast(input), inputRowPitch, inputDepthPitch, - offsetMappedData, mappedImage.RowPitch, mappedImage.DepthPitch); - - unmap(); - - return gl::Error(GL_NO_ERROR); -} - -gl::Error Image11::copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea, RenderTarget *source) -{ - RenderTarget11 *sourceRenderTarget = RenderTarget11::makeRenderTarget11(source); - ASSERT(sourceRenderTarget->getTexture()); - - UINT subresourceIndex = sourceRenderTarget->getSubresourceIndex(); - ID3D11Texture2D *sourceTexture2D = d3d11::DynamicCastComObject(sourceRenderTarget->getTexture()); - - if (!sourceTexture2D) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to retrieve the ID3D11Texture2D from the source RenderTarget."); - } - - gl::Error error = copy(xoffset, yoffset, zoffset, sourceArea, sourceTexture2D, subresourceIndex); - - SafeRelease(sourceTexture2D); - - return error; -} - -gl::Error Image11::copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea, const gl::ImageIndex &sourceIndex, TextureStorage *source) -{ - TextureStorage11 *sourceStorage11 = TextureStorage11::makeTextureStorage11(source); - - UINT subresourceIndex = sourceStorage11->getSubresourceIndex(sourceIndex); - ID3D11Resource *resource = NULL; - gl::Error error = sourceStorage11->getResource(&resource); - if (error.isError()) - { - return error; - } - - ID3D11Texture2D *sourceTexture2D = d3d11::DynamicCastComObject(resource); - - if (!sourceTexture2D) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to retrieve the ID3D11Texture2D from the source TextureStorage."); - } - - error = copy(xoffset, yoffset, zoffset, sourceArea, sourceTexture2D, subresourceIndex); - - SafeRelease(sourceTexture2D); - - return error; -} - -gl::Error Image11::copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea, ID3D11Texture2D *source, UINT sourceSubResource) -{ - D3D11_TEXTURE2D_DESC textureDesc; - source->GetDesc(&textureDesc); - - if (textureDesc.Format == mDXGIFormat) - { - // No conversion needed-- use copyback fastpath - ID3D11Resource *stagingTexture = NULL; - unsigned int stagingSubresourceIndex = 0; - gl::Error error = getStagingTexture(&stagingTexture, &stagingSubresourceIndex); - if (error.isError()) - { - return error; - } - - ID3D11Device *device = mRenderer->getDevice(); - ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); - - UINT subresourceAfterResolve = sourceSubResource; - - 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)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create resolve texture for Image11::copy, HRESULT: 0x%X.", result); - } - - deviceContext->ResolveSubresource(srcTex, 0, source, sourceSubResource, textureDesc.Format); - subresourceAfterResolve = 0; - } - else - { - srcTex = source; - } - - D3D11_BOX srcBox; - srcBox.left = sourceArea.x; - srcBox.right = sourceArea.x + sourceArea.width; - srcBox.top = sourceArea.y; - srcBox.bottom = sourceArea.y + sourceArea.height; - srcBox.front = 0; - srcBox.back = 1; - - deviceContext->CopySubresourceRegion(stagingTexture, stagingSubresourceIndex, xoffset, yoffset, zoffset, srcTex, subresourceAfterResolve, &srcBox); - - if (textureDesc.SampleDesc.Count > 1) - { - SafeRelease(srcTex); - } - } - else - { - // This format requires conversion, so we must copy the texture to staging and manually convert via readPixels - D3D11_MAPPED_SUBRESOURCE mappedImage; - gl::Error error = map(D3D11_MAP_WRITE, &mappedImage); - if (error.isError()) - { - return error; - } - - // determine the offset coordinate into the destination buffer - GLsizei rowOffset = gl::GetInternalFormatInfo(mActualFormat).pixelBytes * xoffset; - uint8_t *dataOffset = static_cast(mappedImage.pData) + mappedImage.RowPitch * yoffset + rowOffset + zoffset * mappedImage.DepthPitch; - - const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat); - - error = mRenderer->readTextureData(source, sourceSubResource, sourceArea, formatInfo.format, formatInfo.type, mappedImage.RowPitch, gl::PixelPackState(), dataOffset); - - unmap(); - - if (error.isError()) - { - return error; - } - } - - mDirty = true; - - return gl::Error(GL_NO_ERROR); -} - -gl::Error Image11::getStagingTexture(ID3D11Resource **outStagingTexture, unsigned int *outSubresourceIndex) -{ - gl::Error error = createStagingTexture(); - if (error.isError()) - { - return error; - } - - *outStagingTexture = mStagingTexture; - *outSubresourceIndex = mStagingSubresource; - return gl::Error(GL_NO_ERROR); -} - -void Image11::releaseStagingTexture() -{ - SafeRelease(mStagingTexture); -} - -gl::Error Image11::createStagingTexture() -{ - if (mStagingTexture) - { - return gl::Error(GL_NO_ERROR); - } - - ASSERT(mWidth > 0 && mHeight > 0 && mDepth > 0); - - const DXGI_FORMAT dxgiFormat = getDXGIFormat(); - - ID3D11Device *device = mRenderer->getDevice(); - HRESULT result; - - int lodOffset = 1; - GLsizei width = mWidth; - GLsizei height = mHeight; - - // adjust size if needed for compressed textures - d3d11::MakeValidSize(false, dxgiFormat, &width, &height, &lodOffset); - - if (mTarget == GL_TEXTURE_3D) - { - ID3D11Texture3D *newTexture = NULL; - - D3D11_TEXTURE3D_DESC desc; - desc.Width = width; - desc.Height = height; - desc.Depth = mDepth; - desc.MipLevels = lodOffset + 1; - desc.Format = dxgiFormat; - desc.Usage = D3D11_USAGE_STAGING; - desc.BindFlags = 0; - desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; - desc.MiscFlags = 0; - - if (d3d11::GetTextureFormatInfo(mInternalFormat).dataInitializerFunction != NULL) - { - std::vector initialData; - std::vector< std::vector > textureData; - d3d11::GenerateInitialTextureData(mInternalFormat, width, height, mDepth, - lodOffset + 1, &initialData, &textureData); - - result = device->CreateTexture3D(&desc, initialData.data(), &newTexture); - } - else - { - result = device->CreateTexture3D(&desc, NULL, &newTexture); - } - - if (FAILED(result)) - { - ASSERT(result == E_OUTOFMEMORY); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create staging texture, result: 0x%X.", result); - } - - mStagingTexture = newTexture; - mStagingSubresource = D3D11CalcSubresource(lodOffset, 0, lodOffset + 1); - } - else if (mTarget == GL_TEXTURE_2D || mTarget == GL_TEXTURE_2D_ARRAY || mTarget == GL_TEXTURE_CUBE_MAP) - { - ID3D11Texture2D *newTexture = NULL; - - D3D11_TEXTURE2D_DESC desc; - desc.Width = width; - desc.Height = height; - desc.MipLevels = lodOffset + 1; - desc.ArraySize = 1; - desc.Format = dxgiFormat; - desc.SampleDesc.Count = 1; - desc.SampleDesc.Quality = 0; - desc.Usage = D3D11_USAGE_STAGING; - desc.BindFlags = 0; - desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; - desc.MiscFlags = 0; - - if (d3d11::GetTextureFormatInfo(mInternalFormat).dataInitializerFunction != NULL) - { - std::vector initialData; - std::vector< std::vector > textureData; - d3d11::GenerateInitialTextureData(mInternalFormat, width, height, 1, - lodOffset + 1, &initialData, &textureData); - - result = device->CreateTexture2D(&desc, initialData.data(), &newTexture); - } - else - { - result = device->CreateTexture2D(&desc, NULL, &newTexture); - } - - if (FAILED(result)) - { - ASSERT(result == E_OUTOFMEMORY); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create staging texture, result: 0x%X.", result); - } - - mStagingTexture = newTexture; - mStagingSubresource = D3D11CalcSubresource(lodOffset, 0, lodOffset + 1); - } - else - { - UNREACHABLE(); - } - - mDirty = false; - return gl::Error(GL_NO_ERROR); -} - -gl::Error Image11::map(D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map) -{ - // We must recover from the TextureStorage if necessary, even for D3D11_MAP_WRITE. - gl::Error error = recoverFromAssociatedStorage(); - if (error.isError()) - { - return error; - } - - ID3D11Resource *stagingTexture = NULL; - unsigned int subresourceIndex = 0; - error = getStagingTexture(&stagingTexture, &subresourceIndex); - if (error.isError()) - { - return error; - } - - ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); - - ASSERT(mStagingTexture); - HRESULT result = deviceContext->Map(stagingTexture, subresourceIndex, mapType, 0, map); - - // this can fail if the device is removed (from TDR) - if (d3d11::isDeviceLostError(result)) - { - mRenderer->notifyDeviceLost(); - } - else if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to map staging texture, result: 0x%X.", result); - } - - mDirty = true; - - return gl::Error(GL_NO_ERROR); -} - -void Image11::unmap() -{ - if (mStagingTexture) - { - ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); - deviceContext->Unmap(mStagingTexture, mStagingSubresource); - } -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Image11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Image11.h deleted file mode 100644 index a936e6d7b2..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Image11.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. -// - -// 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/d3d/ImageD3D.h" -#include "libGLESv2/ImageIndex.h" - -#include "common/debug.h" - -namespace gl -{ -class Framebuffer; -} - -namespace rx -{ -class Renderer11; -class TextureStorage11; - -class Image11 : public ImageD3D -{ - public: - Image11(); - virtual ~Image11(); - - static Image11 *makeImage11(Image *img); - - static gl::Error generateMipmap(Image11 *dest, Image11 *src); - - virtual bool isDirty() const; - - virtual gl::Error copyToStorage(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box ®ion); - - bool redefine(RendererD3D *renderer, GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, bool forceRelease) override; - - DXGI_FORMAT getDXGIFormat() const; - - virtual gl::Error loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, - GLint unpackAlignment, GLenum type, const void *input); - virtual gl::Error loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, - const void *input); - - virtual gl::Error copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea, RenderTarget *source); - virtual gl::Error copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea, - const gl::ImageIndex &sourceIndex, TextureStorage *source); - - gl::Error recoverFromAssociatedStorage(); - bool isAssociatedStorageValid(TextureStorage11* textureStorage) const; - void disassociateStorage(); - - protected: - gl::Error map(D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map); - void unmap(); - - private: - DISALLOW_COPY_AND_ASSIGN(Image11); - - gl::Error copyToStorageImpl(TextureStorage11 *storage11, const gl::ImageIndex &index, const gl::Box ®ion); - gl::Error copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea, ID3D11Texture2D *source, UINT sourceSubResource); - - gl::Error getStagingTexture(ID3D11Resource **outStagingTexture, unsigned int *outSubresourceIndex); - gl::Error createStagingTexture(); - void releaseStagingTexture(); - - Renderer11 *mRenderer; - - DXGI_FORMAT mDXGIFormat; - ID3D11Resource *mStagingTexture; - unsigned int mStagingSubresource; - - bool mRecoverFromStorage; - TextureStorage11 *mAssociatedStorage; - gl::ImageIndex mAssociatedImageIndex; - unsigned int mRecoveredFromStorageCount; -}; - -} - -#endif // LIBGLESV2_RENDERER_IMAGE11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/IndexBuffer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/IndexBuffer11.cpp deleted file mode 100644 index 9a61182ee9..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/IndexBuffer11.cpp +++ /dev/null @@ -1,162 +0,0 @@ -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// IndexBuffer11.cpp: Defines the D3D11 IndexBuffer implementation. - -#include "libGLESv2/renderer/d3d/d3d11/IndexBuffer11.h" -#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" - -namespace rx -{ - -IndexBuffer11::IndexBuffer11(Renderer11 *const renderer) : mRenderer(renderer) -{ - mBuffer = NULL; - mBufferSize = 0; - mDynamicUsage = false; -} - -IndexBuffer11::~IndexBuffer11() -{ - SafeRelease(mBuffer); -} - -gl::Error IndexBuffer11::initialize(unsigned int bufferSize, GLenum indexType, bool dynamic) -{ - SafeRelease(mBuffer); - - 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 gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal index buffer of size, %lu.", bufferSize); - } - } - - mBufferSize = bufferSize; - mIndexType = indexType; - mDynamicUsage = dynamic; - - return gl::Error(GL_NO_ERROR); -} - -IndexBuffer11 *IndexBuffer11::makeIndexBuffer11(IndexBuffer *indexBuffer) -{ - ASSERT(HAS_DYNAMIC_TYPE(IndexBuffer11*, indexBuffer)); - return static_cast(indexBuffer); -} - -gl::Error IndexBuffer11::mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory) -{ - if (!mBuffer) - { - return gl::Error(GL_OUT_OF_MEMORY, "Internal index buffer is not initialized."); - } - - // Check for integer overflows and out-out-bounds map requests - if (offset + size < offset || offset + size > mBufferSize) - { - return gl::Error(GL_OUT_OF_MEMORY, "Index buffer map range is not inside the buffer."); - } - - ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); - - D3D11_MAPPED_SUBRESOURCE mappedResource; - HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mappedResource); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal index buffer, HRESULT: 0x%08x.", result); - } - - *outMappedMemory = reinterpret_cast(mappedResource.pData) + offset; - return gl::Error(GL_NO_ERROR); -} - -gl::Error IndexBuffer11::unmapBuffer() -{ - if (!mBuffer) - { - return gl::Error(GL_OUT_OF_MEMORY, "Internal index buffer is not initialized."); - } - - ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); - dxContext->Unmap(mBuffer, 0); - return gl::Error(GL_NO_ERROR); -} - -GLenum IndexBuffer11::getIndexType() const -{ - return mIndexType; -} - -unsigned int IndexBuffer11::getBufferSize() const -{ - return mBufferSize; -} - -gl::Error IndexBuffer11::setSize(unsigned int bufferSize, GLenum indexType) -{ - if (bufferSize > mBufferSize || indexType != mIndexType) - { - return initialize(bufferSize, indexType, mDynamicUsage); - } - else - { - return gl::Error(GL_NO_ERROR); - } -} - -gl::Error IndexBuffer11::discard() -{ - if (!mBuffer) - { - return gl::Error(GL_OUT_OF_MEMORY, "Internal index buffer is not initialized."); - } - - ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); - - D3D11_MAPPED_SUBRESOURCE mappedResource; - HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal index buffer, HRESULT: 0x%08x.", result); - } - - dxContext->Unmap(mBuffer, 0); - - return gl::Error(GL_NO_ERROR); -} - -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; -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/IndexBuffer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/IndexBuffer11.h deleted file mode 100644 index 3351df5ec1..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/IndexBuffer11.h +++ /dev/null @@ -1,53 +0,0 @@ -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// IndexBuffer11.h: Defines the D3D11 IndexBuffer implementation. - -#ifndef LIBGLESV2_RENDERER_INDEXBUFFER11_H_ -#define LIBGLESV2_RENDERER_INDEXBUFFER11_H_ - -#include "libGLESv2/renderer/d3d/IndexBuffer.h" - -namespace rx -{ -class Renderer11; - -class IndexBuffer11 : public IndexBuffer -{ - public: - explicit IndexBuffer11(Renderer11 *const renderer); - virtual ~IndexBuffer11(); - - virtual gl::Error initialize(unsigned int bufferSize, GLenum indexType, bool dynamic); - - static IndexBuffer11 *makeIndexBuffer11(IndexBuffer *indexBuffer); - - virtual gl::Error mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory); - virtual gl::Error unmapBuffer(); - - virtual GLenum getIndexType() const; - virtual unsigned int getBufferSize() const; - virtual gl::Error setSize(unsigned int bufferSize, GLenum indexType); - - virtual gl::Error discard(); - - DXGI_FORMAT getIndexFormat() const; - ID3D11Buffer *getBuffer() const; - - private: - DISALLOW_COPY_AND_ASSIGN(IndexBuffer11); - - 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/d3d/d3d11/InputLayoutCache.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.cpp deleted file mode 100644 index ff90a6a69a..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.cpp +++ /dev/null @@ -1,255 +0,0 @@ -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// InputLayoutCache.cpp: Defines InputLayoutCache, a class that builds and caches -// D3D11 input layouts. - -#include "libGLESv2/renderer/d3d/d3d11/InputLayoutCache.h" -#include "libGLESv2/renderer/d3d/d3d11/VertexBuffer11.h" -#include "libGLESv2/renderer/d3d/d3d11/Buffer11.h" -#include "libGLESv2/renderer/d3d/d3d11/ShaderExecutable11.h" -#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" -#include "libGLESv2/renderer/d3d/ProgramD3D.h" -#include "libGLESv2/renderer/d3d/VertexDataManager.h" -#include "libGLESv2/ProgramBinary.h" -#include "libGLESv2/VertexAttribute.h" - -#include "third_party/murmurhash/MurmurHash3.h" - -namespace rx -{ - -static void GetInputLayout(const TranslatedAttribute translatedAttributes[gl::MAX_VERTEX_ATTRIBS], - gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS]) -{ - for (unsigned int attributeIndex = 0; attributeIndex < gl::MAX_VERTEX_ATTRIBS; attributeIndex++) - { - const TranslatedAttribute &translatedAttribute = translatedAttributes[attributeIndex]; - - if (translatedAttributes[attributeIndex].active) - { - inputLayout[attributeIndex] = gl::VertexFormat(*translatedAttribute.attribute, - translatedAttribute.currentValueType); - } - } -} - -const unsigned int InputLayoutCache::kMaxInputLayouts = 1024; - -InputLayoutCache::InputLayoutCache() : mInputLayoutMap(kMaxInputLayouts, hashInputLayout, compareInputLayouts) -{ - mCounter = 0; - mDevice = NULL; - mDeviceContext = NULL; - mCurrentIL = NULL; - for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) - { - mCurrentBuffers[i] = NULL; - mCurrentVertexStrides[i] = -1; - mCurrentVertexOffsets[i] = -1; - } -} - -InputLayoutCache::~InputLayoutCache() -{ - clear(); -} - -void InputLayoutCache::initialize(ID3D11Device *device, ID3D11DeviceContext *context) -{ - clear(); - mDevice = device; - mDeviceContext = context; -} - -void InputLayoutCache::clear() -{ - for (InputLayoutMap::iterator i = mInputLayoutMap.begin(); i != mInputLayoutMap.end(); i++) - { - SafeRelease(i->second.inputLayout); - } - mInputLayoutMap.clear(); - markDirty(); -} - -void InputLayoutCache::markDirty() -{ - mCurrentIL = NULL; - for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) - { - mCurrentBuffers[i] = NULL; - mCurrentVertexStrides[i] = -1; - mCurrentVertexOffsets[i] = -1; - } -} - -gl::Error InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS], - gl::ProgramBinary *programBinary) -{ - int sortedSemanticIndices[gl::MAX_VERTEX_ATTRIBS]; - programBinary->sortAttributesByLayout(attributes, sortedSemanticIndices); - - if (!mDevice || !mDeviceContext) - { - return gl::Error(GL_OUT_OF_MEMORY, "Internal input layout cache is not initialized."); - } - - InputLayoutKey ilKey = { 0 }; - - static const char* semanticName = "TEXCOORD"; - - for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) - { - if (attributes[i].active) - { - D3D11_INPUT_CLASSIFICATION inputClass = attributes[i].divisor > 0 ? D3D11_INPUT_PER_INSTANCE_DATA : D3D11_INPUT_PER_VERTEX_DATA; - - gl::VertexFormat vertexFormat(*attributes[i].attribute, attributes[i].currentValueType); - const d3d11::VertexFormat &vertexFormatInfo = d3d11::GetVertexFormatInfo(vertexFormat); - - // Record the type of the associated vertex shader vector in our key - // This will prevent mismatched vertex shaders from using the same input layout - GLint attributeSize; - programBinary->getActiveAttribute(sortedSemanticIndices[i], 0, NULL, &attributeSize, &ilKey.elements[ilKey.elementCount].glslElementType, NULL); - - ilKey.elements[ilKey.elementCount].desc.SemanticName = semanticName; - ilKey.elements[ilKey.elementCount].desc.SemanticIndex = i; - ilKey.elements[ilKey.elementCount].desc.Format = vertexFormatInfo.nativeFormat; - ilKey.elements[ilKey.elementCount].desc.InputSlot = i; - ilKey.elements[ilKey.elementCount].desc.AlignedByteOffset = 0; - ilKey.elements[ilKey.elementCount].desc.InputSlotClass = inputClass; - ilKey.elements[ilKey.elementCount].desc.InstanceDataStepRate = attributes[i].divisor; - ilKey.elementCount++; - } - } - - ID3D11InputLayout *inputLayout = NULL; - - InputLayoutMap::iterator keyIter = mInputLayoutMap.find(ilKey); - if (keyIter != mInputLayoutMap.end()) - { - inputLayout = keyIter->second.inputLayout; - keyIter->second.lastUsedTime = mCounter++; - } - else - { - gl::VertexFormat shaderInputLayout[gl::MAX_VERTEX_ATTRIBS]; - GetInputLayout(attributes, shaderInputLayout); - ProgramD3D *programD3D = ProgramD3D::makeProgramD3D(programBinary->getImplementation()); - - ShaderExecutable *shader = NULL; - gl::Error error = programD3D->getVertexExecutableForInputLayout(shaderInputLayout, &shader); - if (error.isError()) - { - return error; - } - - ShaderExecutable *shader11 = ShaderExecutable11::makeShaderExecutable11(shader); - - D3D11_INPUT_ELEMENT_DESC descs[gl::MAX_VERTEX_ATTRIBS]; - for (unsigned int j = 0; j < ilKey.elementCount; ++j) - { - descs[j] = ilKey.elements[j].desc; - } - - HRESULT result = mDevice->CreateInputLayout(descs, ilKey.elementCount, shader11->getFunction(), shader11->getLength(), &inputLayout); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal input layout, HRESULT: 0x%08x", result); - } - - 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; - } - } - SafeRelease(leastRecentlyUsed->second.inputLayout); - mInputLayoutMap.erase(leastRecentlyUsed); - } - - InputLayoutCounterPair inputCounterPair; - inputCounterPair.inputLayout = inputLayout; - inputCounterPair.lastUsedTime = mCounter++; - - mInputLayoutMap.insert(std::make_pair(ilKey, inputCounterPair)); - } - - if (inputLayout != mCurrentIL) - { - mDeviceContext->IASetInputLayout(inputLayout); - mCurrentIL = inputLayout; - } - - bool dirtyBuffers = false; - size_t minDiff = gl::MAX_VERTEX_ATTRIBS; - size_t maxDiff = 0; - for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) - { - ID3D11Buffer *buffer = NULL; - - if (attributes[i].active) - { - VertexBuffer11 *vertexBuffer = VertexBuffer11::makeVertexBuffer11(attributes[i].vertexBuffer); - Buffer11 *bufferStorage = attributes[i].storage ? Buffer11::makeBuffer11(attributes[i].storage) : NULL; - - buffer = bufferStorage ? bufferStorage->getBuffer(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK) - : vertexBuffer->getBuffer(); - } - - UINT vertexStride = attributes[i].stride; - UINT vertexOffset = attributes[i].offset; - - if (buffer != mCurrentBuffers[i] || vertexStride != mCurrentVertexStrides[i] || - vertexOffset != mCurrentVertexOffsets[i]) - { - dirtyBuffers = true; - minDiff = std::min(minDiff, static_cast(i)); - maxDiff = std::max(maxDiff, static_cast(i)); - - mCurrentBuffers[i] = buffer; - mCurrentVertexStrides[i] = vertexStride; - mCurrentVertexOffsets[i] = vertexOffset; - } - } - - if (dirtyBuffers) - { - ASSERT(minDiff <= maxDiff && maxDiff < gl::MAX_VERTEX_ATTRIBS); - mDeviceContext->IASetVertexBuffers(minDiff, maxDiff - minDiff + 1, mCurrentBuffers + minDiff, - mCurrentVertexStrides + minDiff, mCurrentVertexOffsets + minDiff); - } - - return gl::Error(GL_NO_ERROR); -} - -std::size_t InputLayoutCache::hashInputLayout(const InputLayoutKey &inputLayout) -{ - static const unsigned int seed = 0xDEADBEEF; - - std::size_t hash = 0; - MurmurHash3_x86_32(inputLayout.begin(), inputLayout.end() - inputLayout.begin(), seed, &hash); - return hash; -} - -bool InputLayoutCache::compareInputLayouts(const InputLayoutKey &a, const InputLayoutKey &b) -{ - if (a.elementCount != b.elementCount) - { - return false; - } - - return std::equal(a.begin(), a.end(), b.begin()); -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.h deleted file mode 100644 index cc71ac3f6f..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.h +++ /dev/null @@ -1,101 +0,0 @@ -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// InputLayoutCache.h: Defines InputLayoutCache, a class that builds and caches -// D3D11 input layouts. - -#ifndef LIBGLESV2_RENDERER_INPUTLAYOUTCACHE_H_ -#define LIBGLESV2_RENDERER_INPUTLAYOUTCACHE_H_ - -#include "libGLESv2/Constants.h" -#include "libGLESv2/Error.h" -#include "common/angleutils.h" - -#include - -#include -#include - -namespace gl -{ -class ProgramBinary; -} - -namespace rx -{ -struct TranslatedAttribute; - -class InputLayoutCache -{ - public: - InputLayoutCache(); - virtual ~InputLayoutCache(); - - void initialize(ID3D11Device *device, ID3D11DeviceContext *context); - void clear(); - void markDirty(); - - gl::Error applyVertexBuffers(TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS], - gl::ProgramBinary *programBinary); - - private: - DISALLOW_COPY_AND_ASSIGN(InputLayoutCache); - - struct InputLayoutElement - { - D3D11_INPUT_ELEMENT_DESC desc; - GLenum glslElementType; - }; - - struct InputLayoutKey - { - unsigned int elementCount; - InputLayoutElement elements[gl::MAX_VERTEX_ATTRIBS]; - - const char *begin() const - { - return reinterpret_cast(&elementCount); - } - - const char *end() const - { - return reinterpret_cast(&elements[elementCount]); - } - }; - - struct InputLayoutCounterPair - { - ID3D11InputLayout *inputLayout; - unsigned long long lastUsedTime; - }; - - ID3D11InputLayout *mCurrentIL; - ID3D11Buffer *mCurrentBuffers[gl::MAX_VERTEX_ATTRIBS]; - UINT mCurrentVertexStrides[gl::MAX_VERTEX_ATTRIBS]; - UINT mCurrentVertexOffsets[gl::MAX_VERTEX_ATTRIBS]; - - static std::size_t hashInputLayout(const InputLayoutKey &inputLayout); - static bool compareInputLayouts(const InputLayoutKey &a, const InputLayoutKey &b); - - typedef std::size_t (*InputLayoutHashFunction)(const InputLayoutKey &); - typedef bool (*InputLayoutEqualityFunction)(const InputLayoutKey &, const InputLayoutKey &); - typedef std::unordered_map InputLayoutMap; - InputLayoutMap mInputLayoutMap; - - static const unsigned int kMaxInputLayouts; - - unsigned long long mCounter; - - ID3D11Device *mDevice; - ID3D11DeviceContext *mDeviceContext; -}; - -} - -#endif // LIBGLESV2_RENDERER_INPUTLAYOUTCACHE_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.cpp deleted file mode 100644 index 6a3d3475ee..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.cpp +++ /dev/null @@ -1,304 +0,0 @@ -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// PixelTransfer11.cpp: -// Implementation for buffer-to-texture and texture-to-buffer copies. -// Used to implement pixel transfers from unpack and to pack buffers. -// - -#include "libGLESv2/renderer/d3d/d3d11/PixelTransfer11.h" -#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" -#include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h" -#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" -#include "libGLESv2/renderer/d3d/d3d11/Buffer11.h" -#include "libGLESv2/renderer/d3d/d3d11/TextureStorage11.h" -#include "libGLESv2/renderer/d3d/d3d11/RenderTarget11.h" -#include "libGLESv2/formatutils.h" -#include "libGLESv2/Texture.h" -#include "libGLESv2/Buffer.h" -#include "libGLESv2/Context.h" - -// Precompiled shaders -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/buffertotexturevs.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/buffertotexturegs.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/buffertotexture_4fps.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/buffertotexture_4ips.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/buffertotexture_4uips.h" - -namespace rx -{ - -PixelTransfer11::PixelTransfer11(Renderer11 *renderer) - : mRenderer(renderer), - mResourcesLoaded(false), - mBufferToTextureVS(NULL), - mBufferToTextureGS(NULL), - mParamsConstantBuffer(NULL), - mCopyRasterizerState(NULL), - mCopyDepthStencilState(NULL) -{ -} - -PixelTransfer11::~PixelTransfer11() -{ - for (auto shaderMapIt = mBufferToTexturePSMap.begin(); shaderMapIt != mBufferToTexturePSMap.end(); shaderMapIt++) - { - SafeRelease(shaderMapIt->second); - } - - mBufferToTexturePSMap.clear(); - - SafeRelease(mBufferToTextureVS); - SafeRelease(mBufferToTextureGS); - SafeRelease(mParamsConstantBuffer); - SafeRelease(mCopyRasterizerState); - SafeRelease(mCopyDepthStencilState); -} - -gl::Error PixelTransfer11::loadResources() -{ - if (mResourcesLoaded) - { - return gl::Error(GL_NO_ERROR); - } - - HRESULT result = S_OK; - ID3D11Device *device = mRenderer->getDevice(); - - D3D11_RASTERIZER_DESC rasterDesc; - rasterDesc.FillMode = D3D11_FILL_SOLID; - rasterDesc.CullMode = D3D11_CULL_NONE; - rasterDesc.FrontCounterClockwise = FALSE; - rasterDesc.DepthBias = 0; - rasterDesc.SlopeScaledDepthBias = 0.0f; - rasterDesc.DepthBiasClamp = 0.0f; - rasterDesc.DepthClipEnable = TRUE; - rasterDesc.ScissorEnable = FALSE; - rasterDesc.MultisampleEnable = FALSE; - rasterDesc.AntialiasedLineEnable = FALSE; - - result = device->CreateRasterizerState(&rasterDesc, &mCopyRasterizerState); - ASSERT(SUCCEEDED(result)); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal pixel transfer rasterizer state, result: 0x%X.", result); - } - - D3D11_DEPTH_STENCIL_DESC depthStencilDesc; - depthStencilDesc.DepthEnable = true; - depthStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; - depthStencilDesc.DepthFunc = D3D11_COMPARISON_ALWAYS; - depthStencilDesc.StencilEnable = FALSE; - depthStencilDesc.StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK; - depthStencilDesc.StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK; - depthStencilDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; - depthStencilDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP; - depthStencilDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; - depthStencilDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS; - depthStencilDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; - depthStencilDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP; - depthStencilDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; - depthStencilDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS; - - result = device->CreateDepthStencilState(&depthStencilDesc, &mCopyDepthStencilState); - ASSERT(SUCCEEDED(result)); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal pixel transfer depth stencil state, result: 0x%X.", result); - } - - D3D11_BUFFER_DESC constantBufferDesc = { 0 }; - constantBufferDesc.ByteWidth = roundUp(sizeof(CopyShaderParams), 32u); - constantBufferDesc.Usage = D3D11_USAGE_DYNAMIC; - constantBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; - constantBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - constantBufferDesc.MiscFlags = 0; - constantBufferDesc.StructureByteStride = 0; - - result = device->CreateBuffer(&constantBufferDesc, NULL, &mParamsConstantBuffer); - ASSERT(SUCCEEDED(result)); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal pixel transfer constant buffer, result: 0x%X.", result); - } - d3d11::SetDebugName(mParamsConstantBuffer, "PixelTransfer11 constant buffer"); - - // init shaders - mBufferToTextureVS = d3d11::CompileVS(device, g_VS_BufferToTexture, "BufferToTexture VS"); - if (!mBufferToTextureVS) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal buffer to texture vertex shader."); - } - - if (!mRenderer->isLevel9()) - { - mBufferToTextureGS = d3d11::CompileGS(device, g_GS_BufferToTexture, "BufferToTexture GS"); - if (!mBufferToTextureGS) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal buffer to texture geometry shader."); - } - } - - gl::Error error = buildShaderMap(); - if (error.isError()) - { - return error; - } - - StructZero(&mParamsData); - - mResourcesLoaded = true; - - return gl::Error(GL_NO_ERROR); -} - -void PixelTransfer11::setBufferToTextureCopyParams(const gl::Box &destArea, const gl::Extents &destSize, GLenum internalFormat, - const gl::PixelUnpackState &unpack, unsigned int offset, CopyShaderParams *parametersOut) -{ - StructZero(parametersOut); - - float texelCenterX = 0.5f / static_cast(destSize.width - 1); - float texelCenterY = 0.5f / static_cast(destSize.height - 1); - - unsigned int bytesPerPixel = gl::GetInternalFormatInfo(internalFormat).pixelBytes; - unsigned int alignmentBytes = static_cast(unpack.alignment); - unsigned int alignmentPixels = (alignmentBytes <= bytesPerPixel ? 1 : alignmentBytes / bytesPerPixel); - - parametersOut->FirstPixelOffset = offset; - parametersOut->PixelsPerRow = static_cast(destArea.width); - parametersOut->RowStride = roundUp(parametersOut->PixelsPerRow, alignmentPixels); - parametersOut->RowsPerSlice = static_cast(destArea.height); - parametersOut->PositionOffset[0] = texelCenterX + (destArea.x / float(destSize.width)) * 2.0f - 1.0f; - parametersOut->PositionOffset[1] = texelCenterY + ((destSize.height - destArea.y - 1) / float(destSize.height)) * 2.0f - 1.0f; - parametersOut->PositionScale[0] = 2.0f / static_cast(destSize.width); - parametersOut->PositionScale[1] = -2.0f / static_cast(destSize.height); -} - -gl::Error PixelTransfer11::copyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget, - GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea) -{ - gl::Error error = loadResources(); - if (error.isError()) - { - return error; - } - - gl::Extents destSize = destRenderTarget->getExtents(); - - ASSERT(destArea.x >= 0 && destArea.x + destArea.width <= destSize.width && - destArea.y >= 0 && destArea.y + destArea.height <= destSize.height && - destArea.z >= 0 && destArea.z + destArea.depth <= destSize.depth ); - - const gl::Buffer &sourceBuffer = *unpack.pixelBuffer.get(); - - ASSERT(mRenderer->supportsFastCopyBufferToTexture(destinationFormat)); - - ID3D11PixelShader *pixelShader = findBufferToTexturePS(destinationFormat); - ASSERT(pixelShader); - - // The SRV must be in the proper read format, which may be different from the destination format - // EG: for half float data, we can load full precision floats with implicit conversion - GLenum unsizedFormat = gl::GetInternalFormatInfo(destinationFormat).format; - GLenum sourceFormat = gl::GetFormatTypeInfo(unsizedFormat, sourcePixelsType).internalFormat; - - const d3d11::TextureFormat &sourceFormatInfo = d3d11::GetTextureFormatInfo(sourceFormat); - DXGI_FORMAT srvFormat = sourceFormatInfo.srvFormat; - ASSERT(srvFormat != DXGI_FORMAT_UNKNOWN); - Buffer11 *bufferStorage11 = Buffer11::makeBuffer11(sourceBuffer.getImplementation()); - ID3D11ShaderResourceView *bufferSRV = bufferStorage11->getSRV(srvFormat); - ASSERT(bufferSRV != NULL); - - ID3D11RenderTargetView *textureRTV = RenderTarget11::makeRenderTarget11(destRenderTarget)->getRenderTargetView(); - ASSERT(textureRTV != NULL); - - CopyShaderParams shaderParams; - setBufferToTextureCopyParams(destArea, destSize, sourceFormat, unpack, offset, &shaderParams); - - ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); - - ID3D11Buffer *nullBuffer = NULL; - UINT zero = 0; - - // Are we doing a 2D or 3D copy? - ID3D11GeometryShader *geometryShader = ((destSize.depth > 1) ? mBufferToTextureGS : NULL); - - deviceContext->VSSetShader(mBufferToTextureVS, NULL, 0); - deviceContext->GSSetShader(geometryShader, NULL, 0); - deviceContext->PSSetShader(pixelShader, NULL, 0); - mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, bufferSRV); - deviceContext->IASetInputLayout(NULL); - deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST); - - deviceContext->IASetVertexBuffers(0, 1, &nullBuffer, &zero, &zero); - deviceContext->OMSetBlendState(NULL, NULL, 0xFFFFFFF); - deviceContext->OMSetDepthStencilState(mCopyDepthStencilState, 0xFFFFFFFF); - deviceContext->RSSetState(mCopyRasterizerState); - - mRenderer->setOneTimeRenderTarget(textureRTV); - - if (!StructEquals(mParamsData, shaderParams)) - { - d3d11::SetBufferData(deviceContext, mParamsConstantBuffer, shaderParams); - mParamsData = shaderParams; - } - - deviceContext->VSSetConstantBuffers(0, 1, &mParamsConstantBuffer); - - // Set the viewport - D3D11_VIEWPORT viewport; - viewport.TopLeftX = 0; - viewport.TopLeftY = 0; - viewport.Width = destSize.width; - viewport.Height = destSize.height; - viewport.MinDepth = 0.0f; - viewport.MaxDepth = 1.0f; - deviceContext->RSSetViewports(1, &viewport); - - UINT numPixels = (destArea.width * destArea.height * destArea.depth); - deviceContext->Draw(numPixels, 0); - - // Unbind textures and render targets and vertex buffer - mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, NULL); - deviceContext->VSSetConstantBuffers(0, 1, &nullBuffer); - - mRenderer->markAllStateDirty(); - - return gl::Error(GL_NO_ERROR); -} - -gl::Error PixelTransfer11::buildShaderMap() -{ - ID3D11Device *device = mRenderer->getDevice(); - - mBufferToTexturePSMap[GL_FLOAT] = d3d11::CompilePS(device, g_PS_BufferToTexture_4F, "BufferToTexture RGBA ps"); - mBufferToTexturePSMap[GL_INT] = d3d11::CompilePS(device, g_PS_BufferToTexture_4I, "BufferToTexture RGBA-I ps"); - mBufferToTexturePSMap[GL_UNSIGNED_INT] = d3d11::CompilePS(device, g_PS_BufferToTexture_4UI, "BufferToTexture RGBA-UI ps"); - - // Check that all the shaders were created successfully - for (auto shaderMapIt = mBufferToTexturePSMap.begin(); shaderMapIt != mBufferToTexturePSMap.end(); shaderMapIt++) - { - if (shaderMapIt->second == NULL) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal buffer to texture pixel shader."); - } - } - - return gl::Error(GL_NO_ERROR); -} - -ID3D11PixelShader *PixelTransfer11::findBufferToTexturePS(GLenum internalFormat) const -{ - GLenum componentType = gl::GetInternalFormatInfo(internalFormat).componentType; - if (componentType == GL_SIGNED_NORMALIZED || componentType == GL_UNSIGNED_NORMALIZED) - { - componentType = GL_FLOAT; - } - - auto shaderMapIt = mBufferToTexturePSMap.find(componentType); - return (shaderMapIt == mBufferToTexturePSMap.end() ? NULL : shaderMapIt->second); -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.h deleted file mode 100644 index 29552140bb..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.h +++ /dev/null @@ -1,88 +0,0 @@ -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// PixelTransfer11.h: -// Buffer-to-Texture and Texture-to-Buffer data transfers. -// Used to implement pixel unpack and pixel pack buffers in ES3. - -#ifndef LIBGLESV2_PIXELTRANSFER11_H_ -#define LIBGLESV2_PIXELTRANSFER11_H_ - -#include "libGLESv2/Error.h" - -#include "common/platform.h" - -#include - -#include - -namespace gl -{ - -class Buffer; -struct Box; -struct Extents; -struct PixelUnpackState; - -} - -namespace rx -{ -class Renderer11; -class RenderTarget; - -class PixelTransfer11 -{ - public: - explicit PixelTransfer11(Renderer11 *renderer); - ~PixelTransfer11(); - - // unpack: the source buffer is stored in the unpack state, and buffer strides - // offset: the start of the data within the unpack buffer - // destRenderTarget: individual slice/layer of a target texture - // destinationFormat/sourcePixelsType: determines shaders + shader parameters - // destArea: the sub-section of destRenderTarget to copy to - gl::Error copyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget, - GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea); - - private: - - struct CopyShaderParams - { - unsigned int FirstPixelOffset; - unsigned int PixelsPerRow; - unsigned int RowStride; - unsigned int RowsPerSlice; - float PositionOffset[2]; - float PositionScale[2]; - int TexLocationOffset[2]; - int TexLocationScale[2]; - }; - - static void setBufferToTextureCopyParams(const gl::Box &destArea, const gl::Extents &destSize, GLenum internalFormat, - const gl::PixelUnpackState &unpack, unsigned int offset, CopyShaderParams *parametersOut); - - gl::Error loadResources(); - gl::Error buildShaderMap(); - ID3D11PixelShader *findBufferToTexturePS(GLenum internalFormat) const; - - Renderer11 *mRenderer; - - bool mResourcesLoaded; - std::map mBufferToTexturePSMap; - ID3D11VertexShader *mBufferToTextureVS; - ID3D11GeometryShader *mBufferToTextureGS; - ID3D11Buffer *mParamsConstantBuffer; - CopyShaderParams mParamsData; - - ID3D11RasterizerState *mCopyRasterizerState; - ID3D11DepthStencilState *mCopyDepthStencilState; - -}; - -} - -#endif // LIBGLESV2_PIXELTRANSFER11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.cpp deleted file mode 100644 index 17ab1f8ab3..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.cpp +++ /dev/null @@ -1,157 +0,0 @@ -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Query11.cpp: Defines the rx::Query11 class which implements rx::QueryImpl. - -#include "libGLESv2/renderer/d3d/d3d11/Query11.h" -#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" -#include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h" -#include "libGLESv2/main.h" -#include "common/utilities.h" - -#include - -namespace rx -{ - -Query11::Query11(Renderer11 *renderer, GLenum type) - : QueryImpl(type), - mResult(0), - mQueryFinished(false), - mRenderer(renderer), - mQuery(NULL) -{ -} - -Query11::~Query11() -{ - SafeRelease(mQuery); -} - -gl::Error Query11::begin() -{ - if (mQuery == NULL) - { - D3D11_QUERY_DESC queryDesc; - queryDesc.Query = gl_d3d11::ConvertQueryType(getType()); - queryDesc.MiscFlags = 0; - - HRESULT result = mRenderer->getDevice()->CreateQuery(&queryDesc, &mQuery); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Internal query creation failed, result: 0x%X.", result); - } - } - - mRenderer->getDeviceContext()->Begin(mQuery); - return gl::Error(GL_NO_ERROR); -} - -gl::Error Query11::end() -{ - ASSERT(mQuery); - mRenderer->getDeviceContext()->End(mQuery); - - mQueryFinished = false; - mResult = GL_FALSE; - - return gl::Error(GL_NO_ERROR); -} - -gl::Error Query11::getResult(GLuint *params) -{ - while (!mQueryFinished) - { - gl::Error error = testQuery(); - if (error.isError()) - { - return error; - } - - if (!mQueryFinished) - { - Sleep(0); - } - } - - ASSERT(mQueryFinished); - *params = mResult; - - return gl::Error(GL_NO_ERROR); -} - -gl::Error Query11::isResultAvailable(GLuint *available) -{ - gl::Error error = testQuery(); - if (error.isError()) - { - return error; - } - - *available = (mQueryFinished ? GL_TRUE : GL_FALSE); - - return gl::Error(GL_NO_ERROR); -} - -gl::Error Query11::testQuery() -{ - if (!mQueryFinished) - { - ASSERT(mQuery); - - ID3D11DeviceContext *context = mRenderer->getDeviceContext(); - switch (getType()) - { - case GL_ANY_SAMPLES_PASSED_EXT: - case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT: - { - UINT64 numPixels = 0; - HRESULT result = context->GetData(mQuery, &numPixels, sizeof(numPixels), 0); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to get the data of an internal query, result: 0x%X.", result); - } - - if (result == S_OK) - { - mQueryFinished = true; - mResult = (numPixels > 0) ? GL_TRUE : GL_FALSE; - } - } - break; - - case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: - { - D3D11_QUERY_DATA_SO_STATISTICS soStats = { 0 }; - HRESULT result = context->GetData(mQuery, &soStats, sizeof(soStats), 0); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to get the data of an internal query, result: 0x%X.", result); - } - - if (result == S_OK) - { - mQueryFinished = true; - mResult = static_cast(soStats.NumPrimitivesWritten); - } - } - break; - - default: - UNREACHABLE(); - break; - } - - if (!mQueryFinished && mRenderer->testDeviceLost(true)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to test get query result, device is lost."); - } - } - - return gl::Error(GL_NO_ERROR); -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.h deleted file mode 100644 index f9ff467873..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.h +++ /dev/null @@ -1,44 +0,0 @@ -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Query11.h: Defines the rx::Query11 class which implements rx::QueryImpl. - -#ifndef LIBGLESV2_RENDERER_QUERY11_H_ -#define LIBGLESV2_RENDERER_QUERY11_H_ - -#include "libGLESv2/renderer/QueryImpl.h" - -namespace rx -{ -class Renderer11; - -class Query11 : public QueryImpl -{ - public: - Query11(Renderer11 *renderer, GLenum type); - virtual ~Query11(); - - virtual gl::Error begin(); - virtual gl::Error end(); - virtual gl::Error getResult(GLuint *params); - virtual gl::Error isResultAvailable(GLuint *available); - - private: - DISALLOW_COPY_AND_ASSIGN(Query11); - - gl::Error testQuery(); - - GLuint mResult; - - bool mQueryFinished; - - Renderer11 *mRenderer; - ID3D11Query *mQuery; -}; - -} - -#endif // LIBGLESV2_RENDERER_QUERY11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderStateCache.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderStateCache.cpp deleted file mode 100644 index ab4f60bd98..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderStateCache.cpp +++ /dev/null @@ -1,439 +0,0 @@ -// -// Copyright (c) 2012-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// RenderStateCache.cpp: Defines rx::RenderStateCache, a cache of Direct3D render -// state objects. - -#include "libGLESv2/renderer/d3d/d3d11/RenderStateCache.h" -#include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h" -#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" -#include "libGLESv2/Framebuffer.h" -#include "libGLESv2/FramebufferAttachment.h" - -#include "common/debug.h" - -#include "third_party/murmurhash/MurmurHash3.h" - -namespace rx -{ - -template -static void ClearStateMap(mapType &map) -{ - for (typename mapType::iterator i = map.begin(); i != map.end(); i++) - { - SafeRelease(i->second.first); - } - map.clear(); -} - -// 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(Renderer11 *renderer) - : mRenderer(renderer), - 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() -{ - ClearStateMap(mBlendStateCache); - ClearStateMap(mRasterizerStateCache); - ClearStateMap(mDepthStencilStateCache); - ClearStateMap(mSamplerStateCache); -} - -std::size_t RenderStateCache::hashBlendState(const BlendStateKey &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 BlendStateKey &a, const BlendStateKey &b) -{ - return memcmp(&a, &b, sizeof(BlendStateKey)) == 0; -} - -gl::Error RenderStateCache::getBlendState(const gl::Framebuffer *framebuffer, const gl::BlendState &blendState, - ID3D11BlendState **outBlendState) -{ - if (!mDevice) - { - return gl::Error(GL_OUT_OF_MEMORY, "Internal error, RenderStateCache is not initialized."); - } - - bool mrt = false; - - const gl::ColorbufferInfo &colorbuffers = framebuffer->getColorbuffersForRender(mRenderer->getWorkarounds()); - - BlendStateKey key = { 0 }; - key.blendState = blendState; - for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment) - { - const gl::FramebufferAttachment *attachment = colorbuffers[colorAttachment]; - - auto rtChannels = key.rtChannels[colorAttachment]; - - if (attachment) - { - if (colorAttachment > 0) - { - mrt = true; - } - - rtChannels[0] = attachment->getRedSize() > 0; - rtChannels[1] = attachment->getGreenSize() > 0; - rtChannels[2] = attachment->getBlueSize() > 0; - rtChannels[3] = attachment->getAlphaSize() > 0; - } - } - - BlendStateMap::iterator keyIter = mBlendStateCache.find(key); - if (keyIter != mBlendStateCache.end()) - { - BlendStateCounterPair &state = keyIter->second; - state.second = mCounter++; - *outBlendState = state.first; - return gl::Error(GL_NO_ERROR); - } - 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; - } - } - SafeRelease(leastRecentlyUsed->second.first); - mBlendStateCache.erase(leastRecentlyUsed); - } - - // Create a new blend state and insert it into the cache - D3D11_BLEND_DESC blendDesc = { 0 }; - blendDesc.AlphaToCoverageEnable = blendState.sampleAlphaToCoverage; - blendDesc.IndependentBlendEnable = mrt ? TRUE : FALSE; - - for (unsigned int i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++) - { - D3D11_RENDER_TARGET_BLEND_DESC &rtBlend = blendDesc.RenderTarget[i]; - - rtBlend.BlendEnable = blendState.blend; - if (blendState.blend) - { - rtBlend.SrcBlend = gl_d3d11::ConvertBlendFunc(blendState.sourceBlendRGB, false); - rtBlend.DestBlend = gl_d3d11::ConvertBlendFunc(blendState.destBlendRGB, false); - rtBlend.BlendOp = gl_d3d11::ConvertBlendOp(blendState.blendEquationRGB); - - rtBlend.SrcBlendAlpha = gl_d3d11::ConvertBlendFunc(blendState.sourceBlendAlpha, true); - rtBlend.DestBlendAlpha = gl_d3d11::ConvertBlendFunc(blendState.destBlendAlpha, true); - rtBlend.BlendOpAlpha = gl_d3d11::ConvertBlendOp(blendState.blendEquationAlpha); - } - - rtBlend.RenderTargetWriteMask = gl_d3d11::ConvertColorMask(key.rtChannels[i][0] && blendState.colorMaskRed, - key.rtChannels[i][1] && blendState.colorMaskGreen, - key.rtChannels[i][2] && blendState.colorMaskBlue, - key.rtChannels[i][3] && blendState.colorMaskAlpha); - } - - ID3D11BlendState *dx11BlendState = NULL; - HRESULT result = mDevice->CreateBlendState(&blendDesc, &dx11BlendState); - if (FAILED(result) || !dx11BlendState) - { - return gl::Error(GL_OUT_OF_MEMORY, "Unable to create a ID3D11BlendState, HRESULT: 0x%X.", result); - } - - mBlendStateCache.insert(std::make_pair(key, std::make_pair(dx11BlendState, mCounter++))); - - *outBlendState = dx11BlendState; - return gl::Error(GL_NO_ERROR); - } -} - -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; -} - -gl::Error RenderStateCache::getRasterizerState(const gl::RasterizerState &rasterState, bool scissorEnabled, - ID3D11RasterizerState **outRasterizerState) -{ - if (!mDevice) - { - return gl::Error(GL_OUT_OF_MEMORY, "Internal error, RenderStateCache is not initialized."); - } - - RasterizerStateKey key = { 0 }; - key.rasterizerState = rasterState; - key.scissorEnabled = scissorEnabled; - - RasterizerStateMap::iterator keyIter = mRasterizerStateCache.find(key); - if (keyIter != mRasterizerStateCache.end()) - { - RasterizerStateCounterPair &state = keyIter->second; - state.second = mCounter++; - *outRasterizerState = state.first; - return gl::Error(GL_NO_ERROR); - } - 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; - } - } - SafeRelease(leastRecentlyUsed->second.first); - 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.DepthBiasClamp = 0.0f; // MSDN documentation of DepthBiasClamp implies a value of zero will preform no clamping, must be tested though. - rasterDesc.DepthClipEnable = TRUE; - rasterDesc.ScissorEnable = scissorEnabled ? TRUE : FALSE; - rasterDesc.MultisampleEnable = rasterState.multiSample; - rasterDesc.AntialiasedLineEnable = FALSE; - - if (rasterState.polygonOffsetFill) - { - rasterDesc.SlopeScaledDepthBias = rasterState.polygonOffsetFactor; - rasterDesc.DepthBias = (INT)rasterState.polygonOffsetUnits; - } - else - { - rasterDesc.SlopeScaledDepthBias = 0.0f; - rasterDesc.DepthBias = 0; - } - - ID3D11RasterizerState *dx11RasterizerState = NULL; - HRESULT result = mDevice->CreateRasterizerState(&rasterDesc, &dx11RasterizerState); - if (FAILED(result) || !dx11RasterizerState) - { - return gl::Error(GL_OUT_OF_MEMORY, "Unable to create a ID3D11RasterizerState, HRESULT: 0x%X.", result); - } - - mRasterizerStateCache.insert(std::make_pair(key, std::make_pair(dx11RasterizerState, mCounter++))); - - *outRasterizerState = dx11RasterizerState; - return gl::Error(GL_NO_ERROR); - } -} - -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; -} - -gl::Error RenderStateCache::getDepthStencilState(const gl::DepthStencilState &dsState, ID3D11DepthStencilState **outDSState) -{ - if (!mDevice) - { - return gl::Error(GL_OUT_OF_MEMORY, "Internal error, RenderStateCache is not initialized."); - } - - DepthStencilStateMap::iterator keyIter = mDepthStencilStateCache.find(dsState); - if (keyIter != mDepthStencilStateCache.end()) - { - DepthStencilStateCounterPair &state = keyIter->second; - state.second = mCounter++; - *outDSState = state.first; - return gl::Error(GL_NO_ERROR); - } - 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; - } - } - SafeRelease(leastRecentlyUsed->second.first); - 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) - { - return gl::Error(GL_OUT_OF_MEMORY, "Unable to create a ID3D11DepthStencilState, HRESULT: 0x%X.", result); - } - - mDepthStencilStateCache.insert(std::make_pair(dsState, std::make_pair(dx11DepthStencilState, mCounter++))); - - *outDSState = dx11DepthStencilState; - return gl::Error(GL_NO_ERROR); - } -} - -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; -} - -gl::Error RenderStateCache::getSamplerState(const gl::SamplerState &samplerState, ID3D11SamplerState **outSamplerState) -{ - if (!mDevice) - { - return gl::Error(GL_OUT_OF_MEMORY, "Internal error, RenderStateCache is not initialized."); - } - - SamplerStateMap::iterator keyIter = mSamplerStateCache.find(samplerState); - if (keyIter != mSamplerStateCache.end()) - { - SamplerStateCounterPair &state = keyIter->second; - state.second = mCounter++; - *outSamplerState = state.first; - return gl::Error(GL_NO_ERROR); - } - 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; - } - } - SafeRelease(leastRecentlyUsed->second.first); - mSamplerStateCache.erase(leastRecentlyUsed); - } - - D3D11_SAMPLER_DESC samplerDesc; - samplerDesc.Filter = gl_d3d11::ConvertFilter(samplerState.minFilter, samplerState.magFilter, - samplerState.maxAnisotropy, samplerState.compareMode); - samplerDesc.AddressU = gl_d3d11::ConvertTextureWrap(samplerState.wrapS); - samplerDesc.AddressV = gl_d3d11::ConvertTextureWrap(samplerState.wrapT); - samplerDesc.AddressW = gl_d3d11::ConvertTextureWrap(samplerState.wrapR); - samplerDesc.MipLODBias = 0; - samplerDesc.MaxAnisotropy = samplerState.maxAnisotropy; - samplerDesc.ComparisonFunc = gl_d3d11::ConvertComparison(samplerState.compareFunc); - samplerDesc.BorderColor[0] = 0.0f; - samplerDesc.BorderColor[1] = 0.0f; - samplerDesc.BorderColor[2] = 0.0f; - samplerDesc.BorderColor[3] = 0.0f; - samplerDesc.MinLOD = samplerState.minLod; - samplerDesc.MaxLOD = samplerState.maxLod; - - ID3D11SamplerState *dx11SamplerState = NULL; - HRESULT result = mDevice->CreateSamplerState(&samplerDesc, &dx11SamplerState); - if (FAILED(result) || !dx11SamplerState) - { - return gl::Error(GL_OUT_OF_MEMORY, "Unable to create a ID3D11SamplerState, HRESULT: 0x%X.", result); - } - - mSamplerStateCache.insert(std::make_pair(samplerState, std::make_pair(dx11SamplerState, mCounter++))); - - *outSamplerState = dx11SamplerState; - return gl::Error(GL_NO_ERROR); - } -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderStateCache.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderStateCache.h deleted file mode 100644 index dfd1d84265..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderStateCache.h +++ /dev/null @@ -1,113 +0,0 @@ -// -// Copyright (c) 2012-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// 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 "libGLESv2/Error.h" -#include "common/angleutils.h" - -#include - -namespace gl -{ -class Framebuffer; -} - -namespace rx -{ -class Renderer11; - -class RenderStateCache -{ - public: - RenderStateCache(Renderer11 *renderer); - virtual ~RenderStateCache(); - - void initialize(ID3D11Device *device); - void clear(); - - gl::Error getBlendState(const gl::Framebuffer *framebuffer, const gl::BlendState &blendState, ID3D11BlendState **outBlendState); - gl::Error getRasterizerState(const gl::RasterizerState &rasterState, bool scissorEnabled, ID3D11RasterizerState **outRasterizerState); - gl::Error getDepthStencilState(const gl::DepthStencilState &dsState, ID3D11DepthStencilState **outDSState); - gl::Error getSamplerState(const gl::SamplerState &samplerState, ID3D11SamplerState **outSamplerState); - - private: - DISALLOW_COPY_AND_ASSIGN(RenderStateCache); - - Renderer11 *mRenderer; - unsigned long long mCounter; - - // Blend state cache - struct BlendStateKey - { - gl::BlendState blendState; - bool rtChannels[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT][4]; - }; - static std::size_t hashBlendState(const BlendStateKey &blendState); - static bool compareBlendStates(const BlendStateKey &a, const BlendStateKey &b); - static const unsigned int kMaxBlendStates; - - typedef std::size_t (*BlendStateHashFunction)(const BlendStateKey &); - typedef bool (*BlendStateEqualityFunction)(const BlendStateKey &, const BlendStateKey &); - typedef std::pair BlendStateCounterPair; - typedef std::unordered_map BlendStateMap; - BlendStateMap mBlendStateCache; - - // Rasterizer state cache - struct RasterizerStateKey - { - gl::RasterizerState rasterizerState; - bool scissorEnabled; - }; - 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/d3d/d3d11/RenderTarget11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.cpp deleted file mode 100644 index aff3453492..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.cpp +++ /dev/null @@ -1,404 +0,0 @@ -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// RenderTarget11.cpp: Implements a DX11-specific wrapper for ID3D11View pointers -// retained by Renderbuffers. - -#include "libGLESv2/renderer/d3d/d3d11/RenderTarget11.h" -#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" -#include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h" -#include "libGLESv2/renderer/d3d/d3d11/SwapChain11.h" -#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" -#include "libGLESv2/main.h" - -namespace rx -{ - -static bool getTextureProperties(ID3D11Resource *resource, unsigned int *mipLevels, unsigned int *samples) -{ - ID3D11Texture1D *texture1D = d3d11::DynamicCastComObject(resource); - if (texture1D) - { - D3D11_TEXTURE1D_DESC texDesc; - texture1D->GetDesc(&texDesc); - SafeRelease(texture1D); - - *mipLevels = texDesc.MipLevels; - *samples = 0; - - return true; - } - - ID3D11Texture2D *texture2D = d3d11::DynamicCastComObject(resource); - if (texture2D) - { - D3D11_TEXTURE2D_DESC texDesc; - texture2D->GetDesc(&texDesc); - SafeRelease(texture2D); - - *mipLevels = texDesc.MipLevels; - *samples = texDesc.SampleDesc.Count > 1 ? texDesc.SampleDesc.Count : 0; - - return true; - } - - ID3D11Texture3D *texture3D = d3d11::DynamicCastComObject(resource); - if (texture3D) - { - D3D11_TEXTURE3D_DESC texDesc; - texture3D->GetDesc(&texDesc); - SafeRelease(texture3D); - - *mipLevels = texDesc.MipLevels; - *samples = 0; - - return true; - } - - return false; -} - -static unsigned int getRTVSubresourceIndex(ID3D11Resource *resource, ID3D11RenderTargetView *view) -{ - D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; - view->GetDesc(&rtvDesc); - - unsigned int mipSlice = 0; - unsigned int arraySlice = 0; - - 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; - } - - unsigned int mipLevels, samples; - getTextureProperties(resource, &mipLevels, &samples); - - return D3D11CalcSubresource(mipSlice, arraySlice, mipLevels); -} - -static unsigned int getDSVSubresourceIndex(ID3D11Resource *resource, ID3D11DepthStencilView *view) -{ - D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; - view->GetDesc(&dsvDesc); - - unsigned int mipSlice = 0; - unsigned int arraySlice = 0; - - 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_DSV_DIMENSION_UNKNOWN: - UNIMPLEMENTED(); - break; - - default: - UNREACHABLE(); - break; - } - - unsigned int mipLevels, samples; - getTextureProperties(resource, &mipLevels, &samples); - - return D3D11CalcSubresource(mipSlice, arraySlice, mipLevels); -} - -RenderTarget11 *RenderTarget11::makeRenderTarget11(RenderTarget *target) -{ - ASSERT(HAS_DYNAMIC_TYPE(RenderTarget11*, target)); - return static_cast(target); -} - -void RenderTarget11::invalidate(GLint x, GLint y, GLsizei width, GLsizei height) -{ - // Currently a no-op -} - -TextureRenderTarget11::TextureRenderTarget11(ID3D11RenderTargetView *rtv, ID3D11Resource *resource, ID3D11ShaderResourceView *srv, - GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLsizei samples) - : mWidth(width), - mHeight(height), - mDepth(depth), - mInternalFormat(internalFormat), - mActualFormat(internalFormat), - mSamples(samples), - mSubresourceIndex(0), - mTexture(resource), - mRenderTarget(rtv), - mDepthStencil(NULL), - mShaderResource(srv) -{ - if (mTexture) - { - mTexture->AddRef(); - } - - if (mRenderTarget) - { - mRenderTarget->AddRef(); - } - - if (mShaderResource) - { - mShaderResource->AddRef(); - } - - if (mRenderTarget && mTexture) - { - mSubresourceIndex = getRTVSubresourceIndex(mTexture, mRenderTarget); - - D3D11_RENDER_TARGET_VIEW_DESC desc; - mRenderTarget->GetDesc(&desc); - - const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(desc.Format); - mActualFormat = dxgiFormatInfo.internalFormat; - } -} - -TextureRenderTarget11::TextureRenderTarget11(ID3D11DepthStencilView *dsv, ID3D11Resource *resource, ID3D11ShaderResourceView *srv, - GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLsizei samples) - : mWidth(width), - mHeight(height), - mDepth(depth), - mInternalFormat(internalFormat), - mActualFormat(internalFormat), - mSamples(samples), - mSubresourceIndex(0), - mTexture(resource), - mRenderTarget(NULL), - mDepthStencil(dsv), - mShaderResource(srv) -{ - if (mTexture) - { - mTexture->AddRef(); - } - - if (mDepthStencil) - { - mDepthStencil->AddRef(); - } - - if (mShaderResource) - { - mShaderResource->AddRef(); - } - - if (mDepthStencil && mTexture) - { - mSubresourceIndex = getDSVSubresourceIndex(mTexture, mDepthStencil); - - D3D11_DEPTH_STENCIL_VIEW_DESC desc; - mDepthStencil->GetDesc(&desc); - - const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(desc.Format); - mActualFormat = dxgiFormatInfo.internalFormat; - } -} - -TextureRenderTarget11::~TextureRenderTarget11() -{ - SafeRelease(mTexture); - SafeRelease(mRenderTarget); - SafeRelease(mDepthStencil); - SafeRelease(mShaderResource); -} - -ID3D11Resource *TextureRenderTarget11::getTexture() const -{ - return mTexture; -} - -ID3D11RenderTargetView *TextureRenderTarget11::getRenderTargetView() const -{ - return mRenderTarget; -} - -ID3D11DepthStencilView *TextureRenderTarget11::getDepthStencilView() const -{ - return mDepthStencil; -} - -ID3D11ShaderResourceView *TextureRenderTarget11::getShaderResourceView() const -{ - return mShaderResource; -} - -GLsizei TextureRenderTarget11::getWidth() const -{ - return mWidth; -} - -GLsizei TextureRenderTarget11::getHeight() const -{ - return mHeight; -} - -GLsizei TextureRenderTarget11::getDepth() const -{ - return mDepth; -} - -GLenum TextureRenderTarget11::getInternalFormat() const -{ - return mInternalFormat; -} - -GLenum TextureRenderTarget11::getActualFormat() const -{ - return mActualFormat; -} - -GLsizei TextureRenderTarget11::getSamples() const -{ - return mSamples; -} - -unsigned int TextureRenderTarget11::getSubresourceIndex() const -{ - return mSubresourceIndex; -} - - -SurfaceRenderTarget11::SurfaceRenderTarget11(SwapChain11 *swapChain, bool depth) - : mSwapChain(swapChain), - mDepth(depth) -{ - ASSERT(mSwapChain); -} - -SurfaceRenderTarget11::~SurfaceRenderTarget11() -{ -} - -GLsizei SurfaceRenderTarget11::getWidth() const -{ - return mSwapChain->getWidth(); -} - -GLsizei SurfaceRenderTarget11::getHeight() const -{ - return mSwapChain->getHeight(); -} - -GLsizei SurfaceRenderTarget11::getDepth() const -{ - return 1; -} - -GLenum SurfaceRenderTarget11::getInternalFormat() const -{ - return (mDepth ? mSwapChain->GetDepthBufferInternalFormat() : mSwapChain->GetBackBufferInternalFormat()); -} - -GLenum SurfaceRenderTarget11::getActualFormat() const -{ - return d3d11::GetDXGIFormatInfo(d3d11::GetTextureFormatInfo(getInternalFormat()).texFormat).internalFormat; -} - -GLsizei SurfaceRenderTarget11::getSamples() const -{ - // Our EGL surfaces do not support multisampling. - return 0; -} - -ID3D11Resource *SurfaceRenderTarget11::getTexture() const -{ - return (mDepth ? mSwapChain->getDepthStencilTexture() : mSwapChain->getOffscreenTexture()); -} - -ID3D11RenderTargetView *SurfaceRenderTarget11::getRenderTargetView() const -{ - return (mDepth ? NULL : mSwapChain->getRenderTarget()); -} - -ID3D11DepthStencilView *SurfaceRenderTarget11::getDepthStencilView() const -{ - return (mDepth ? mSwapChain->getDepthStencil() : NULL); -} - -ID3D11ShaderResourceView *SurfaceRenderTarget11::getShaderResourceView() const -{ - return (mDepth ? mSwapChain->getDepthStencilShaderResource() : mSwapChain->getRenderTargetShaderResource()); -} - -unsigned int SurfaceRenderTarget11::getSubresourceIndex() const -{ - return 0; -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.h deleted file mode 100644 index c7babdda3f..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.h +++ /dev/null @@ -1,110 +0,0 @@ -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// RenderTarget11.h: Defines a DX11-specific wrapper for ID3D11View pointers -// retained by Renderbuffers. - -#ifndef LIBGLESV2_RENDERER_RENDERTARGET11_H_ -#define LIBGLESV2_RENDERER_RENDERTARGET11_H_ - -#include "libGLESv2/renderer/RenderTarget.h" - -namespace rx -{ -class SwapChain11; - -class RenderTarget11 : public RenderTarget -{ - public: - RenderTarget11() { } - virtual ~RenderTarget11() { } - - static RenderTarget11 *makeRenderTarget11(RenderTarget *renderTarget); - - void invalidate(GLint x, GLint y, GLsizei width, GLsizei height) override; - - virtual ID3D11Resource *getTexture() const = 0; - virtual ID3D11RenderTargetView *getRenderTargetView() const = 0; - virtual ID3D11DepthStencilView *getDepthStencilView() const = 0; - virtual ID3D11ShaderResourceView *getShaderResourceView() const = 0; - - virtual unsigned int getSubresourceIndex() const = 0; - - private: - DISALLOW_COPY_AND_ASSIGN(RenderTarget11); -}; - -class TextureRenderTarget11 : public RenderTarget11 -{ - public: - // TextureRenderTarget11 takes ownership of any D3D11 resources it is given and will AddRef them - TextureRenderTarget11(ID3D11RenderTargetView *rtv, ID3D11Resource *resource, ID3D11ShaderResourceView *srv, - GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLsizei samples); - TextureRenderTarget11(ID3D11DepthStencilView *dsv, ID3D11Resource *resource, ID3D11ShaderResourceView *srv, - GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLsizei samples); - virtual ~TextureRenderTarget11(); - - GLsizei getWidth() const override; - GLsizei getHeight() const override; - GLsizei getDepth() const override; - GLenum getInternalFormat() const override; - GLenum getActualFormat() const override; - GLsizei getSamples() const override; - - ID3D11Resource *getTexture() const override; - ID3D11RenderTargetView *getRenderTargetView() const override; - ID3D11DepthStencilView *getDepthStencilView() const override; - ID3D11ShaderResourceView *getShaderResourceView() const override; - - unsigned int getSubresourceIndex() const override; - - private: - DISALLOW_COPY_AND_ASSIGN(TextureRenderTarget11); - - GLsizei mWidth; - GLsizei mHeight; - GLsizei mDepth; - GLenum mInternalFormat; - GLenum mActualFormat; - GLsizei mSamples; - - unsigned int mSubresourceIndex; - ID3D11Resource *mTexture; - ID3D11RenderTargetView *mRenderTarget; - ID3D11DepthStencilView *mDepthStencil; - ID3D11ShaderResourceView *mShaderResource; -}; - -class SurfaceRenderTarget11 : public RenderTarget11 -{ - public: - SurfaceRenderTarget11(SwapChain11 *swapChain, bool depth); - virtual ~SurfaceRenderTarget11(); - - GLsizei getWidth() const override; - GLsizei getHeight() const override; - GLsizei getDepth() const override; - GLenum getInternalFormat() const override; - GLenum getActualFormat() const override; - GLsizei getSamples() const override; - - ID3D11Resource *getTexture() const override; - ID3D11RenderTargetView *getRenderTargetView() const override; - ID3D11DepthStencilView *getDepthStencilView() const override; - ID3D11ShaderResourceView *getShaderResourceView() const override; - - unsigned int getSubresourceIndex() const override; - - private: - DISALLOW_COPY_AND_ASSIGN(SurfaceRenderTarget11); - - SwapChain11 *mSwapChain; - bool mDepth; -}; - -} - -#endif // LIBGLESV2_RENDERER_RENDERTARGET11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp deleted file mode 100644 index 777308e6cc..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp +++ /dev/null @@ -1,3422 +0,0 @@ -// -// Copyright (c) 2012-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Renderer11.cpp: Implements a back-end specific class for the D3D11 renderer. - -#include "libGLESv2/main.h" -#include "libGLESv2/Buffer.h" -#include "libGLESv2/FramebufferAttachment.h" -#include "libGLESv2/ProgramBinary.h" -#include "libGLESv2/Framebuffer.h" -#include "libGLESv2/State.h" -#include "libGLESv2/renderer/d3d/ProgramD3D.h" -#include "libGLESv2/renderer/d3d/ShaderD3D.h" -#include "libGLESv2/renderer/d3d/TextureD3D.h" -#include "libGLESv2/renderer/d3d/TransformFeedbackD3D.h" -#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" -#include "libGLESv2/renderer/d3d/d3d11/RenderTarget11.h" -#include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h" -#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" -#include "libGLESv2/renderer/d3d/d3d11/ShaderExecutable11.h" -#include "libGLESv2/renderer/d3d/d3d11/SwapChain11.h" -#include "libGLESv2/renderer/d3d/d3d11/Image11.h" -#include "libGLESv2/renderer/d3d/d3d11/VertexBuffer11.h" -#include "libGLESv2/renderer/d3d/d3d11/IndexBuffer11.h" -#include "libGLESv2/renderer/d3d/d3d11/Buffer11.h" -#include "libGLESv2/renderer/d3d/VertexDataManager.h" -#include "libGLESv2/renderer/d3d/IndexDataManager.h" -#include "libGLESv2/renderer/d3d/d3d11/TextureStorage11.h" -#include "libGLESv2/renderer/d3d/d3d11/Query11.h" -#include "libGLESv2/renderer/d3d/d3d11/Fence11.h" -#include "libGLESv2/renderer/d3d/d3d11/Blit11.h" -#include "libGLESv2/renderer/d3d/d3d11/Clear11.h" -#include "libGLESv2/renderer/d3d/d3d11/PixelTransfer11.h" -#include "libGLESv2/renderer/d3d/d3d11/VertexArray11.h" -#include "libGLESv2/renderer/d3d/d3d11/Buffer11.h" -#include "libGLESv2/renderer/d3d/RenderbufferD3D.h" - -#include "libEGL/Display.h" - -#include "common/utilities.h" -#include "common/tls.h" - -#include - -#include - -// Enable ANGLE_SKIP_DXGI_1_2_CHECK if there is not a possibility of using cross-process -// HWNDs or the Windows 7 Platform Update (KB2670838) is expected to be installed. -#ifndef ANGLE_SKIP_DXGI_1_2_CHECK -#define ANGLE_SKIP_DXGI_1_2_CHECK 0 -#endif - -#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 -{ - -namespace -{ -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 -}; - -// Does *not* increment the resource ref count!! -ID3D11Resource *GetSRVResource(ID3D11ShaderResourceView *srv) -{ - ID3D11Resource *resource = NULL; - ASSERT(srv); - srv->GetResource(&resource); - resource->Release(); - return resource; -} - -} - -Renderer11::Renderer11(egl::Display *display, EGLNativeDisplayType hDc, const egl::AttributeMap &attributes) - : RendererD3D(display), - mDc(hDc), - mStateCache(this) -{ - mVertexDataManager = NULL; - mIndexDataManager = NULL; - - mLineLoopIB = NULL; - mTriangleFanIB = NULL; - - mBlit = NULL; - mPixelTransfer = NULL; - - mClear = NULL; - - mSyncQuery = NULL; - - mD3d11Module = NULL; - mDxgiModule = NULL; - - mDeviceLost = false; - - mDevice = NULL; - mDeviceContext = NULL; - mDxgiAdapter = NULL; - mDxgiFactory = NULL; - - mDriverConstantBufferVS = NULL; - mDriverConstantBufferPS = NULL; - - mAppliedVertexShader = NULL; - mAppliedGeometryShader = NULL; - mCurPointGeometryShader = NULL; - mAppliedPixelShader = NULL; - - EGLint requestedMajorVersion = attributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, EGL_DONT_CARE); - EGLint requestedMinorVersion = attributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, EGL_DONT_CARE); - - if (requestedMajorVersion == EGL_DONT_CARE || requestedMajorVersion >= 11) - { - if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 0) - { - mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_11_0); - } - } - - if (requestedMajorVersion == EGL_DONT_CARE || requestedMajorVersion >= 10) - { - if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 1) - { - mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_10_1); - } - if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 0) - { - mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_10_0); - } - } - -#if !defined(ANGLE_ENABLE_D3D9) - if (requestedMajorVersion == EGL_DONT_CARE || requestedMajorVersion >= 9) - { - if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 3) - { - mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_3); - } - if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 2) - { - mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_2); - } - if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 1) - { - mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_1); - } - } -#endif - - mDriverType = (attributes.get(EGL_PLATFORM_ANGLE_USE_WARP_ANGLE, EGL_FALSE) == EGL_TRUE) ? D3D_DRIVER_TYPE_WARP - : D3D_DRIVER_TYPE_HARDWARE; -} - -Renderer11::~Renderer11() -{ - release(); -} - -Renderer11 *Renderer11::makeRenderer11(Renderer *renderer) -{ - ASSERT(HAS_DYNAMIC_TYPE(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 (!mCompiler.initialize()) - { - return EGL_NOT_INITIALIZED; - } - -#if !defined(ANGLE_ENABLE_WINDOWS_STORE) - mDxgiModule = LoadLibrary(TEXT("dxgi.dll")); - mD3d11Module = LoadLibrary(TEXT("d3d11.dll")); - - if (mD3d11Module == NULL || mDxgiModule == NULL) - { - ERR("Could not load D3D11 or DXGI library - aborting!\n"); - return EGL_NOT_INITIALIZED; - } - - // create the D3D11 device - ASSERT(mDevice == NULL); - PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE)GetProcAddress(mD3d11Module, "D3D11CreateDevice"); - - if (D3D11CreateDevice == NULL) - { - ERR("Could not retrieve D3D11CreateDevice address - aborting!\n"); - return EGL_NOT_INITIALIZED; - } -#endif - - HRESULT result = S_OK; -#ifdef _DEBUG - result = D3D11CreateDevice(NULL, - mDriverType, - NULL, - D3D11_CREATE_DEVICE_DEBUG, - mAvailableFeatureLevels.data(), - mAvailableFeatureLevels.size(), - D3D11_SDK_VERSION, - &mDevice, - &mFeatureLevel, - &mDeviceContext); - - if (!mDevice || FAILED(result)) - { - ERR("Failed creating Debug D3D11 device - falling back to release runtime.\n"); - } - - if (!mDevice || FAILED(result)) -#endif - { - result = D3D11CreateDevice(NULL, - mDriverType, - NULL, - 0, - mAvailableFeatureLevels.data(), - mAvailableFeatureLevels.size(), - D3D11_SDK_VERSION, - &mDevice, - &mFeatureLevel, - &mDeviceContext); - - if (!mDevice || FAILED(result)) - { - ERR("Could not create D3D11 device - aborting!\n"); - return EGL_NOT_INITIALIZED; // Cleanup done by destructor through glDestroyRenderer - } - } - -#if !defined(ANGLE_ENABLE_WINDOWS_STORE) - static wchar_t *qt_d3dcreate_multihreaded_var = _wgetenv(L"QT_D3DCREATE_MULTITHREADED"); - if (qt_d3dcreate_multihreaded_var && wcsstr(qt_d3dcreate_multihreaded_var, L"1")) - { - ID3D10Multithread *multithread; - result = mDevice->QueryInterface(IID_PPV_ARGS(&multithread)); - ASSERT(SUCCEEDED(result)); - result = multithread->SetMultithreadProtected(true); - ASSERT(SUCCEEDED(result)); - multithread->Release(); - } -#if !ANGLE_SKIP_DXGI_1_2_CHECK - // In order to create a swap chain for an HWND owned by another process, DXGI 1.2 is required. - // The easiest way to check is to query for a IDXGIDevice2. - bool requireDXGI1_2 = false; - HWND hwnd = WindowFromDC(mDc); - if (hwnd) - { - DWORD currentProcessId = GetCurrentProcessId(); - DWORD wndProcessId; - GetWindowThreadProcessId(hwnd, &wndProcessId); - requireDXGI1_2 = (currentProcessId != wndProcessId); - } - else - { - requireDXGI1_2 = true; - } - - if (requireDXGI1_2) - { - IDXGIDevice2 *dxgiDevice2 = NULL; - result = mDevice->QueryInterface(__uuidof(IDXGIDevice2), (void**)&dxgiDevice2); - if (FAILED(result)) - { - ERR("DXGI 1.2 required to present to HWNDs owned by another process.\n"); - return EGL_NOT_INITIALIZED; - } - SafeRelease(dxgiDevice2); - } -#endif -#endif - - 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; - } - - SafeRelease(dxgiDevice); - - 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(IID_ID3D11InfoQueue, (void **)&infoQueue); - - if (SUCCEEDED(result)) - { - D3D11_MESSAGE_ID hideMessages[] = - { - D3D11_MESSAGE_ID_DEVICE_DRAW_RENDERTARGETVIEW_NOT_SET - }; - - D3D11_INFO_QUEUE_FILTER filter = {0}; - filter.DenyList.NumIDs = ArraySize(hideMessages); - filter.DenyList.pIDList = hideMessages; - - infoQueue->AddStorageFilterEntries(&filter); - SafeRelease(infoQueue); - } -#endif - - 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 Renderer11::initializeDevice() -{ - mStateCache.initialize(mDevice); - mInputLayoutCache.initialize(mDevice, mDeviceContext); - - ASSERT(!mVertexDataManager && !mIndexDataManager); - mVertexDataManager = new VertexDataManager(this); - mIndexDataManager = new IndexDataManager(this); - - ASSERT(!mBlit); - mBlit = new Blit11(this); - - ASSERT(!mClear); - mClear = new Clear11(this); - - ASSERT(!mPixelTransfer); - mPixelTransfer = new PixelTransfer11(this); - - const gl::Caps &rendererCaps = getRendererCaps(); - - mForceSetVertexSamplerStates.resize(rendererCaps.maxVertexTextureImageUnits); - mCurVertexSamplerStates.resize(rendererCaps.maxVertexTextureImageUnits); - - mForceSetPixelSamplerStates.resize(rendererCaps.maxTextureImageUnits); - mCurPixelSamplerStates.resize(rendererCaps.maxTextureImageUnits); - - mCurVertexSRVs.resize(rendererCaps.maxVertexTextureImageUnits); - mCurPixelSRVs.resize(rendererCaps.maxTextureImageUnits); - - 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++) - { - const d3d11::DXGIFormat &renderTargetFormatInfo = d3d11::GetDXGIFormatInfo(RenderTargetFormats[formatIndex]); - const gl::TextureCaps &renderTargetFormatCaps = getRendererTextureCaps().get(renderTargetFormatInfo.internalFormat); - if (renderTargetFormatCaps.renderable) - { - for (unsigned int depthStencilIndex = 0; depthStencilIndex < numDepthFormats; depthStencilIndex++) - { - const d3d11::DXGIFormat &depthStencilFormatInfo = d3d11::GetDXGIFormatInfo(DepthStencilFormats[depthStencilIndex]); - const gl::TextureCaps &depthStencilFormatCaps = getRendererTextureCaps().get(depthStencilFormatInfo.internalFormat); - if (depthStencilFormatCaps.renderable || DepthStencilFormats[depthStencilIndex] == DXGI_FORMAT_UNKNOWN) - { - ConfigDesc newConfig; - newConfig.renderTargetFormat = renderTargetFormatInfo.internalFormat; - newConfig.depthStencilFormat = depthStencilFormatInfo.internalFormat; - newConfig.multiSample = 0; // FIXME: enumerate multi-sampling - newConfig.fastConfig = true; // Assume all DX11 format conversions to be fast - newConfig.es3Capable = true; - - (*configDescList)[numConfigs++] = newConfig; - } - } - } - } - - return numConfigs; -} - -void Renderer11::deleteConfigs(ConfigDesc *configDescList) -{ - delete [] (configDescList); -} - -gl::Error 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)); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create event query, result: 0x%X.", result); - } - } - - mDeviceContext->End(mSyncQuery); - mDeviceContext->Flush(); - - do - { - result = mDeviceContext->GetData(mSyncQuery, NULL, 0, D3D11_ASYNC_GETDATA_DONOTFLUSH); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to get event query data, result: 0x%X.", result); - } - - // Keep polling, but allow other threads to do something useful first - Sleep(0); - - if (testDeviceLost(true)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Device was lost while waiting for sync."); - } - } - while (result == S_FALSE); - } - else - { - mDeviceContext->Flush(); - } - - return gl::Error(GL_NO_ERROR); -} - -SwapChain *Renderer11::createSwapChain(NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) -{ - return new SwapChain11(this, nativeWindow, shareHandle, backBufferFormat, depthBufferFormat); -} - -gl::Error Renderer11::generateSwizzle(gl::Texture *texture) -{ - if (texture) - { - TextureD3D *textureD3D = TextureD3D::makeTextureD3D(texture->getImplementation()); - ASSERT(textureD3D); - - TextureStorage *texStorage = textureD3D->getNativeTexture(); - if (texStorage) - { - TextureStorage11 *storage11 = TextureStorage11::makeTextureStorage11(texStorage); - gl::Error error = storage11->generateSwizzles(texture->getSamplerState().swizzleRed, - texture->getSamplerState().swizzleGreen, - texture->getSamplerState().swizzleBlue, - texture->getSamplerState().swizzleAlpha); - if (error.isError()) - { - return error; - } - } - } - - return gl::Error(GL_NO_ERROR); -} - -gl::Error Renderer11::setSamplerState(gl::SamplerType type, int index, gl::Texture *texture, const gl::SamplerState &samplerStateParam) -{ - // Make sure to add the level offset for our tiny compressed texture workaround - TextureD3D *textureD3D = TextureD3D::makeTextureD3D(texture->getImplementation()); - gl::SamplerState samplerStateInternal = samplerStateParam; - samplerStateInternal.baseLevel += textureD3D->getNativeTexture()->getTopLevel(); - - if (type == gl::SAMPLER_PIXEL) - { - ASSERT(static_cast(index) < getRendererCaps().maxTextureImageUnits); - - if (mForceSetPixelSamplerStates[index] || memcmp(&samplerStateInternal, &mCurPixelSamplerStates[index], sizeof(gl::SamplerState)) != 0) - { - ID3D11SamplerState *dxSamplerState = NULL; - gl::Error error = mStateCache.getSamplerState(samplerStateInternal, &dxSamplerState); - if (error.isError()) - { - return error; - } - - ASSERT(dxSamplerState != NULL); - mDeviceContext->PSSetSamplers(index, 1, &dxSamplerState); - - mCurPixelSamplerStates[index] = samplerStateInternal; - } - - mForceSetPixelSamplerStates[index] = false; - } - else if (type == gl::SAMPLER_VERTEX) - { - ASSERT(static_cast(index) < getRendererCaps().maxVertexTextureImageUnits); - - if (mForceSetVertexSamplerStates[index] || memcmp(&samplerStateInternal, &mCurVertexSamplerStates[index], sizeof(gl::SamplerState)) != 0) - { - ID3D11SamplerState *dxSamplerState = NULL; - gl::Error error = mStateCache.getSamplerState(samplerStateInternal, &dxSamplerState); - if (error.isError()) - { - return error; - } - - ASSERT(dxSamplerState != NULL); - mDeviceContext->VSSetSamplers(index, 1, &dxSamplerState); - - mCurVertexSamplerStates[index] = samplerStateInternal; - } - - mForceSetVertexSamplerStates[index] = false; - } - else UNREACHABLE(); - - return gl::Error(GL_NO_ERROR); -} - -gl::Error Renderer11::setTexture(gl::SamplerType type, int index, gl::Texture *texture) -{ - ID3D11ShaderResourceView *textureSRV = NULL; - - if (texture) - { - TextureD3D *textureImpl = TextureD3D::makeTextureD3D(texture->getImplementation()); - TextureStorage *texStorage = textureImpl->getNativeTexture(); - ASSERT(texStorage != NULL); - - TextureStorage11 *storage11 = TextureStorage11::makeTextureStorage11(texStorage); - - // Make sure to add the level offset for our tiny compressed texture workaround - gl::SamplerState samplerState = texture->getSamplerState(); - samplerState.baseLevel += storage11->getTopLevel(); - - gl::Error error = storage11->getSRV(samplerState, &textureSRV); - if (error.isError()) - { - return error; - } - - // 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); - - textureImpl->resetDirty(); - } - - ASSERT((type == gl::SAMPLER_PIXEL && static_cast(index) < getRendererCaps().maxTextureImageUnits) || - (type == gl::SAMPLER_VERTEX && static_cast(index) < getRendererCaps().maxVertexTextureImageUnits)); - - setShaderResource(type, index, textureSRV); - - return gl::Error(GL_NO_ERROR); -} - -gl::Error Renderer11::setUniformBuffers(const gl::Buffer *vertexUniformBuffers[], const gl::Buffer *fragmentUniformBuffers[]) -{ - for (unsigned int uniformBufferIndex = 0; uniformBufferIndex < gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS; uniformBufferIndex++) - { - const gl::Buffer *uniformBuffer = vertexUniformBuffers[uniformBufferIndex]; - if (uniformBuffer) - { - Buffer11 *bufferStorage = Buffer11::makeBuffer11(uniformBuffer->getImplementation()); - ID3D11Buffer *constantBuffer = bufferStorage->getBuffer(BUFFER_USAGE_UNIFORM); - - if (!constantBuffer) - { - return gl::Error(GL_OUT_OF_MEMORY); - } - - if (mCurrentConstantBufferVS[uniformBufferIndex] != bufferStorage->getSerial()) - { - mDeviceContext->VSSetConstantBuffers(getReservedVertexUniformBuffers() + uniformBufferIndex, - 1, &constantBuffer); - mCurrentConstantBufferVS[uniformBufferIndex] = bufferStorage->getSerial(); - } - } - } - - for (unsigned int uniformBufferIndex = 0; uniformBufferIndex < gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS; uniformBufferIndex++) - { - const gl::Buffer *uniformBuffer = fragmentUniformBuffers[uniformBufferIndex]; - if (uniformBuffer) - { - Buffer11 *bufferStorage = Buffer11::makeBuffer11(uniformBuffer->getImplementation()); - ID3D11Buffer *constantBuffer = bufferStorage->getBuffer(BUFFER_USAGE_UNIFORM); - - if (!constantBuffer) - { - return gl::Error(GL_OUT_OF_MEMORY); - } - - if (mCurrentConstantBufferPS[uniformBufferIndex] != bufferStorage->getSerial()) - { - mDeviceContext->PSSetConstantBuffers(getReservedFragmentUniformBuffers() + uniformBufferIndex, - 1, &constantBuffer); - mCurrentConstantBufferPS[uniformBufferIndex] = bufferStorage->getSerial(); - } - } - } - - return gl::Error(GL_NO_ERROR); -} - -gl::Error Renderer11::setRasterizerState(const gl::RasterizerState &rasterState) -{ - if (mForceSetRasterState || memcmp(&rasterState, &mCurRasterState, sizeof(gl::RasterizerState)) != 0) - { - ID3D11RasterizerState *dxRasterState = NULL; - gl::Error error = mStateCache.getRasterizerState(rasterState, mScissorEnabled, &dxRasterState); - if (error.isError()) - { - return error; - } - - mDeviceContext->RSSetState(dxRasterState); - - mCurRasterState = rasterState; - } - - mForceSetRasterState = false; - - return gl::Error(GL_NO_ERROR); -} - -gl::Error Renderer11::setBlendState(const gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::ColorF &blendColor, - unsigned int sampleMask) -{ - if (mForceSetBlendState || - memcmp(&blendState, &mCurBlendState, sizeof(gl::BlendState)) != 0 || - memcmp(&blendColor, &mCurBlendColor, sizeof(gl::ColorF)) != 0 || - sampleMask != mCurSampleMask) - { - ID3D11BlendState *dxBlendState = NULL; - gl::Error error = mStateCache.getBlendState(framebuffer, blendState, &dxBlendState); - if (error.isError()) - { - return error; - } - - ASSERT(dxBlendState != NULL); - - float blendColors[4] = {0.0f}; - if (blendState.sourceBlendRGB != GL_CONSTANT_ALPHA && blendState.sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA && - blendState.destBlendRGB != GL_CONSTANT_ALPHA && blendState.destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA) - { - blendColors[0] = blendColor.red; - blendColors[1] = blendColor.green; - blendColors[2] = blendColor.blue; - blendColors[3] = blendColor.alpha; - } - else - { - blendColors[0] = blendColor.alpha; - blendColors[1] = blendColor.alpha; - blendColors[2] = blendColor.alpha; - blendColors[3] = blendColor.alpha; - } - - mDeviceContext->OMSetBlendState(dxBlendState, blendColors, sampleMask); - - mCurBlendState = blendState; - mCurBlendColor = blendColor; - mCurSampleMask = sampleMask; - } - - mForceSetBlendState = false; - - return gl::Error(GL_NO_ERROR); -} - -gl::Error 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) - { - ASSERT(depthStencilState.stencilWritemask == depthStencilState.stencilBackWritemask); - ASSERT(stencilRef == stencilBackRef); - ASSERT(depthStencilState.stencilMask == depthStencilState.stencilBackMask); - - ID3D11DepthStencilState *dxDepthStencilState = NULL; - gl::Error error = mStateCache.getDepthStencilState(depthStencilState, &dxDepthStencilState); - if (error.isError()) - { - return error; - } - - ASSERT(dxDepthStencilState); - - // Max D3D11 stencil reference value is 0xFF, corresponding to the max 8 bits in a stencil buffer - // GL specifies we should clamp the ref value to the nearest bit depth when doing stencil ops - META_ASSERT(D3D11_DEFAULT_STENCIL_READ_MASK == 0xFF); - META_ASSERT(D3D11_DEFAULT_STENCIL_WRITE_MASK == 0xFF); - UINT dxStencilRef = std::min(stencilRef, 0xFFu); - - mDeviceContext->OMSetDepthStencilState(dxDepthStencilState, dxStencilRef); - - mCurDepthStencilState = depthStencilState; - mCurStencilRef = stencilRef; - mCurStencilBackRef = stencilBackRef; - } - - mForceSetDepthStencilState = false; - - return gl::Error(GL_NO_ERROR); -} - -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; -} - -void 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; - } - - const gl::Caps& caps = getRendererCaps(); - - // 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, -static_cast(caps.maxViewportWidth), static_cast(caps.maxViewportWidth)); - dxViewport.TopLeftY = gl::clamp(actualViewport.y, -static_cast(caps.maxViewportHeight), static_cast(caps.maxViewportHeight)); - dxViewport.Width = gl::clamp(actualViewport.width, 0, static_cast(caps.maxViewportWidth - dxViewport.TopLeftX)); - dxViewport.Height = gl::clamp(actualViewport.height, 0, static_cast(caps.maxViewportHeight - dxViewport.TopLeftY)); - dxViewport.MinDepth = actualZNear; - dxViewport.MaxDepth = actualZFar; - - 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; -} - -bool Renderer11::applyPrimitiveType(GLenum mode, GLsizei count) -{ - D3D11_PRIMITIVE_TOPOLOGY primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED; - - GLsizei minCount = 0; - - switch (mode) - { - case GL_POINTS: primitiveTopology = D3D11_PRIMITIVE_TOPOLOGY_POINTLIST; minCount = 1; break; - case GL_LINES: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINELIST; minCount = 2; break; - case GL_LINE_LOOP: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP; minCount = 2; break; - case GL_LINE_STRIP: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP; minCount = 2; break; - case GL_TRIANGLES: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; minCount = 3; break; - case GL_TRIANGLE_STRIP: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP; minCount = 3; break; - // emulate fans via rewriting index buffer - case GL_TRIANGLE_FAN: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; minCount = 3; break; - default: - UNREACHABLE(); - return false; - } - - if (primitiveTopology != mCurrentPrimitiveTopology) - { - mDeviceContext->IASetPrimitiveTopology(primitiveTopology); - mCurrentPrimitiveTopology = primitiveTopology; - } - - return count >= minCount; -} - -void Renderer11::unsetSRVsWithResource(gl::SamplerType samplerType, const ID3D11Resource *resource) -{ - std::vector ¤tSRVs = (samplerType == gl::SAMPLER_VERTEX ? mCurVertexSRVs : mCurPixelSRVs); - - for (size_t resourceIndex = 0; resourceIndex < currentSRVs.size(); ++resourceIndex) - { - ID3D11ShaderResourceView *srv = currentSRVs[resourceIndex]; - - if (srv && GetSRVResource(srv) == resource) - { - setShaderResource(samplerType, static_cast(resourceIndex), NULL); - } - } -} - -gl::Error Renderer11::applyRenderTarget(const 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; - - const gl::ColorbufferInfo &colorbuffers = framebuffer->getColorbuffersForRender(getWorkarounds()); - - for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment) - { - gl::FramebufferAttachment *colorbuffer = colorbuffers[colorAttachment]; - - if (colorbuffer) - { - // the draw buffer must be either "none", "back" for the default buffer or the same index as this color (in order) - - // 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 gl::Error(GL_NO_ERROR); - } - - renderTargetSerials[colorAttachment] = GetAttachmentSerial(colorbuffer); - - // Extract the render target dimensions and view - RenderTarget11 *renderTarget = NULL; - gl::Error error = d3d11::GetAttachmentRenderTarget(colorbuffer, &renderTarget); - if (error.isError()) - { - return error; - } - ASSERT(renderTarget); - - framebufferRTVs[colorAttachment] = renderTarget->getRenderTargetView(); - ASSERT(framebufferRTVs[colorAttachment]); - - if (missingColorRenderTarget) - { - renderTargetWidth = colorbuffer->getWidth(); - renderTargetHeight = colorbuffer->getHeight(); - renderTargetFormat = colorbuffer->getActualFormat(); - missingColorRenderTarget = false; - } - -#if !defined(NDEBUG) - // Unbind render target SRVs from the shader here to prevent D3D11 warnings. - ID3D11Resource *renderTargetResource = renderTarget->getTexture(); - unsetSRVsWithResource(gl::SAMPLER_VERTEX, renderTargetResource); - unsetSRVsWithResource(gl::SAMPLER_PIXEL, renderTargetResource); -#endif - } - } - - // Get the depth stencil render buffter and serials - gl::FramebufferAttachment *depthStencil = framebuffer->getDepthbuffer(); - unsigned int depthbufferSerial = 0; - unsigned int stencilbufferSerial = 0; - if (depthStencil) - { - depthbufferSerial = GetAttachmentSerial(depthStencil); - } - else if (framebuffer->getStencilbuffer()) - { - depthStencil = framebuffer->getStencilbuffer(); - stencilbufferSerial = GetAttachmentSerial(depthStencil); - } - - ID3D11DepthStencilView* framebufferDSV = NULL; - if (depthStencil) - { - RenderTarget11 *depthStencilRenderTarget = NULL; - gl::Error error = d3d11::GetAttachmentRenderTarget(depthStencil, &depthStencilRenderTarget); - if (error.isError()) - { - SafeRelease(framebufferRTVs); - return error; - } - ASSERT(depthStencilRenderTarget); - - framebufferDSV = depthStencilRenderTarget->getDepthStencilView(); - ASSERT(framebufferDSV); - - // 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(); - } - } - - // Apply the render target and depth stencil - if (!mRenderTargetDescInitialized || !mDepthStencilInitialized || - memcmp(renderTargetSerials, mAppliedRenderTargetSerials, sizeof(renderTargetSerials)) != 0 || - depthbufferSerial != mAppliedDepthbufferSerial || - stencilbufferSerial != mAppliedStencilbufferSerial) - { - mDeviceContext->OMSetRenderTargets(getRendererCaps().maxDrawBuffers, framebufferRTVs, framebufferDSV); - - mRenderTargetDesc.width = renderTargetWidth; - mRenderTargetDesc.height = renderTargetHeight; - mRenderTargetDesc.format = renderTargetFormat; - mForceSetViewport = true; - mForceSetScissor = true; - mForceSetBlendState = true; - - if (!mDepthStencilInitialized) - { - mForceSetRasterState = true; - } - - for (unsigned int rtIndex = 0; rtIndex < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; rtIndex++) - { - mAppliedRenderTargetSerials[rtIndex] = renderTargetSerials[rtIndex]; - } - mAppliedDepthbufferSerial = depthbufferSerial; - mAppliedStencilbufferSerial = stencilbufferSerial; - mRenderTargetDescInitialized = true; - mDepthStencilInitialized = true; - } - - invalidateFramebufferSwizzles(framebuffer); - - return gl::Error(GL_NO_ERROR); -} - -gl::Error Renderer11::applyVertexBuffer(const gl::State &state, GLint first, GLsizei count, GLsizei instances) -{ - TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS]; - gl::Error error = mVertexDataManager->prepareVertexData(state, first, count, attributes, instances); - if (error.isError()) - { - return error; - } - - return mInputLayoutCache.applyVertexBuffers(attributes, state.getCurrentProgramBinary()); -} - -gl::Error Renderer11::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo) -{ - gl::Error error = mIndexDataManager->prepareIndexData(type, count, elementArrayBuffer, indices, indexInfo); - if (error.isError()) - { - return error; - } - - ID3D11Buffer *buffer = NULL; - DXGI_FORMAT bufferFormat = (indexInfo->indexType == GL_UNSIGNED_INT) ? DXGI_FORMAT_R32_UINT : DXGI_FORMAT_R16_UINT; - - if (indexInfo->storage) - { - Buffer11 *storage = Buffer11::makeBuffer11(indexInfo->storage); - buffer = storage->getBuffer(BUFFER_USAGE_INDEX); - } - else - { - IndexBuffer11* indexBuffer = IndexBuffer11::makeIndexBuffer11(indexInfo->indexBuffer); - buffer = indexBuffer->getBuffer(); - } - - if (buffer != mAppliedIB || bufferFormat != mAppliedIBFormat || indexInfo->startOffset != mAppliedIBOffset) - { - mDeviceContext->IASetIndexBuffer(buffer, bufferFormat, indexInfo->startOffset); - - mAppliedIB = buffer; - mAppliedIBFormat = bufferFormat; - mAppliedIBOffset = indexInfo->startOffset; - } - - return gl::Error(GL_NO_ERROR); -} - -void Renderer11::applyTransformFeedbackBuffers(const gl::State& state) -{ - size_t numXFBBindings = state.getTransformFeedbackBufferIndexRange(); - ASSERT(numXFBBindings <= gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS); - - bool requiresUpdate = false; - for (size_t i = 0; i < numXFBBindings; i++) - { - gl::Buffer *curXFBBuffer = state.getIndexedTransformFeedbackBuffer(i); - GLintptr curXFBOffset = state.getIndexedTransformFeedbackBufferOffset(i); - ID3D11Buffer *d3dBuffer = NULL; - if (curXFBBuffer) - { - Buffer11 *storage = Buffer11::makeBuffer11(curXFBBuffer->getImplementation()); - d3dBuffer = storage->getBuffer(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK); - } - - // TODO: mAppliedTFBuffers and friends should also be kept in a vector. - if (d3dBuffer != mAppliedTFBuffers[i] || curXFBOffset != mAppliedTFOffsets[i]) - { - requiresUpdate = true; - } - } - - if (requiresUpdate) - { - for (size_t i = 0; i < numXFBBindings; ++i) - { - gl::Buffer *curXFBBuffer = state.getIndexedTransformFeedbackBuffer(i); - GLintptr curXFBOffset = state.getIndexedTransformFeedbackBufferOffset(i); - - if (curXFBBuffer) - { - Buffer11 *storage = Buffer11::makeBuffer11(curXFBBuffer->getImplementation()); - ID3D11Buffer *d3dBuffer = storage->getBuffer(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK); - - mCurrentD3DOffsets[i] = (mAppliedTFBuffers[i] != d3dBuffer && mAppliedTFOffsets[i] != curXFBOffset) ? - static_cast(curXFBOffset) : -1; - mAppliedTFBuffers[i] = d3dBuffer; - } - else - { - mAppliedTFBuffers[i] = NULL; - mCurrentD3DOffsets[i] = 0; - } - mAppliedTFOffsets[i] = curXFBOffset; - } - - mDeviceContext->SOSetTargets(numXFBBindings, mAppliedTFBuffers, mCurrentD3DOffsets); - } -} - -gl::Error Renderer11::drawArrays(GLenum mode, GLsizei count, GLsizei instances, bool transformFeedbackActive) -{ - if (mode == GL_POINTS && transformFeedbackActive) - { - // Since point sprites are generated with a geometry shader, too many vertices will - // be written if transform feedback is active. To work around this, draw only the points - // with the stream out shader and no pixel shader to feed the stream out buffers and then - // draw again with the point sprite geometry shader to rasterize the point sprites. - - mDeviceContext->PSSetShader(NULL, NULL, 0); - - if (instances > 0) - { - mDeviceContext->DrawInstanced(count, instances, 0, 0); - } - else - { - mDeviceContext->Draw(count, 0); - } - - mDeviceContext->GSSetShader(mCurPointGeometryShader, NULL, 0); - mDeviceContext->PSSetShader(mAppliedPixelShader, NULL, 0); - - if (instances > 0) - { - mDeviceContext->DrawInstanced(count, instances, 0, 0); - } - else - { - mDeviceContext->Draw(count, 0); - } - - mDeviceContext->GSSetShader(mAppliedGeometryShader, NULL, 0); - - return gl::Error(GL_NO_ERROR); - } - else if (mode == GL_LINE_LOOP) - { - return drawLineLoop(count, GL_NONE, NULL, 0, NULL); - } - else if (mode == GL_TRIANGLE_FAN) - { - return drawTriangleFan(count, GL_NONE, NULL, 0, NULL, instances); - } - else if (instances > 0) - { - mDeviceContext->DrawInstanced(count, instances, 0, 0); - return gl::Error(GL_NO_ERROR); - } - else - { - mDeviceContext->Draw(count, 0); - return gl::Error(GL_NO_ERROR); - } -} - -gl::Error Renderer11::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, - gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances) -{ - int minIndex = static_cast(indexInfo.indexRange.start); - - if (mode == GL_LINE_LOOP) - { - return drawLineLoop(count, type, indices, minIndex, elementArrayBuffer); - } - else if (mode == GL_TRIANGLE_FAN) - { - return drawTriangleFan(count, type, indices, minIndex, elementArrayBuffer, instances); - } - else if (instances > 0) - { - mDeviceContext->DrawIndexedInstanced(count, instances, 0, -minIndex, 0); - return gl::Error(GL_NO_ERROR); - } - else - { - mDeviceContext->DrawIndexed(count, 0, -minIndex); - return gl::Error(GL_NO_ERROR); - } -} -template -static void fillLineLoopIndices(GLenum type, GLsizei count, const GLvoid *indices, T *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(); - } -} - -template -static void fillTriangleFanIndices(GLenum type, unsigned int numTris, const GLvoid *indices, T *data) -{ - switch (type) - { - case GL_NONE: // Non-indexed draw - for (unsigned int i = 0; i < numTris; i++) - { - data[i*3 + 0] = 0; - data[i*3 + 1] = i + 1; - data[i*3 + 2] = i + 2; - } - break; - case GL_UNSIGNED_BYTE: - for (unsigned int i = 0; i < numTris; i++) - { - data[i*3 + 0] = static_cast(indices)[0]; - data[i*3 + 1] = static_cast(indices)[i + 1]; - data[i*3 + 2] = static_cast(indices)[i + 2]; - } - break; - case GL_UNSIGNED_SHORT: - for (unsigned int i = 0; i < numTris; i++) - { - data[i*3 + 0] = static_cast(indices)[0]; - data[i*3 + 1] = static_cast(indices)[i + 1]; - data[i*3 + 2] = static_cast(indices)[i + 2]; - } - break; - case GL_UNSIGNED_INT: - for (unsigned int i = 0; i < numTris; i++) - { - data[i*3 + 0] = static_cast(indices)[0]; - data[i*3 + 1] = static_cast(indices)[i + 1]; - data[i*3 + 2] = static_cast(indices)[i + 2]; - } - break; - default: UNREACHABLE(); - } -} - -gl::Error 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) - { - BufferD3D *storage = BufferD3D::makeFromBuffer(elementArrayBuffer); - intptr_t offset = reinterpret_cast(indices); - - const uint8_t *bufferData = NULL; - gl::Error error = storage->getData(&bufferData); - if (error.isError()) - { - return error; - } - - indices = bufferData + offset; - } - - // TODO: some level 9 hardware supports 32-bit indices; test and store support instead - const int indexType = isLevel9() ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT; - - if (!mLineLoopIB) - { - mLineLoopIB = new StreamingIndexBufferInterface(this); - gl::Error error = mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, indexType); - if (error.isError()) - { - SafeDelete(mLineLoopIB); - return error; - } - } - - // Checked by Renderer11::applyPrimitiveType - ASSERT(count >= 0); - - int indexTypeSize = indexType == GL_UNSIGNED_SHORT ? sizeof(unsigned short) : sizeof(unsigned int); - if (static_cast(count) + 1 > (std::numeric_limits::max() / indexTypeSize)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create a 32-bit looping index buffer for GL_LINE_LOOP, too many indices required."); - } - - const unsigned int spaceNeeded = (static_cast(count) + 1) * sizeof(unsigned int); - gl::Error error = mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT); - if (error.isError()) - { - return error; - } - - void* mappedMemory = NULL; - unsigned int offset; - error = mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset); - if (error.isError()) - { - return error; - } - - if (indexType == GL_UNSIGNED_SHORT) - fillLineLoopIndices(type, count, indices, reinterpret_cast(mappedMemory)); - else - fillLineLoopIndices(type, count, indices, reinterpret_cast(mappedMemory)); - unsigned int indexBufferOffset = offset; - - error = mLineLoopIB->unmapBuffer(); - if (error.isError()) - { - return error; - } - - IndexBuffer11 *indexBuffer = IndexBuffer11::makeIndexBuffer11(mLineLoopIB->getIndexBuffer()); - ID3D11Buffer *d3dIndexBuffer = indexBuffer->getBuffer(); - DXGI_FORMAT indexFormat = indexBuffer->getIndexFormat(); - - if (mAppliedIB != d3dIndexBuffer || mAppliedIBFormat != indexFormat || mAppliedIBOffset != indexBufferOffset) - { - mDeviceContext->IASetIndexBuffer(d3dIndexBuffer, indexFormat, indexBufferOffset); - mAppliedIB = d3dIndexBuffer; - mAppliedIBFormat = indexFormat; - mAppliedIBOffset = indexBufferOffset; - } - - mDeviceContext->DrawIndexed(count + 1, 0, -minIndex); - - return gl::Error(GL_NO_ERROR); -} - -gl::Error 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) - { - BufferD3D *storage = BufferD3D::makeFromBuffer(elementArrayBuffer); - intptr_t offset = reinterpret_cast(indices); - - const uint8_t *bufferData = NULL; - gl::Error error = storage->getData(&bufferData); - if (error.isError()) - { - return error; - } - - indices = bufferData + offset; - } - - const int indexType = isLevel9() ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT; - - if (!mTriangleFanIB) - { - mTriangleFanIB = new StreamingIndexBufferInterface(this); - gl::Error error = mTriangleFanIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, indexType); - if (error.isError()) - { - SafeDelete(mTriangleFanIB); - return error; - } - } - - // Checked by Renderer11::applyPrimitiveType - ASSERT(count >= 3); - - const unsigned int numTris = count - 2; - - int indexTypeSize = indexType == GL_UNSIGNED_SHORT ? sizeof(unsigned short) : sizeof(unsigned int); - if (numTris > (std::numeric_limits::max() / (indexTypeSize * 3))) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create a scratch index buffer for GL_TRIANGLE_FAN, too many indices required."); - } - - const unsigned int spaceNeeded = (numTris * 3) * indexTypeSize; - gl::Error error = mTriangleFanIB->reserveBufferSpace(spaceNeeded, indexType); - if (error.isError()) - { - return error; - } - - void* mappedMemory = NULL; - unsigned int offset; - error = mTriangleFanIB->mapBuffer(spaceNeeded, &mappedMemory, &offset); - if (error.isError()) - { - return error; - } - - if (indexType == GL_UNSIGNED_SHORT) - fillTriangleFanIndices(type, numTris, indices, reinterpret_cast(mappedMemory)); - else - fillTriangleFanIndices(type, numTris, indices, reinterpret_cast(mappedMemory)); - - unsigned int indexBufferOffset = offset; - - error = mTriangleFanIB->unmapBuffer(); - if (error.isError()) - { - return error; - } - - IndexBuffer11 *indexBuffer = IndexBuffer11::makeIndexBuffer11(mTriangleFanIB->getIndexBuffer()); - ID3D11Buffer *d3dIndexBuffer = indexBuffer->getBuffer(); - DXGI_FORMAT indexFormat = indexBuffer->getIndexFormat(); - - if (mAppliedIB != d3dIndexBuffer || mAppliedIBFormat != indexFormat || mAppliedIBOffset != indexBufferOffset) - { - mDeviceContext->IASetIndexBuffer(d3dIndexBuffer, indexFormat, indexBufferOffset); - mAppliedIB = d3dIndexBuffer; - mAppliedIBFormat = indexFormat; - mAppliedIBOffset = indexBufferOffset; - } - - if (instances > 0) - { - mDeviceContext->DrawIndexedInstanced(numTris * 3, instances, 0, -minIndex, 0); - } - else - { - mDeviceContext->DrawIndexed(numTris * 3, 0, -minIndex); - } - - return gl::Error(GL_NO_ERROR); -} - -gl::Error Renderer11::applyShaders(gl::ProgramBinary *programBinary, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer, - bool rasterizerDiscard, bool transformFeedbackActive) -{ - ProgramD3D *programD3D = ProgramD3D::makeProgramD3D(programBinary->getImplementation()); - - ShaderExecutable *vertexExe = NULL; - gl::Error error = programD3D->getVertexExecutableForInputLayout(inputLayout, &vertexExe); - if (error.isError()) - { - return error; - } - - ShaderExecutable *pixelExe = NULL; - error = programD3D->getPixelExecutableForFramebuffer(framebuffer, &pixelExe); - if (error.isError()) - { - return error; - } - - ShaderExecutable *geometryExe = programD3D->getGeometryExecutable(); - - ID3D11VertexShader *vertexShader = (vertexExe ? ShaderExecutable11::makeShaderExecutable11(vertexExe)->getVertexShader() : NULL); - - ID3D11PixelShader *pixelShader = NULL; - // Skip pixel shader if we're doing rasterizer discard. - if (!rasterizerDiscard) - { - pixelShader = (pixelExe ? ShaderExecutable11::makeShaderExecutable11(pixelExe)->getPixelShader() : NULL); - } - - ID3D11GeometryShader *geometryShader = NULL; - if (transformFeedbackActive) - { - geometryShader = (vertexExe ? ShaderExecutable11::makeShaderExecutable11(vertexExe)->getStreamOutShader() : NULL); - } - else if (mCurRasterState.pointDrawMode) - { - geometryShader = (geometryExe ? ShaderExecutable11::makeShaderExecutable11(geometryExe)->getGeometryShader() : NULL); - } - - bool dirtyUniforms = false; - - if (vertexShader != mAppliedVertexShader) - { - mDeviceContext->VSSetShader(vertexShader, NULL, 0); - mAppliedVertexShader = vertexShader; - dirtyUniforms = true; - } - - if (geometryShader != mAppliedGeometryShader) - { - mDeviceContext->GSSetShader(geometryShader, NULL, 0); - mAppliedGeometryShader = geometryShader; - dirtyUniforms = true; - } - - if (geometryExe && mCurRasterState.pointDrawMode) - { - mCurPointGeometryShader = ShaderExecutable11::makeShaderExecutable11(geometryExe)->getGeometryShader(); - } - else - { - mCurPointGeometryShader = NULL; - } - - if (pixelShader != mAppliedPixelShader) - { - mDeviceContext->PSSetShader(pixelShader, NULL, 0); - mAppliedPixelShader = pixelShader; - dirtyUniforms = true; - } - - if (dirtyUniforms) - { - programD3D->dirtyAllUniforms(); - } - - return gl::Error(GL_NO_ERROR); -} - -gl::Error Renderer11::applyUniforms(const ProgramImpl &program, const std::vector &uniformArray) -{ - unsigned int totalRegisterCountVS = 0; - unsigned int totalRegisterCountPS = 0; - - bool vertexUniformsDirty = false; - bool pixelUniformsDirty = false; - - for (size_t uniformIndex = 0; uniformIndex < uniformArray.size(); uniformIndex++) - { - const gl::LinkedUniform &uniform = *uniformArray[uniformIndex]; - - if (uniform.isReferencedByVertexShader() && !uniform.isSampler()) - { - totalRegisterCountVS += uniform.registerCount; - vertexUniformsDirty = (vertexUniformsDirty || uniform.dirty); - } - - if (uniform.isReferencedByFragmentShader() && !uniform.isSampler()) - { - totalRegisterCountPS += uniform.registerCount; - pixelUniformsDirty = (pixelUniformsDirty || uniform.dirty); - } - } - - const ProgramD3D *programD3D = ProgramD3D::makeProgramD3D(&program); - const UniformStorage11 *vertexUniformStorage = UniformStorage11::makeUniformStorage11(&programD3D->getVertexUniformStorage()); - const UniformStorage11 *fragmentUniformStorage = UniformStorage11::makeUniformStorage11(&programD3D->getFragmentUniformStorage()); - ASSERT(vertexUniformStorage); - ASSERT(fragmentUniformStorage); - - ID3D11Buffer *vertexConstantBuffer = vertexUniformStorage->getConstantBuffer(); - ID3D11Buffer *pixelConstantBuffer = fragmentUniformStorage->getConstantBuffer(); - - 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); - UNUSED_ASSERTION_VARIABLE(result); - 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); - UNUSED_ASSERTION_VARIABLE(result); - ASSERT(SUCCEEDED(result)); - mapPS = (float(*)[4])map.pData; - } - - for (size_t uniformIndex = 0; uniformIndex < uniformArray.size(); uniformIndex++) - { - gl::LinkedUniform *uniform = uniformArray[uniformIndex]; - - if (!uniform->isSampler()) - { - unsigned int componentCount = (4 - uniform->registerElement); - - // we assume that uniforms from structs are arranged in struct order in our uniforms list. otherwise we would - // overwrite previously written regions of memory. - - if (uniform->isReferencedByVertexShader() && mapVS) - { - memcpy(&mapVS[uniform->vsRegisterIndex][uniform->registerElement], uniform->data, uniform->registerCount * sizeof(float) * componentCount); - } - - if (uniform->isReferencedByFragmentShader() && mapPS) - { - memcpy(&mapPS[uniform->psRegisterIndex][uniform->registerElement], uniform->data, uniform->registerCount * sizeof(float) * componentCount); - } - } - } - - if (mapVS) - { - mDeviceContext->Unmap(vertexConstantBuffer, 0); - } - - if (mapPS) - { - mDeviceContext->Unmap(pixelConstantBuffer, 0); - } - - if (mCurrentVertexConstantBuffer != vertexConstantBuffer) - { - mDeviceContext->VSSetConstantBuffers(0, 1, &vertexConstantBuffer); - mCurrentVertexConstantBuffer = vertexConstantBuffer; - } - - if (mCurrentPixelConstantBuffer != pixelConstantBuffer) - { - mDeviceContext->PSSetConstantBuffers(0, 1, &pixelConstantBuffer); - mCurrentPixelConstantBuffer = pixelConstantBuffer; - } - - // Driver uniforms - if (!mDriverConstantBufferVS) - { - D3D11_BUFFER_DESC constantBufferDescription = {0}; - constantBufferDescription.ByteWidth = sizeof(dx_VertexConstants); - constantBufferDescription.Usage = D3D11_USAGE_DEFAULT; - constantBufferDescription.BindFlags = D3D11_BIND_CONSTANT_BUFFER; - constantBufferDescription.CPUAccessFlags = 0; - constantBufferDescription.MiscFlags = 0; - constantBufferDescription.StructureByteStride = 0; - - HRESULT result = mDevice->CreateBuffer(&constantBufferDescription, NULL, &mDriverConstantBufferVS); - UNUSED_ASSERTION_VARIABLE(result); - 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); - UNUSED_ASSERTION_VARIABLE(result); - ASSERT(SUCCEEDED(result)); - - mDeviceContext->PSSetConstantBuffers(1, 1, &mDriverConstantBufferPS); - } - - if (memcmp(&mVertexConstants, &mAppliedVertexConstants, sizeof(dx_VertexConstants)) != 0) - { - mDeviceContext->UpdateSubresource(mDriverConstantBufferVS, 0, NULL, &mVertexConstants, 16, 0); - memcpy(&mAppliedVertexConstants, &mVertexConstants, sizeof(dx_VertexConstants)); - } - - if (memcmp(&mPixelConstants, &mAppliedPixelConstants, sizeof(dx_PixelConstants)) != 0) - { - mDeviceContext->UpdateSubresource(mDriverConstantBufferPS, 0, NULL, &mPixelConstants, 16, 0); - memcpy(&mAppliedPixelConstants, &mPixelConstants, sizeof(dx_PixelConstants)); - } - - // needed for the point sprite geometry shader - if (mFeatureLevel >= D3D_FEATURE_LEVEL_10_0 && mCurrentGeometryConstantBuffer != mDriverConstantBufferPS) - { - mDeviceContext->GSSetConstantBuffers(0, 1, &mDriverConstantBufferPS); - mCurrentGeometryConstantBuffer = mDriverConstantBufferPS; - } - - return gl::Error(GL_NO_ERROR); -} - -gl::Error Renderer11::clear(const gl::ClearParameters &clearParams, const gl::Framebuffer *frameBuffer) -{ - gl::Error error = mClear->clearFramebuffer(clearParams, frameBuffer); - if (error.isError()) - { - return error; - } - - invalidateFramebufferSwizzles(frameBuffer); - - return gl::Error(GL_NO_ERROR); -} - -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; - - ASSERT(mForceSetVertexSamplerStates.size() == mCurVertexSRVs.size()); - for (size_t vsamplerId = 0; vsamplerId < mForceSetVertexSamplerStates.size(); ++vsamplerId) - { - mForceSetVertexSamplerStates[vsamplerId] = true; - } - - ASSERT(mForceSetPixelSamplerStates.size() == mCurPixelSRVs.size()); - for (size_t fsamplerId = 0; fsamplerId < mForceSetPixelSamplerStates.size(); ++fsamplerId) - { - mForceSetPixelSamplerStates[fsamplerId] = true; - } - - mForceSetBlendState = true; - mForceSetRasterState = true; - mForceSetDepthStencilState = true; - mForceSetScissor = true; - mForceSetViewport = true; - - mAppliedIB = NULL; - mAppliedIBFormat = DXGI_FORMAT_UNKNOWN; - mAppliedIBOffset = 0; - - mAppliedVertexShader = NULL; - mAppliedGeometryShader = NULL; - mCurPointGeometryShader = NULL; - mAppliedPixelShader = NULL; - - for (size_t i = 0; i < gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS; i++) - { - mAppliedTFBuffers[i] = NULL; - mAppliedTFOffsets[i] = 0; - } - - memset(&mAppliedVertexConstants, 0, sizeof(dx_VertexConstants)); - memset(&mAppliedPixelConstants, 0, sizeof(dx_PixelConstants)); - - mInputLayoutCache.markDirty(); - - for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS; i++) - { - mCurrentConstantBufferVS[i] = -1; - mCurrentConstantBufferPS[i] = -1; - } - - mCurrentVertexConstantBuffer = NULL; - mCurrentPixelConstantBuffer = NULL; - mCurrentGeometryConstantBuffer = NULL; - - mCurrentPrimitiveTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED; -} - -void Renderer11::releaseDeviceResources() -{ - mStateCache.clear(); - mInputLayoutCache.clear(); - - SafeDelete(mVertexDataManager); - SafeDelete(mIndexDataManager); - SafeDelete(mLineLoopIB); - SafeDelete(mTriangleFanIB); - SafeDelete(mBlit); - SafeDelete(mClear); - SafeDelete(mPixelTransfer); - - SafeRelease(mDriverConstantBufferVS); - SafeRelease(mDriverConstantBufferPS); - SafeRelease(mSyncQuery); -} - -void Renderer11::notifyDeviceLost() -{ - mDeviceLost = true; - mDisplay->notifyDeviceLost(); -} - -bool Renderer11::isDeviceLost() -{ - return mDeviceLost; -} - -// set notify to true to broadcast a message to all contexts of the device loss -bool Renderer11::testDeviceLost(bool notify) -{ - bool isLost = false; - - // GetRemovedReason is used to test if the device is removed - HRESULT result = mDevice->GetDeviceRemovedReason(); - isLost = d3d11::isDeviceLostError(result); - - if (isLost) - { - // Log error if this is a new device lost event - if (mDeviceLost == false) - { - ERR("The D3D11 device was removed: 0x%08X", result); - } - - // ensure we note the device loss -- - // we'll probably get this done again by notifyDeviceLost - // but best to remember it! - // Note that we don't want to clear the device loss status here - // -- this needs to be done by resetDevice - mDeviceLost = true; - if (notify) - { - notifyDeviceLost(); - } - } - - return isLost; -} - -bool Renderer11::testDeviceResettable() -{ - // determine if the device is resettable by creating a dummy device - PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE)GetProcAddress(mD3d11Module, "D3D11CreateDevice"); - - if (D3D11CreateDevice == NULL) - { - return false; - } - - ID3D11Device* dummyDevice; - D3D_FEATURE_LEVEL dummyFeatureLevel; - ID3D11DeviceContext* dummyContext; - - HRESULT result = D3D11CreateDevice(NULL, - mDriverType, - NULL, - #if defined(_DEBUG) - D3D11_CREATE_DEVICE_DEBUG, - #else - 0, - #endif - mAvailableFeatureLevels.data(), - mAvailableFeatureLevels.size(), - D3D11_SDK_VERSION, - &dummyDevice, - &dummyFeatureLevel, - &dummyContext); - - if (!mDevice || FAILED(result)) - { - return false; - } - - SafeRelease(dummyContext); - SafeRelease(dummyDevice); - - return true; -} - -void Renderer11::release() -{ - RendererD3D::cleanup(); - - releaseShaderCompiler(); - releaseDeviceResources(); - - SafeRelease(mDxgiFactory); - SafeRelease(mDxgiAdapter); - - if (mDeviceContext) - { - mDeviceContext->ClearState(); - mDeviceContext->Flush(); - SafeRelease(mDeviceContext); - } - - SafeRelease(mDevice); - - if (mD3d11Module) - { - FreeLibrary(mD3d11Module); - mD3d11Module = NULL; - } - - if (mDxgiModule) - { - FreeLibrary(mDxgiModule); - mDxgiModule = NULL; - } - - mCompiler.release(); -} - -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; -} - -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::getReservedVertexUniformBuffers() const -{ - // we reserve one buffer for the application uniforms, and one for driver uniforms - return 2; -} - -unsigned int Renderer11::getReservedFragmentUniformBuffers() const -{ - // we reserve one buffer for the application uniforms, and one for driver uniforms - return 2; -} - -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 getRendererExtensions().textureFormatBGRA8888 && !gl::perfActive(); -} - -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: - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: 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: - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return D3D10_SHADER_MINOR_VERSION; // 0 - default: UNREACHABLE(); return 0; - } -} - -int Renderer11::getMinSwapInterval() const -{ - return 0; -} - -int Renderer11::getMaxSwapInterval() const -{ - return 4; -} - -gl::Error Renderer11::copyImage2D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, TextureStorage *storage, GLint level) -{ - gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer(); - ASSERT(colorbuffer); - - RenderTarget11 *sourceRenderTarget = NULL; - gl::Error error = d3d11::GetAttachmentRenderTarget(colorbuffer, &sourceRenderTarget); - if (error.isError()) - { - return error; - } - ASSERT(sourceRenderTarget); - - ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView(); - ASSERT(source); - - TextureStorage11_2D *storage11 = TextureStorage11_2D::makeTextureStorage11_2D(storage); - ASSERT(storage11); - - gl::ImageIndex index = gl::ImageIndex::Make2D(level); - RenderTarget *destRenderTarget = NULL; - error = storage11->getRenderTarget(index, &destRenderTarget); - if (error.isError()) - { - return error; - } - ASSERT(destRenderTarget); - - ID3D11RenderTargetView *dest = RenderTarget11::makeRenderTarget11(destRenderTarget)->getRenderTargetView(); - ASSERT(dest); - - gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1); - gl::Extents sourceSize(sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), 1); - - gl::Box destArea(xoffset, yoffset, 0, sourceRect.width, sourceRect.height, 1); - gl::Extents destSize(destRenderTarget->getWidth(), destRenderTarget->getHeight(), 1); - - // Use nearest filtering because source and destination are the same size for the direct - // copy - mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL, destFormat, GL_NEAREST); - if (error.isError()) - { - return error; - } - - storage11->invalidateSwizzleCacheLevel(level); - - return gl::Error(GL_NO_ERROR); -} - -gl::Error Renderer11::copyImageCube(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, TextureStorage *storage, GLenum target, GLint level) -{ - gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer(); - ASSERT(colorbuffer); - - RenderTarget11 *sourceRenderTarget = NULL; - gl::Error error = d3d11::GetAttachmentRenderTarget(colorbuffer, &sourceRenderTarget); - if (error.isError()) - { - return error; - } - ASSERT(sourceRenderTarget); - - ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView(); - ASSERT(source); - - TextureStorage11_Cube *storage11 = TextureStorage11_Cube::makeTextureStorage11_Cube(storage); - ASSERT(storage11); - - gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level); - RenderTarget *destRenderTarget = NULL; - error = storage11->getRenderTarget(index, &destRenderTarget); - if (error.isError()) - { - return error; - } - ASSERT(destRenderTarget); - - ID3D11RenderTargetView *dest = RenderTarget11::makeRenderTarget11(destRenderTarget)->getRenderTargetView(); - ASSERT(dest); - - gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1); - gl::Extents sourceSize(sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), 1); - - gl::Box destArea(xoffset, yoffset, 0, sourceRect.width, sourceRect.height, 1); - gl::Extents destSize(destRenderTarget->getWidth(), destRenderTarget->getHeight(), 1); - - // Use nearest filtering because source and destination are the same size for the direct - // copy - error = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL, destFormat, GL_NEAREST); - if (error.isError()) - { - return error; - } - - storage11->invalidateSwizzleCacheLevel(level); - - return gl::Error(GL_NO_ERROR); -} - -gl::Error Renderer11::copyImage3D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level) -{ - gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer(); - ASSERT(colorbuffer); - - RenderTarget11 *sourceRenderTarget = NULL; - gl::Error error = d3d11::GetAttachmentRenderTarget(colorbuffer, &sourceRenderTarget); - if (error.isError()) - { - return error; - } - ASSERT(sourceRenderTarget); - - ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView(); - ASSERT(source); - - TextureStorage11_3D *storage11 = TextureStorage11_3D::makeTextureStorage11_3D(storage); - ASSERT(storage11); - - gl::ImageIndex index = gl::ImageIndex::Make3D(level, zOffset); - RenderTarget *destRenderTarget = NULL; - error = storage11->getRenderTarget(index, &destRenderTarget); - if (error.isError()) - { - return error; - } - ASSERT(destRenderTarget); - - ID3D11RenderTargetView *dest = RenderTarget11::makeRenderTarget11(destRenderTarget)->getRenderTargetView(); - ASSERT(dest); - - gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1); - gl::Extents sourceSize(sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), 1); - - gl::Box destArea(xoffset, yoffset, 0, sourceRect.width, sourceRect.height, 1); - gl::Extents destSize(destRenderTarget->getWidth(), destRenderTarget->getHeight(), 1); - - // Use nearest filtering because source and destination are the same size for the direct - // copy - error = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL, destFormat, GL_NEAREST); - if (error.isError()) - { - return error; - } - - storage11->invalidateSwizzleCacheLevel(level); - - return gl::Error(GL_NO_ERROR); -} - -gl::Error Renderer11::copyImage2DArray(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level) -{ - gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer(); - ASSERT(colorbuffer); - - RenderTarget11 *sourceRenderTarget = NULL; - gl::Error error = d3d11::GetAttachmentRenderTarget(colorbuffer, &sourceRenderTarget); - if (error.isError()) - { - return error; - } - ASSERT(sourceRenderTarget); - - ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView(); - ASSERT(source); - - TextureStorage11_2DArray *storage11 = TextureStorage11_2DArray::makeTextureStorage11_2DArray(storage); - ASSERT(storage11); - - gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, zOffset); - RenderTarget *destRenderTarget = NULL; - error = storage11->getRenderTarget(index, &destRenderTarget); - if (error.isError()) - { - return error; - } - ASSERT(destRenderTarget); - - ID3D11RenderTargetView *dest = RenderTarget11::makeRenderTarget11(destRenderTarget)->getRenderTargetView(); - ASSERT(dest); - - gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1); - gl::Extents sourceSize(sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), 1); - - gl::Box destArea(xoffset, yoffset, 0, sourceRect.width, sourceRect.height, 1); - gl::Extents destSize(destRenderTarget->getWidth(), destRenderTarget->getHeight(), 1); - - // Use nearest filtering because source and destination are the same size for the direct - // copy - error = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL, destFormat, GL_NEAREST); - if (error.isError()) - { - return error; - } - - storage11->invalidateSwizzleCacheLevel(level); - - return gl::Error(GL_NO_ERROR); -} - -void Renderer11::unapplyRenderTargets() -{ - setOneTimeRenderTarget(NULL); -} - -void Renderer11::setOneTimeRenderTarget(ID3D11RenderTargetView *renderTargetView) -{ - ID3D11RenderTargetView *rtvArray[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS] = {NULL}; - - rtvArray[0] = renderTargetView; - - mDeviceContext->OMSetRenderTargets(getRendererCaps().maxDrawBuffers, 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; - } -} - -gl::Error Renderer11::createRenderTarget(SwapChain *swapChain, bool depth, RenderTarget **outRT) -{ - SwapChain11 *swapChain11 = SwapChain11::makeSwapChain11(swapChain); - *outRT = new SurfaceRenderTarget11(swapChain11, depth); - return gl::Error(GL_NO_ERROR); -} - -gl::Error Renderer11::createRenderTarget(int width, int height, GLenum format, GLsizei samples, RenderTarget **outRT) -{ - const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(format); - - const gl::TextureCaps &textureCaps = getRendererTextureCaps().get(format); - GLuint supportedSamples = textureCaps.getNearestSamples(samples); - - 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 = formatInfo.texFormat; - desc.SampleDesc.Count = (supportedSamples == 0) ? 1 : supportedSamples; - desc.SampleDesc.Quality = 0; - desc.Usage = D3D11_USAGE_DEFAULT; - desc.CPUAccessFlags = 0; - desc.MiscFlags = 0; - - // If a rendertarget or depthstencil format exists for this texture format, - // we'll flag it to allow binding that way. Shader resource views are a little - // more complicated. - bool bindRTV = false, bindDSV = false, bindSRV = false; - bindRTV = (formatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN); - bindDSV = (formatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN); - if (formatInfo.srvFormat != DXGI_FORMAT_UNKNOWN) - { - // Multisample targets flagged for binding as depth stencil cannot also be - // flagged for binding as SRV, so make certain not to add the SRV flag for - // these targets. - bindSRV = !(formatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN && desc.SampleDesc.Count > 1); - } - - desc.BindFlags = (bindRTV ? D3D11_BIND_RENDER_TARGET : 0) | - (bindDSV ? D3D11_BIND_DEPTH_STENCIL : 0) | - (bindSRV ? D3D11_BIND_SHADER_RESOURCE : 0); - - // The format must be either an RTV or a DSV - ASSERT(bindRTV != bindDSV); - - ID3D11Texture2D *texture = NULL; - HRESULT result = mDevice->CreateTexture2D(&desc, NULL, &texture); - if (FAILED(result)) - { - ASSERT(result == E_OUTOFMEMORY); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create render target texture, result: 0x%X.", result); - } - - ID3D11ShaderResourceView *srv = NULL; - if (bindSRV) - { - D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; - srvDesc.Format = formatInfo.srvFormat; - srvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_SRV_DIMENSION_TEXTURE2D : D3D11_SRV_DIMENSION_TEXTURE2DMS; - srvDesc.Texture2D.MostDetailedMip = 0; - srvDesc.Texture2D.MipLevels = 1; - - result = mDevice->CreateShaderResourceView(texture, &srvDesc, &srv); - if (FAILED(result)) - { - ASSERT(result == E_OUTOFMEMORY); - SafeRelease(texture); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create render target shader resource view, result: 0x%X.", result); - } - } - - if (bindDSV) - { - D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; - dsvDesc.Format = formatInfo.dsvFormat; - dsvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_DSV_DIMENSION_TEXTURE2D : D3D11_DSV_DIMENSION_TEXTURE2DMS; - dsvDesc.Texture2D.MipSlice = 0; - dsvDesc.Flags = 0; - - ID3D11DepthStencilView *dsv = NULL; - result = mDevice->CreateDepthStencilView(texture, &dsvDesc, &dsv); - if (FAILED(result)) - { - ASSERT(result == E_OUTOFMEMORY); - SafeRelease(texture); - SafeRelease(srv); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create render target depth stencil view, result: 0x%X.", result); - } - - *outRT = new TextureRenderTarget11(dsv, texture, srv, format, width, height, 1, supportedSamples); - - SafeRelease(dsv); - } - else if (bindRTV) - { - D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; - rtvDesc.Format = formatInfo.rtvFormat; - rtvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_RTV_DIMENSION_TEXTURE2D : D3D11_RTV_DIMENSION_TEXTURE2DMS; - rtvDesc.Texture2D.MipSlice = 0; - - ID3D11RenderTargetView *rtv = NULL; - result = mDevice->CreateRenderTargetView(texture, &rtvDesc, &rtv); - if (FAILED(result)) - { - ASSERT(result == E_OUTOFMEMORY); - SafeRelease(texture); - SafeRelease(srv); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create render target render target view, result: 0x%X.", result); - } - - if (formatInfo.dataInitializerFunction != NULL) - { - const float clearValues[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; - mDeviceContext->ClearRenderTargetView(rtv, clearValues); - } - - *outRT = new TextureRenderTarget11(rtv, texture, srv, format, width, height, 1, supportedSamples); - - SafeRelease(rtv); - } - else - { - UNREACHABLE(); - } - - SafeRelease(texture); - SafeRelease(srv); - } - else - { - *outRT = new TextureRenderTarget11(reinterpret_cast(NULL), NULL, NULL, format, width, height, 1, supportedSamples); - } - - return gl::Error(GL_NO_ERROR); -} - -ShaderImpl *Renderer11::createShader(const gl::Data &data, GLenum type) -{ - return new ShaderD3D(data, type, this); -} - -ProgramImpl *Renderer11::createProgram() -{ - return new ProgramD3D(this); -} - -void Renderer11::releaseShaderCompiler() -{ - ShaderD3D::releaseCompiler(); -} - -gl::Error Renderer11::loadExecutable(const void *function, size_t length, ShaderType type, - const std::vector &transformFeedbackVaryings, - bool separatedOutputBuffers, ShaderExecutable **outExecutable) -{ - switch (type) - { - case SHADER_VERTEX: - { - ID3D11VertexShader *vertexShader = NULL; - ID3D11GeometryShader *streamOutShader = NULL; - - HRESULT result = mDevice->CreateVertexShader(function, length, NULL, &vertexShader); - ASSERT(SUCCEEDED(result)); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create vertex shader, result: 0x%X.", result); - } - - if (transformFeedbackVaryings.size() > 0) - { - std::vector soDeclaration; - for (size_t i = 0; i < transformFeedbackVaryings.size(); i++) - { - const gl::LinkedVarying &varying = transformFeedbackVaryings[i]; - GLenum transposedType = gl::TransposeMatrixType(varying.type); - - for (size_t j = 0; j < varying.semanticIndexCount; j++) - { - D3D11_SO_DECLARATION_ENTRY entry = { 0 }; - entry.Stream = 0; - entry.SemanticName = varying.semanticName.c_str(); - entry.SemanticIndex = varying.semanticIndex + j; - entry.StartComponent = 0; - entry.ComponentCount = gl::VariableColumnCount(transposedType); - entry.OutputSlot = (separatedOutputBuffers ? i : 0); - soDeclaration.push_back(entry); - } - } - - result = mDevice->CreateGeometryShaderWithStreamOutput(function, length, soDeclaration.data(), soDeclaration.size(), - NULL, 0, 0, NULL, &streamOutShader); - ASSERT(SUCCEEDED(result)); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create steam output shader, result: 0x%X.", result); - } - } - - *outExecutable = new ShaderExecutable11(function, length, vertexShader, streamOutShader); - } - break; - case SHADER_PIXEL: - { - ID3D11PixelShader *pixelShader = NULL; - - HRESULT result = mDevice->CreatePixelShader(function, length, NULL, &pixelShader); - ASSERT(SUCCEEDED(result)); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create pixel shader, result: 0x%X.", result); - } - - *outExecutable = new ShaderExecutable11(function, length, pixelShader); - } - break; - case SHADER_GEOMETRY: - { - ID3D11GeometryShader *geometryShader = NULL; - - HRESULT result = mDevice->CreateGeometryShader(function, length, NULL, &geometryShader); - ASSERT(SUCCEEDED(result)); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create geometry shader, result: 0x%X.", result); - } - - *outExecutable = new ShaderExecutable11(function, length, geometryShader); - } - break; - default: - UNREACHABLE(); - return gl::Error(GL_INVALID_OPERATION); - } - - return gl::Error(GL_NO_ERROR); -} - -gl::Error Renderer11::compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, ShaderType type, - const std::vector &transformFeedbackVaryings, - bool separatedOutputBuffers, D3DWorkaroundType workaround, - ShaderExecutable **outExectuable) -{ - const char *profileType = NULL; - switch (type) - { - case SHADER_VERTEX: - profileType = "vs"; - break; - case SHADER_PIXEL: - profileType = "ps"; - break; - case SHADER_GEOMETRY: - profileType = "gs"; - break; - default: - UNREACHABLE(); - return gl::Error(GL_INVALID_OPERATION); - } - - unsigned int profileMajorVersion = 0; - unsigned int profileMinorVersion = 0; - const char *profileSuffix = NULL; - switch (mFeatureLevel) - { - case D3D_FEATURE_LEVEL_11_0: - profileMajorVersion = 5; - profileMinorVersion = 0; - break; - case D3D_FEATURE_LEVEL_10_1: - profileMajorVersion = 4; - profileMinorVersion = 1; - break; - case D3D_FEATURE_LEVEL_10_0: - profileMajorVersion = 4; - profileMinorVersion = 0; - break; - case D3D_FEATURE_LEVEL_9_3: - profileMajorVersion = 4; - profileMinorVersion = 0; - profileSuffix = "_level_9_3"; - break; - case D3D_FEATURE_LEVEL_9_2: - profileMajorVersion = 4; - profileMinorVersion = 0; - profileSuffix = "_level_9_2"; - break; - case D3D_FEATURE_LEVEL_9_1: - profileMajorVersion = 4; - profileMinorVersion = 0; - profileSuffix = "_level_9_1"; - break; - break; - default: - UNREACHABLE(); - return gl::Error(GL_INVALID_OPERATION); - } - - std::string profile = FormatString("%s_%u_%u", profileType, profileMajorVersion, profileMinorVersion); - if (profileSuffix) - profile += profileSuffix; - - UINT flags = D3DCOMPILE_OPTIMIZATION_LEVEL2; - - if (gl::perfActive()) - { -#ifndef NDEBUG - flags = D3DCOMPILE_SKIP_OPTIMIZATION; -#endif - - flags |= D3DCOMPILE_DEBUG; - } - - // 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. - std::vector configs; - configs.push_back(CompileConfig(flags, "default" )); - configs.push_back(CompileConfig(flags | D3DCOMPILE_SKIP_VALIDATION, "skip validation" )); - configs.push_back(CompileConfig(flags | D3DCOMPILE_SKIP_OPTIMIZATION, "skip optimization")); - - D3D_SHADER_MACRO loopMacros[] = { {"ANGLE_ENABLE_LOOP_FLATTEN", "1"}, {0, 0} }; - - ID3DBlob *binary = NULL; - std::string debugInfo; - gl::Error error = mCompiler.compileToBinary(infoLog, shaderHLSL, profile, configs, loopMacros, &binary, &debugInfo); - if (error.isError()) - { - return error; - } - - // It's possible that binary is NULL if the compiler failed in all configurations. Set the executable to NULL - // and return GL_NO_ERROR to signify that there was a link error but the internal state is still OK. - if (!binary) - { - *outExectuable = NULL; - return gl::Error(GL_NO_ERROR); - } - - error = loadExecutable(binary->GetBufferPointer(), binary->GetBufferSize(), type, - transformFeedbackVaryings, separatedOutputBuffers, outExectuable); - - SafeRelease(binary); - if (error.isError()) - { - return error; - } - - if (!debugInfo.empty()) - { - (*outExectuable)->appendDebugInfo(debugInfo); - } - - return gl::Error(GL_NO_ERROR); -} - -UniformStorage *Renderer11::createUniformStorage(size_t storageSize) -{ - return new UniformStorage11(this, storageSize); -} - -VertexBuffer *Renderer11::createVertexBuffer() -{ - return new VertexBuffer11(this); -} - -IndexBuffer *Renderer11::createIndexBuffer() -{ - return new IndexBuffer11(this); -} - -BufferImpl *Renderer11::createBuffer() -{ - return new Buffer11(this); -} - -VertexArrayImpl *Renderer11::createVertexArray() -{ - return new VertexArray11(this); -} - -QueryImpl *Renderer11::createQuery(GLenum type) -{ - return new Query11(this, type); -} - -FenceNVImpl *Renderer11::createFenceNV() -{ - return new FenceNV11(this); -} - -FenceSyncImpl *Renderer11::createFenceSync() -{ - return new FenceSync11(this); -} - -TransformFeedbackImpl* Renderer11::createTransformFeedback() -{ - return new TransformFeedbackD3D(); -} - -bool Renderer11::supportsFastCopyBufferToTexture(GLenum internalFormat) const -{ - ASSERT(getRendererExtensions().pixelBufferObject); - - const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat); - const d3d11::TextureFormat &d3d11FormatInfo = d3d11::GetTextureFormatInfo(internalFormat); - const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(d3d11FormatInfo.texFormat); - - // sRGB formats do not work with D3D11 buffer SRVs - if (internalFormatInfo.colorEncoding == GL_SRGB) - { - return false; - } - - // We cannot support direct copies to non-color-renderable formats - if (d3d11FormatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN) - { - return false; - } - - // We skip all 3-channel formats since sometimes format support is missing - if (internalFormatInfo.componentCount == 3) - { - return false; - } - - // We don't support formats which we can't represent without conversion - if (dxgiFormatInfo.internalFormat != internalFormat) - { - return false; - } - - return true; -} - -gl::Error Renderer11::fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget, - GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea) -{ - ASSERT(supportsFastCopyBufferToTexture(destinationFormat)); - return mPixelTransfer->copyBufferToTexture(unpack, offset, destRenderTarget, destinationFormat, sourcePixelsType, destArea); -} - -gl::Error Renderer11::getRenderTargetResource(gl::FramebufferAttachment *colorbuffer, unsigned int *subresourceIndexOut, ID3D11Texture2D **texture2DOut) - -{ - ASSERT(colorbuffer); - - RenderTarget11 *renderTarget = NULL; - gl::Error error = d3d11::GetAttachmentRenderTarget(colorbuffer, &renderTarget); - if (error.isError()) - { - return error; - } - - ID3D11Resource *renderTargetResource = renderTarget->getTexture(); - ASSERT(renderTargetResource); - - *subresourceIndexOut = renderTarget->getSubresourceIndex(); - *texture2DOut = d3d11::DynamicCastComObject(renderTargetResource); - - if (!(*texture2DOut)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to query the ID3D11Texture2D from a RenderTarget"); - } - - return gl::Error(GL_NO_ERROR); -} - -gl::Error Renderer11::blitRect(const gl::Framebuffer *readTarget, const gl::Rectangle &readRect, - const gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect, - const gl::Rectangle *scissor, bool blitRenderTarget, - bool blitDepth, bool blitStencil, GLenum filter) -{ - if (blitRenderTarget) - { - gl::FramebufferAttachment *readBuffer = readTarget->getReadColorbuffer(); - ASSERT(readBuffer); - - RenderTarget *readRenderTarget = NULL; - gl::Error error = GetAttachmentRenderTarget(readBuffer, &readRenderTarget); - if (error.isError()) - { - return error; - } - ASSERT(readRenderTarget); - - for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) - { - if (drawTarget->isEnabledColorAttachment(colorAttachment)) - { - gl::FramebufferAttachment *drawBuffer = drawTarget->getColorbuffer(colorAttachment); - ASSERT(drawBuffer); - - RenderTarget *drawRenderTarget = NULL; - error = GetAttachmentRenderTarget(drawBuffer, &drawRenderTarget); - if (error.isError()) - { - return error; - } - ASSERT(drawRenderTarget); - - error = blitRenderbufferRect(readRect, drawRect, readRenderTarget, drawRenderTarget, filter, scissor, blitRenderTarget, - false, false); - if (error.isError()) - { - return error; - } - } - } - } - - if (blitDepth || blitStencil) - { - gl::FramebufferAttachment *readBuffer = readTarget->getDepthOrStencilbuffer(); - ASSERT(readBuffer); - - RenderTarget *readRenderTarget = NULL; - gl::Error error = GetAttachmentRenderTarget(readBuffer, &readRenderTarget); - if (error.isError()) - { - return error; - } - ASSERT(readRenderTarget); - - gl::FramebufferAttachment *drawBuffer = drawTarget->getDepthOrStencilbuffer(); - ASSERT(drawBuffer); - - RenderTarget *drawRenderTarget = NULL; - error = GetAttachmentRenderTarget(drawBuffer, &drawRenderTarget); - if (error.isError()) - { - return error; - } - ASSERT(drawRenderTarget); - - error = blitRenderbufferRect(readRect, drawRect, readRenderTarget, drawRenderTarget, filter, scissor, false, - blitDepth, blitStencil); - if (error.isError()) - { - return error; - } - } - - invalidateFramebufferSwizzles(drawTarget); - - return gl::Error(GL_NO_ERROR); -} - -gl::Error Renderer11::readPixels(const gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, - GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, uint8_t *pixels) -{ - ID3D11Texture2D *colorBufferTexture = NULL; - unsigned int subresourceIndex = 0; - - gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer(); - ASSERT(colorbuffer); - - gl::Error error = getRenderTargetResource(colorbuffer, &subresourceIndex, &colorBufferTexture); - if (error.isError()) - { - return error; - } - - gl::Rectangle area; - area.x = x; - area.y = y; - area.width = width; - area.height = height; - - gl::Buffer *packBuffer = pack.pixelBuffer.get(); - if (packBuffer != NULL) - { - Buffer11 *packBufferStorage = Buffer11::makeBuffer11(packBuffer->getImplementation()); - PackPixelsParams packParams(area, format, type, outputPitch, pack, reinterpret_cast(pixels)); - - error = packBufferStorage->packPixels(colorBufferTexture, subresourceIndex, packParams); - if (error.isError()) - { - SafeRelease(colorBufferTexture); - return error; - } - - packBuffer->getIndexRangeCache()->clear(); - } - else - { - error = readTextureData(colorBufferTexture, subresourceIndex, area, format, type, outputPitch, pack, pixels); - if (error.isError()) - { - SafeRelease(colorBufferTexture); - return error; - } - } - - SafeRelease(colorBufferTexture); - - return gl::Error(GL_NO_ERROR); -} - -Image *Renderer11::createImage() -{ - return new Image11(); -} - -gl::Error Renderer11::generateMipmap(Image *dest, Image *src) -{ - Image11 *dest11 = Image11::makeImage11(dest); - Image11 *src11 = Image11::makeImage11(src); - return Image11::generateMipmap(dest11, src11); -} - -TextureStorage *Renderer11::createTextureStorage2D(SwapChain *swapChain) -{ - SwapChain11 *swapChain11 = SwapChain11::makeSwapChain11(swapChain); - return new TextureStorage11_2D(this, swapChain11); -} - -TextureStorage *Renderer11::createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels) -{ - return new TextureStorage11_2D(this, internalformat, renderTarget, width, height, levels); -} - -TextureStorage *Renderer11::createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels) -{ - return new TextureStorage11_Cube(this, internalformat, renderTarget, size, levels); -} - -TextureStorage *Renderer11::createTextureStorage3D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) -{ - return new TextureStorage11_3D(this, internalformat, renderTarget, width, height, depth, levels); -} - -TextureStorage *Renderer11::createTextureStorage2DArray(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) -{ - return new TextureStorage11_2DArray(this, internalformat, renderTarget, width, height, depth, levels); -} - -TextureImpl *Renderer11::createTexture(GLenum target) -{ - switch(target) - { - case GL_TEXTURE_2D: return new TextureD3D_2D(this); - case GL_TEXTURE_CUBE_MAP: return new TextureD3D_Cube(this); - case GL_TEXTURE_3D: return new TextureD3D_3D(this); - case GL_TEXTURE_2D_ARRAY: return new TextureD3D_2DArray(this); - default: - UNREACHABLE(); - } - - return NULL; -} - -RenderbufferImpl *Renderer11::createRenderbuffer() -{ - RenderbufferD3D *renderbuffer = new RenderbufferD3D(this); - return renderbuffer; -} - -RenderbufferImpl *Renderer11::createRenderbuffer(SwapChain *swapChain, bool depth) -{ - RenderbufferD3D *renderbuffer = new RenderbufferD3D(this); - renderbuffer->setStorage(swapChain, depth); - return renderbuffer; -} - -gl::Error Renderer11::readTextureData(ID3D11Texture2D *texture, unsigned int subResource, const gl::Rectangle &area, GLenum format, - GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, uint8_t *pixels) -{ - ASSERT(area.width >= 0); - ASSERT(area.height >= 0); - - D3D11_TEXTURE2D_DESC textureDesc; - texture->GetDesc(&textureDesc); - - // Clamp read region to the defined texture boundaries, preventing out of bounds reads - // and reads of uninitialized data. - gl::Rectangle safeArea; - safeArea.x = gl::clamp(area.x, 0, static_cast(textureDesc.Width)); - safeArea.y = gl::clamp(area.y, 0, static_cast(textureDesc.Height)); - safeArea.width = gl::clamp(area.width + std::min(area.x, 0), 0, - static_cast(textureDesc.Width) - safeArea.x); - safeArea.height = gl::clamp(area.height + std::min(area.y, 0), 0, - static_cast(textureDesc.Height) - safeArea.y); - - ASSERT(safeArea.x >= 0 && safeArea.y >= 0); - ASSERT(safeArea.x + safeArea.width <= static_cast(textureDesc.Width)); - ASSERT(safeArea.y + safeArea.height <= static_cast(textureDesc.Height)); - - if (safeArea.width == 0 || safeArea.height == 0) - { - // no work to do - return gl::Error(GL_NO_ERROR); - } - - D3D11_TEXTURE2D_DESC stagingDesc; - stagingDesc.Width = safeArea.width; - stagingDesc.Height = safeArea.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)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal staging texture for ReadPixels, HRESULT: 0x%X.", result); - } - - 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)) - { - SafeRelease(stagingTex); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal resolve texture for ReadPixels, HRESULT: 0x%X.", result); - } - - mDeviceContext->ResolveSubresource(srcTex, 0, texture, subResource, textureDesc.Format); - subResource = 0; - } - else - { - srcTex = texture; - srcTex->AddRef(); - } - - D3D11_BOX srcBox; - srcBox.left = static_cast(safeArea.x); - srcBox.right = static_cast(safeArea.x + safeArea.width); - srcBox.top = static_cast(safeArea.y); - srcBox.bottom = static_cast(safeArea.y + safeArea.height); - srcBox.front = 0; - srcBox.back = 1; - - mDeviceContext->CopySubresourceRegion(stagingTex, 0, 0, 0, 0, srcTex, subResource, &srcBox); - - SafeRelease(srcTex); - - PackPixelsParams packParams(safeArea, format, type, outputPitch, pack, 0); - gl::Error error = packPixels(stagingTex, packParams, pixels); - - SafeRelease(stagingTex); - - return error; -} - -gl::Error Renderer11::packPixels(ID3D11Texture2D *readTexture, const PackPixelsParams ¶ms, uint8_t *pixelsOut) -{ - D3D11_TEXTURE2D_DESC textureDesc; - readTexture->GetDesc(&textureDesc); - - D3D11_MAPPED_SUBRESOURCE mapping; - HRESULT hr = mDeviceContext->Map(readTexture, 0, D3D11_MAP_READ, 0, &mapping); - if (FAILED(hr)) - { - ASSERT(hr == E_OUTOFMEMORY); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal texture for reading, result: 0x%X.", hr); - } - - uint8_t *source; - int inputPitch; - if (params.pack.reverseRowOrder) - { - source = static_cast(mapping.pData) + mapping.RowPitch * (params.area.height - 1); - inputPitch = -static_cast(mapping.RowPitch); - } - else - { - source = static_cast(mapping.pData); - inputPitch = static_cast(mapping.RowPitch); - } - - const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(textureDesc.Format); - const gl::InternalFormat &sourceFormatInfo = gl::GetInternalFormatInfo(dxgiFormatInfo.internalFormat); - if (sourceFormatInfo.format == params.format && sourceFormatInfo.type == params.type) - { - uint8_t *dest = pixelsOut + params.offset; - for (int y = 0; y < params.area.height; y++) - { - memcpy(dest + y * params.outputPitch, source + y * inputPitch, params.area.width * sourceFormatInfo.pixelBytes); - } - } - else - { - const d3d11::DXGIFormat &sourceDXGIFormatInfo = d3d11::GetDXGIFormatInfo(textureDesc.Format); - ColorCopyFunction fastCopyFunc = sourceDXGIFormatInfo.getFastCopyFunction(params.format, params.type); - - const gl::FormatType &destFormatTypeInfo = gl::GetFormatTypeInfo(params.format, params.type); - const gl::InternalFormat &destFormatInfo = gl::GetInternalFormatInfo(destFormatTypeInfo.internalFormat); - - if (fastCopyFunc) - { - // Fast copy is possible through some special function - for (int y = 0; y < params.area.height; y++) - { - for (int x = 0; x < params.area.width; x++) - { - uint8_t *dest = pixelsOut + params.offset + y * params.outputPitch + x * destFormatInfo.pixelBytes; - const uint8_t *src = source + y * inputPitch + x * sourceFormatInfo.pixelBytes; - - fastCopyFunc(src, dest); - } - } - } - else - { - uint8_t temp[16]; // Maximum size of any Color type used. - META_ASSERT(sizeof(temp) >= sizeof(gl::ColorF) && - sizeof(temp) >= sizeof(gl::ColorUI) && - sizeof(temp) >= sizeof(gl::ColorI)); - - for (int y = 0; y < params.area.height; y++) - { - for (int x = 0; x < params.area.width; x++) - { - uint8_t *dest = pixelsOut + params.offset + y * params.outputPitch + x * destFormatInfo.pixelBytes; - const uint8_t *src = source + y * inputPitch + x * sourceFormatInfo.pixelBytes; - - // readFunc and writeFunc will be using the same type of color, CopyTexImage - // will not allow the copy otherwise. - sourceDXGIFormatInfo.colorReadFunction(src, temp); - destFormatTypeInfo.colorWriteFunction(temp, dest); - } - } - } - } - - mDeviceContext->Unmap(readTexture, 0); - - return gl::Error(GL_NO_ERROR); -} - -gl::Error Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const gl::Rectangle &drawRect, RenderTarget *readRenderTarget, - RenderTarget *drawRenderTarget, GLenum filter, const gl::Rectangle *scissor, - bool colorBlit, bool depthBlit, bool stencilBlit) -{ - // Since blitRenderbufferRect is called for each render buffer that needs to be blitted, - // it should never be the case that both color and depth/stencil need to be blitted at - // at the same time. - ASSERT(colorBlit != (depthBlit || stencilBlit)); - - RenderTarget11 *drawRenderTarget11 = RenderTarget11::makeRenderTarget11(drawRenderTarget); - if (!drawRenderTarget) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to retrieve the internal draw render target from the draw framebuffer."); - } - - ID3D11Resource *drawTexture = drawRenderTarget11->getTexture(); - unsigned int drawSubresource = drawRenderTarget11->getSubresourceIndex(); - ID3D11RenderTargetView *drawRTV = drawRenderTarget11->getRenderTargetView(); - ID3D11DepthStencilView *drawDSV = drawRenderTarget11->getDepthStencilView(); - - RenderTarget11 *readRenderTarget11 = RenderTarget11::makeRenderTarget11(readRenderTarget); - if (!readRenderTarget) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to retrieve the internal read render target from the read framebuffer."); - } - - ID3D11Resource *readTexture = NULL; - ID3D11ShaderResourceView *readSRV = NULL; - unsigned int readSubresource = 0; - if (readRenderTarget->getSamples() > 0) - { - ID3D11Resource *unresolvedResource = readRenderTarget11->getTexture(); - ID3D11Texture2D *unresolvedTexture = d3d11::DynamicCastComObject(unresolvedResource); - - if (unresolvedTexture) - { - readTexture = resolveMultisampledTexture(unresolvedTexture, readRenderTarget11->getSubresourceIndex()); - readSubresource = 0; - - SafeRelease(unresolvedTexture); - - HRESULT hresult = mDevice->CreateShaderResourceView(readTexture, NULL, &readSRV); - if (FAILED(hresult)) - { - SafeRelease(readTexture); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create shader resource view to resolve multisampled framebuffer."); - } - } - } - else - { - readTexture = readRenderTarget11->getTexture(); - readTexture->AddRef(); - readSubresource = readRenderTarget11->getSubresourceIndex(); - readSRV = readRenderTarget11->getShaderResourceView(); - readSRV->AddRef(); - } - - if (!readTexture || !readSRV) - { - SafeRelease(readTexture); - SafeRelease(readSRV); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to retrieve the internal read render target view from the read render target."); - } - - gl::Extents readSize(readRenderTarget->getWidth(), readRenderTarget->getHeight(), 1); - gl::Extents drawSize(drawRenderTarget->getWidth(), drawRenderTarget->getHeight(), 1); - - bool scissorNeeded = scissor && gl::ClipRectangle(drawRect, *scissor, NULL); - - bool wholeBufferCopy = !scissorNeeded && - readRect.x == 0 && readRect.width == readSize.width && - readRect.y == 0 && readRect.height == readSize.height && - drawRect.x == 0 && drawRect.width == drawSize.width && - drawRect.y == 0 && drawRect.height == drawSize.height; - - bool stretchRequired = readRect.width != drawRect.width || readRect.height != drawRect.height; - - bool flipRequired = readRect.width < 0 || readRect.height < 0 || drawRect.width < 0 || drawRect.height < 0; - - bool outOfBounds = readRect.x < 0 || readRect.x + readRect.width > readSize.width || - readRect.y < 0 || readRect.y + readRect.height > readSize.height || - drawRect.x < 0 || drawRect.x + drawRect.width > drawSize.width || - drawRect.y < 0 || drawRect.y + drawRect.height > drawSize.height; - - const gl::InternalFormat &actualFormatInfo = gl::GetInternalFormatInfo(drawRenderTarget->getActualFormat()); - bool partialDSBlit = (actualFormatInfo.depthBits > 0 && depthBlit) != (actualFormatInfo.stencilBits > 0 && stencilBlit); - - gl::Error result(GL_NO_ERROR); - - if (readRenderTarget11->getActualFormat() == drawRenderTarget->getActualFormat() && - !stretchRequired && !outOfBounds && !flipRequired && !partialDSBlit && - (!(depthBlit || stencilBlit) || wholeBufferCopy)) - { - UINT dstX = drawRect.x; - UINT dstY = drawRect.y; - - 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; - - if (scissorNeeded) - { - // drawRect is guaranteed to have positive width and height because stretchRequired is false. - ASSERT(drawRect.width >= 0 || drawRect.height >= 0); - - if (drawRect.x < scissor->x) - { - dstX = scissor->x; - readBox.left += (scissor->x - drawRect.x); - } - if (drawRect.y < scissor->y) - { - dstY = scissor->y; - readBox.top += (scissor->y - drawRect.y); - } - if (drawRect.x + drawRect.width > scissor->x + scissor->width) - { - readBox.right -= ((drawRect.x + drawRect.width) - (scissor->x + scissor->width)); - } - if (drawRect.y + drawRect.height > scissor->y + scissor->height) - { - readBox.bottom -= ((drawRect.y + drawRect.height) - (scissor->y + scissor->height)); - } - } - - // 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, dstX, dstY, 0, - readTexture, readSubresource, pSrcBox); - result = gl::Error(GL_NO_ERROR); - } - else - { - gl::Box readArea(readRect.x, readRect.y, 0, readRect.width, readRect.height, 1); - gl::Box drawArea(drawRect.x, drawRect.y, 0, drawRect.width, drawRect.height, 1); - - if (depthBlit && stencilBlit) - { - result = mBlit->copyDepthStencil(readTexture, readSubresource, readArea, readSize, - drawTexture, drawSubresource, drawArea, drawSize, - scissor); - } - else if (depthBlit) - { - result = mBlit->copyDepth(readSRV, readArea, readSize, drawDSV, drawArea, drawSize, - scissor); - } - else if (stencilBlit) - { - result = mBlit->copyStencil(readTexture, readSubresource, readArea, readSize, - drawTexture, drawSubresource, drawArea, drawSize, - scissor); - } - else - { - GLenum format = gl::GetInternalFormatInfo(drawRenderTarget->getInternalFormat()).format; - result = mBlit->copyTexture(readSRV, readArea, readSize, drawRTV, drawArea, drawSize, - scissor, format, filter); - } - } - - SafeRelease(readTexture); - SafeRelease(readSRV); - - return result; -} - -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; - } -} - -void Renderer11::invalidateFBOAttachmentSwizzles(gl::FramebufferAttachment *attachment, int mipLevel) -{ - ASSERT(attachment->isTexture()); - gl::Texture *texture = attachment->getTexture(); - - TextureD3D *textureD3D = TextureD3D::makeTextureD3D(texture->getImplementation()); - TextureStorage *texStorage = textureD3D->getNativeTexture(); - if (texStorage) - { - TextureStorage11 *texStorage11 = TextureStorage11::makeTextureStorage11(texStorage); - if (!texStorage11) - { - ERR("texture storage pointer unexpectedly null."); - return; - } - - texStorage11->invalidateSwizzleCacheLevel(mipLevel); - } -} - -void Renderer11::invalidateFramebufferSwizzles(const gl::Framebuffer *framebuffer) -{ - for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) - { - gl::FramebufferAttachment *attachment = framebuffer->getColorbuffer(colorAttachment); - if (attachment && attachment->isTexture()) - { - invalidateFBOAttachmentSwizzles(attachment, attachment->mipLevel()); - } - } - - gl::FramebufferAttachment *depthAttachment = framebuffer->getDepthbuffer(); - if (depthAttachment && depthAttachment->isTexture()) - { - invalidateFBOAttachmentSwizzles(depthAttachment, depthAttachment->mipLevel()); - } - - gl::FramebufferAttachment *stencilAttachment = framebuffer->getStencilbuffer(); - if (stencilAttachment && stencilAttachment->isTexture()) - { - invalidateFBOAttachmentSwizzles(stencilAttachment, stencilAttachment->mipLevel()); - } -} - -bool Renderer11::getLUID(LUID *adapterLuid) const -{ - adapterLuid->HighPart = 0; - adapterLuid->LowPart = 0; - - if (!mDxgiAdapter) - { - return false; - } - - DXGI_ADAPTER_DESC adapterDesc; - if (FAILED(mDxgiAdapter->GetDesc(&adapterDesc))) - { - return false; - } - - *adapterLuid = adapterDesc.AdapterLuid; - return true; -} - -VertexConversionType Renderer11::getVertexConversionType(const gl::VertexFormat &vertexFormat) const -{ - return d3d11::GetVertexFormatInfo(vertexFormat).conversionType; -} - -GLenum Renderer11::getVertexComponentType(const gl::VertexFormat &vertexFormat) const -{ - return d3d11::GetDXGIFormatInfo(d3d11::GetVertexFormatInfo(vertexFormat).nativeFormat).componentType; -} - -void Renderer11::generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureCaps, gl::Extensions *outExtensions) const -{ - d3d11_gl::GenerateCaps(mDevice, outCaps, outTextureCaps, outExtensions); -} - -Workarounds Renderer11::generateWorkarounds() const -{ - return d3d11::GenerateWorkarounds(); -} - -void Renderer11::setShaderResource(gl::SamplerType shaderType, UINT resourceSlot, ID3D11ShaderResourceView *srv) -{ - std::vector ¤tSRVs = (shaderType == gl::SAMPLER_VERTEX ? mCurVertexSRVs : mCurPixelSRVs); - - ASSERT(static_cast(resourceSlot) < currentSRVs.size()); - - if (currentSRVs[resourceSlot] != srv) - { - if (shaderType == gl::SAMPLER_VERTEX) - { - mDeviceContext->VSSetShaderResources(resourceSlot, 1, &srv); - } - else - { - mDeviceContext->PSSetShaderResources(resourceSlot, 1, &srv); - } - - currentSRVs[resourceSlot] = srv; - } -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h deleted file mode 100644 index d44bd2fd30..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h +++ /dev/null @@ -1,362 +0,0 @@ -// -// Copyright (c) 2012-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// 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 "common/mathutil.h" - -#include "libGLESv2/renderer/d3d/d3d11/RenderStateCache.h" -#include "libGLESv2/renderer/d3d/d3d11/InputLayoutCache.h" -#include "libGLESv2/renderer/d3d/HLSLCompiler.h" -#include "libGLESv2/renderer/d3d/RendererD3D.h" -#include "libGLESv2/renderer/RenderTarget.h" - -#include "libEGL/AttributeMap.h" - -namespace gl -{ -class FramebufferAttachment; -} - -namespace rx -{ - -class VertexDataManager; -class IndexDataManager; -class StreamingIndexBufferInterface; -class Blit11; -class Clear11; -class PixelTransfer11; -class RenderTarget11; -struct PackPixelsParams; - -enum -{ - MAX_VERTEX_UNIFORM_VECTORS_D3D11 = 1024, - MAX_FRAGMENT_UNIFORM_VECTORS_D3D11 = 1024 -}; - -class Renderer11 : public RendererD3D -{ - public: - Renderer11(egl::Display *display, EGLNativeDisplayType hDc, const egl::AttributeMap &attributes); - virtual ~Renderer11(); - - static Renderer11 *makeRenderer11(Renderer *renderer); - - virtual EGLint initialize(); - virtual bool resetDevice(); - - virtual int generateConfigs(ConfigDesc **configDescList); - virtual void deleteConfigs(ConfigDesc *configDescList); - - virtual gl::Error sync(bool block); - - virtual SwapChain *createSwapChain(NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat); - - virtual gl::Error generateSwizzle(gl::Texture *texture); - virtual gl::Error setSamplerState(gl::SamplerType type, int index, gl::Texture *texture, const gl::SamplerState &sampler); - virtual gl::Error setTexture(gl::SamplerType type, int index, gl::Texture *texture); - - virtual gl::Error setUniformBuffers(const gl::Buffer *vertexUniformBuffers[], const gl::Buffer *fragmentUniformBuffers[]); - - virtual gl::Error setRasterizerState(const gl::RasterizerState &rasterState); - gl::Error setBlendState(const gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::ColorF &blendColor, - unsigned int sampleMask) override; - virtual gl::Error setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef, - int stencilBackRef, bool frontFaceCCW); - - virtual void setScissorRectangle(const gl::Rectangle &scissor, bool enabled); - virtual void setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace, - bool ignoreViewport); - - virtual bool applyPrimitiveType(GLenum mode, GLsizei count); - gl::Error applyRenderTarget(const gl::Framebuffer *frameBuffer) override; - virtual gl::Error applyShaders(gl::ProgramBinary *programBinary, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer, - bool rasterizerDiscard, bool transformFeedbackActive); - - virtual gl::Error applyUniforms(const ProgramImpl &program, const std::vector &uniformArray); - virtual gl::Error applyVertexBuffer(const gl::State &state, GLint first, GLsizei count, GLsizei instances); - virtual gl::Error applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo); - virtual void applyTransformFeedbackBuffers(const gl::State &state); - - virtual gl::Error drawArrays(GLenum mode, GLsizei count, GLsizei instances, bool transformFeedbackActive); - virtual gl::Error drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, - gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances); - - gl::Error clear(const gl::ClearParameters &clearParams, const gl::Framebuffer *frameBuffer) override; - - virtual void markAllStateDirty(); - - // lost device - void notifyDeviceLost() override; - bool isDeviceLost() override; - bool testDeviceLost(bool notify) override; - bool testDeviceResettable() override; - - DWORD getAdapterVendor() const override; - std::string getRendererDescription() const override; - GUID getAdapterIdentifier() const override; - - virtual unsigned int getReservedVertexUniformVectors() const; - virtual unsigned int getReservedFragmentUniformVectors() const; - virtual unsigned int getReservedVertexUniformBuffers() const; - virtual unsigned int getReservedFragmentUniformBuffers() const; - virtual bool getShareHandleSupport() const; - virtual bool getPostSubBufferSupport() const; - - virtual int getMajorShaderModel() const; - virtual int getMinSwapInterval() const; - virtual int getMaxSwapInterval() const; - - // Pixel operations - virtual gl::Error copyImage2D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, TextureStorage *storage, GLint level); - virtual gl::Error copyImageCube(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, TextureStorage *storage, GLenum target, GLint level); - virtual gl::Error copyImage3D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level); - virtual gl::Error copyImage2DArray(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level); - - gl::Error blitRect(const gl::Framebuffer *readTarget, const gl::Rectangle &readRect, const gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect, - const gl::Rectangle *scissor, bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter) override; - - virtual gl::Error readPixels(const gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, - GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, uint8_t *pixels); - - // RenderTarget creation - virtual gl::Error createRenderTarget(SwapChain *swapChain, bool depth, RenderTarget **outRT); - virtual gl::Error createRenderTarget(int width, int height, GLenum format, GLsizei samples, RenderTarget **outRT); - - // Shader creation - virtual ShaderImpl *createShader(const gl::Data &data, GLenum type); - virtual ProgramImpl *createProgram(); - - // Shader operations - void releaseShaderCompiler() override; - virtual gl::Error loadExecutable(const void *function, size_t length, ShaderType type, - const std::vector &transformFeedbackVaryings, - bool separatedOutputBuffers, ShaderExecutable **outExecutable); - virtual gl::Error compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, ShaderType type, - const std::vector &transformFeedbackVaryings, - bool separatedOutputBuffers, D3DWorkaroundType workaround, - ShaderExecutable **outExectuable); - virtual UniformStorage *createUniformStorage(size_t storageSize); - - // Image operations - virtual Image *createImage(); - gl::Error generateMipmap(Image *dest, Image *source) override; - virtual TextureStorage *createTextureStorage2D(SwapChain *swapChain); - virtual TextureStorage *createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels); - virtual TextureStorage *createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels); - virtual TextureStorage *createTextureStorage3D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels); - virtual TextureStorage *createTextureStorage2DArray(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels); - - // Texture creation - virtual TextureImpl *createTexture(GLenum target); - - // Renderbuffer creation - virtual RenderbufferImpl *createRenderbuffer(); - virtual RenderbufferImpl *createRenderbuffer(SwapChain *swapChain, bool depth); - - // Buffer creation - virtual BufferImpl *createBuffer(); - virtual VertexBuffer *createVertexBuffer(); - virtual IndexBuffer *createIndexBuffer(); - - // Vertex Array creation - virtual VertexArrayImpl *createVertexArray(); - - // Query and Fence creation - virtual QueryImpl *createQuery(GLenum type); - virtual FenceNVImpl *createFenceNV(); - virtual FenceSyncImpl *createFenceSync(); - - // Transform Feedback creation - virtual TransformFeedbackImpl* createTransformFeedback(); - - // D3D11-renderer specific methods - ID3D11Device *getDevice() { return mDevice; } - ID3D11DeviceContext *getDeviceContext() { return mDeviceContext; }; - DXGIFactory *getDxgiFactory() { return mDxgiFactory; }; - bool isLevel9() { return mFeatureLevel <= D3D_FEATURE_LEVEL_9_3; } - - Blit11 *getBlitter() { return mBlit; } - - // Buffer-to-texture and Texture-to-buffer copies - virtual bool supportsFastCopyBufferToTexture(GLenum internalFormat) const; - virtual gl::Error fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget, - GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea); - - gl::Error getRenderTargetResource(gl::FramebufferAttachment *colorbuffer, unsigned int *subresourceIndexOut, ID3D11Texture2D **texture2DOut); - - void unapplyRenderTargets(); - void setOneTimeRenderTarget(ID3D11RenderTargetView *renderTargetView); - gl::Error packPixels(ID3D11Texture2D *readTexture, const PackPixelsParams ¶ms, uint8_t *pixelsOut); - - virtual bool getLUID(LUID *adapterLuid) const; - virtual VertexConversionType getVertexConversionType(const gl::VertexFormat &vertexFormat) const; - virtual GLenum getVertexComponentType(const gl::VertexFormat &vertexFormat) const; - - gl::Error readTextureData(ID3D11Texture2D *texture, unsigned int subResource, const gl::Rectangle &area, GLenum format, - GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, uint8_t *pixels); - - void setShaderResource(gl::SamplerType shaderType, UINT resourceSlot, ID3D11ShaderResourceView *srv); - - private: - DISALLOW_COPY_AND_ASSIGN(Renderer11); - - void generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureCaps, gl::Extensions *outExtensions) const override; - Workarounds generateWorkarounds() const override; - - gl::Error drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer); - gl::Error drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer, int instances); - - gl::Error blitRenderbufferRect(const gl::Rectangle &readRect, const gl::Rectangle &drawRect, RenderTarget *readRenderTarget, - RenderTarget *drawRenderTarget, GLenum filter, const gl::Rectangle *scissor, - bool colorBlit, bool depthBlit, bool stencilBlit); - ID3D11Texture2D *resolveMultisampledTexture(ID3D11Texture2D *source, unsigned int subresource); - void unsetSRVsWithResource(gl::SamplerType shaderType, const ID3D11Resource *resource); - - static void invalidateFBOAttachmentSwizzles(gl::FramebufferAttachment *attachment, int mipLevel); - static void invalidateFramebufferSwizzles(const gl::Framebuffer *framebuffer); - - HMODULE mD3d11Module; - HMODULE mDxgiModule; - EGLNativeDisplayType mDc; - std::vector mAvailableFeatureLevels; - D3D_DRIVER_TYPE mDriverType; - - HLSLCompiler mCompiler; - - bool mDeviceLost; - - void initializeDevice(); - void releaseDeviceResources(); - int getMinorShaderModel() const; - void release(); - - RenderStateCache mStateCache; - - // current render target states - unsigned int mAppliedRenderTargetSerials[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS]; - unsigned int mAppliedDepthbufferSerial; - unsigned int mAppliedStencilbufferSerial; - bool mDepthStencilInitialized; - bool mRenderTargetDescInitialized; - RenderTarget::Desc mRenderTargetDesc; - - // Currently applied sampler states - std::vector mForceSetVertexSamplerStates; - std::vector mCurVertexSamplerStates; - - std::vector mForceSetPixelSamplerStates; - std::vector mCurPixelSamplerStates; - - // Currently applied textures - std::vector mCurVertexSRVs; - std::vector mCurPixelSRVs; - - // Currently applied blend state - bool mForceSetBlendState; - gl::BlendState mCurBlendState; - gl::ColorF mCurBlendColor; - unsigned int mCurSampleMask; - - // Currently applied rasterizer state - bool mForceSetRasterState; - gl::RasterizerState mCurRasterState; - - // Currently applied depth stencil state - bool mForceSetDepthStencilState; - gl::DepthStencilState mCurDepthStencilState; - int mCurStencilRef; - int mCurStencilBackRef; - - // Currently applied scissor rectangle - bool mForceSetScissor; - bool mScissorEnabled; - gl::Rectangle mCurScissor; - - // Currently applied viewport - bool mForceSetViewport; - gl::Rectangle mCurViewport; - float mCurNear; - float mCurFar; - - // Currently applied primitive topology - D3D11_PRIMITIVE_TOPOLOGY mCurrentPrimitiveTopology; - - // Currently applied index buffer - ID3D11Buffer *mAppliedIB; - DXGI_FORMAT mAppliedIBFormat; - unsigned int mAppliedIBOffset; - - // Currently applied transform feedback buffers - ID3D11Buffer *mAppliedTFBuffers[gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS]; // Tracks the current D3D buffers - // in use for streamout - GLintptr mAppliedTFOffsets[gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS]; // Tracks the current GL-specified - // buffer offsets to transform feedback - // buffers - UINT mCurrentD3DOffsets[gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS]; // Tracks the D3D buffer offsets, - // which may differ from GLs, due - // to different append behavior - - // Currently applied shaders - ID3D11VertexShader *mAppliedVertexShader; - ID3D11GeometryShader *mAppliedGeometryShader; - ID3D11GeometryShader *mCurPointGeometryShader; - ID3D11PixelShader *mAppliedPixelShader; - - dx_VertexConstants mVertexConstants; - dx_VertexConstants mAppliedVertexConstants; - ID3D11Buffer *mDriverConstantBufferVS; - ID3D11Buffer *mCurrentVertexConstantBuffer; - unsigned int mCurrentConstantBufferVS[gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS]; - - dx_PixelConstants mPixelConstants; - dx_PixelConstants mAppliedPixelConstants; - ID3D11Buffer *mDriverConstantBufferPS; - ID3D11Buffer *mCurrentPixelConstantBuffer; - unsigned int mCurrentConstantBufferPS[gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS]; - - ID3D11Buffer *mCurrentGeometryConstantBuffer; - - // Vertex, index and input layouts - VertexDataManager *mVertexDataManager; - IndexDataManager *mIndexDataManager; - InputLayoutCache mInputLayoutCache; - - StreamingIndexBufferInterface *mLineLoopIB; - StreamingIndexBufferInterface *mTriangleFanIB; - - // Texture copy resources - Blit11 *mBlit; - PixelTransfer11 *mPixelTransfer; - - // Masked clear resources - Clear11 *mClear; - - // Sync query - ID3D11Query *mSyncQuery; - - ID3D11Device *mDevice; - D3D_FEATURE_LEVEL mFeatureLevel; - ID3D11DeviceContext *mDeviceContext; - IDXGIAdapter *mDxgiAdapter; - DXGI_ADAPTER_DESC mAdapterDescription; - char mDescription[128]; - DXGIFactory *mDxgiFactory; -}; - -} -#endif // LIBGLESV2_RENDERER_RENDERER11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/ShaderExecutable11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/ShaderExecutable11.cpp deleted file mode 100644 index 52f34887fb..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/ShaderExecutable11.cpp +++ /dev/null @@ -1,110 +0,0 @@ -// -// Copyright (c) 2012-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// ShaderExecutable11.cpp: Implements a D3D11-specific class to contain shader -// executable implementation details. - -#include "libGLESv2/renderer/d3d/d3d11/ShaderExecutable11.h" -#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" - -namespace rx -{ - -ShaderExecutable11::ShaderExecutable11(const void *function, size_t length, ID3D11PixelShader *executable) - : ShaderExecutable(function, length) -{ - mPixelExecutable = executable; - mVertexExecutable = NULL; - mGeometryExecutable = NULL; - mStreamOutExecutable = NULL; -} - -ShaderExecutable11::ShaderExecutable11(const void *function, size_t length, ID3D11VertexShader *executable, ID3D11GeometryShader *streamOut) - : ShaderExecutable(function, length) -{ - mVertexExecutable = executable; - mPixelExecutable = NULL; - mGeometryExecutable = NULL; - mStreamOutExecutable = streamOut; -} - -ShaderExecutable11::ShaderExecutable11(const void *function, size_t length, ID3D11GeometryShader *executable) - : ShaderExecutable(function, length) -{ - mGeometryExecutable = executable; - mVertexExecutable = NULL; - mPixelExecutable = NULL; - mStreamOutExecutable = NULL; -} - -ShaderExecutable11::~ShaderExecutable11() -{ - SafeRelease(mVertexExecutable); - SafeRelease(mPixelExecutable); - SafeRelease(mGeometryExecutable); - SafeRelease(mStreamOutExecutable); -} - -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; -} - -ID3D11GeometryShader *ShaderExecutable11::getStreamOutShader() const -{ - return mStreamOutExecutable; -} - -UniformStorage11::UniformStorage11(Renderer11 *renderer, size_t initialSize) - : UniformStorage(initialSize), - mConstantBuffer(NULL) -{ - ID3D11Device *d3d11Device = renderer->getDevice(); - - if (initialSize > 0) - { - D3D11_BUFFER_DESC constantBufferDescription = {0}; - constantBufferDescription.ByteWidth = initialSize; - 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 = d3d11Device->CreateBuffer(&constantBufferDescription, NULL, &mConstantBuffer); - UNUSED_ASSERTION_VARIABLE(result); - ASSERT(SUCCEEDED(result)); - } -} - -UniformStorage11::~UniformStorage11() -{ - SafeRelease(mConstantBuffer); -} - -const UniformStorage11 *UniformStorage11::makeUniformStorage11(const UniformStorage *uniformStorage) -{ - ASSERT(HAS_DYNAMIC_TYPE(const UniformStorage11*, uniformStorage)); - return static_cast(uniformStorage); -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/ShaderExecutable11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/ShaderExecutable11.h deleted file mode 100644 index 74a1e03915..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/ShaderExecutable11.h +++ /dev/null @@ -1,61 +0,0 @@ -// -// Copyright (c) 2012-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// 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 Renderer11; -class UniformStorage11; - -class ShaderExecutable11 : public ShaderExecutable -{ - public: - ShaderExecutable11(const void *function, size_t length, ID3D11PixelShader *executable); - ShaderExecutable11(const void *function, size_t length, ID3D11VertexShader *executable, ID3D11GeometryShader *streamOut); - 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; - ID3D11GeometryShader *getStreamOutShader() const; - - private: - DISALLOW_COPY_AND_ASSIGN(ShaderExecutable11); - - ID3D11PixelShader *mPixelExecutable; - ID3D11VertexShader *mVertexExecutable; - ID3D11GeometryShader *mGeometryExecutable; - ID3D11GeometryShader *mStreamOutExecutable; -}; - -class UniformStorage11 : public UniformStorage -{ - public: - UniformStorage11(Renderer11 *renderer, size_t initialSize); - virtual ~UniformStorage11(); - - static const UniformStorage11 *makeUniformStorage11(const UniformStorage *uniformStorage); - - ID3D11Buffer *getConstantBuffer() const { return mConstantBuffer; } - - private: - ID3D11Buffer *mConstantBuffer; -}; - -} - -#endif // LIBGLESV2_RENDERER_SHADEREXECUTABLE11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp deleted file mode 100644 index 52c8a81633..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp +++ /dev/null @@ -1,675 +0,0 @@ -// -// Copyright (c) 2012-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// SwapChain11.cpp: Implements a back-end specific class for the D3D11 swap chain. - -#include "libGLESv2/renderer/d3d/d3d11/SwapChain11.h" -#include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h" -#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" -#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" - -// Precompiled shaders -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthrough2dvs.h" -#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dps.h" - -#include "common/features.h" -#include "common/NativeWindow.h" - -namespace rx -{ - -SwapChain11::SwapChain11(Renderer11 *renderer, NativeWindow nativeWindow, HANDLE shareHandle, - GLenum backBufferFormat, GLenum depthBufferFormat) - : mRenderer(renderer), - SwapChain(nativeWindow, shareHandle, backBufferFormat, depthBufferFormat) -{ - mSwapChain = NULL; - mBackBufferTexture = NULL; - mBackBufferRTView = NULL; - mOffscreenTexture = NULL; - mOffscreenRTView = NULL; - mOffscreenSRView = NULL; - mDepthStencilTexture = NULL; - mDepthStencilDSView = NULL; - mDepthStencilSRView = NULL; - mQuadVB = NULL; - mPassThroughSampler = NULL; - mPassThroughIL = NULL; - mPassThroughVS = NULL; - mPassThroughPS = NULL; - mWidth = -1; - mHeight = -1; - mRotateL = false; - mRotateR = false; - mSwapInterval = 0; - mAppCreatedShareHandle = mShareHandle != NULL; - mPassThroughResourcesInit = false; -} - -SwapChain11::~SwapChain11() -{ - release(); -} - -void SwapChain11::release() -{ - SafeRelease(mSwapChain); - SafeRelease(mBackBufferTexture); - SafeRelease(mBackBufferRTView); - SafeRelease(mOffscreenTexture); - SafeRelease(mOffscreenRTView); - SafeRelease(mOffscreenSRView); - SafeRelease(mDepthStencilTexture); - SafeRelease(mDepthStencilDSView); - SafeRelease(mDepthStencilSRView); - SafeRelease(mQuadVB); - SafeRelease(mPassThroughSampler); - SafeRelease(mPassThroughIL); - SafeRelease(mPassThroughVS); - SafeRelease(mPassThroughPS); - - if (!mAppCreatedShareHandle) - { - mShareHandle = NULL; - } -} - -void SwapChain11::releaseOffscreenTexture() -{ - SafeRelease(mOffscreenTexture); - SafeRelease(mOffscreenRTView); - SafeRelease(mOffscreenSRView); - SafeRelease(mDepthStencilTexture); - SafeRelease(mDepthStencilDSView); - SafeRelease(mDepthStencilSRView); -} - -EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHeight) -{ - ID3D11Device *device = mRenderer->getDevice(); - - ASSERT(device != NULL); - - // D3D11 does not allow zero size textures - ASSERT(backbufferWidth != 0); - ASSERT(backbufferHeight != 0); - - // Preserve the render target content -#if !defined(ANGLE_ENABLE_WINDOWS_STORE) - ID3D11Texture2D *previousOffscreenTexture = mOffscreenTexture; - if (previousOffscreenTexture) - { - previousOffscreenTexture->AddRef(); - } - const int previousWidth = mWidth; - const int previousHeight = mHeight; -#endif - - releaseOffscreenTexture(); - - const d3d11::TextureFormat &backbufferFormatInfo = d3d11::GetTextureFormatInfo(mBackBufferFormat); - - // 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); - SafeRelease(tempResource11); - - 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(abs(backbufferWidth)) || - offscreenTextureDesc.Height != UINT(abs(backbufferHeight)) || - offscreenTextureDesc.Format != backbufferFormatInfo.texFormat || - 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 = !mNativeWindow.getNativeWindow() && mRenderer->getShareHandleSupport(); - - D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0}; - offscreenTextureDesc.Width = abs(backbufferWidth); - offscreenTextureDesc.Height = abs(backbufferHeight); - offscreenTextureDesc.Format = backbufferFormatInfo.texFormat; - 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 back buffer 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); - SafeRelease(offscreenTextureResource); - - if (FAILED(result)) - { - mShareHandle = NULL; - ERR("Could not get offscreen texture shared handle: %08lX", result); - } - } - } - } - - - D3D11_RENDER_TARGET_VIEW_DESC offscreenRTVDesc; - offscreenRTVDesc.Format = backbufferFormatInfo.rtvFormat; - offscreenRTVDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; - offscreenRTVDesc.Texture2D.MipSlice = 0; - - HRESULT result = device->CreateRenderTargetView(mOffscreenTexture, &offscreenRTVDesc, &mOffscreenRTView); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mOffscreenRTView, "Offscreen back buffer render target"); - - D3D11_SHADER_RESOURCE_VIEW_DESC offscreenSRVDesc; - offscreenSRVDesc.Format = backbufferFormatInfo.srvFormat; - offscreenSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; - offscreenSRVDesc.Texture2D.MostDetailedMip = 0; - offscreenSRVDesc.Texture2D.MipLevels = -1; - - result = device->CreateShaderResourceView(mOffscreenTexture, &offscreenSRVDesc, &mOffscreenSRView); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mOffscreenSRView, "Offscreen back buffer shader resource"); - - const d3d11::TextureFormat &depthBufferFormatInfo = d3d11::GetTextureFormatInfo(mDepthBufferFormat); - - if (mDepthBufferFormat != GL_NONE) - { - D3D11_TEXTURE2D_DESC depthStencilTextureDesc; - depthStencilTextureDesc.Width = abs(backbufferWidth); - depthStencilTextureDesc.Height = abs(backbufferHeight); - depthStencilTextureDesc.Format = depthBufferFormatInfo.texFormat; - depthStencilTextureDesc.MipLevels = 1; - depthStencilTextureDesc.ArraySize = 1; - depthStencilTextureDesc.SampleDesc.Count = 1; - depthStencilTextureDesc.SampleDesc.Quality = 0; - depthStencilTextureDesc.Usage = D3D11_USAGE_DEFAULT; - depthStencilTextureDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE; - depthStencilTextureDesc.CPUAccessFlags = 0; - depthStencilTextureDesc.MiscFlags = 0; - - result = device->CreateTexture2D(&depthStencilTextureDesc, 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, "Offscreen depth stencil texture"); - - D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilDesc; - depthStencilDesc.Format = depthBufferFormatInfo.dsvFormat; - depthStencilDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; - depthStencilDesc.Flags = 0; - depthStencilDesc.Texture2D.MipSlice = 0; - - result = device->CreateDepthStencilView(mDepthStencilTexture, &depthStencilDesc, &mDepthStencilDSView); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mDepthStencilDSView, "Offscreen depth stencil view"); - - D3D11_SHADER_RESOURCE_VIEW_DESC depthStencilSRVDesc; - depthStencilSRVDesc.Format = depthBufferFormatInfo.srvFormat; - depthStencilSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; - depthStencilSRVDesc.Texture2D.MostDetailedMip = 0; - depthStencilSRVDesc.Texture2D.MipLevels = -1; - - result = device->CreateShaderResourceView(mDepthStencilTexture, &depthStencilSRVDesc, &mDepthStencilSRView); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mDepthStencilSRView, "Offscreen depth stencil shader resource"); - } - - mWidth = backbufferWidth; - mHeight = backbufferHeight; - -#if !defined(ANGLE_ENABLE_WINDOWS_STORE) - 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); - - SafeRelease(previousOffscreenTexture); - - if (mSwapChain) - { - swapRect(0, 0, mWidth, mHeight); - } - } -#endif - - return EGL_SUCCESS; -} - -EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight) -{ - ID3D11Device *device = mRenderer->getDevice(); - - if (device == NULL) - { - return EGL_BAD_ACCESS; - } - - // Windows Phone works around the rotation limitation by using negative values for the swap chain size -#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) - mRotateL = backbufferWidth < 0; // Landscape/InvertedLandscape - mRotateR = backbufferHeight < 0; // InvertedPortrait/InvertedLandscape - backbufferWidth = abs(backbufferWidth); - backbufferHeight = abs(backbufferHeight); -#endif - - // EGL allows creating a surface with 0x0 dimension, however, DXGI does not like 0x0 swapchains - if (backbufferWidth == 0 || backbufferHeight == 0) - { - return EGL_SUCCESS; - } - - // Can only call resize if we have already created our swap buffer and resources - ASSERT(mSwapChain && mBackBufferTexture && mBackBufferRTView); - -#if !defined(ANGLE_ENABLE_WINDOWS_STORE) || (WINAPI_FAMILY == WINAPI_FAMILY_PC_APP) // The swap chain is not directly resized on Windows Phone - SafeRelease(mBackBufferTexture); - SafeRelease(mBackBufferRTView); - - // Resize swap chain - DXGI_SWAP_CHAIN_DESC desc; - mSwapChain->GetDesc(&desc); - const d3d11::TextureFormat &backbufferFormatInfo = d3d11::GetTextureFormatInfo(mBackBufferFormat); - HRESULT result = mSwapChain->ResizeBuffers(desc.BufferCount, backbufferWidth, backbufferHeight, backbufferFormatInfo.texFormat, 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"); - } -#endif - - return resetOffscreenTexture(backbufferWidth, backbufferHeight); -} - -EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swapInterval) -{ - ID3D11Device *device = mRenderer->getDevice(); - - if (device == NULL) - { - return EGL_BAD_ACCESS; - } - - // Release specific resources to free up memory for the new render target, while the - // old render target still exists for the purpose of preserving its contents. - SafeRelease(mSwapChain); - SafeRelease(mBackBufferTexture); - SafeRelease(mBackBufferRTView); - - mSwapInterval = static_cast(swapInterval); - if (mSwapInterval > 4) - { - // IDXGISwapChain::Present documentation states that valid sync intervals are in the [0,4] range - return EGL_BAD_PARAMETER; - } - - // EGL allows creating a surface with 0x0 dimension, however, DXGI does not like 0x0 swapchains - if (backbufferWidth < 1 || backbufferHeight < 1) - { - releaseOffscreenTexture(); - return EGL_SUCCESS; - } - - if (mNativeWindow.getNativeWindow()) - { - const d3d11::TextureFormat &backbufferFormatInfo = d3d11::GetTextureFormatInfo(mBackBufferFormat); - - HRESULT result = mNativeWindow.createSwapChain(device, mRenderer->getDxgiFactory(), - backbufferFormatInfo.texFormat, - backbufferWidth, backbufferHeight, &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_Passthrough2D, sizeof(g_VS_Passthrough2D), &mPassThroughIL); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mPassThroughIL, "Swap chain pass through layout"); - - result = device->CreateVertexShader(g_VS_Passthrough2D, sizeof(g_VS_Passthrough2D), NULL, &mPassThroughVS); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mPassThroughVS, "Swap chain pass through vertex shader"); - - result = device->CreatePixelShader(g_PS_PassthroughRGBA2D, sizeof(g_PS_PassthroughRGBA2D), 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(); - - // 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); - - const bool rotateL = mRotateL; - const bool rotateR = mRotateR; - - // 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); - - d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, rotateL ? u2 : u1, rotateR ? v2 : v1); - d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, rotateR ? u2 : u1, rotateL ? v1 : v2); - d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, rotateR ? u1 : u2, rotateL ? v2 : v1); - d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, rotateL ? u1 : u2, rotateR ? v1 : 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.0f; - viewport.TopLeftY = 0.0f; - const bool invertViewport = (mRotateL || mRotateR) && !(mRotateL && mRotateR); - viewport.Width = FLOAT(invertViewport ? mHeight : mWidth); - viewport.Height = FLOAT(invertViewport ? mWidth : mHeight); - viewport.MinDepth = 0.0f; - viewport.MaxDepth = 1.0f; - deviceContext->RSSetViewports(1, &viewport); - - // Apply textures - mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, mOffscreenSRView); - deviceContext->PSSetSamplers(0, 1, &mPassThroughSampler); - - // Draw - deviceContext->Draw(4, 0); - -#if ANGLE_VSYNC == ANGLE_DISABLED - result = mSwapChain->Present(0, 0); -#else - result = mSwapChain->Present(mSwapInterval, 0); -#endif - - if (result == DXGI_ERROR_DEVICE_REMOVED) - { - HRESULT removedReason = device->GetDeviceRemovedReason(); - UNUSED_TRACE_VARIABLE(removedReason); - 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 - mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, NULL); - - mRenderer->unapplyRenderTargets(); - mRenderer->markAllStateDirty(); - - return EGL_SUCCESS; -} - -ID3D11Texture2D *SwapChain11::getOffscreenTexture() -{ - return mOffscreenTexture; -} - -ID3D11RenderTargetView *SwapChain11::getRenderTarget() -{ - return mOffscreenRTView; -} - -ID3D11ShaderResourceView *SwapChain11::getRenderTargetShaderResource() -{ - return mOffscreenSRView; -} - -ID3D11DepthStencilView *SwapChain11::getDepthStencil() -{ - return mDepthStencilDSView; -} - -ID3D11ShaderResourceView * SwapChain11::getDepthStencilShaderResource() -{ - return mDepthStencilSRView; -} - -ID3D11Texture2D *SwapChain11::getDepthStencilTexture() -{ - return mDepthStencilTexture; -} - -SwapChain11 *SwapChain11::makeSwapChain11(SwapChain *swapChain) -{ - ASSERT(HAS_DYNAMIC_TYPE(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/d3d/d3d11/SwapChain11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.h deleted file mode 100644 index 77509edcd3..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.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. -// - -// 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, NativeWindow nativeWindow, 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(); - virtual ID3D11ShaderResourceView *getDepthStencilShaderResource(); - - 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 mRotateL; - bool mRotateR; - bool mAppCreatedShareHandle; - unsigned int mSwapInterval; - bool mPassThroughResourcesInit; - - DXGISwapChain *mSwapChain; - - ID3D11Texture2D *mBackBufferTexture; - ID3D11RenderTargetView *mBackBufferRTView; - - ID3D11Texture2D *mOffscreenTexture; - ID3D11RenderTargetView *mOffscreenRTView; - ID3D11ShaderResourceView *mOffscreenSRView; - - ID3D11Texture2D *mDepthStencilTexture; - ID3D11DepthStencilView *mDepthStencilDSView; - ID3D11ShaderResourceView *mDepthStencilSRView; - - ID3D11Buffer *mQuadVB; - ID3D11SamplerState *mPassThroughSampler; - ID3D11InputLayout *mPassThroughIL; - ID3D11VertexShader *mPassThroughVS; - ID3D11PixelShader *mPassThroughPS; -}; - -} -#endif // LIBGLESV2_RENDERER_SWAPCHAIN11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.cpp deleted file mode 100644 index 74af27e8b3..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.cpp +++ /dev/null @@ -1,2112 +0,0 @@ -// -// Copyright (c) 2012-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// 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/d3d/d3d11/TextureStorage11.h" - -#include - -#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" -#include "libGLESv2/renderer/d3d/d3d11/RenderTarget11.h" -#include "libGLESv2/renderer/d3d/d3d11/SwapChain11.h" -#include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h" -#include "libGLESv2/renderer/d3d/d3d11/Blit11.h" -#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" -#include "libGLESv2/renderer/d3d/d3d11/Image11.h" -#include "libGLESv2/renderer/d3d/MemoryBuffer.h" -#include "libGLESv2/renderer/d3d/TextureD3D.h" -#include "libGLESv2/main.h" -#include "libGLESv2/ImageIndex.h" - -#include "common/utilities.h" - -namespace rx -{ - -TextureStorage11::SwizzleCacheValue::SwizzleCacheValue() - : swizzleRed(GL_NONE), swizzleGreen(GL_NONE), swizzleBlue(GL_NONE), swizzleAlpha(GL_NONE) -{ -} - -TextureStorage11::SwizzleCacheValue::SwizzleCacheValue(GLenum red, GLenum green, GLenum blue, GLenum alpha) - : swizzleRed(red), swizzleGreen(green), swizzleBlue(blue), swizzleAlpha(alpha) -{ -} - -bool TextureStorage11::SwizzleCacheValue::operator==(const SwizzleCacheValue &other) const -{ - return swizzleRed == other.swizzleRed && - swizzleGreen == other.swizzleGreen && - swizzleBlue == other.swizzleBlue && - swizzleAlpha == other.swizzleAlpha; -} - -bool TextureStorage11::SwizzleCacheValue::operator!=(const SwizzleCacheValue &other) const -{ - return !(*this == other); -} - -TextureStorage11::SRVKey::SRVKey(int baseLevel, int mipLevels, bool swizzle) - : baseLevel(baseLevel), mipLevels(mipLevels), swizzle(swizzle) -{ -} - -bool TextureStorage11::SRVKey::operator<(const SRVKey &rhs) const -{ - return std::tie(baseLevel, mipLevels, swizzle) < std::tie(rhs.baseLevel, rhs.mipLevels, rhs.swizzle); -} - -TextureStorage11::TextureStorage11(Renderer11 *renderer, UINT bindFlags) - : mBindFlags(bindFlags), - mTopLevel(0), - mMipLevels(0), - mInternalFormat(GL_NONE), - mTextureFormat(DXGI_FORMAT_UNKNOWN), - mShaderResourceFormat(DXGI_FORMAT_UNKNOWN), - mRenderTargetFormat(DXGI_FORMAT_UNKNOWN), - mDepthStencilFormat(DXGI_FORMAT_UNKNOWN), - mTextureWidth(0), - mTextureHeight(0), - mTextureDepth(0) -{ - mRenderer = Renderer11::makeRenderer11(renderer); - - for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) - { - mLevelSRVs[i] = NULL; - } -} - -TextureStorage11::~TextureStorage11() -{ - for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) - { - SafeRelease(mLevelSRVs[level]); - } - - for (SRVCache::iterator i = mSrvCache.begin(); i != mSrvCache.end(); i++) - { - SafeRelease(i->second); - } - mSrvCache.clear(); -} - -TextureStorage11 *TextureStorage11::makeTextureStorage11(TextureStorage *storage) -{ - ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11*, storage)); - return static_cast(storage); -} - -DWORD TextureStorage11::GetTextureBindFlags(GLenum internalFormat, bool renderTarget) -{ - UINT bindFlags = 0; - - const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalFormat); - if (formatInfo.srvFormat != DXGI_FORMAT_UNKNOWN) - { - bindFlags |= D3D11_BIND_SHADER_RESOURCE; - } - if (formatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN) - { - bindFlags |= D3D11_BIND_DEPTH_STENCIL; - } - if (formatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN && renderTarget) - { - bindFlags |= D3D11_BIND_RENDER_TARGET; - } - - return bindFlags; -} - -UINT TextureStorage11::getBindFlags() const -{ - return mBindFlags; -} - -int TextureStorage11::getTopLevel() const -{ - return mTopLevel; -} - -bool TextureStorage11::isRenderTarget() const -{ - return (mBindFlags & (D3D11_BIND_RENDER_TARGET | D3D11_BIND_DEPTH_STENCIL)) != 0; -} - -bool TextureStorage11::isManaged() const -{ - return false; -} - -int TextureStorage11::getLevelCount() const -{ - return mMipLevels - mTopLevel; -} - -int TextureStorage11::getLevelWidth(int mipLevel) const -{ - return std::max(static_cast(mTextureWidth) >> mipLevel, 1); -} - -int TextureStorage11::getLevelHeight(int mipLevel) const -{ - return std::max(static_cast(mTextureHeight) >> mipLevel, 1); -} - -int TextureStorage11::getLevelDepth(int mipLevel) const -{ - return std::max(static_cast(mTextureDepth) >> mipLevel, 1); -} - -UINT TextureStorage11::getSubresourceIndex(const gl::ImageIndex &index) const -{ - UINT mipSlice = static_cast(index.mipIndex + mTopLevel); - UINT arraySlice = static_cast(index.hasLayer() ? index.layerIndex : 0); - UINT subresource = D3D11CalcSubresource(mipSlice, arraySlice, mMipLevels); - ASSERT(subresource != std::numeric_limits::max()); - return subresource; -} - -gl::Error TextureStorage11::getSRV(const gl::SamplerState &samplerState, ID3D11ShaderResourceView **outSRV) -{ - bool swizzleRequired = samplerState.swizzleRequired(); - bool mipmapping = gl::IsMipmapFiltered(samplerState); - unsigned int mipLevels = mipmapping ? (samplerState.maxLevel - samplerState.baseLevel) : 1; - - // Make sure there's 'mipLevels' mipmap levels below the base level (offset by the top level, which corresponds to GL level 0) - mipLevels = std::min(mipLevels, mMipLevels - mTopLevel - samplerState.baseLevel); - - if (swizzleRequired) - { - verifySwizzleExists(samplerState.swizzleRed, samplerState.swizzleGreen, samplerState.swizzleBlue, samplerState.swizzleAlpha); - } - - SRVKey key(samplerState.baseLevel, mipLevels, swizzleRequired); - SRVCache::const_iterator iter = mSrvCache.find(key); - if (iter != mSrvCache.end()) - { - *outSRV = iter->second; - } - else - { - ID3D11Resource *texture = NULL; - if (swizzleRequired) - { - gl::Error error = getSwizzleTexture(&texture); - if (error.isError()) - { - return error; - } - } - else - { - gl::Error error = getResource(&texture); - if (error.isError()) - { - return error; - } - } - - ID3D11ShaderResourceView *srv = NULL; - DXGI_FORMAT format = (swizzleRequired ? mSwizzleShaderResourceFormat : mShaderResourceFormat); - gl::Error error = createSRV(samplerState.baseLevel, mipLevels, format, texture, &srv); - if (error.isError()) - { - return error; - } - - mSrvCache.insert(std::make_pair(key, srv)); - *outSRV = srv; - } - - return gl::Error(GL_NO_ERROR); -} - -gl::Error TextureStorage11::getSRVLevel(int mipLevel, ID3D11ShaderResourceView **outSRV) -{ - ASSERT(mipLevel >= 0 && mipLevel < getLevelCount()); - - if (!mLevelSRVs[mipLevel]) - { - ID3D11Resource *resource = NULL; - gl::Error error = getResource(&resource); - if (error.isError()) - { - return error; - } - - error = createSRV(mipLevel, 1, mShaderResourceFormat, resource, &mLevelSRVs[mipLevel]); - if (error.isError()) - { - return error; - } - } - - *outSRV = mLevelSRVs[mipLevel]; - - return gl::Error(GL_NO_ERROR); -} - -gl::Error TextureStorage11::generateSwizzles(GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha) -{ - SwizzleCacheValue swizzleTarget(swizzleRed, swizzleGreen, swizzleBlue, swizzleAlpha); - for (int level = 0; level < getLevelCount(); level++) - { - // Check if the swizzle for this level is out of date - if (mSwizzleCache[level] != swizzleTarget) - { - // Need to re-render the swizzle for this level - ID3D11ShaderResourceView *sourceSRV = NULL; - gl::Error error = getSRVLevel(level, &sourceSRV); - if (error.isError()) - { - return error; - } - - ID3D11RenderTargetView *destRTV = NULL; - error = getSwizzleRenderTarget(level, &destRTV); - if (error.isError()) - { - return error; - } - - gl::Extents size(getLevelWidth(level), getLevelHeight(level), getLevelDepth(level)); - - Blit11 *blitter = mRenderer->getBlitter(); - - error = blitter->swizzleTexture(sourceSRV, destRTV, size, swizzleRed, swizzleGreen, swizzleBlue, swizzleAlpha); - if (error.isError()) - { - return error; - } - - mSwizzleCache[level] = swizzleTarget; - } - } - - return gl::Error(GL_NO_ERROR); -} - -void TextureStorage11::invalidateSwizzleCacheLevel(int mipLevel) -{ - if (mipLevel >= 0 && static_cast(mipLevel) < ArraySize(mSwizzleCache)) - { - // The default constructor of SwizzleCacheValue has GL_NONE for all channels which is not a - // valid swizzle combination - mSwizzleCache[mipLevel] = SwizzleCacheValue(); - } -} - -void TextureStorage11::invalidateSwizzleCache() -{ - for (unsigned int mipLevel = 0; mipLevel < ArraySize(mSwizzleCache); mipLevel++) - { - invalidateSwizzleCacheLevel(mipLevel); - } -} - -gl::Error TextureStorage11::updateSubresourceLevel(ID3D11Resource *srcTexture, unsigned int sourceSubresource, - const gl::ImageIndex &index, const gl::Box ©Area) -{ - ASSERT(srcTexture); - - GLint level = index.mipIndex; - - invalidateSwizzleCacheLevel(level); - - gl::Extents texSize(getLevelWidth(level), getLevelHeight(level), getLevelDepth(level)); - - bool fullCopy = copyArea.x == 0 && - copyArea.y == 0 && - copyArea.z == 0 && - copyArea.width == texSize.width && - copyArea.height == texSize.height && - copyArea.depth == texSize.depth; - - ID3D11Resource *dstTexture = NULL; - gl::Error error = getResource(&dstTexture); - if (error.isError()) - { - return error; - } - - unsigned int dstSubresource = getSubresourceIndex(index); - - ASSERT(dstTexture); - - const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mTextureFormat); - if (!fullCopy && (dxgiFormatInfo.depthBits > 0 || dxgiFormatInfo.stencilBits > 0)) - { - // CopySubresourceRegion cannot copy partial depth stencils, use the blitter instead - Blit11 *blitter = mRenderer->getBlitter(); - - return blitter->copyDepthStencil(srcTexture, sourceSubresource, copyArea, texSize, - dstTexture, dstSubresource, copyArea, texSize, - NULL); - } - else - { - const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mTextureFormat); - - D3D11_BOX srcBox; - srcBox.left = copyArea.x; - srcBox.top = copyArea.y; - srcBox.right = copyArea.x + roundUp(static_cast(copyArea.width), dxgiFormatInfo.blockWidth); - srcBox.bottom = copyArea.y + roundUp(static_cast(copyArea.height), dxgiFormatInfo.blockHeight); - srcBox.front = copyArea.z; - srcBox.back = copyArea.z + copyArea.depth; - - ID3D11DeviceContext *context = mRenderer->getDeviceContext(); - - context->CopySubresourceRegion(dstTexture, dstSubresource, copyArea.x, copyArea.y, copyArea.z, - srcTexture, sourceSubresource, fullCopy ? NULL : &srcBox); - return gl::Error(GL_NO_ERROR); - } -} - -gl::Error TextureStorage11::copySubresourceLevel(ID3D11Resource* dstTexture, unsigned int dstSubresource, - const gl::ImageIndex &index, const gl::Box ®ion) -{ - ASSERT(dstTexture); - - ID3D11Resource *srcTexture = NULL; - gl::Error error = getResource(&srcTexture); - if (error.isError()) - { - return error; - } - - ASSERT(srcTexture); - - unsigned int srcSubresource = getSubresourceIndex(index); - - ID3D11DeviceContext *context = mRenderer->getDeviceContext(); - context->CopySubresourceRegion(dstTexture, dstSubresource, region.x, region.y, region.z, - srcTexture, srcSubresource, NULL); - - return gl::Error(GL_NO_ERROR); -} - -gl::Error TextureStorage11::generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex) -{ - ASSERT(sourceIndex.layerIndex == destIndex.layerIndex); - - invalidateSwizzleCacheLevel(destIndex.mipIndex); - - RenderTarget *source = NULL; - gl::Error error = getRenderTarget(sourceIndex, &source); - if (error.isError()) - { - return error; - } - - RenderTarget *dest = NULL; - error = getRenderTarget(destIndex, &dest); - if (error.isError()) - { - return error; - } - - ID3D11ShaderResourceView *sourceSRV = RenderTarget11::makeRenderTarget11(source)->getShaderResourceView(); - ID3D11RenderTargetView *destRTV = RenderTarget11::makeRenderTarget11(dest)->getRenderTargetView(); - - gl::Box sourceArea(0, 0, 0, source->getWidth(), source->getHeight(), source->getDepth()); - gl::Extents sourceSize(source->getWidth(), source->getHeight(), source->getDepth()); - - gl::Box destArea(0, 0, 0, dest->getWidth(), dest->getHeight(), dest->getDepth()); - gl::Extents destSize(dest->getWidth(), dest->getHeight(), dest->getDepth()); - - Blit11 *blitter = mRenderer->getBlitter(); - return blitter->copyTexture(sourceSRV, sourceArea, sourceSize, destRTV, destArea, destSize, NULL, - gl::GetInternalFormatInfo(source->getInternalFormat()).format, GL_LINEAR); -} - -void TextureStorage11::verifySwizzleExists(GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha) -{ - SwizzleCacheValue swizzleTarget(swizzleRed, swizzleGreen, swizzleBlue, swizzleAlpha); - for (unsigned int level = 0; level < mMipLevels; level++) - { - ASSERT(mSwizzleCache[level] == swizzleTarget); - } -} - -gl::Error TextureStorage11::copyToStorage(TextureStorage *destStorage) -{ - ASSERT(destStorage); - - ID3D11Resource *sourceResouce = NULL; - gl::Error error = getResource(&sourceResouce); - if (error.isError()) - { - return error; - } - - TextureStorage11 *dest11 = TextureStorage11::makeTextureStorage11(destStorage); - ID3D11Resource *destResource = NULL; - error = dest11->getResource(&destResource); - if (error.isError()) - { - return error; - } - - ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext(); - immediateContext->CopyResource(destResource, sourceResouce); - - dest11->invalidateSwizzleCache(); - - return gl::Error(GL_NO_ERROR); -} - -gl::Error TextureStorage11::setData(const gl::ImageIndex &index, Image *image, const gl::Box *destBox, GLenum type, - const gl::PixelUnpackState &unpack, const uint8_t *pixelData) -{ - ID3D11Resource *resource = NULL; - gl::Error error = getResource(&resource); - if (error.isError()) - { - return error; - } - ASSERT(resource); - - UINT destSubresource = getSubresourceIndex(index); - - const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(image->getInternalFormat()); - - bool fullUpdate = (destBox == NULL || *destBox == gl::Box(0, 0, 0, mTextureWidth, mTextureHeight, mTextureDepth)); - ASSERT(internalFormatInfo.depthBits == 0 || fullUpdate); - - // TODO(jmadill): Handle compressed formats - // Compressed formats have different load syntax, so we'll have to handle them with slightly - // different logic. Will implemnent this in a follow-up patch, and ensure we do not use SetData - // with compressed formats in the calling logic. - ASSERT(!internalFormatInfo.compressed); - - int width = destBox ? destBox->width : static_cast(image->getWidth()); - int height = destBox ? destBox->height : static_cast(image->getHeight()); - int depth = destBox ? destBox->depth : static_cast(image->getDepth()); - UINT srcRowPitch = internalFormatInfo.computeRowPitch(type, width, unpack.alignment); - UINT srcDepthPitch = internalFormatInfo.computeDepthPitch(type, width, height, unpack.alignment); - - const d3d11::TextureFormat &d3d11Format = d3d11::GetTextureFormatInfo(image->getInternalFormat()); - const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(d3d11Format.texFormat); - - size_t outputPixelSize = dxgiFormatInfo.pixelBytes; - - UINT bufferRowPitch = outputPixelSize * width; - UINT bufferDepthPitch = bufferRowPitch * height; - - MemoryBuffer conversionBuffer; - if (!conversionBuffer.resize(bufferDepthPitch * depth)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal buffer."); - } - - // TODO: fast path - LoadImageFunction loadFunction = d3d11Format.loadFunctions.at(type); - loadFunction(width, height, depth, - pixelData, srcRowPitch, srcDepthPitch, - conversionBuffer.data(), bufferRowPitch, bufferDepthPitch); - - ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext(); - - if (!fullUpdate) - { - ASSERT(destBox); - - D3D11_BOX destD3DBox; - destD3DBox.left = destBox->x; - destD3DBox.right = destBox->x + destBox->width; - destD3DBox.top = destBox->y; - destD3DBox.bottom = destBox->y + destBox->height; - destD3DBox.front = 0; - destD3DBox.back = 1; - - immediateContext->UpdateSubresource(resource, destSubresource, - &destD3DBox, conversionBuffer.data(), - bufferRowPitch, bufferDepthPitch); - } - else - { - immediateContext->UpdateSubresource(resource, destSubresource, - NULL, conversionBuffer.data(), - bufferRowPitch, bufferDepthPitch); - } - - return gl::Error(GL_NO_ERROR); -} - -TextureStorage11_2D::TextureStorage11_2D(Renderer11 *renderer, SwapChain11 *swapchain) - : TextureStorage11(renderer, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE), - mTexture(swapchain->getOffscreenTexture()), - mSwizzleTexture(NULL) -{ - mTexture->AddRef(); - - for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) - { - mAssociatedImages[i] = NULL; - mRenderTarget[i] = NULL; - mSwizzleRenderTargets[i] = NULL; - } - - D3D11_TEXTURE2D_DESC texDesc; - mTexture->GetDesc(&texDesc); - mMipLevels = texDesc.MipLevels; - mTextureFormat = texDesc.Format; - mTextureWidth = texDesc.Width; - mTextureHeight = texDesc.Height; - mTextureDepth = 1; - - mInternalFormat = swapchain->GetBackBufferInternalFormat(); - - ID3D11ShaderResourceView *srv = swapchain->getRenderTargetShaderResource(); - D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; - srv->GetDesc(&srvDesc); - mShaderResourceFormat = srvDesc.Format; - - ID3D11RenderTargetView* offscreenRTV = swapchain->getRenderTarget(); - D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; - offscreenRTV->GetDesc(&rtvDesc); - mRenderTargetFormat = rtvDesc.Format; - - const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mTextureFormat); - const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(dxgiFormatInfo.internalFormat); - mSwizzleTextureFormat = formatInfo.swizzleTexFormat; - mSwizzleShaderResourceFormat = formatInfo.swizzleSRVFormat; - mSwizzleRenderTargetFormat = formatInfo.swizzleRTVFormat; - - mDepthStencilFormat = DXGI_FORMAT_UNKNOWN; - - initializeSerials(1, 1); -} - -TextureStorage11_2D::TextureStorage11_2D(Renderer11 *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels) - : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderTarget)), - mTexture(NULL), - mSwizzleTexture(NULL) -{ - for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) - { - mAssociatedImages[i] = NULL; - mRenderTarget[i] = NULL; - mSwizzleRenderTargets[i] = NULL; - } - - mInternalFormat = internalformat; - - const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat); - mTextureFormat = formatInfo.texFormat; - mShaderResourceFormat = formatInfo.srvFormat; - mDepthStencilFormat = formatInfo.dsvFormat; - mRenderTargetFormat = formatInfo.rtvFormat; - mSwizzleTextureFormat = formatInfo.swizzleTexFormat; - mSwizzleShaderResourceFormat = formatInfo.swizzleSRVFormat; - mSwizzleRenderTargetFormat = formatInfo.swizzleRTVFormat; - - d3d11::MakeValidSize(false, mTextureFormat, &width, &height, &mTopLevel); - mMipLevels = mTopLevel + levels; - mTextureWidth = width; - mTextureHeight = height; - mTextureDepth = 1; - - initializeSerials(getLevelCount(), 1); -} - -TextureStorage11_2D::~TextureStorage11_2D() -{ - for (unsigned i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) - { - if (mAssociatedImages[i] != NULL) - { - bool imageAssociationCorrect = mAssociatedImages[i]->isAssociatedStorageValid(this); - ASSERT(imageAssociationCorrect); - - if (imageAssociationCorrect) - { - // We must let the Images recover their data before we delete it from the TextureStorage. - gl::Error error = mAssociatedImages[i]->recoverFromAssociatedStorage(); - if (error.isError()) - { - // TODO: Find a way to report this back to the context - } - } - } - } - - SafeRelease(mTexture); - SafeRelease(mSwizzleTexture); - - for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) - { - SafeDelete(mRenderTarget[i]); - SafeRelease(mSwizzleRenderTargets[i]); - } -} - -TextureStorage11_2D *TextureStorage11_2D::makeTextureStorage11_2D(TextureStorage *storage) -{ - ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_2D*, storage)); - return static_cast(storage); -} - -void TextureStorage11_2D::associateImage(Image11* image, const gl::ImageIndex &index) -{ - GLint level = index.mipIndex; - - ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); - - if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) - { - mAssociatedImages[level] = image; - } -} - -bool TextureStorage11_2D::isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage) -{ - GLint level = index.mipIndex; - - if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) - { - // This validation check should never return false. It means the Image/TextureStorage association is broken. - bool retValue = (mAssociatedImages[level] == expectedImage); - ASSERT(retValue); - return retValue; - } - - return false; -} - -// disassociateImage allows an Image to end its association with a Storage. -void TextureStorage11_2D::disassociateImage(const gl::ImageIndex &index, Image11* expectedImage) -{ - GLint level = index.mipIndex; - - ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); - - if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) - { - ASSERT(mAssociatedImages[level] == expectedImage); - - if (mAssociatedImages[level] == expectedImage) - { - mAssociatedImages[level] = NULL; - } - } -} - -// releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image recover its data before ending the association. -gl::Error TextureStorage11_2D::releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage) -{ - GLint level = index.mipIndex; - - ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); - - if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) - { - // No need to let the old Image recover its data, if it is also the incoming Image. - if (mAssociatedImages[level] != NULL && mAssociatedImages[level] != incomingImage) - { - // Ensure that the Image is still associated with this TextureStorage. This should be true. - bool imageAssociationCorrect = mAssociatedImages[level]->isAssociatedStorageValid(this); - ASSERT(imageAssociationCorrect); - - if (imageAssociationCorrect) - { - // Force the image to recover from storage before its data is overwritten. - // This will reset mAssociatedImages[level] to NULL too. - gl::Error error = mAssociatedImages[level]->recoverFromAssociatedStorage(); - if (error.isError()) - { - return error; - } - } - } - } - - return gl::Error(GL_NO_ERROR); -} - -gl::Error TextureStorage11_2D::getResource(ID3D11Resource **outResource) -{ - // 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 (mTexture == NULL && mTextureWidth > 0 && mTextureHeight > 0) - { - ASSERT(mMipLevels > 0); - - ID3D11Device *device = mRenderer->getDevice(); - - D3D11_TEXTURE2D_DESC desc; - desc.Width = mTextureWidth; // Compressed texture size constraints? - desc.Height = mTextureHeight; - desc.MipLevels = mRenderer->isLevel9() ? 1 : mMipLevels; - 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(); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create 2D texture storage, result: 0x%X.", result); - } - else if (FAILED(result)) - { - ASSERT(result == E_OUTOFMEMORY); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create 2D texture storage, result: 0x%X.", result); - } - } - - *outResource = mTexture; - return gl::Error(GL_NO_ERROR); -} - -gl::Error TextureStorage11_2D::getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT) -{ - ASSERT(!index.hasLayer()); - - int level = index.mipIndex; - ASSERT(level >= 0 && level < getLevelCount()); - - if (!mRenderTarget[level]) - { - ID3D11Resource *texture = NULL; - gl::Error error = getResource(&texture); - if (error.isError()) - { - return error; - } - - ID3D11ShaderResourceView *srv = NULL; - error = getSRVLevel(level, &srv); - if (error.isError()) - { - return error; - } - - if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN) - { - ID3D11Device *device = mRenderer->getDevice(); - - D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; - rtvDesc.Format = mRenderTargetFormat; - rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; - rtvDesc.Texture2D.MipSlice = mTopLevel + level; - - ID3D11RenderTargetView *rtv; - HRESULT result = device->CreateRenderTargetView(texture, &rtvDesc, &rtv); - - ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal render target view for texture storage, result: 0x%X.", result); - } - - mRenderTarget[level] = new TextureRenderTarget11(rtv, texture, srv, mInternalFormat, getLevelWidth(level), getLevelHeight(level), 1, 0); - - // RenderTarget will take ownership of these resources - SafeRelease(rtv); - } - else if (mDepthStencilFormat != DXGI_FORMAT_UNKNOWN) - { - ID3D11Device *device = mRenderer->getDevice(); - - D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; - dsvDesc.Format = mDepthStencilFormat; - dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; - dsvDesc.Texture2D.MipSlice = mTopLevel + level; - dsvDesc.Flags = 0; - - ID3D11DepthStencilView *dsv; - HRESULT result = device->CreateDepthStencilView(texture, &dsvDesc, &dsv); - - ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY,"Failed to create internal depth stencil view for texture storage, result: 0x%X.", result); - } - - mRenderTarget[level] = new TextureRenderTarget11(dsv, texture, srv, mInternalFormat, getLevelWidth(level), getLevelHeight(level), 1, 0); - - // RenderTarget will take ownership of these resources - SafeRelease(dsv); - } - else - { - UNREACHABLE(); - } - } - - ASSERT(outRT); - *outRT = mRenderTarget[level]; - return gl::Error(GL_NO_ERROR); -} - -gl::Error TextureStorage11_2D::createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture, - ID3D11ShaderResourceView **outSRV) const -{ - ASSERT(outSRV); - - D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; - srvDesc.Format = format; - srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MostDetailedMip = mTopLevel + baseLevel; - srvDesc.Texture2D.MipLevels = mRenderer->isLevel9() ? -1 : mipLevels; - - ID3D11Device *device = mRenderer->getDevice(); - HRESULT result = device->CreateShaderResourceView(texture, &srvDesc, outSRV); - - ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal texture storage SRV, result: 0x%X.", result); - } - - return gl::Error(GL_NO_ERROR); -} - -gl::Error TextureStorage11_2D::getSwizzleTexture(ID3D11Resource **outTexture) -{ - ASSERT(outTexture); - - if (!mSwizzleTexture) - { - ID3D11Device *device = mRenderer->getDevice(); - - D3D11_TEXTURE2D_DESC desc; - desc.Width = mTextureWidth; - desc.Height = mTextureHeight; - desc.MipLevels = mMipLevels; - desc.ArraySize = 1; - desc.Format = mSwizzleTextureFormat; - desc.SampleDesc.Count = 1; - desc.SampleDesc.Quality = 0; - desc.Usage = D3D11_USAGE_DEFAULT; - desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET; - desc.CPUAccessFlags = 0; - desc.MiscFlags = 0; - - HRESULT result = device->CreateTexture2D(&desc, NULL, &mSwizzleTexture); - - ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal swizzle texture, result: 0x%X.", result); - } - } - - *outTexture = mSwizzleTexture; - return gl::Error(GL_NO_ERROR); -} - -gl::Error TextureStorage11_2D::getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV) -{ - ASSERT(mipLevel >= 0 && mipLevel < getLevelCount()); - ASSERT(outRTV); - - if (!mSwizzleRenderTargets[mipLevel]) - { - ID3D11Resource *swizzleTexture = NULL; - gl::Error error = getSwizzleTexture(&swizzleTexture); - if (error.isError()) - { - return error; - } - - ID3D11Device *device = mRenderer->getDevice(); - - D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; - rtvDesc.Format = mSwizzleRenderTargetFormat; - rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; - rtvDesc.Texture2D.MipSlice = mTopLevel + mipLevel; - - HRESULT result = device->CreateRenderTargetView(mSwizzleTexture, &rtvDesc, &mSwizzleRenderTargets[mipLevel]); - - ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal swizzle render target view, result: 0x%X.", result); - } - } - - *outRTV = mSwizzleRenderTargets[mipLevel]; - return gl::Error(GL_NO_ERROR); -} - -TextureStorage11_Cube::TextureStorage11_Cube(Renderer11 *renderer, GLenum internalformat, bool renderTarget, int size, int levels) - : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderTarget)) -{ - mTexture = NULL; - mSwizzleTexture = NULL; - - for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) - { - mSwizzleRenderTargets[level] = NULL; - for (unsigned int face = 0; face < CUBE_FACE_COUNT; face++) - { - mAssociatedImages[face][level] = NULL; - mRenderTarget[face][level] = NULL; - } - } - - mInternalFormat = internalformat; - - const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat); - mTextureFormat = formatInfo.texFormat; - mShaderResourceFormat = formatInfo.srvFormat; - mDepthStencilFormat = formatInfo.dsvFormat; - mRenderTargetFormat = formatInfo.rtvFormat; - mSwizzleTextureFormat = formatInfo.swizzleTexFormat; - mSwizzleShaderResourceFormat = formatInfo.swizzleSRVFormat; - mSwizzleRenderTargetFormat = formatInfo.swizzleRTVFormat; - - // adjust size if needed for compressed textures - int height = size; - d3d11::MakeValidSize(false, mTextureFormat, &size, &height, &mTopLevel); - - mMipLevels = mTopLevel + levels; - mTextureWidth = size; - mTextureHeight = size; - mTextureDepth = 1; - - initializeSerials(getLevelCount() * CUBE_FACE_COUNT, CUBE_FACE_COUNT); -} - -TextureStorage11_Cube::~TextureStorage11_Cube() -{ - for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) - { - for (unsigned int face = 0; face < CUBE_FACE_COUNT; face++) - { - if (mAssociatedImages[face][level] != NULL) - { - bool imageAssociationCorrect = mAssociatedImages[face][level]->isAssociatedStorageValid(this); - ASSERT(imageAssociationCorrect); - - if (imageAssociationCorrect) - { - // We must let the Images recover their data before we delete it from the TextureStorage. - mAssociatedImages[face][level]->recoverFromAssociatedStorage(); - } - } - } - } - - SafeRelease(mTexture); - SafeRelease(mSwizzleTexture); - - for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) - { - SafeRelease(mSwizzleRenderTargets[level]); - for (unsigned int face = 0; face < CUBE_FACE_COUNT; face++) - { - SafeDelete(mRenderTarget[face][level]); - } - } -} - -TextureStorage11_Cube *TextureStorage11_Cube::makeTextureStorage11_Cube(TextureStorage *storage) -{ - ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_Cube*, storage)); - return static_cast(storage); -} - -void TextureStorage11_Cube::associateImage(Image11* image, const gl::ImageIndex &index) -{ - GLint level = index.mipIndex; - GLint layerTarget = index.layerIndex; - - ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); - ASSERT(0 <= layerTarget && layerTarget < CUBE_FACE_COUNT); - - if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) - { - if (0 <= layerTarget && layerTarget < CUBE_FACE_COUNT) - { - mAssociatedImages[layerTarget][level] = image; - } - } -} - -bool TextureStorage11_Cube::isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage) -{ - GLint level = index.mipIndex; - GLint layerTarget = index.layerIndex; - - if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) - { - if (0 <= layerTarget && layerTarget < CUBE_FACE_COUNT) - { - // This validation check should never return false. It means the Image/TextureStorage association is broken. - bool retValue = (mAssociatedImages[layerTarget][level] == expectedImage); - ASSERT(retValue); - return retValue; - } - } - - return false; -} - -// disassociateImage allows an Image to end its association with a Storage. -void TextureStorage11_Cube::disassociateImage(const gl::ImageIndex &index, Image11* expectedImage) -{ - GLint level = index.mipIndex; - GLint layerTarget = index.layerIndex; - - ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); - ASSERT(0 <= layerTarget && layerTarget < CUBE_FACE_COUNT); - - if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) - { - if (0 <= layerTarget && layerTarget < CUBE_FACE_COUNT) - { - ASSERT(mAssociatedImages[layerTarget][level] == expectedImage); - - if (mAssociatedImages[layerTarget][level] == expectedImage) - { - mAssociatedImages[layerTarget][level] = NULL; - } - } - } -} - -// releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image recover its data before ending the association. -gl::Error TextureStorage11_Cube::releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage) -{ - GLint level = index.mipIndex; - GLint layerTarget = index.layerIndex; - - ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); - ASSERT(0 <= layerTarget && layerTarget < CUBE_FACE_COUNT); - - if ((0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)) - { - if (0 <= layerTarget && layerTarget < CUBE_FACE_COUNT) - { - // No need to let the old Image recover its data, if it is also the incoming Image. - if (mAssociatedImages[layerTarget][level] != NULL && mAssociatedImages[layerTarget][level] != incomingImage) - { - // Ensure that the Image is still associated with this TextureStorage. This should be true. - bool imageAssociationCorrect = mAssociatedImages[layerTarget][level]->isAssociatedStorageValid(this); - ASSERT(imageAssociationCorrect); - - if (imageAssociationCorrect) - { - // Force the image to recover from storage before its data is overwritten. - // This will reset mAssociatedImages[level] to NULL too. - gl::Error error = mAssociatedImages[layerTarget][level]->recoverFromAssociatedStorage(); - if (error.isError()) - { - return error; - } - } - } - } - } - - return gl::Error(GL_NO_ERROR); -} - -gl::Error TextureStorage11_Cube::getResource(ID3D11Resource **outResource) -{ - // 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 (mTexture == NULL && mTextureWidth > 0 && mTextureHeight > 0) - { - ASSERT(mMipLevels > 0); - - ID3D11Device *device = mRenderer->getDevice(); - - D3D11_TEXTURE2D_DESC desc; - desc.Width = mTextureWidth; - desc.Height = mTextureHeight; - desc.MipLevels = mMipLevels; - desc.ArraySize = CUBE_FACE_COUNT; - 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); - - // this can happen from windows TDR - if (d3d11::isDeviceLostError(result)) - { - mRenderer->notifyDeviceLost(); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create cube texture storage, result: 0x%X.", result); - } - else if (FAILED(result)) - { - ASSERT(result == E_OUTOFMEMORY); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create cube texture storage, result: 0x%X.", result); - } - } - - *outResource = mTexture; - return gl::Error(GL_NO_ERROR); -} - -gl::Error TextureStorage11_Cube::getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT) -{ - int faceIndex = index.layerIndex; - int level = index.mipIndex; - - ASSERT(level >= 0 && level < getLevelCount()); - ASSERT(faceIndex >= 0 && faceIndex < CUBE_FACE_COUNT); - - if (!mRenderTarget[faceIndex][level]) - { - ID3D11Device *device = mRenderer->getDevice(); - HRESULT result; - - ID3D11Resource *texture = NULL; - gl::Error error = getResource(&texture); - if (error.isError()) - { - return error; - } - - D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; - srvDesc.Format = mShaderResourceFormat; - srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; // Will be used with Texture2D sampler, not TextureCube - srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + level; - srvDesc.Texture2DArray.MipLevels = 1; - srvDesc.Texture2DArray.FirstArraySlice = faceIndex; - srvDesc.Texture2DArray.ArraySize = 1; - - ID3D11ShaderResourceView *srv; - result = device->CreateShaderResourceView(texture, &srvDesc, &srv); - - ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal shader resource view for texture storage, result: 0x%X.", result); - } - - if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN) - { - D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; - rtvDesc.Format = mRenderTargetFormat; - rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; - rtvDesc.Texture2DArray.MipSlice = mTopLevel + level; - rtvDesc.Texture2DArray.FirstArraySlice = faceIndex; - rtvDesc.Texture2DArray.ArraySize = 1; - - ID3D11RenderTargetView *rtv; - result = device->CreateRenderTargetView(texture, &rtvDesc, &rtv); - - ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); - if (FAILED(result)) - { - SafeRelease(srv); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal render target view for texture storage, result: 0x%X.", result); - } - - mRenderTarget[faceIndex][level] = new TextureRenderTarget11(rtv, texture, srv, mInternalFormat, getLevelWidth(level), getLevelHeight(level), 1, 0); - - // RenderTarget will take ownership of these resources - SafeRelease(rtv); - SafeRelease(srv); - } - else if (mDepthStencilFormat != DXGI_FORMAT_UNKNOWN) - { - D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; - dsvDesc.Format = mDepthStencilFormat; - dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY; - dsvDesc.Flags = 0; - dsvDesc.Texture2DArray.MipSlice = mTopLevel + level; - dsvDesc.Texture2DArray.FirstArraySlice = faceIndex; - dsvDesc.Texture2DArray.ArraySize = 1; - - ID3D11DepthStencilView *dsv; - result = device->CreateDepthStencilView(texture, &dsvDesc, &dsv); - - ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); - if (FAILED(result)) - { - SafeRelease(srv); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal depth stencil view for texture storage, result: 0x%X.", result); - } - - mRenderTarget[faceIndex][level] = new TextureRenderTarget11(dsv, texture, srv, mInternalFormat, getLevelWidth(level), getLevelHeight(level), 1, 0); - - // RenderTarget will take ownership of these resources - SafeRelease(dsv); - SafeRelease(srv); - } - else - { - UNREACHABLE(); - } - } - - ASSERT(outRT); - *outRT = mRenderTarget[faceIndex][level]; - return gl::Error(GL_NO_ERROR); -} - -gl::Error TextureStorage11_Cube::createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture, - ID3D11ShaderResourceView **outSRV) const -{ - ASSERT(outSRV); - - D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; - srvDesc.Format = format; - - // Unnormalized integer cube maps are not supported by DX11; we emulate them as an array of six 2D textures - const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(format); - if (dxgiFormatInfo.componentType == GL_INT || dxgiFormatInfo.componentType == GL_UNSIGNED_INT) - { - srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; - srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + baseLevel; - srvDesc.Texture2DArray.MipLevels = 1; - srvDesc.Texture2DArray.FirstArraySlice = 0; - srvDesc.Texture2DArray.ArraySize = CUBE_FACE_COUNT; - } - else - { - srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE; - srvDesc.TextureCube.MipLevels = mipLevels; - srvDesc.TextureCube.MostDetailedMip = mTopLevel + baseLevel; - } - - ID3D11Device *device = mRenderer->getDevice(); - HRESULT result = device->CreateShaderResourceView(texture, &srvDesc, outSRV); - - ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal texture storage SRV, result: 0x%X.", result); - } - - return gl::Error(GL_NO_ERROR); -} - -gl::Error TextureStorage11_Cube::getSwizzleTexture(ID3D11Resource **outTexture) -{ - ASSERT(outTexture); - - if (!mSwizzleTexture) - { - ID3D11Device *device = mRenderer->getDevice(); - - D3D11_TEXTURE2D_DESC desc; - desc.Width = mTextureWidth; - desc.Height = mTextureHeight; - desc.MipLevels = mMipLevels; - desc.ArraySize = CUBE_FACE_COUNT; - desc.Format = mSwizzleTextureFormat; - desc.SampleDesc.Count = 1; - desc.SampleDesc.Quality = 0; - desc.Usage = D3D11_USAGE_DEFAULT; - desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET; - desc.CPUAccessFlags = 0; - desc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE; - - HRESULT result = device->CreateTexture2D(&desc, NULL, &mSwizzleTexture); - - ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal swizzle texture, result: 0x%X.", result); - } - } - - *outTexture = mSwizzleTexture; - return gl::Error(GL_NO_ERROR); -} - -gl::Error TextureStorage11_Cube::getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV) -{ - ASSERT(mipLevel >= 0 && mipLevel < getLevelCount()); - ASSERT(outRTV); - - if (!mSwizzleRenderTargets[mipLevel]) - { - ID3D11Resource *swizzleTexture = NULL; - gl::Error error = getSwizzleTexture(&swizzleTexture); - if (error.isError()) - { - return error; - } - - ID3D11Device *device = mRenderer->getDevice(); - - D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; - rtvDesc.Format = mSwizzleRenderTargetFormat; - rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; - rtvDesc.Texture2DArray.MipSlice = mTopLevel + mipLevel; - rtvDesc.Texture2DArray.FirstArraySlice = 0; - rtvDesc.Texture2DArray.ArraySize = CUBE_FACE_COUNT; - - HRESULT result = device->CreateRenderTargetView(mSwizzleTexture, &rtvDesc, &mSwizzleRenderTargets[mipLevel]); - - ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal swizzle render target view, result: 0x%X.", result); - } - } - - *outRTV = mSwizzleRenderTargets[mipLevel]; - return gl::Error(GL_NO_ERROR); -} - -TextureStorage11_3D::TextureStorage11_3D(Renderer11 *renderer, GLenum internalformat, bool renderTarget, - GLsizei width, GLsizei height, GLsizei depth, int levels) - : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderTarget)) -{ - mTexture = NULL; - mSwizzleTexture = NULL; - - for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) - { - mAssociatedImages[i] = NULL; - mLevelRenderTargets[i] = NULL; - mSwizzleRenderTargets[i] = NULL; - } - - mInternalFormat = internalformat; - - const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat); - mTextureFormat = formatInfo.texFormat; - mShaderResourceFormat = formatInfo.srvFormat; - mDepthStencilFormat = formatInfo.dsvFormat; - mRenderTargetFormat = formatInfo.rtvFormat; - mSwizzleTextureFormat = formatInfo.swizzleTexFormat; - mSwizzleShaderResourceFormat = formatInfo.swizzleSRVFormat; - mSwizzleRenderTargetFormat = formatInfo.swizzleRTVFormat; - - // adjust size if needed for compressed textures - d3d11::MakeValidSize(false, mTextureFormat, &width, &height, &mTopLevel); - - mMipLevels = mTopLevel + levels; - mTextureWidth = width; - mTextureHeight = height; - mTextureDepth = depth; - - initializeSerials(getLevelCount() * depth, depth); -} - -TextureStorage11_3D::~TextureStorage11_3D() -{ - for (unsigned i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) - { - if (mAssociatedImages[i] != NULL) - { - bool imageAssociationCorrect = mAssociatedImages[i]->isAssociatedStorageValid(this); - ASSERT(imageAssociationCorrect); - - if (imageAssociationCorrect) - { - // We must let the Images recover their data before we delete it from the TextureStorage. - mAssociatedImages[i]->recoverFromAssociatedStorage(); - } - } - } - - SafeRelease(mTexture); - SafeRelease(mSwizzleTexture); - - for (RenderTargetMap::iterator i = mLevelLayerRenderTargets.begin(); i != mLevelLayerRenderTargets.end(); i++) - { - SafeDelete(i->second); - } - mLevelLayerRenderTargets.clear(); - - for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) - { - SafeDelete(mLevelRenderTargets[i]); - SafeRelease(mSwizzleRenderTargets[i]); - } -} - -TextureStorage11_3D *TextureStorage11_3D::makeTextureStorage11_3D(TextureStorage *storage) -{ - ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_3D*, storage)); - return static_cast(storage); -} - -void TextureStorage11_3D::associateImage(Image11* image, const gl::ImageIndex &index) -{ - GLint level = index.mipIndex; - - ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); - - if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) - { - mAssociatedImages[level] = image; - } -} - -bool TextureStorage11_3D::isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage) -{ - GLint level = index.mipIndex; - - if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) - { - // This validation check should never return false. It means the Image/TextureStorage association is broken. - bool retValue = (mAssociatedImages[level] == expectedImage); - ASSERT(retValue); - return retValue; - } - - return false; -} - -// disassociateImage allows an Image to end its association with a Storage. -void TextureStorage11_3D::disassociateImage(const gl::ImageIndex &index, Image11* expectedImage) -{ - GLint level = index.mipIndex; - - ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); - - if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) - { - ASSERT(mAssociatedImages[level] == expectedImage); - - if (mAssociatedImages[level] == expectedImage) - { - mAssociatedImages[level] = NULL; - } - } -} - -// releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image recover its data before ending the association. -gl::Error TextureStorage11_3D::releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage) -{ - GLint level = index.mipIndex; - - ASSERT((0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)); - - if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) - { - // No need to let the old Image recover its data, if it is also the incoming Image. - if (mAssociatedImages[level] != NULL && mAssociatedImages[level] != incomingImage) - { - // Ensure that the Image is still associated with this TextureStorage. This should be true. - bool imageAssociationCorrect = mAssociatedImages[level]->isAssociatedStorageValid(this); - ASSERT(imageAssociationCorrect); - - if (imageAssociationCorrect) - { - // Force the image to recover from storage before its data is overwritten. - // This will reset mAssociatedImages[level] to NULL too. - gl::Error error = mAssociatedImages[level]->recoverFromAssociatedStorage(); - if (error.isError()) - { - return error; - } - } - } - } - - return gl::Error(GL_NO_ERROR); -} - -gl::Error TextureStorage11_3D::getResource(ID3D11Resource **outResource) -{ - // If the width, height or depth are not positive this should be treated as an incomplete texture - // we handle that here by skipping the d3d texture creation - if (mTexture == NULL && mTextureWidth > 0 && mTextureHeight > 0 && mTextureDepth > 0) - { - ASSERT(mMipLevels > 0); - - ID3D11Device *device = mRenderer->getDevice(); - - D3D11_TEXTURE3D_DESC desc; - desc.Width = mTextureWidth; - desc.Height = mTextureHeight; - desc.Depth = mTextureDepth; - desc.MipLevels = mMipLevels; - desc.Format = mTextureFormat; - desc.Usage = D3D11_USAGE_DEFAULT; - desc.BindFlags = getBindFlags(); - desc.CPUAccessFlags = 0; - desc.MiscFlags = 0; - - HRESULT result = device->CreateTexture3D(&desc, NULL, &mTexture); - - // this can happen from windows TDR - if (d3d11::isDeviceLostError(result)) - { - mRenderer->notifyDeviceLost(); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create 3D texture storage, result: 0x%X.", result); - } - else if (FAILED(result)) - { - ASSERT(result == E_OUTOFMEMORY); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create 3D texture storage, result: 0x%X.", result); - } - } - - *outResource = mTexture; - return gl::Error(GL_NO_ERROR); -} - -gl::Error TextureStorage11_3D::createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture, - ID3D11ShaderResourceView **outSRV) const -{ - ASSERT(outSRV); - - D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; - srvDesc.Format = format; - srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D; - srvDesc.Texture3D.MostDetailedMip = baseLevel; - srvDesc.Texture3D.MipLevels = mipLevels; - - ID3D11Device *device = mRenderer->getDevice(); - HRESULT result = device->CreateShaderResourceView(texture, &srvDesc, outSRV); - - ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal texture storage SRV, result: 0x%X.", result); - } - - return gl::Error(GL_NO_ERROR); -} - -gl::Error TextureStorage11_3D::getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT) -{ - int mipLevel = index.mipIndex; - ASSERT(mipLevel >= 0 && mipLevel < getLevelCount()); - - ASSERT(mRenderTargetFormat != DXGI_FORMAT_UNKNOWN); - - if (!index.hasLayer()) - { - if (!mLevelRenderTargets[mipLevel]) - { - ID3D11Resource *texture = NULL; - gl::Error error = getResource(&texture); - if (error.isError()) - { - return error; - } - - ID3D11ShaderResourceView *srv = NULL; - error = getSRVLevel(mipLevel, &srv); - if (error.isError()) - { - return error; - } - - ID3D11Device *device = mRenderer->getDevice(); - - D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; - rtvDesc.Format = mRenderTargetFormat; - rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D; - rtvDesc.Texture3D.MipSlice = mTopLevel + mipLevel; - rtvDesc.Texture3D.FirstWSlice = 0; - rtvDesc.Texture3D.WSize = -1; - - ID3D11RenderTargetView *rtv; - HRESULT result = device->CreateRenderTargetView(texture, &rtvDesc, &rtv); - - ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); - if (FAILED(result)) - { - SafeRelease(srv); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal render target view for texture storage, result: 0x%X.", result); - } - - mLevelRenderTargets[mipLevel] = new TextureRenderTarget11(rtv, texture, srv, mInternalFormat, getLevelWidth(mipLevel), getLevelHeight(mipLevel), getLevelDepth(mipLevel), 0); - - // RenderTarget will take ownership of these resources - SafeRelease(rtv); - } - - ASSERT(outRT); - *outRT = mLevelRenderTargets[mipLevel]; - return gl::Error(GL_NO_ERROR); - } - else - { - int layer = index.layerIndex; - - LevelLayerKey key(mipLevel, layer); - if (mLevelLayerRenderTargets.find(key) == mLevelLayerRenderTargets.end()) - { - ID3D11Device *device = mRenderer->getDevice(); - HRESULT result; - - ID3D11Resource *texture = NULL; - gl::Error error = getResource(&texture); - if (error.isError()) - { - return error; - } - - // TODO, what kind of SRV is expected here? - ID3D11ShaderResourceView *srv = NULL; - - D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; - rtvDesc.Format = mRenderTargetFormat; - rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D; - rtvDesc.Texture3D.MipSlice = mTopLevel + mipLevel; - rtvDesc.Texture3D.FirstWSlice = layer; - rtvDesc.Texture3D.WSize = 1; - - ID3D11RenderTargetView *rtv; - result = device->CreateRenderTargetView(texture, &rtvDesc, &rtv); - - ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); - if (FAILED(result)) - { - SafeRelease(srv); return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal render target view for texture storage, result: 0x%X.", result); - } - ASSERT(SUCCEEDED(result)); - - mLevelLayerRenderTargets[key] = new TextureRenderTarget11(rtv, texture, srv, mInternalFormat, getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1, 0); - - // RenderTarget will take ownership of these resources - SafeRelease(rtv); - } - - ASSERT(outRT); - *outRT = mLevelLayerRenderTargets[key]; - return gl::Error(GL_NO_ERROR); - } -} - -gl::Error TextureStorage11_3D::getSwizzleTexture(ID3D11Resource **outTexture) -{ - ASSERT(outTexture); - - if (!mSwizzleTexture) - { - ID3D11Device *device = mRenderer->getDevice(); - - D3D11_TEXTURE3D_DESC desc; - desc.Width = mTextureWidth; - desc.Height = mTextureHeight; - desc.Depth = mTextureDepth; - desc.MipLevels = mMipLevels; - desc.Format = mSwizzleTextureFormat; - desc.Usage = D3D11_USAGE_DEFAULT; - desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET; - desc.CPUAccessFlags = 0; - desc.MiscFlags = 0; - - HRESULT result = device->CreateTexture3D(&desc, NULL, &mSwizzleTexture); - - ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal swizzle texture, result: 0x%X.", result); - } - } - - *outTexture = mSwizzleTexture; - return gl::Error(GL_NO_ERROR); -} - -gl::Error TextureStorage11_3D::getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV) -{ - ASSERT(mipLevel >= 0 && mipLevel < getLevelCount()); - ASSERT(outRTV); - - if (!mSwizzleRenderTargets[mipLevel]) - { - ID3D11Resource *swizzleTexture = NULL; - gl::Error error = getSwizzleTexture(&swizzleTexture); - if (error.isError()) - { - return error; - } - - ID3D11Device *device = mRenderer->getDevice(); - - D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; - rtvDesc.Format = mSwizzleRenderTargetFormat; - rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D; - rtvDesc.Texture3D.MipSlice = mTopLevel + mipLevel; - rtvDesc.Texture3D.FirstWSlice = 0; - rtvDesc.Texture3D.WSize = -1; - - HRESULT result = device->CreateRenderTargetView(mSwizzleTexture, &rtvDesc, &mSwizzleRenderTargets[mipLevel]); - - ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal swizzle render target view, result: 0x%X.", result); - } - } - - *outRTV = mSwizzleRenderTargets[mipLevel]; - return gl::Error(GL_NO_ERROR); -} - -TextureStorage11_2DArray::TextureStorage11_2DArray(Renderer11 *renderer, GLenum internalformat, bool renderTarget, - GLsizei width, GLsizei height, GLsizei depth, int levels) - : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderTarget)) -{ - mTexture = NULL; - mSwizzleTexture = NULL; - - for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) - { - mSwizzleRenderTargets[level] = NULL; - } - - mInternalFormat = internalformat; - - const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat); - mTextureFormat = formatInfo.texFormat; - mShaderResourceFormat = formatInfo.srvFormat; - mDepthStencilFormat = formatInfo.dsvFormat; - mRenderTargetFormat = formatInfo.rtvFormat; - mSwizzleTextureFormat = formatInfo.swizzleTexFormat; - mSwizzleShaderResourceFormat = formatInfo.swizzleSRVFormat; - mSwizzleRenderTargetFormat = formatInfo.swizzleRTVFormat; - - // adjust size if needed for compressed textures - d3d11::MakeValidSize(false, mTextureFormat, &width, &height, &mTopLevel); - - mMipLevels = mTopLevel + levels; - mTextureWidth = width; - mTextureHeight = height; - mTextureDepth = depth; - - initializeSerials(getLevelCount() * depth, depth); -} - -TextureStorage11_2DArray::~TextureStorage11_2DArray() -{ - for (ImageMap::iterator i = mAssociatedImages.begin(); i != mAssociatedImages.end(); i++) - { - bool imageAssociationCorrect = i->second->isAssociatedStorageValid(this); - ASSERT(imageAssociationCorrect); - - if (imageAssociationCorrect) - { - // We must let the Images recover their data before we delete it from the TextureStorage. - i->second->recoverFromAssociatedStorage(); - } - } - mAssociatedImages.clear(); - - SafeRelease(mTexture); - SafeRelease(mSwizzleTexture); - - for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) - { - SafeRelease(mSwizzleRenderTargets[level]); - } - - for (RenderTargetMap::iterator i = mRenderTargets.begin(); i != mRenderTargets.end(); i++) - { - SafeDelete(i->second); - } - mRenderTargets.clear(); -} - -TextureStorage11_2DArray *TextureStorage11_2DArray::makeTextureStorage11_2DArray(TextureStorage *storage) -{ - ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_2DArray*, storage)); - return static_cast(storage); -} - -void TextureStorage11_2DArray::associateImage(Image11* image, const gl::ImageIndex &index) -{ - GLint level = index.mipIndex; - GLint layerTarget = index.layerIndex; - - ASSERT(0 <= level && level < getLevelCount()); - - if (0 <= level && level < getLevelCount()) - { - LevelLayerKey key(level, layerTarget); - mAssociatedImages[key] = image; - } -} - -bool TextureStorage11_2DArray::isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage) -{ - GLint level = index.mipIndex; - GLint layerTarget = index.layerIndex; - - LevelLayerKey key(level, layerTarget); - - // This validation check should never return false. It means the Image/TextureStorage association is broken. - bool retValue = (mAssociatedImages.find(key) != mAssociatedImages.end() && (mAssociatedImages[key] == expectedImage)); - ASSERT(retValue); - return retValue; -} - -// disassociateImage allows an Image to end its association with a Storage. -void TextureStorage11_2DArray::disassociateImage(const gl::ImageIndex &index, Image11* expectedImage) -{ - GLint level = index.mipIndex; - GLint layerTarget = index.layerIndex; - - LevelLayerKey key(level, layerTarget); - - bool imageAssociationCorrect = (mAssociatedImages.find(key) != mAssociatedImages.end() && (mAssociatedImages[key] == expectedImage)); - ASSERT(imageAssociationCorrect); - - if (imageAssociationCorrect) - { - mAssociatedImages[key] = NULL; - } -} - -// releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image recover its data before ending the association. -gl::Error TextureStorage11_2DArray::releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage) -{ - GLint level = index.mipIndex; - GLint layerTarget = index.layerIndex; - - LevelLayerKey key(level, layerTarget); - - ASSERT(mAssociatedImages.find(key) != mAssociatedImages.end()); - - if (mAssociatedImages.find(key) != mAssociatedImages.end()) - { - if (mAssociatedImages[key] != NULL && mAssociatedImages[key] != incomingImage) - { - // Ensure that the Image is still associated with this TextureStorage. This should be true. - bool imageAssociationCorrect = mAssociatedImages[key]->isAssociatedStorageValid(this); - ASSERT(imageAssociationCorrect); - - if (imageAssociationCorrect) - { - // Force the image to recover from storage before its data is overwritten. - // This will reset mAssociatedImages[level] to NULL too. - gl::Error error = mAssociatedImages[key]->recoverFromAssociatedStorage(); - if (error.isError()) - { - return error; - } - } - } - } - - return gl::Error(GL_NO_ERROR); -} - -gl::Error TextureStorage11_2DArray::getResource(ID3D11Resource **outResource) -{ - // if the width, height or depth is not positive this should be treated as an incomplete texture - // we handle that here by skipping the d3d texture creation - if (mTexture == NULL && mTextureWidth > 0 && mTextureHeight > 0 && mTextureDepth > 0) - { - ASSERT(mMipLevels > 0); - - ID3D11Device *device = mRenderer->getDevice(); - - D3D11_TEXTURE2D_DESC desc; - desc.Width = mTextureWidth; - desc.Height = mTextureHeight; - desc.MipLevels = mMipLevels; - desc.ArraySize = mTextureDepth; - 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(); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create 2D array texture storage, result: 0x%X.", result); - } - else if (FAILED(result)) - { - ASSERT(result == E_OUTOFMEMORY); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create 2D array texture storage, result: 0x%X.", result); - } - } - - *outResource = mTexture; - return gl::Error(GL_NO_ERROR); -} - -gl::Error TextureStorage11_2DArray::createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture, - ID3D11ShaderResourceView **outSRV) const -{ - D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; - srvDesc.Format = format; - srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; - srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + baseLevel; - srvDesc.Texture2DArray.MipLevels = mipLevels; - srvDesc.Texture2DArray.FirstArraySlice = 0; - srvDesc.Texture2DArray.ArraySize = mTextureDepth; - - ID3D11Device *device = mRenderer->getDevice(); - HRESULT result = device->CreateShaderResourceView(texture, &srvDesc, outSRV); - - ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal texture storage SRV, result: 0x%X.", result); - } - - return gl::Error(GL_NO_ERROR); -} - -gl::Error TextureStorage11_2DArray::getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT) -{ - ASSERT(index.hasLayer()); - - int mipLevel = index.mipIndex; - int layer = index.layerIndex; - - ASSERT(mipLevel >= 0 && mipLevel < getLevelCount()); - - LevelLayerKey key(mipLevel, layer); - if (mRenderTargets.find(key) == mRenderTargets.end()) - { - ID3D11Device *device = mRenderer->getDevice(); - HRESULT result; - - ID3D11Resource *texture = NULL; - gl::Error error = getResource(&texture); - if (error.isError()) - { - return error; - } - - D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; - srvDesc.Format = mShaderResourceFormat; - srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; - srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + mipLevel; - srvDesc.Texture2DArray.MipLevels = 1; - srvDesc.Texture2DArray.FirstArraySlice = layer; - srvDesc.Texture2DArray.ArraySize = 1; - - ID3D11ShaderResourceView *srv; - result = device->CreateShaderResourceView(texture, &srvDesc, &srv); - - ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal shader resource view for texture storage, result: 0x%X.", result); - } - - if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN) - { - D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; - rtvDesc.Format = mRenderTargetFormat; - rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; - rtvDesc.Texture2DArray.MipSlice = mTopLevel + mipLevel; - rtvDesc.Texture2DArray.FirstArraySlice = layer; - rtvDesc.Texture2DArray.ArraySize = 1; - - ID3D11RenderTargetView *rtv; - result = device->CreateRenderTargetView(texture, &rtvDesc, &rtv); - - ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); - if (FAILED(result)) - { - SafeRelease(srv); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal render target view for texture storage, result: 0x%X.", result); - } - - mRenderTargets[key] = new TextureRenderTarget11(rtv, texture, srv, mInternalFormat, getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1, 0); - - // RenderTarget will take ownership of these resources - SafeRelease(rtv); - SafeRelease(srv); - } - else - { - UNREACHABLE(); - } - } - - ASSERT(outRT); - *outRT = mRenderTargets[key]; - return gl::Error(GL_NO_ERROR); -} - -gl::Error TextureStorage11_2DArray::getSwizzleTexture(ID3D11Resource **outTexture) -{ - if (!mSwizzleTexture) - { - ID3D11Device *device = mRenderer->getDevice(); - - D3D11_TEXTURE2D_DESC desc; - desc.Width = mTextureWidth; - desc.Height = mTextureHeight; - desc.MipLevels = mMipLevels; - desc.ArraySize = mTextureDepth; - desc.Format = mSwizzleTextureFormat; - desc.SampleDesc.Count = 1; - desc.SampleDesc.Quality = 0; - desc.Usage = D3D11_USAGE_DEFAULT; - desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET; - desc.CPUAccessFlags = 0; - desc.MiscFlags = 0; - - HRESULT result = device->CreateTexture2D(&desc, NULL, &mSwizzleTexture); - - ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal swizzle texture, result: 0x%X.", result); - } - } - - *outTexture = mSwizzleTexture; - return gl::Error(GL_NO_ERROR); -} - -gl::Error TextureStorage11_2DArray::getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV) -{ - ASSERT(mipLevel >= 0 && mipLevel < getLevelCount()); - ASSERT(outRTV); - - if (!mSwizzleRenderTargets[mipLevel]) - { - ID3D11Resource *swizzleTexture = NULL; - gl::Error error = getSwizzleTexture(&swizzleTexture); - if (error.isError()) - { - return error; - } - - ID3D11Device *device = mRenderer->getDevice(); - - D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; - rtvDesc.Format = mSwizzleRenderTargetFormat; - rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; - rtvDesc.Texture2DArray.MipSlice = mTopLevel + mipLevel; - rtvDesc.Texture2DArray.FirstArraySlice = 0; - rtvDesc.Texture2DArray.ArraySize = mTextureDepth; - - HRESULT result = device->CreateRenderTargetView(mSwizzleTexture, &rtvDesc, &mSwizzleRenderTargets[mipLevel]); - - ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal swizzle render target view, result: 0x%X.", result); - } - } - - *outRTV = mSwizzleRenderTargets[mipLevel]; - return gl::Error(GL_NO_ERROR); -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.h deleted file mode 100644 index 930300a63d..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.h +++ /dev/null @@ -1,298 +0,0 @@ -// -// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// 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/Error.h" -#include "libGLESv2/renderer/d3d/TextureStorage.h" - -#include - -namespace gl -{ -struct ImageIndex; -} - -namespace rx -{ -class RenderTarget; -class RenderTarget11; -class Renderer11; -class SwapChain11; -class Image11; - -class TextureStorage11 : public TextureStorage -{ - public: - virtual ~TextureStorage11(); - - static TextureStorage11 *makeTextureStorage11(TextureStorage *storage); - - static DWORD GetTextureBindFlags(GLenum internalFormat, bool renderTarget); - - UINT getBindFlags() const; - - virtual gl::Error getResource(ID3D11Resource **outResource) = 0; - virtual gl::Error getSRV(const gl::SamplerState &samplerState, ID3D11ShaderResourceView **outSRV); - virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT) = 0; - - virtual gl::Error generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex); - - virtual int getTopLevel() const; - virtual bool isRenderTarget() const; - virtual bool isManaged() const; - virtual int getLevelCount() const; - UINT getSubresourceIndex(const gl::ImageIndex &index) const; - - gl::Error generateSwizzles(GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha); - void invalidateSwizzleCacheLevel(int mipLevel); - void invalidateSwizzleCache(); - - gl::Error updateSubresourceLevel(ID3D11Resource *texture, unsigned int sourceSubresource, - const gl::ImageIndex &index, const gl::Box ©Area); - - gl::Error copySubresourceLevel(ID3D11Resource* dstTexture, unsigned int dstSubresource, - const gl::ImageIndex &index, const gl::Box ®ion); - - virtual void associateImage(Image11* image, const gl::ImageIndex &index) = 0; - virtual void disassociateImage(const gl::ImageIndex &index, Image11* expectedImage) = 0; - virtual bool isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage) = 0; - virtual gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage) = 0; - - virtual gl::Error copyToStorage(TextureStorage *destStorage); - virtual gl::Error setData(const gl::ImageIndex &index, Image *image, const gl::Box *destBox, GLenum type, - const gl::PixelUnpackState &unpack, const uint8_t *pixelData); - - protected: - TextureStorage11(Renderer11 *renderer, UINT bindFlags); - int getLevelWidth(int mipLevel) const; - int getLevelHeight(int mipLevel) const; - int getLevelDepth(int mipLevel) const; - - virtual gl::Error getSwizzleTexture(ID3D11Resource **outTexture) = 0; - virtual gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV) = 0; - gl::Error getSRVLevel(int mipLevel, ID3D11ShaderResourceView **outSRV); - - virtual gl::Error createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture, - ID3D11ShaderResourceView **outSRV) const = 0; - - void verifySwizzleExists(GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha); - - Renderer11 *mRenderer; - int mTopLevel; - unsigned int mMipLevels; - - GLenum mInternalFormat; - DXGI_FORMAT mTextureFormat; - DXGI_FORMAT mShaderResourceFormat; - DXGI_FORMAT mRenderTargetFormat; - DXGI_FORMAT mDepthStencilFormat; - DXGI_FORMAT mSwizzleTextureFormat; - DXGI_FORMAT mSwizzleShaderResourceFormat; - DXGI_FORMAT mSwizzleRenderTargetFormat; - unsigned int mTextureWidth; - unsigned int mTextureHeight; - unsigned int mTextureDepth; - - struct SwizzleCacheValue - { - GLenum swizzleRed; - GLenum swizzleGreen; - GLenum swizzleBlue; - GLenum swizzleAlpha; - - SwizzleCacheValue(); - SwizzleCacheValue(GLenum red, GLenum green, GLenum blue, GLenum alpha); - - bool operator ==(const SwizzleCacheValue &other) const; - bool operator !=(const SwizzleCacheValue &other) const; - }; - SwizzleCacheValue mSwizzleCache[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; - - private: - DISALLOW_COPY_AND_ASSIGN(TextureStorage11); - - const UINT mBindFlags; - - struct SRVKey - { - SRVKey(int baseLevel = 0, int mipLevels = 0, bool swizzle = false); - - bool operator<(const SRVKey &rhs) const; - - int baseLevel; - int mipLevels; - bool swizzle; - }; - typedef std::map SRVCache; - - SRVCache mSrvCache; - ID3D11ShaderResourceView *mLevelSRVs[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; -}; - -class TextureStorage11_2D : public TextureStorage11 -{ - public: - TextureStorage11_2D(Renderer11 *renderer, SwapChain11 *swapchain); - TextureStorage11_2D(Renderer11 *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels); - virtual ~TextureStorage11_2D(); - - static TextureStorage11_2D *makeTextureStorage11_2D(TextureStorage *storage); - - virtual gl::Error getResource(ID3D11Resource **outResource); - virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT); - - virtual void associateImage(Image11* image, const gl::ImageIndex &index); - virtual void disassociateImage(const gl::ImageIndex &index, Image11* expectedImage); - virtual bool isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage); - virtual gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage); - - protected: - virtual gl::Error getSwizzleTexture(ID3D11Resource **outTexture); - virtual gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV); - - private: - DISALLOW_COPY_AND_ASSIGN(TextureStorage11_2D); - - virtual gl::Error createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture, - ID3D11ShaderResourceView **outSRV) const; - - ID3D11Texture2D *mTexture; - RenderTarget11 *mRenderTarget[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; - - ID3D11Texture2D *mSwizzleTexture; - ID3D11RenderTargetView *mSwizzleRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; - - Image11 *mAssociatedImages[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; -}; - -class TextureStorage11_Cube : public TextureStorage11 -{ - public: - TextureStorage11_Cube(Renderer11 *renderer, GLenum internalformat, bool renderTarget, int size, int levels); - virtual ~TextureStorage11_Cube(); - - static TextureStorage11_Cube *makeTextureStorage11_Cube(TextureStorage *storage); - - virtual gl::Error getResource(ID3D11Resource **outResource); - virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT); - - virtual void associateImage(Image11* image, const gl::ImageIndex &index); - virtual void disassociateImage(const gl::ImageIndex &index, Image11* expectedImage); - virtual bool isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage); - virtual gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage); - - protected: - virtual gl::Error getSwizzleTexture(ID3D11Resource **outTexture); - virtual gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV); - - private: - DISALLOW_COPY_AND_ASSIGN(TextureStorage11_Cube); - - virtual gl::Error createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture, - ID3D11ShaderResourceView **outSRV) const; - - static const size_t CUBE_FACE_COUNT = 6; - - ID3D11Texture2D *mTexture; - RenderTarget11 *mRenderTarget[CUBE_FACE_COUNT][gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; - - ID3D11Texture2D *mSwizzleTexture; - ID3D11RenderTargetView *mSwizzleRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; - - Image11 *mAssociatedImages[CUBE_FACE_COUNT][gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; -}; - -class TextureStorage11_3D : public TextureStorage11 -{ - public: - TextureStorage11_3D(Renderer11 *renderer, GLenum internalformat, bool renderTarget, - GLsizei width, GLsizei height, GLsizei depth, int levels); - virtual ~TextureStorage11_3D(); - - static TextureStorage11_3D *makeTextureStorage11_3D(TextureStorage *storage); - - virtual gl::Error getResource(ID3D11Resource **outResource); - - // Handles both layer and non-layer RTs - virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT); - - virtual void associateImage(Image11* image, const gl::ImageIndex &index); - virtual void disassociateImage(const gl::ImageIndex &index, Image11* expectedImage); - virtual bool isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage); - virtual gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage); - - protected: - virtual gl::Error getSwizzleTexture(ID3D11Resource **outTexture); - virtual gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV); - - private: - DISALLOW_COPY_AND_ASSIGN(TextureStorage11_3D); - - virtual gl::Error createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture, - ID3D11ShaderResourceView **outSRV) const; - - typedef std::pair LevelLayerKey; - typedef std::map RenderTargetMap; - RenderTargetMap mLevelLayerRenderTargets; - - RenderTarget11 *mLevelRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; - - ID3D11Texture3D *mTexture; - ID3D11Texture3D *mSwizzleTexture; - ID3D11RenderTargetView *mSwizzleRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; - - Image11 *mAssociatedImages[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; -}; - -class TextureStorage11_2DArray : public TextureStorage11 -{ - public: - TextureStorage11_2DArray(Renderer11 *renderer, GLenum internalformat, bool renderTarget, - GLsizei width, GLsizei height, GLsizei depth, int levels); - virtual ~TextureStorage11_2DArray(); - - static TextureStorage11_2DArray *makeTextureStorage11_2DArray(TextureStorage *storage); - - virtual gl::Error getResource(ID3D11Resource **outResource); - virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT); - - virtual void associateImage(Image11* image, const gl::ImageIndex &index); - virtual void disassociateImage(const gl::ImageIndex &index, Image11* expectedImage); - virtual bool isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage); - virtual gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage); - - protected: - virtual gl::Error getSwizzleTexture(ID3D11Resource **outTexture); - virtual gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV); - - private: - DISALLOW_COPY_AND_ASSIGN(TextureStorage11_2DArray); - - virtual gl::Error createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture, - ID3D11ShaderResourceView **outSRV) const; - - typedef std::pair LevelLayerKey; - typedef std::map RenderTargetMap; - RenderTargetMap mRenderTargets; - - ID3D11Texture2D *mTexture; - - ID3D11Texture2D *mSwizzleTexture; - ID3D11RenderTargetView *mSwizzleRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; - - typedef std::map ImageMap; - ImageMap mAssociatedImages; -}; - -} - -#endif // LIBGLESV2_RENDERER_TEXTURESTORAGE11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexArray11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexArray11.h deleted file mode 100644 index 70bc3bb26f..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexArray11.h +++ /dev/null @@ -1,42 +0,0 @@ -// -// Copyright 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// VertexArray11.h: Defines the rx::VertexArray11 class which implements rx::VertexArrayImpl. - -#ifndef LIBGLESV2_RENDERER_VERTEXARRAY11_H_ -#define LIBGLESV2_RENDERER_VERTEXARRAY11_H_ - -#include "libGLESv2/renderer/VertexArrayImpl.h" -#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" - -namespace rx -{ -class Renderer11; - -class VertexArray11 : public VertexArrayImpl -{ - public: - VertexArray11(Renderer11 *renderer) - : VertexArrayImpl(), - mRenderer(renderer) - { - } - virtual ~VertexArray11() { } - - virtual void setElementArrayBuffer(const gl::Buffer *buffer) { } - virtual void setAttribute(size_t idx, const gl::VertexAttribute &attr) { } - virtual void setAttributeDivisor(size_t idx, GLuint divisor) { } - virtual void enableAttribute(size_t idx, bool enabledState) { } - - private: - DISALLOW_COPY_AND_ASSIGN(VertexArray11); - - Renderer11 *mRenderer; -}; - -} - -#endif // LIBGLESV2_RENDERER_VERTEXARRAY11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.cpp deleted file mode 100644 index a9d6fa2ca4..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.cpp +++ /dev/null @@ -1,214 +0,0 @@ -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// VertexBuffer11.cpp: Defines the D3D11 VertexBuffer implementation. - -#include "libGLESv2/renderer/d3d/d3d11/VertexBuffer11.h" -#include "libGLESv2/renderer/d3d/d3d11/Buffer11.h" -#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" -#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" -#include "libGLESv2/Buffer.h" -#include "libGLESv2/VertexAttribute.h" - -namespace rx -{ - -VertexBuffer11::VertexBuffer11(Renderer11 *const renderer) : mRenderer(renderer) -{ - mBuffer = NULL; - mBufferSize = 0; - mDynamicUsage = false; -} - -VertexBuffer11::~VertexBuffer11() -{ - SafeRelease(mBuffer); -} - -gl::Error VertexBuffer11::initialize(unsigned int size, bool dynamicUsage) -{ - SafeRelease(mBuffer); - - 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 gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal vertex buffer of size, %lu.", size); - } - } - - mBufferSize = size; - mDynamicUsage = dynamicUsage; - - return gl::Error(GL_NO_ERROR); -} - -VertexBuffer11 *VertexBuffer11::makeVertexBuffer11(VertexBuffer *vetexBuffer) -{ - ASSERT(HAS_DYNAMIC_TYPE(VertexBuffer11*, vetexBuffer)); - return static_cast(vetexBuffer); -} - -gl::Error VertexBuffer11::storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData ¤tValue, - GLint start, GLsizei count, GLsizei instances, unsigned int offset) -{ - if (!mBuffer) - { - return gl::Error(GL_OUT_OF_MEMORY, "Internal vertex buffer is not initialized."); - } - - gl::Buffer *buffer = attrib.buffer.get(); - int inputStride = ComputeVertexAttributeStride(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)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal vertex buffer, HRESULT: 0x%08x.", result); - } - - uint8_t *output = reinterpret_cast(mappedResource.pData) + offset; - - const uint8_t *input = NULL; - if (attrib.enabled) - { - if (buffer) - { - BufferD3D *storage = BufferD3D::makeFromBuffer(buffer); - gl::Error error = storage->getData(&input); - if (error.isError()) - { - return error; - } - input += static_cast(attrib.offset); - } - else - { - input = static_cast(attrib.pointer); - } - } - else - { - input = reinterpret_cast(currentValue.FloatValues); - } - - if (instances == 0 || attrib.divisor == 0) - { - input += inputStride * start; - } - - gl::VertexFormat vertexFormat(attrib, currentValue.Type); - const d3d11::VertexFormat &vertexFormatInfo = d3d11::GetVertexFormatInfo(vertexFormat); - ASSERT(vertexFormatInfo.copyFunction != NULL); - vertexFormatInfo.copyFunction(input, inputStride, count, output); - - dxContext->Unmap(mBuffer, 0); - - return gl::Error(GL_NO_ERROR); -} - -gl::Error VertexBuffer11::getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, - GLsizei instances, unsigned int *outSpaceRequired) const -{ - unsigned int elementCount = 0; - if (attrib.enabled) - { - if (instances == 0 || attrib.divisor == 0) - { - elementCount = count; - } - else - { - // Round up to divisor, if possible - elementCount = UnsignedCeilDivide(static_cast(instances), attrib.divisor); - } - - gl::VertexFormat vertexFormat(attrib); - const d3d11::VertexFormat &vertexFormatInfo = d3d11::GetVertexFormatInfo(vertexFormat); - const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(vertexFormatInfo.nativeFormat); - unsigned int elementSize = dxgiFormatInfo.pixelBytes; - if (elementSize <= std::numeric_limits::max() / elementCount) - { - if (outSpaceRequired) - { - *outSpaceRequired = elementSize * elementCount; - } - return gl::Error(GL_NO_ERROR); - } - else - { - return gl::Error(GL_OUT_OF_MEMORY, "New vertex buffer size would result in an overflow."); - } - } - else - { - const unsigned int elementSize = 4; - if (outSpaceRequired) - { - *outSpaceRequired = elementSize * 4; - } - return gl::Error(GL_NO_ERROR); - } -} - -unsigned int VertexBuffer11::getBufferSize() const -{ - return mBufferSize; -} - -gl::Error VertexBuffer11::setBufferSize(unsigned int size) -{ - if (size > mBufferSize) - { - return initialize(size, mDynamicUsage); - } - else - { - return gl::Error(GL_NO_ERROR); - } -} - -gl::Error VertexBuffer11::discard() -{ - if (!mBuffer) - { - return gl::Error(GL_OUT_OF_MEMORY, "Internal vertex buffer is not initialized."); - } - - ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); - - D3D11_MAPPED_SUBRESOURCE mappedResource; - HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal buffer for discarding, HRESULT: 0x%08x", result); - } - - dxContext->Unmap(mBuffer, 0); - - return gl::Error(GL_NO_ERROR); -} - -ID3D11Buffer *VertexBuffer11::getBuffer() const -{ - return mBuffer; -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.h deleted file mode 100644 index a9bbac98fa..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.h +++ /dev/null @@ -1,52 +0,0 @@ -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// VertexBuffer11.h: Defines the D3D11 VertexBuffer implementation. - -#ifndef LIBGLESV2_RENDERER_VERTEXBUFFER11_H_ -#define LIBGLESV2_RENDERER_VERTEXBUFFER11_H_ - -#include "libGLESv2/renderer/d3d/VertexBuffer.h" - -namespace rx -{ -class Renderer11; - -class VertexBuffer11 : public VertexBuffer -{ - public: - explicit VertexBuffer11(Renderer11 *const renderer); - virtual ~VertexBuffer11(); - - virtual gl::Error initialize(unsigned int size, bool dynamicUsage); - - static VertexBuffer11 *makeVertexBuffer11(VertexBuffer *vetexBuffer); - - virtual gl::Error storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData ¤tValue, - GLint start, GLsizei count, GLsizei instances, unsigned int offset); - - virtual gl::Error getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances, - unsigned int *outSpaceRequired) const; - - virtual unsigned int getBufferSize() const; - virtual gl::Error setBufferSize(unsigned int size); - virtual gl::Error discard(); - - ID3D11Buffer *getBuffer() const; - - private: - DISALLOW_COPY_AND_ASSIGN(VertexBuffer11); - - Renderer11 *const mRenderer; - - ID3D11Buffer *mBuffer; - unsigned int mBufferSize; - bool mDynamicUsage; -}; - -} - -#endif // LIBGLESV2_RENDERER_VERTEXBUFFER11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.cpp deleted file mode 100644 index 90a879e170..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.cpp +++ /dev/null @@ -1,1075 +0,0 @@ -// -// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// formatutils11.cpp: Queries for GL image formats and their translations to D3D11 -// formats. - -#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" -#include "libGLESv2/renderer/generatemip.h" -#include "libGLESv2/renderer/loadimage.h" -#include "libGLESv2/renderer/copyimage.h" -#include "libGLESv2/renderer/Renderer.h" -#include "libGLESv2/renderer/copyvertex.h" - -namespace rx -{ - -namespace d3d11 -{ - -typedef std::map DXGIToESFormatMap; - -inline void AddDXGIToESEntry(DXGIToESFormatMap *map, DXGI_FORMAT key, GLenum value) -{ - map->insert(std::make_pair(key, value)); -} - -static DXGIToESFormatMap BuildDXGIToESFormatMap() -{ - DXGIToESFormatMap map; - - AddDXGIToESEntry(&map, DXGI_FORMAT_UNKNOWN, GL_NONE); - - AddDXGIToESEntry(&map, DXGI_FORMAT_A8_UNORM, GL_ALPHA8_EXT); - AddDXGIToESEntry(&map, DXGI_FORMAT_R8_UNORM, GL_R8); - AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8_UNORM, GL_RG8); - AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8B8A8_UNORM, GL_RGBA8); - AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, GL_SRGB8_ALPHA8); - AddDXGIToESEntry(&map, DXGI_FORMAT_B8G8R8A8_UNORM, GL_BGRA8_EXT); - - AddDXGIToESEntry(&map, DXGI_FORMAT_R8_SNORM, GL_R8_SNORM); - AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8_SNORM, GL_RG8_SNORM); - AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8B8A8_SNORM, GL_RGBA8_SNORM); - - AddDXGIToESEntry(&map, DXGI_FORMAT_R8_UINT, GL_R8UI); - AddDXGIToESEntry(&map, DXGI_FORMAT_R16_UINT, GL_R16UI); - AddDXGIToESEntry(&map, DXGI_FORMAT_R32_UINT, GL_R32UI); - AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8_UINT, GL_RG8UI); - AddDXGIToESEntry(&map, DXGI_FORMAT_R16G16_UINT, GL_RG16UI); - AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32_UINT, GL_RG32UI); - AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32B32_UINT, GL_RGB32UI); - AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8B8A8_UINT, GL_RGBA8UI); - AddDXGIToESEntry(&map, DXGI_FORMAT_R16G16B16A16_UINT, GL_RGBA16UI); - AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32B32A32_UINT, GL_RGBA32UI); - - AddDXGIToESEntry(&map, DXGI_FORMAT_R8_SINT, GL_R8I); - AddDXGIToESEntry(&map, DXGI_FORMAT_R16_SINT, GL_R16I); - AddDXGIToESEntry(&map, DXGI_FORMAT_R32_SINT, GL_R32I); - AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8_SINT, GL_RG8I); - AddDXGIToESEntry(&map, DXGI_FORMAT_R16G16_SINT, GL_RG16I); - AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32_SINT, GL_RG32I); - AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32B32_SINT, GL_RGB32I); - AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8B8A8_SINT, GL_RGBA8I); - AddDXGIToESEntry(&map, DXGI_FORMAT_R16G16B16A16_SINT, GL_RGBA16I); - AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32B32A32_SINT, GL_RGBA32I); - - AddDXGIToESEntry(&map, DXGI_FORMAT_R10G10B10A2_UNORM, GL_RGB10_A2); - AddDXGIToESEntry(&map, DXGI_FORMAT_R10G10B10A2_UINT, GL_RGB10_A2UI); - - AddDXGIToESEntry(&map, DXGI_FORMAT_R16_FLOAT, GL_R16F); - AddDXGIToESEntry(&map, DXGI_FORMAT_R16G16_FLOAT, GL_RG16F); - AddDXGIToESEntry(&map, DXGI_FORMAT_R16G16B16A16_FLOAT, GL_RGBA16F); - - AddDXGIToESEntry(&map, DXGI_FORMAT_R32_FLOAT, GL_R32F); - AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32_FLOAT, GL_RG32F); - AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32B32_FLOAT, GL_RGB32F); - AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32B32A32_FLOAT, GL_RGBA32F); - - AddDXGIToESEntry(&map, DXGI_FORMAT_R9G9B9E5_SHAREDEXP, GL_RGB9_E5); - AddDXGIToESEntry(&map, DXGI_FORMAT_R11G11B10_FLOAT, GL_R11F_G11F_B10F); - - AddDXGIToESEntry(&map, DXGI_FORMAT_R16_TYPELESS, GL_DEPTH_COMPONENT16); - AddDXGIToESEntry(&map, DXGI_FORMAT_R16_UNORM, GL_DEPTH_COMPONENT16); - AddDXGIToESEntry(&map, DXGI_FORMAT_D16_UNORM, GL_DEPTH_COMPONENT16); - AddDXGIToESEntry(&map, DXGI_FORMAT_R24G8_TYPELESS, GL_DEPTH24_STENCIL8_OES); - AddDXGIToESEntry(&map, DXGI_FORMAT_R24_UNORM_X8_TYPELESS, GL_DEPTH24_STENCIL8_OES); - AddDXGIToESEntry(&map, DXGI_FORMAT_D24_UNORM_S8_UINT, GL_DEPTH24_STENCIL8_OES); - AddDXGIToESEntry(&map, DXGI_FORMAT_R32G8X24_TYPELESS, GL_DEPTH32F_STENCIL8); - AddDXGIToESEntry(&map, DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS, GL_DEPTH32F_STENCIL8); - AddDXGIToESEntry(&map, DXGI_FORMAT_D32_FLOAT_S8X24_UINT, GL_DEPTH32F_STENCIL8); - AddDXGIToESEntry(&map, DXGI_FORMAT_R32_TYPELESS, GL_DEPTH_COMPONENT32F); - AddDXGIToESEntry(&map, DXGI_FORMAT_D32_FLOAT, GL_DEPTH_COMPONENT32F); - - AddDXGIToESEntry(&map, DXGI_FORMAT_BC1_UNORM, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT); - AddDXGIToESEntry(&map, DXGI_FORMAT_BC2_UNORM, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE); - AddDXGIToESEntry(&map, DXGI_FORMAT_BC3_UNORM, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE); - - return map; -} - -struct D3D11FastCopyFormat -{ - GLenum destFormat; - GLenum destType; - ColorCopyFunction copyFunction; - - D3D11FastCopyFormat(GLenum destFormat, GLenum destType, ColorCopyFunction copyFunction) - : destFormat(destFormat), destType(destType), copyFunction(copyFunction) - { } - - bool operator<(const D3D11FastCopyFormat& other) const - { - return memcmp(this, &other, sizeof(D3D11FastCopyFormat)) < 0; - } -}; - -typedef std::multimap D3D11FastCopyMap; - -static D3D11FastCopyMap BuildFastCopyMap() -{ - D3D11FastCopyMap map; - - map.insert(std::make_pair(DXGI_FORMAT_B8G8R8A8_UNORM, D3D11FastCopyFormat(GL_RGBA, GL_UNSIGNED_BYTE, CopyBGRA8ToRGBA8))); - - return map; -} - -struct DXGIDepthStencilInfo -{ - unsigned int depthBits; - unsigned int depthOffset; - unsigned int stencilBits; - unsigned int stencilOffset; -}; - -typedef std::map DepthStencilInfoMap; -typedef std::pair DepthStencilInfoPair; - -static inline void InsertDXGIDepthStencilInfo(DepthStencilInfoMap *map, DXGI_FORMAT format, unsigned int depthBits, - unsigned int depthOffset, unsigned int stencilBits, unsigned int stencilOffset) -{ - DXGIDepthStencilInfo info; - info.depthBits = depthBits; - info.depthOffset = depthOffset; - info.stencilBits = stencilBits; - info.stencilOffset = stencilOffset; - - map->insert(std::make_pair(format, info)); -} - -static DepthStencilInfoMap BuildDepthStencilInfoMap() -{ - DepthStencilInfoMap map; - - InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_R16_TYPELESS, 16, 0, 0, 0); - InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_R16_UNORM, 16, 0, 0, 0); - InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_D16_UNORM, 16, 0, 0, 0); - - InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_R24G8_TYPELESS, 24, 0, 8, 24); - InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_R24_UNORM_X8_TYPELESS, 24, 0, 8, 24); - InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_D24_UNORM_S8_UINT, 24, 0, 8, 24); - - InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_R32_TYPELESS, 32, 0, 0, 0); - InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_R32_FLOAT, 32, 0, 0, 0); - InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_D32_FLOAT, 32, 0, 0, 0); - - InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_R32G8X24_TYPELESS, 32, 0, 8, 32); - InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS, 32, 0, 8, 32); - InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_D32_FLOAT_S8X24_UINT, 32, 0, 8, 32); - - return map; -} - -typedef std::map DXGIFormatInfoMap; - -DXGIFormat::DXGIFormat() - : pixelBytes(0), - blockWidth(0), - blockHeight(0), - depthBits(0), - depthOffset(0), - stencilBits(0), - stencilOffset(0), - internalFormat(GL_NONE), - componentType(GL_NONE), - mipGenerationFunction(NULL), - colorReadFunction(NULL), - fastCopyFunctions() -{ -} - -ColorCopyFunction DXGIFormat::getFastCopyFunction(GLenum format, GLenum type) const -{ - FastCopyFunctionMap::const_iterator iter = fastCopyFunctions.find(std::make_pair(format, type)); - return (iter != fastCopyFunctions.end()) ? iter->second : NULL; -} - -void AddDXGIFormat(DXGIFormatInfoMap *map, DXGI_FORMAT dxgiFormat, GLuint pixelBits, GLuint blockWidth, GLuint blockHeight, - GLenum componentType, MipGenerationFunction mipFunc, ColorReadFunction readFunc) -{ - DXGIFormat info; - info.pixelBytes = pixelBits / 8; - info.blockWidth = blockWidth; - info.blockHeight = blockHeight; - - static const DepthStencilInfoMap dsInfoMap = BuildDepthStencilInfoMap(); - DepthStencilInfoMap::const_iterator dsInfoIter = dsInfoMap.find(dxgiFormat); - if (dsInfoIter != dsInfoMap.end()) - { - info.depthBits = dsInfoIter->second.depthBits; - info.depthOffset = dsInfoIter->second.depthOffset; - info.stencilBits = dsInfoIter->second.stencilBits; - info.stencilOffset = dsInfoIter->second.stencilOffset; - } - else - { - info.depthBits = 0; - info.depthOffset = 0; - info.stencilBits = 0; - info.stencilOffset = 0; - } - - static const DXGIToESFormatMap dxgiToESMap = BuildDXGIToESFormatMap(); - DXGIToESFormatMap::const_iterator dxgiToESIter = dxgiToESMap.find(dxgiFormat); - info.internalFormat = (dxgiToESIter != dxgiToESMap.end()) ? dxgiToESIter->second : GL_NONE; - - info.componentType = componentType; - - info.mipGenerationFunction = mipFunc; - info.colorReadFunction = readFunc; - - static const D3D11FastCopyMap fastCopyMap = BuildFastCopyMap(); - std::pair fastCopyIter = fastCopyMap.equal_range(dxgiFormat); - for (D3D11FastCopyMap::const_iterator i = fastCopyIter.first; i != fastCopyIter.second; i++) - { - info.fastCopyFunctions.insert(std::make_pair(std::make_pair(i->second.destFormat, i->second.destType), i->second.copyFunction)); - } - - map->insert(std::make_pair(dxgiFormat, info)); -} - -// A map to determine the pixel size and mipmap generation function of a given DXGI format -static DXGIFormatInfoMap BuildDXGIFormatInfoMap() -{ - DXGIFormatInfoMap map; - - // | DXGI format |S |W |H |Component Type | Mip generation function | Color read function - AddDXGIFormat(&map, DXGI_FORMAT_UNKNOWN, 0, 0, 0, GL_NONE, NULL, NULL); - - AddDXGIFormat(&map, DXGI_FORMAT_A8_UNORM, 8, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R8_UNORM, 8, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R8G8_UNORM, 16, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R8G8B8A8_UNORM, 32, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, 32, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_B8G8R8A8_UNORM, 32, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip, ReadColor); - - AddDXGIFormat(&map, DXGI_FORMAT_R8_SNORM, 8, 1, 1, GL_SIGNED_NORMALIZED, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R8G8_SNORM, 16, 1, 1, GL_SIGNED_NORMALIZED, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R8G8B8A8_SNORM, 32, 1, 1, GL_SIGNED_NORMALIZED, GenerateMip, ReadColor); - - AddDXGIFormat(&map, DXGI_FORMAT_R8_UINT, 8, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R16_UINT, 16, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R32_UINT, 32, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R8G8_UINT, 16, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R16G16_UINT, 32, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R32G32_UINT, 64, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R32G32B32_UINT, 96, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R8G8B8A8_UINT, 32, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R16G16B16A16_UINT, 64, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R32G32B32A32_UINT, 128, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor); - - AddDXGIFormat(&map, DXGI_FORMAT_R8_SINT, 8, 1, 1, GL_INT, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R16_SINT, 16, 1, 1, GL_INT, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R32_SINT, 32, 1, 1, GL_INT, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R8G8_SINT, 16, 1, 1, GL_INT, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R16G16_SINT, 32, 1, 1, GL_INT, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R32G32_SINT, 64, 1, 1, GL_INT, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R32G32B32_SINT, 96, 1, 1, GL_INT, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R8G8B8A8_SINT, 32, 1, 1, GL_INT, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R16G16B16A16_SINT, 64, 1, 1, GL_INT, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R32G32B32A32_SINT, 128, 1, 1, GL_INT, GenerateMip, ReadColor); - - AddDXGIFormat(&map, DXGI_FORMAT_R10G10B10A2_UNORM, 32, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R10G10B10A2_UINT, 32, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor); - - AddDXGIFormat(&map, DXGI_FORMAT_R16_FLOAT, 16, 1, 1, GL_FLOAT, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R16G16_FLOAT, 32, 1, 1, GL_FLOAT, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R16G16B16A16_FLOAT, 64, 1, 1, GL_FLOAT, GenerateMip, ReadColor); - - AddDXGIFormat(&map, DXGI_FORMAT_R32_FLOAT, 32, 1, 1, GL_FLOAT, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R32G32_FLOAT, 64, 1, 1, GL_FLOAT, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R32G32B32_FLOAT, 96, 1, 1, GL_FLOAT, NULL, NULL); - AddDXGIFormat(&map, DXGI_FORMAT_R32G32B32A32_FLOAT, 128, 1, 1, GL_FLOAT, GenerateMip, ReadColor); - - AddDXGIFormat(&map, DXGI_FORMAT_R9G9B9E5_SHAREDEXP, 32, 1, 1, GL_FLOAT, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R11G11B10_FLOAT, 32, 1, 1, GL_FLOAT, GenerateMip, ReadColor); - - AddDXGIFormat(&map, DXGI_FORMAT_R16_TYPELESS, 16, 1, 1, GL_NONE, NULL, NULL); - AddDXGIFormat(&map, DXGI_FORMAT_R16_UNORM, 16, 1, 1, GL_UNSIGNED_NORMALIZED, NULL, NULL); - AddDXGIFormat(&map, DXGI_FORMAT_D16_UNORM, 16, 1, 1, GL_UNSIGNED_NORMALIZED, NULL, NULL); - AddDXGIFormat(&map, DXGI_FORMAT_R24G8_TYPELESS, 32, 1, 1, GL_NONE, NULL, NULL); - AddDXGIFormat(&map, DXGI_FORMAT_R24_UNORM_X8_TYPELESS, 32, 1, 1, GL_NONE, NULL, NULL); - AddDXGIFormat(&map, DXGI_FORMAT_D24_UNORM_S8_UINT, 32, 1, 1, GL_UNSIGNED_INT, NULL, NULL); - AddDXGIFormat(&map, DXGI_FORMAT_R32G8X24_TYPELESS, 64, 1, 1, GL_NONE, NULL, NULL); - AddDXGIFormat(&map, DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS, 64, 1, 1, GL_NONE, NULL, NULL); - AddDXGIFormat(&map, DXGI_FORMAT_D32_FLOAT_S8X24_UINT, 64, 1, 1, GL_UNSIGNED_INT, NULL, NULL); - AddDXGIFormat(&map, DXGI_FORMAT_R32_TYPELESS, 32, 1, 1, GL_NONE, NULL, NULL); - AddDXGIFormat(&map, DXGI_FORMAT_D32_FLOAT, 32, 1, 1, GL_FLOAT, NULL, NULL); - - AddDXGIFormat(&map, DXGI_FORMAT_BC1_UNORM, 64, 4, 4, GL_UNSIGNED_NORMALIZED, NULL, NULL); - AddDXGIFormat(&map, DXGI_FORMAT_BC2_UNORM, 128, 4, 4, GL_UNSIGNED_NORMALIZED, NULL, NULL); - AddDXGIFormat(&map, DXGI_FORMAT_BC3_UNORM, 128, 4, 4, GL_UNSIGNED_NORMALIZED, NULL, NULL); - - // Useful formats for vertex buffers - AddDXGIFormat(&map, DXGI_FORMAT_R16_UNORM, 16, 1, 1, GL_UNSIGNED_NORMALIZED, NULL, NULL); - AddDXGIFormat(&map, DXGI_FORMAT_R16_SNORM, 16, 1, 1, GL_SIGNED_NORMALIZED, NULL, NULL); - AddDXGIFormat(&map, DXGI_FORMAT_R16G16_UNORM, 32, 1, 1, GL_UNSIGNED_NORMALIZED, NULL, NULL); - AddDXGIFormat(&map, DXGI_FORMAT_R16G16_SNORM, 32, 1, 1, GL_SIGNED_NORMALIZED, NULL, NULL); - AddDXGIFormat(&map, DXGI_FORMAT_R16G16B16A16_UNORM, 64, 1, 1, GL_UNSIGNED_NORMALIZED, NULL, NULL); - AddDXGIFormat(&map, DXGI_FORMAT_R16G16B16A16_SNORM, 64, 1, 1, GL_SIGNED_NORMALIZED, NULL, NULL); - - return map; -} - -const DXGIFormat &GetDXGIFormatInfo(DXGI_FORMAT format) -{ - static const DXGIFormatInfoMap infoMap = BuildDXGIFormatInfoMap(); - DXGIFormatInfoMap::const_iterator iter = infoMap.find(format); - if (iter != infoMap.end()) - { - return iter->second; - } - else - { - static DXGIFormat defaultInfo; - return defaultInfo; - } -} - -struct SwizzleSizeType -{ - size_t maxComponentSize; - GLenum componentType; - - SwizzleSizeType() - : maxComponentSize(0), componentType(GL_NONE) - { } - - SwizzleSizeType(size_t maxComponentSize, GLenum componentType) - : maxComponentSize(maxComponentSize), componentType(componentType) - { } - - bool operator<(const SwizzleSizeType& other) const - { - return (maxComponentSize != other.maxComponentSize) ? (maxComponentSize < other.maxComponentSize) - : (componentType < other.componentType); - } -}; - -struct SwizzleFormatInfo -{ - DXGI_FORMAT mTexFormat; - DXGI_FORMAT mSRVFormat; - DXGI_FORMAT mRTVFormat; - - SwizzleFormatInfo() - : mTexFormat(DXGI_FORMAT_UNKNOWN), mSRVFormat(DXGI_FORMAT_UNKNOWN), mRTVFormat(DXGI_FORMAT_UNKNOWN) - { } - - SwizzleFormatInfo(DXGI_FORMAT texFormat, DXGI_FORMAT srvFormat, DXGI_FORMAT rtvFormat) - : mTexFormat(texFormat), mSRVFormat(srvFormat), mRTVFormat(rtvFormat) - { } -}; - -typedef std::map SwizzleInfoMap; -typedef std::pair SwizzleInfoPair; - -static SwizzleInfoMap BuildSwizzleInfoMap() -{ - SwizzleInfoMap map; - - map.insert(SwizzleInfoPair(SwizzleSizeType( 8, GL_UNSIGNED_NORMALIZED), SwizzleFormatInfo(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM ))); - map.insert(SwizzleInfoPair(SwizzleSizeType(16, GL_UNSIGNED_NORMALIZED), SwizzleFormatInfo(DXGI_FORMAT_R16G16B16A16_UNORM, DXGI_FORMAT_R16G16B16A16_UNORM, DXGI_FORMAT_R16G16B16A16_UNORM))); - map.insert(SwizzleInfoPair(SwizzleSizeType(24, GL_UNSIGNED_NORMALIZED), SwizzleFormatInfo(DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT))); - map.insert(SwizzleInfoPair(SwizzleSizeType(32, GL_UNSIGNED_NORMALIZED), SwizzleFormatInfo(DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT))); - - map.insert(SwizzleInfoPair(SwizzleSizeType( 8, GL_SIGNED_NORMALIZED ), SwizzleFormatInfo(DXGI_FORMAT_R8G8B8A8_SNORM, DXGI_FORMAT_R8G8B8A8_SNORM, DXGI_FORMAT_R8G8B8A8_SNORM ))); - - map.insert(SwizzleInfoPair(SwizzleSizeType(16, GL_FLOAT ), SwizzleFormatInfo(DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT))); - map.insert(SwizzleInfoPair(SwizzleSizeType(32, GL_FLOAT ), SwizzleFormatInfo(DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT))); - - map.insert(SwizzleInfoPair(SwizzleSizeType( 8, GL_UNSIGNED_INT ), SwizzleFormatInfo(DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_R8G8B8A8_UINT ))); - map.insert(SwizzleInfoPair(SwizzleSizeType(16, GL_UNSIGNED_INT ), SwizzleFormatInfo(DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_R16G16B16A16_UINT ))); - map.insert(SwizzleInfoPair(SwizzleSizeType(32, GL_UNSIGNED_INT ), SwizzleFormatInfo(DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_R32G32B32A32_UINT ))); - - map.insert(SwizzleInfoPair(SwizzleSizeType( 8, GL_INT ), SwizzleFormatInfo(DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_R8G8B8A8_SINT ))); - map.insert(SwizzleInfoPair(SwizzleSizeType(16, GL_INT ), SwizzleFormatInfo(DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_R16G16B16A16_SINT ))); - map.insert(SwizzleInfoPair(SwizzleSizeType(32, GL_INT ), SwizzleFormatInfo(DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_R32G32B32A32_SINT ))); - - return map; -} - -typedef std::pair InternalFormatInitializerPair; -typedef std::map InternalFormatInitializerMap; - -static InternalFormatInitializerMap BuildInternalFormatInitializerMap() -{ - InternalFormatInitializerMap map; - - map.insert(InternalFormatInitializerPair(GL_RGB8, Initialize4ComponentData )); - map.insert(InternalFormatInitializerPair(GL_RGB565, Initialize4ComponentData )); - map.insert(InternalFormatInitializerPair(GL_SRGB8, Initialize4ComponentData )); - map.insert(InternalFormatInitializerPair(GL_RGB16F, Initialize4ComponentData)); - map.insert(InternalFormatInitializerPair(GL_RGB32F, Initialize4ComponentData)); - map.insert(InternalFormatInitializerPair(GL_RGB8UI, Initialize4ComponentData )); - map.insert(InternalFormatInitializerPair(GL_RGB8I, Initialize4ComponentData )); - map.insert(InternalFormatInitializerPair(GL_RGB16UI, Initialize4ComponentData )); - map.insert(InternalFormatInitializerPair(GL_RGB16I, Initialize4ComponentData )); - map.insert(InternalFormatInitializerPair(GL_RGB32UI, Initialize4ComponentData )); - map.insert(InternalFormatInitializerPair(GL_RGB32I, Initialize4ComponentData )); - - return map; -} - -// ES3 image loading functions vary based on the internal format and data type given, -// this map type determines the loading function from the internal format and type supplied -// to glTex*Image*D and the destination DXGI_FORMAT. Source formats and types are taken from -// Tables 3.2 and 3.3 of the ES 3 spec. -typedef std::pair TypeLoadFunctionPair; -typedef std::map > D3D11LoadFunctionMap; - -static void UnimplementedLoadFunction(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) -{ - UNIMPLEMENTED(); -} - -static void UnreachableLoadFunction(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) -{ - UNREACHABLE(); -} - -// A helper function to insert data into the D3D11LoadFunctionMap with fewer characters. -static inline void InsertLoadFunction(D3D11LoadFunctionMap *map, GLenum internalFormat, GLenum type, - LoadImageFunction loadFunc) -{ - (*map)[internalFormat].push_back(TypeLoadFunctionPair(type, loadFunc)); -} - -D3D11LoadFunctionMap BuildD3D11LoadFunctionMap() -{ - D3D11LoadFunctionMap map; - - // | Internal format | Type | Load function | - InsertLoadFunction(&map, GL_RGBA8, GL_UNSIGNED_BYTE, LoadToNative ); - InsertLoadFunction(&map, GL_RGB5_A1, GL_UNSIGNED_BYTE, LoadToNative ); - InsertLoadFunction(&map, GL_RGBA4, GL_UNSIGNED_BYTE, LoadToNative ); - InsertLoadFunction(&map, GL_SRGB8_ALPHA8, GL_UNSIGNED_BYTE, LoadToNative ); - InsertLoadFunction(&map, GL_RGBA8_SNORM, GL_BYTE, LoadToNative ); - InsertLoadFunction(&map, GL_RGBA4, GL_UNSIGNED_SHORT_4_4_4_4, LoadRGBA4ToRGBA8 ); - InsertLoadFunction(&map, GL_RGB10_A2, GL_UNSIGNED_INT_2_10_10_10_REV, LoadToNative ); - InsertLoadFunction(&map, GL_RGB5_A1, GL_UNSIGNED_SHORT_5_5_5_1, LoadRGB5A1ToRGBA8 ); - InsertLoadFunction(&map, GL_RGB5_A1, GL_UNSIGNED_INT_2_10_10_10_REV, LoadRGB10A2ToRGBA8 ); - InsertLoadFunction(&map, GL_RGBA16F, GL_HALF_FLOAT, LoadToNative ); - InsertLoadFunction(&map, GL_RGBA16F, GL_HALF_FLOAT_OES, LoadToNative ); - InsertLoadFunction(&map, GL_RGBA32F, GL_FLOAT, LoadToNative ); - InsertLoadFunction(&map, GL_RGBA16F, GL_FLOAT, Load32FTo16F<4> ); - InsertLoadFunction(&map, GL_RGBA8UI, GL_UNSIGNED_BYTE, LoadToNative ); - InsertLoadFunction(&map, GL_RGBA8I, GL_BYTE, LoadToNative ); - InsertLoadFunction(&map, GL_RGBA16UI, GL_UNSIGNED_SHORT, LoadToNative ); - InsertLoadFunction(&map, GL_RGBA16I, GL_SHORT, LoadToNative ); - InsertLoadFunction(&map, GL_RGBA32UI, GL_UNSIGNED_INT, LoadToNative ); - InsertLoadFunction(&map, GL_RGBA32I, GL_INT, LoadToNative ); - InsertLoadFunction(&map, GL_RGB10_A2UI, GL_UNSIGNED_INT_2_10_10_10_REV, LoadToNative ); - InsertLoadFunction(&map, GL_RGB8, GL_UNSIGNED_BYTE, LoadToNative3To4 ); - InsertLoadFunction(&map, GL_RGB565, GL_UNSIGNED_BYTE, LoadToNative3To4 ); - InsertLoadFunction(&map, GL_SRGB8, GL_UNSIGNED_BYTE, LoadToNative3To4 ); - InsertLoadFunction(&map, GL_RGB8_SNORM, GL_BYTE, LoadToNative3To4 ); - InsertLoadFunction(&map, GL_RGB565, GL_UNSIGNED_SHORT_5_6_5, LoadR5G6B5ToRGBA8 ); - InsertLoadFunction(&map, GL_R11F_G11F_B10F, GL_UNSIGNED_INT_10F_11F_11F_REV, LoadToNative ); - InsertLoadFunction(&map, GL_RGB9_E5, GL_UNSIGNED_INT_5_9_9_9_REV, LoadToNative ); - InsertLoadFunction(&map, GL_RGB16F, GL_HALF_FLOAT, LoadToNative3To4); - InsertLoadFunction(&map, GL_RGB16F, GL_HALF_FLOAT_OES, LoadToNative3To4); - InsertLoadFunction(&map, GL_R11F_G11F_B10F, GL_HALF_FLOAT, LoadRGB16FToRG11B10F ); - InsertLoadFunction(&map, GL_R11F_G11F_B10F, GL_HALF_FLOAT_OES, LoadRGB16FToRG11B10F ); - InsertLoadFunction(&map, GL_RGB9_E5, GL_HALF_FLOAT, LoadRGB16FToRGB9E5 ); - InsertLoadFunction(&map, GL_RGB9_E5, GL_HALF_FLOAT_OES, LoadRGB16FToRGB9E5 ); - InsertLoadFunction(&map, GL_RGB32F, GL_FLOAT, LoadToNative3To4); - InsertLoadFunction(&map, GL_RGB16F, GL_FLOAT, LoadRGB32FToRGBA16F ); - InsertLoadFunction(&map, GL_R11F_G11F_B10F, GL_FLOAT, LoadRGB32FToRG11B10F ); - InsertLoadFunction(&map, GL_RGB9_E5, GL_FLOAT, LoadRGB32FToRGB9E5 ); - InsertLoadFunction(&map, GL_RGB8UI, GL_UNSIGNED_BYTE, LoadToNative3To4 ); - InsertLoadFunction(&map, GL_RGB8I, GL_BYTE, LoadToNative3To4 ); - InsertLoadFunction(&map, GL_RGB16UI, GL_UNSIGNED_SHORT, LoadToNative3To4 ); - InsertLoadFunction(&map, GL_RGB16I, GL_SHORT, LoadToNative3To4 ); - InsertLoadFunction(&map, GL_RGB32UI, GL_UNSIGNED_INT, LoadToNative3To4 ); - InsertLoadFunction(&map, GL_RGB32I, GL_INT, LoadToNative3To4 ); - InsertLoadFunction(&map, GL_RG8, GL_UNSIGNED_BYTE, LoadToNative ); - InsertLoadFunction(&map, GL_RG8_SNORM, GL_BYTE, LoadToNative ); - InsertLoadFunction(&map, GL_RG16F, GL_HALF_FLOAT, LoadToNative ); - InsertLoadFunction(&map, GL_RG16F, GL_HALF_FLOAT_OES, LoadToNative ); - InsertLoadFunction(&map, GL_RG32F, GL_FLOAT, LoadToNative ); - InsertLoadFunction(&map, GL_RG16F, GL_FLOAT, Load32FTo16F<2> ); - InsertLoadFunction(&map, GL_RG8UI, GL_UNSIGNED_BYTE, LoadToNative ); - InsertLoadFunction(&map, GL_RG8I, GL_BYTE, LoadToNative ); - InsertLoadFunction(&map, GL_RG16UI, GL_UNSIGNED_SHORT, LoadToNative ); - InsertLoadFunction(&map, GL_RG16I, GL_SHORT, LoadToNative ); - InsertLoadFunction(&map, GL_RG32UI, GL_UNSIGNED_INT, LoadToNative ); - InsertLoadFunction(&map, GL_RG32I, GL_INT, LoadToNative ); - InsertLoadFunction(&map, GL_R8, GL_UNSIGNED_BYTE, LoadToNative ); - InsertLoadFunction(&map, GL_R8_SNORM, GL_BYTE, LoadToNative ); - InsertLoadFunction(&map, GL_R16F, GL_HALF_FLOAT, LoadToNative ); - InsertLoadFunction(&map, GL_R16F, GL_HALF_FLOAT_OES, LoadToNative ); - InsertLoadFunction(&map, GL_R32F, GL_FLOAT, LoadToNative ); - InsertLoadFunction(&map, GL_R16F, GL_FLOAT, Load32FTo16F<1> ); - InsertLoadFunction(&map, GL_R8UI, GL_UNSIGNED_BYTE, LoadToNative ); - InsertLoadFunction(&map, GL_R8I, GL_BYTE, LoadToNative ); - InsertLoadFunction(&map, GL_R16UI, GL_UNSIGNED_SHORT, LoadToNative ); - InsertLoadFunction(&map, GL_R16I, GL_SHORT, LoadToNative ); - InsertLoadFunction(&map, GL_R32UI, GL_UNSIGNED_INT, LoadToNative ); - InsertLoadFunction(&map, GL_R32I, GL_INT, LoadToNative ); - InsertLoadFunction(&map, GL_DEPTH_COMPONENT16, GL_UNSIGNED_SHORT, LoadToNative ); - InsertLoadFunction(&map, GL_DEPTH_COMPONENT24, GL_UNSIGNED_INT, LoadR32ToR24G8 ); - InsertLoadFunction(&map, GL_DEPTH_COMPONENT16, GL_UNSIGNED_INT, LoadR32ToR16 ); - InsertLoadFunction(&map, GL_DEPTH_COMPONENT32F, GL_FLOAT, LoadToNative ); - InsertLoadFunction(&map, GL_DEPTH24_STENCIL8, GL_UNSIGNED_INT_24_8, LoadR32ToR24G8 ); - InsertLoadFunction(&map, GL_DEPTH32F_STENCIL8, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, LoadToNative ); - - // Unsized formats - // Load functions are unreachable because they are converted to sized internal formats based on - // the format and type before loading takes place. - InsertLoadFunction(&map, GL_RGBA, GL_UNSIGNED_BYTE, UnreachableLoadFunction ); - InsertLoadFunction(&map, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, UnreachableLoadFunction ); - InsertLoadFunction(&map, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, UnreachableLoadFunction ); - InsertLoadFunction(&map, GL_RGB, GL_UNSIGNED_BYTE, UnreachableLoadFunction ); - InsertLoadFunction(&map, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, UnreachableLoadFunction ); - InsertLoadFunction(&map, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, UnreachableLoadFunction ); - InsertLoadFunction(&map, GL_LUMINANCE, GL_UNSIGNED_BYTE, UnreachableLoadFunction ); - InsertLoadFunction(&map, GL_ALPHA, GL_UNSIGNED_BYTE, UnreachableLoadFunction ); - - // From GL_OES_texture_float - InsertLoadFunction(&map, GL_LUMINANCE_ALPHA, GL_FLOAT, LoadLA32FToRGBA32F ); - InsertLoadFunction(&map, GL_LUMINANCE, GL_FLOAT, LoadL32FToRGBA32F ); - InsertLoadFunction(&map, GL_ALPHA, GL_FLOAT, LoadA32FToRGBA32F ); - - // From GL_OES_texture_half_float - InsertLoadFunction(&map, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT, LoadLA16FToRGBA16F ); - InsertLoadFunction(&map, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES, LoadLA16FToRGBA16F ); - InsertLoadFunction(&map, GL_LUMINANCE, GL_HALF_FLOAT, LoadL16FToRGBA16F ); - InsertLoadFunction(&map, GL_LUMINANCE, GL_HALF_FLOAT_OES, LoadL16FToRGBA16F ); - InsertLoadFunction(&map, GL_ALPHA, GL_HALF_FLOAT, LoadA16FToRGBA16F ); - InsertLoadFunction(&map, GL_ALPHA, GL_HALF_FLOAT_OES, LoadA16FToRGBA16F ); - - // From GL_EXT_texture_storage - InsertLoadFunction(&map, GL_ALPHA8_EXT, GL_UNSIGNED_BYTE, LoadA8ToRGBA8 ); - InsertLoadFunction(&map, GL_LUMINANCE8_EXT, GL_UNSIGNED_BYTE, LoadL8ToRGBA8 ); - InsertLoadFunction(&map, GL_LUMINANCE8_ALPHA8_EXT, GL_UNSIGNED_BYTE, LoadLA8ToRGBA8 ); - InsertLoadFunction(&map, GL_ALPHA32F_EXT, GL_FLOAT, LoadA32FToRGBA32F ); - InsertLoadFunction(&map, GL_LUMINANCE32F_EXT, GL_FLOAT, LoadL32FToRGBA32F ); - InsertLoadFunction(&map, GL_LUMINANCE_ALPHA32F_EXT, GL_FLOAT, LoadLA32FToRGBA32F ); - InsertLoadFunction(&map, GL_ALPHA16F_EXT, GL_HALF_FLOAT, LoadA16FToRGBA16F ); - InsertLoadFunction(&map, GL_ALPHA16F_EXT, GL_HALF_FLOAT_OES, LoadA16FToRGBA16F ); - InsertLoadFunction(&map, GL_LUMINANCE16F_EXT, GL_HALF_FLOAT, LoadL16FToRGBA16F ); - InsertLoadFunction(&map, GL_LUMINANCE16F_EXT, GL_HALF_FLOAT_OES, LoadL16FToRGBA16F ); - InsertLoadFunction(&map, GL_LUMINANCE_ALPHA16F_EXT, GL_HALF_FLOAT, LoadLA16FToRGBA16F ); - InsertLoadFunction(&map, GL_LUMINANCE_ALPHA16F_EXT, GL_HALF_FLOAT_OES, LoadLA16FToRGBA16F ); - - // From GL_ANGLE_depth_texture - InsertLoadFunction(&map, GL_DEPTH_COMPONENT32_OES, GL_UNSIGNED_INT, LoadR32ToR24G8 ); - - // From GL_EXT_texture_format_BGRA8888 - InsertLoadFunction(&map, GL_BGRA8_EXT, GL_UNSIGNED_BYTE, LoadToNative ); - InsertLoadFunction(&map, GL_BGRA4_ANGLEX, GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT, LoadRGBA4ToRGBA8 ); - InsertLoadFunction(&map, GL_BGRA4_ANGLEX, GL_UNSIGNED_BYTE, LoadToNative ); - InsertLoadFunction(&map, GL_BGR5_A1_ANGLEX, GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT, LoadRGB5A1ToRGBA8 ); - InsertLoadFunction(&map, GL_BGR5_A1_ANGLEX, GL_UNSIGNED_BYTE, LoadToNative ); - - // Compressed formats - // From ES 3.0.1 spec, table 3.16 - // | Internal format | Type | Load function | - InsertLoadFunction(&map, GL_COMPRESSED_R11_EAC, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); - InsertLoadFunction(&map, GL_COMPRESSED_R11_EAC, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); - InsertLoadFunction(&map, GL_COMPRESSED_SIGNED_R11_EAC, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); - InsertLoadFunction(&map, GL_COMPRESSED_RG11_EAC, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); - InsertLoadFunction(&map, GL_COMPRESSED_SIGNED_RG11_EAC, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); - InsertLoadFunction(&map, GL_COMPRESSED_RGB8_ETC2, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); - InsertLoadFunction(&map, GL_COMPRESSED_SRGB8_ETC2, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); - InsertLoadFunction(&map, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); - InsertLoadFunction(&map, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); - InsertLoadFunction(&map, GL_COMPRESSED_RGBA8_ETC2_EAC, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); - InsertLoadFunction(&map, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); - - // From GL_EXT_texture_compression_dxt1 - InsertLoadFunction(&map, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, LoadCompressedToNative<4, 4, 8>); - InsertLoadFunction(&map, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, LoadCompressedToNative<4, 4, 8>); - - // From GL_ANGLE_texture_compression_dxt3 - InsertLoadFunction(&map, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, GL_UNSIGNED_BYTE, LoadCompressedToNative<4, 4, 16>); - - // From GL_ANGLE_texture_compression_dxt5 - InsertLoadFunction(&map, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, GL_UNSIGNED_BYTE, LoadCompressedToNative<4, 4, 16>); - - return map; -} - -// For sized GL internal formats, there is only one corresponding D3D11 format. This map type allows -// querying for the DXGI texture formats to use for textures, SRVs, RTVs and DSVs given a GL internal -// format. -typedef std::map D3D11ES3FormatMap; - -TextureFormat::TextureFormat() - : texFormat(DXGI_FORMAT_UNKNOWN), - srvFormat(DXGI_FORMAT_UNKNOWN), - rtvFormat(DXGI_FORMAT_UNKNOWN), - dsvFormat(DXGI_FORMAT_UNKNOWN), - renderFormat(DXGI_FORMAT_UNKNOWN), - swizzleTexFormat(DXGI_FORMAT_UNKNOWN), - swizzleSRVFormat(DXGI_FORMAT_UNKNOWN), - swizzleRTVFormat(DXGI_FORMAT_UNKNOWN), - dataInitializerFunction(NULL), - loadFunctions() -{ -} - -static inline void InsertD3D11FormatInfo(D3D11ES3FormatMap *map, GLenum internalFormat, DXGI_FORMAT texFormat, - DXGI_FORMAT srvFormat, DXGI_FORMAT rtvFormat, DXGI_FORMAT dsvFormat) -{ - TextureFormat info; - info.texFormat = texFormat; - info.srvFormat = srvFormat; - info.rtvFormat = rtvFormat; - info.dsvFormat = dsvFormat; - - // Given a GL internal format, the renderFormat is the DSV format if it is depth- or stencil-renderable, - // the RTV format if it is color-renderable, and the (nonrenderable) texture format otherwise. - if (dsvFormat != DXGI_FORMAT_UNKNOWN) - { - info.renderFormat = dsvFormat; - } - else if (rtvFormat != DXGI_FORMAT_UNKNOWN) - { - info.renderFormat = rtvFormat; - } - else if (texFormat != DXGI_FORMAT_UNKNOWN) - { - info.renderFormat = texFormat; - } - else - { - info.renderFormat = DXGI_FORMAT_UNKNOWN; - } - - // Compute the swizzle formats - const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat); - if (internalFormat != GL_NONE && formatInfo.pixelBytes > 0) - { - if (formatInfo.componentCount != 4 || texFormat == DXGI_FORMAT_UNKNOWN || - srvFormat == DXGI_FORMAT_UNKNOWN || rtvFormat == DXGI_FORMAT_UNKNOWN) - { - // Get the maximum sized component - unsigned int maxBits = 1; - if (formatInfo.compressed) - { - unsigned int compressedBitsPerBlock = formatInfo.pixelBytes * 8; - unsigned int blockSize = formatInfo.compressedBlockWidth * formatInfo.compressedBlockHeight; - maxBits = std::max(compressedBitsPerBlock / blockSize, maxBits); - } - else - { - maxBits = std::max(maxBits, formatInfo.alphaBits); - maxBits = std::max(maxBits, formatInfo.redBits); - maxBits = std::max(maxBits, formatInfo.greenBits); - maxBits = std::max(maxBits, formatInfo.blueBits); - maxBits = std::max(maxBits, formatInfo.luminanceBits); - maxBits = std::max(maxBits, formatInfo.depthBits); - } - - maxBits = roundUp(maxBits, 8U); - - static const SwizzleInfoMap swizzleMap = BuildSwizzleInfoMap(); - SwizzleInfoMap::const_iterator swizzleIter = swizzleMap.find(SwizzleSizeType(maxBits, formatInfo.componentType)); - ASSERT(swizzleIter != swizzleMap.end()); - - const SwizzleFormatInfo &swizzleInfo = swizzleIter->second; - info.swizzleTexFormat = swizzleInfo.mTexFormat; - info.swizzleSRVFormat = swizzleInfo.mSRVFormat; - info.swizzleRTVFormat = swizzleInfo.mRTVFormat; - } - else - { - // The original texture format is suitable for swizzle operations - info.swizzleTexFormat = texFormat; - info.swizzleSRVFormat = srvFormat; - info.swizzleRTVFormat = rtvFormat; - } - } - else - { - // Not possible to swizzle with this texture format since it is either unsized or GL_NONE - info.swizzleTexFormat = DXGI_FORMAT_UNKNOWN; - info.swizzleSRVFormat = DXGI_FORMAT_UNKNOWN; - info.swizzleRTVFormat = DXGI_FORMAT_UNKNOWN; - } - - // Check if there is an initialization function for this texture format - static const InternalFormatInitializerMap initializerMap = BuildInternalFormatInitializerMap(); - InternalFormatInitializerMap::const_iterator initializerIter = initializerMap.find(internalFormat); - info.dataInitializerFunction = (initializerIter != initializerMap.end()) ? initializerIter->second : NULL; - - // Gather all the load functions for this internal format - static const D3D11LoadFunctionMap loadFunctions = BuildD3D11LoadFunctionMap(); - D3D11LoadFunctionMap::const_iterator loadFunctionIter = loadFunctions.find(internalFormat); - if (loadFunctionIter != loadFunctions.end()) - { - const std::vector &loadFunctionVector = loadFunctionIter->second; - for (size_t i = 0; i < loadFunctionVector.size(); i++) - { - GLenum type = loadFunctionVector[i].first; - LoadImageFunction function = loadFunctionVector[i].second; - info.loadFunctions.insert(std::make_pair(type, function)); - } - } - - map->insert(std::make_pair(internalFormat, info)); -} - -static D3D11ES3FormatMap BuildD3D11FormatMap() -{ - D3D11ES3FormatMap map; - - // | GL internal format | D3D11 texture format | D3D11 SRV format | D3D11 RTV format | D3D11 DSV format | - InsertD3D11FormatInfo(&map, GL_NONE, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_R8, DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_R8_SNORM, DXGI_FORMAT_R8_SNORM, DXGI_FORMAT_R8_SNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RG8, DXGI_FORMAT_R8G8_UNORM, DXGI_FORMAT_R8G8_UNORM, DXGI_FORMAT_R8G8_UNORM, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RG8_SNORM, DXGI_FORMAT_R8G8_SNORM, DXGI_FORMAT_R8G8_SNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RGB8, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RGB8_SNORM, DXGI_FORMAT_R8G8B8A8_SNORM, DXGI_FORMAT_R8G8B8A8_SNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RGB565, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RGBA4, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RGB5_A1, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RGBA8, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RGBA8_SNORM, DXGI_FORMAT_R8G8B8A8_SNORM, DXGI_FORMAT_R8G8B8A8_SNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RGB10_A2, DXGI_FORMAT_R10G10B10A2_UNORM, DXGI_FORMAT_R10G10B10A2_UNORM, DXGI_FORMAT_R10G10B10A2_UNORM, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RGB10_A2UI, DXGI_FORMAT_R10G10B10A2_UINT, DXGI_FORMAT_R10G10B10A2_UINT, DXGI_FORMAT_R10G10B10A2_UINT, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_SRGB8, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_SRGB8_ALPHA8, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_R16F, DXGI_FORMAT_R16_FLOAT, DXGI_FORMAT_R16_FLOAT, DXGI_FORMAT_R16_FLOAT, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RG16F, DXGI_FORMAT_R16G16_FLOAT, DXGI_FORMAT_R16G16_FLOAT, DXGI_FORMAT_R16G16_FLOAT, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RGB16F, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RGBA16F, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_R32F, DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RG32F, DXGI_FORMAT_R32G32_FLOAT, DXGI_FORMAT_R32G32_FLOAT, DXGI_FORMAT_R32G32_FLOAT, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RGB32F, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RGBA32F, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_R11F_G11F_B10F, DXGI_FORMAT_R11G11B10_FLOAT, DXGI_FORMAT_R11G11B10_FLOAT, DXGI_FORMAT_R11G11B10_FLOAT, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RGB9_E5, DXGI_FORMAT_R9G9B9E5_SHAREDEXP, DXGI_FORMAT_R9G9B9E5_SHAREDEXP, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_R8I, DXGI_FORMAT_R8_SINT, DXGI_FORMAT_R8_SINT, DXGI_FORMAT_R8_SINT, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_R8UI, DXGI_FORMAT_R8_UINT, DXGI_FORMAT_R8_UINT, DXGI_FORMAT_R8_UINT, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_R16I, DXGI_FORMAT_R16_SINT, DXGI_FORMAT_R16_SINT, DXGI_FORMAT_R16_SINT, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_R16UI, DXGI_FORMAT_R16_UINT, DXGI_FORMAT_R16_UINT, DXGI_FORMAT_R16_UINT, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_R32I, DXGI_FORMAT_R32_SINT, DXGI_FORMAT_R32_SINT, DXGI_FORMAT_R32_SINT, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_R32UI, DXGI_FORMAT_R32_UINT, DXGI_FORMAT_R32_UINT, DXGI_FORMAT_R32_UINT, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RG8I, DXGI_FORMAT_R8G8_SINT, DXGI_FORMAT_R8G8_SINT, DXGI_FORMAT_R8G8_SINT, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RG8UI, DXGI_FORMAT_R8G8_UINT, DXGI_FORMAT_R8G8_UINT, DXGI_FORMAT_R8G8_UINT, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RG16I, DXGI_FORMAT_R16G16_SINT, DXGI_FORMAT_R16G16_SINT, DXGI_FORMAT_R16G16_SINT, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RG16UI, DXGI_FORMAT_R16G16_UINT, DXGI_FORMAT_R16G16_UINT, DXGI_FORMAT_R16G16_UINT, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RG32I, DXGI_FORMAT_R32G32_SINT, DXGI_FORMAT_R32G32_SINT, DXGI_FORMAT_R32G32_SINT, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RG32UI, DXGI_FORMAT_R32G32_UINT, DXGI_FORMAT_R32G32_UINT, DXGI_FORMAT_R32G32_UINT, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RGB8I, DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RGB8UI, DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RGB16I, DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RGB16UI, DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RGB32I, DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RGB32UI, DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RGBA8I, DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RGBA8UI, DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RGBA16I, DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RGBA16UI, DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RGBA32I, DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RGBA32UI, DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_UNKNOWN); - - // Unsized formats, TODO: Are types of float and half float allowed for the unsized types? Would it change the DXGI format? - InsertD3D11FormatInfo(&map, GL_ALPHA, DXGI_FORMAT_A8_UNORM, DXGI_FORMAT_A8_UNORM, DXGI_FORMAT_A8_UNORM, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_LUMINANCE, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_LUMINANCE_ALPHA, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RGB, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RGBA, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_BGRA_EXT, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_UNKNOWN); - - // From GL_EXT_texture_storage - // | GL internal format | D3D11 texture format | D3D11 SRV format | D3D11 RTV format | D3D11 DSV format | - InsertD3D11FormatInfo(&map, GL_ALPHA8_EXT, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN ); - InsertD3D11FormatInfo(&map, GL_LUMINANCE8_EXT, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN ); - InsertD3D11FormatInfo(&map, GL_ALPHA32F_EXT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_UNKNOWN ); - InsertD3D11FormatInfo(&map, GL_LUMINANCE32F_EXT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_UNKNOWN ); - InsertD3D11FormatInfo(&map, GL_ALPHA16F_EXT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_UNKNOWN ); - InsertD3D11FormatInfo(&map, GL_LUMINANCE16F_EXT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_UNKNOWN ); - InsertD3D11FormatInfo(&map, GL_LUMINANCE8_ALPHA8_EXT, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN ); - InsertD3D11FormatInfo(&map, GL_LUMINANCE_ALPHA32F_EXT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_UNKNOWN ); - InsertD3D11FormatInfo(&map, GL_LUMINANCE_ALPHA16F_EXT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_UNKNOWN ); - InsertD3D11FormatInfo(&map, GL_BGRA8_EXT, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_UNKNOWN ); - InsertD3D11FormatInfo(&map, GL_BGRA4_ANGLEX, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_UNKNOWN ); - InsertD3D11FormatInfo(&map, GL_BGR5_A1_ANGLEX, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_UNKNOWN ); - - // Depth stencil formats - InsertD3D11FormatInfo(&map, GL_DEPTH_COMPONENT16, DXGI_FORMAT_R16_TYPELESS, DXGI_FORMAT_R16_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D16_UNORM ); - InsertD3D11FormatInfo(&map, GL_DEPTH_COMPONENT24, DXGI_FORMAT_R24G8_TYPELESS, DXGI_FORMAT_R24_UNORM_X8_TYPELESS, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D24_UNORM_S8_UINT ); - InsertD3D11FormatInfo(&map, GL_DEPTH_COMPONENT32F, DXGI_FORMAT_R32_TYPELESS, DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D32_FLOAT ); - InsertD3D11FormatInfo(&map, GL_DEPTH24_STENCIL8, DXGI_FORMAT_R24G8_TYPELESS, DXGI_FORMAT_R24_UNORM_X8_TYPELESS, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D24_UNORM_S8_UINT ); - InsertD3D11FormatInfo(&map, GL_DEPTH32F_STENCIL8, DXGI_FORMAT_R32G8X24_TYPELESS, DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D32_FLOAT_S8X24_UINT); - InsertD3D11FormatInfo(&map, GL_STENCIL_INDEX8, DXGI_FORMAT_R24G8_TYPELESS, DXGI_FORMAT_X24_TYPELESS_G8_UINT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D24_UNORM_S8_UINT ); - - // From GL_ANGLE_depth_texture - // Since D3D11 doesn't have a D32_UNORM format, use D24S8 which has comparable precision and matches the ES3 format. - InsertD3D11FormatInfo(&map, GL_DEPTH_COMPONENT32_OES, DXGI_FORMAT_R24G8_TYPELESS, DXGI_FORMAT_R24_UNORM_X8_TYPELESS, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D24_UNORM_S8_UINT); - - // Compressed formats, From ES 3.0.1 spec, table 3.16 - // | GL internal format | D3D11 texture format | D3D11 SRV format | D3D11 RTV format | D3D11 DSV format | - InsertD3D11FormatInfo(&map, GL_COMPRESSED_R11_EAC, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_COMPRESSED_SIGNED_R11_EAC, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_COMPRESSED_RG11_EAC, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_COMPRESSED_SIGNED_RG11_EAC, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_COMPRESSED_RGB8_ETC2, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_COMPRESSED_SRGB8_ETC2, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_COMPRESSED_RGBA8_ETC2_EAC, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); - - // From GL_EXT_texture_compression_dxt1 - InsertD3D11FormatInfo(&map, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, DXGI_FORMAT_BC1_UNORM, DXGI_FORMAT_BC1_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, DXGI_FORMAT_BC1_UNORM, DXGI_FORMAT_BC1_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); - - // From GL_ANGLE_texture_compression_dxt3 - InsertD3D11FormatInfo(&map, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, DXGI_FORMAT_BC2_UNORM, DXGI_FORMAT_BC2_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); - - // From GL_ANGLE_texture_compression_dxt5 - InsertD3D11FormatInfo(&map, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, DXGI_FORMAT_BC3_UNORM, DXGI_FORMAT_BC3_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); - - return map; -} - -const TextureFormat &GetTextureFormatInfo(GLenum internalFormat) -{ - static const D3D11ES3FormatMap formatMap = BuildD3D11FormatMap(); - D3D11ES3FormatMap::const_iterator iter = formatMap.find(internalFormat); - if (iter != formatMap.end()) - { - return iter->second; - } - else - { - static const TextureFormat defaultInfo; - return defaultInfo; - } -} - -typedef std::map D3D11VertexFormatInfoMap; -typedef std::pair D3D11VertexFormatPair; - -VertexFormat::VertexFormat() - : conversionType(VERTEX_CONVERT_NONE), - nativeFormat(DXGI_FORMAT_UNKNOWN), - copyFunction(NULL) -{ -} - -static void AddVertexFormatInfo(D3D11VertexFormatInfoMap *map, GLenum inputType, GLboolean normalized, GLuint componentCount, - VertexConversionType conversionType, DXGI_FORMAT nativeFormat, VertexCopyFunction copyFunction) -{ - gl::VertexFormat inputFormat(inputType, normalized, componentCount, false); - - VertexFormat info; - info.conversionType = conversionType; - info.nativeFormat = nativeFormat; - info.copyFunction = copyFunction; - - map->insert(D3D11VertexFormatPair(inputFormat, info)); -} - -static void AddIntegerVertexFormatInfo(D3D11VertexFormatInfoMap *map, GLenum inputType, GLuint componentCount, - VertexConversionType conversionType, DXGI_FORMAT nativeFormat, VertexCopyFunction copyFunction) -{ - gl::VertexFormat inputFormat(inputType, GL_FALSE, componentCount, true); - - VertexFormat info; - info.conversionType = conversionType; - info.nativeFormat = nativeFormat; - info.copyFunction = copyFunction; - - map->insert(D3D11VertexFormatPair(inputFormat, info)); -} - -static D3D11VertexFormatInfoMap BuildD3D11VertexFormatInfoMap() -{ - D3D11VertexFormatInfoMap map; - - // TODO: column legend - - // - // Float formats - // - - // GL_BYTE -- un-normalized - AddVertexFormatInfo(&map, GL_BYTE, GL_FALSE, 1, VERTEX_CONVERT_GPU, DXGI_FORMAT_R8_SINT, &CopyNativeVertexData); - AddVertexFormatInfo(&map, GL_BYTE, GL_FALSE, 2, VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8_SINT, &CopyNativeVertexData); - AddVertexFormatInfo(&map, GL_BYTE, GL_FALSE, 3, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R8G8B8A8_SINT, &CopyNativeVertexData); - AddVertexFormatInfo(&map, GL_BYTE, GL_FALSE, 4, VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8B8A8_SINT, &CopyNativeVertexData); - - // GL_BYTE -- normalized - AddVertexFormatInfo(&map, GL_BYTE, GL_TRUE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_SNORM, &CopyNativeVertexData); - AddVertexFormatInfo(&map, GL_BYTE, GL_TRUE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_SNORM, &CopyNativeVertexData); - AddVertexFormatInfo(&map, GL_BYTE, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_SNORM, &CopyNativeVertexData); - AddVertexFormatInfo(&map, GL_BYTE, GL_TRUE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_SNORM, &CopyNativeVertexData); - - // GL_UNSIGNED_BYTE -- un-normalized - AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_FALSE, 1, VERTEX_CONVERT_GPU, DXGI_FORMAT_R8_UINT, &CopyNativeVertexData); - AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_FALSE, 2, VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8_UINT, &CopyNativeVertexData); - AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_FALSE, 3, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R8G8B8A8_UINT, &CopyNativeVertexData); - AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_FALSE, 4, VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8B8A8_UINT, &CopyNativeVertexData); - - // GL_UNSIGNED_BYTE -- normalized - AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_TRUE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_UNORM, &CopyNativeVertexData); - AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_TRUE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_UNORM, &CopyNativeVertexData); - AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_UNORM, &CopyNativeVertexData); - AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_TRUE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_UNORM, &CopyNativeVertexData); - - // GL_SHORT -- un-normalized - AddVertexFormatInfo(&map, GL_SHORT, GL_FALSE, 1, VERTEX_CONVERT_GPU, DXGI_FORMAT_R16_SINT, &CopyNativeVertexData); - AddVertexFormatInfo(&map, GL_SHORT, GL_FALSE, 2, VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16_SINT, &CopyNativeVertexData); - AddVertexFormatInfo(&map, GL_SHORT, GL_FALSE, 3, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16B16A16_SINT, &CopyNativeVertexData); - AddVertexFormatInfo(&map, GL_SHORT, GL_FALSE, 4, VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16B16A16_SINT, &CopyNativeVertexData); - - // GL_SHORT -- normalized - AddVertexFormatInfo(&map, GL_SHORT, GL_TRUE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_SNORM, &CopyNativeVertexData); - AddVertexFormatInfo(&map, GL_SHORT, GL_TRUE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_SNORM, &CopyNativeVertexData); - AddVertexFormatInfo(&map, GL_SHORT, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SNORM, &CopyNativeVertexData); - AddVertexFormatInfo(&map, GL_SHORT, GL_TRUE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_SNORM, &CopyNativeVertexData); - - // GL_UNSIGNED_SHORT -- un-normalized - AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_FALSE, 1, VERTEX_CONVERT_GPU, DXGI_FORMAT_R16_UINT, &CopyNativeVertexData); - AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_FALSE, 2, VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16_UINT, &CopyNativeVertexData); - AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_FALSE, 3, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16B16A16_UINT, &CopyNativeVertexData); - AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_FALSE, 4, VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16B16A16_UINT, &CopyNativeVertexData); - - // GL_UNSIGNED_SHORT -- normalized - AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_TRUE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_UNORM, &CopyNativeVertexData); - AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_TRUE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_UNORM, &CopyNativeVertexData); - AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_UNORM, &CopyNativeVertexData); - AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_TRUE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_UNORM, &CopyNativeVertexData); - - // GL_INT -- un-normalized - AddVertexFormatInfo(&map, GL_INT, GL_FALSE, 1, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32_SINT, &CopyNativeVertexData); - AddVertexFormatInfo(&map, GL_INT, GL_FALSE, 2, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32_SINT, &CopyNativeVertexData); - AddVertexFormatInfo(&map, GL_INT, GL_FALSE, 3, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32_SINT, &CopyNativeVertexData); - AddVertexFormatInfo(&map, GL_INT, GL_FALSE, 4, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32A32_SINT, &CopyNativeVertexData); - - // GL_INT -- normalized - AddVertexFormatInfo(&map, GL_INT, GL_TRUE, 1, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32_FLOAT, &CopyTo32FVertexData); - AddVertexFormatInfo(&map, GL_INT, GL_TRUE, 2, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, &CopyTo32FVertexData); - AddVertexFormatInfo(&map, GL_INT, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT, &CopyTo32FVertexData); - AddVertexFormatInfo(&map, GL_INT, GL_TRUE, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyTo32FVertexData); - - // GL_UNSIGNED_INT -- un-normalized - AddVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_FALSE, 1, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32_UINT, &CopyNativeVertexData); - AddVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_FALSE, 2, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32_UINT, &CopyNativeVertexData); - AddVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_FALSE, 3, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32_UINT, &CopyNativeVertexData); - AddVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_FALSE, 4, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32A32_UINT, &CopyNativeVertexData); - - // GL_UNSIGNED_INT -- normalized - AddVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_TRUE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32_FLOAT, &CopyTo32FVertexData); - AddVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_TRUE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_FLOAT, &CopyTo32FVertexData); - AddVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT, &CopyTo32FVertexData); - AddVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_TRUE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyTo32FVertexData); - - // GL_FIXED - AddVertexFormatInfo(&map, GL_FIXED, GL_FALSE, 1, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32_FLOAT, &Copy32FixedTo32FVertexData<1>); - AddVertexFormatInfo(&map, GL_FIXED, GL_FALSE, 2, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, &Copy32FixedTo32FVertexData<2>); - AddVertexFormatInfo(&map, GL_FIXED, GL_FALSE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT, &Copy32FixedTo32FVertexData<3>); - AddVertexFormatInfo(&map, GL_FIXED, GL_FALSE, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, &Copy32FixedTo32FVertexData<4>); - - // GL_HALF_FLOAT - AddVertexFormatInfo(&map, GL_HALF_FLOAT, GL_FALSE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_FLOAT, &CopyNativeVertexData); - AddVertexFormatInfo(&map, GL_HALF_FLOAT, GL_FALSE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_FLOAT, &CopyNativeVertexData); - AddVertexFormatInfo(&map, GL_HALF_FLOAT, GL_FALSE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_FLOAT, &CopyNativeVertexData); - AddVertexFormatInfo(&map, GL_HALF_FLOAT, GL_FALSE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_FLOAT, &CopyNativeVertexData); - - // GL_FLOAT - AddVertexFormatInfo(&map, GL_FLOAT, GL_FALSE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32_FLOAT, &CopyNativeVertexData); - AddVertexFormatInfo(&map, GL_FLOAT, GL_FALSE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_FLOAT, &CopyNativeVertexData); - AddVertexFormatInfo(&map, GL_FLOAT, GL_FALSE, 3, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32_FLOAT, &CopyNativeVertexData); - AddVertexFormatInfo(&map, GL_FLOAT, GL_FALSE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyNativeVertexData); - - // GL_INT_2_10_10_10_REV - AddVertexFormatInfo(&map, GL_INT_2_10_10_10_REV, GL_FALSE, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyXYZ10W2ToXYZW32FVertexData); - AddVertexFormatInfo(&map, GL_INT_2_10_10_10_REV, GL_TRUE, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyXYZ10W2ToXYZW32FVertexData); - - // GL_UNSIGNED_INT_2_10_10_10_REV - AddVertexFormatInfo(&map, GL_UNSIGNED_INT_2_10_10_10_REV, GL_FALSE, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyXYZ10W2ToXYZW32FVertexData); - AddVertexFormatInfo(&map, GL_UNSIGNED_INT_2_10_10_10_REV, GL_TRUE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R10G10B10A2_UNORM, &CopyNativeVertexData); - - // - // Integer Formats - // - - // GL_BYTE - AddIntegerVertexFormatInfo(&map, GL_BYTE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_SINT, &CopyNativeVertexData); - AddIntegerVertexFormatInfo(&map, GL_BYTE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_SINT, &CopyNativeVertexData); - AddIntegerVertexFormatInfo(&map, GL_BYTE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_SINT, &CopyNativeVertexData); - AddIntegerVertexFormatInfo(&map, GL_BYTE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_SINT, &CopyNativeVertexData); - - // GL_UNSIGNED_BYTE - AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_BYTE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_UINT, &CopyNativeVertexData); - AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_BYTE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_UINT, &CopyNativeVertexData); - AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_BYTE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_UINT, &CopyNativeVertexData); - AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_BYTE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_UINT, &CopyNativeVertexData); - - // GL_SHORT - AddIntegerVertexFormatInfo(&map, GL_SHORT, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_SINT, &CopyNativeVertexData); - AddIntegerVertexFormatInfo(&map, GL_SHORT, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_SINT, &CopyNativeVertexData); - AddIntegerVertexFormatInfo(&map, GL_SHORT, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SINT, &CopyNativeVertexData); - AddIntegerVertexFormatInfo(&map, GL_SHORT, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_SINT, &CopyNativeVertexData); - - // GL_UNSIGNED_SHORT - AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_SHORT, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_UINT, &CopyNativeVertexData); - AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_SHORT, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_UINT, &CopyNativeVertexData); - AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_SHORT, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_UINT, &CopyNativeVertexData); - AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_SHORT, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_UINT, &CopyNativeVertexData); - - // GL_INT - AddIntegerVertexFormatInfo(&map, GL_INT, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32_SINT, &CopyNativeVertexData); - AddIntegerVertexFormatInfo(&map, GL_INT, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_SINT, &CopyNativeVertexData); - AddIntegerVertexFormatInfo(&map, GL_INT, 3, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32_SINT, &CopyNativeVertexData); - AddIntegerVertexFormatInfo(&map, GL_INT, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32A32_SINT, &CopyNativeVertexData); - - // GL_UNSIGNED_INT - AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_INT, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32_SINT, &CopyNativeVertexData); - AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_INT, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_SINT, &CopyNativeVertexData); - AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_INT, 3, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32_SINT, &CopyNativeVertexData); - AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_INT, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32A32_SINT, &CopyNativeVertexData); - - // GL_INT_2_10_10_10_REV - AddIntegerVertexFormatInfo(&map, GL_INT_2_10_10_10_REV, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SINT, &CopyXYZ10W2ToXYZW32FVertexData); - - // GL_UNSIGNED_INT_2_10_10_10_REV - AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_INT_2_10_10_10_REV, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R10G10B10A2_UINT, &CopyNativeVertexData); - - return map; -} - -const VertexFormat &GetVertexFormatInfo(const gl::VertexFormat &vertexFormat) -{ - static const D3D11VertexFormatInfoMap vertexFormatMap = BuildD3D11VertexFormatInfoMap(); - - D3D11VertexFormatInfoMap::const_iterator iter = vertexFormatMap.find(vertexFormat); - if (iter != vertexFormatMap.end()) - { - return iter->second; - } - else - { - static const VertexFormat defaultInfo; - return defaultInfo; - } -} - -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.h deleted file mode 100644 index ea11aaa74c..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.h +++ /dev/null @@ -1,84 +0,0 @@ -// -// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// formatutils11.h: Queries for GL image formats and their translations to D3D11 -// formats. - -#ifndef LIBGLESV2_RENDERER_FORMATUTILS11_H_ -#define LIBGLESV2_RENDERER_FORMATUTILS11_H_ - -#include "libGLESv2/formatutils.h" - -#include - -namespace rx -{ - -namespace d3d11 -{ - -typedef std::map, ColorCopyFunction> FastCopyFunctionMap; - -struct DXGIFormat -{ - DXGIFormat(); - - GLuint pixelBytes; - GLuint blockWidth; - GLuint blockHeight; - - GLuint depthBits; - GLuint depthOffset; - GLuint stencilBits; - GLuint stencilOffset; - - GLenum internalFormat; - GLenum componentType; - - MipGenerationFunction mipGenerationFunction; - ColorReadFunction colorReadFunction; - - FastCopyFunctionMap fastCopyFunctions; - ColorCopyFunction getFastCopyFunction(GLenum format, GLenum type) const; -}; -const DXGIFormat &GetDXGIFormatInfo(DXGI_FORMAT format); - -struct TextureFormat -{ - TextureFormat(); - - DXGI_FORMAT texFormat; - DXGI_FORMAT srvFormat; - DXGI_FORMAT rtvFormat; - DXGI_FORMAT dsvFormat; - DXGI_FORMAT renderFormat; - - DXGI_FORMAT swizzleTexFormat; - DXGI_FORMAT swizzleSRVFormat; - DXGI_FORMAT swizzleRTVFormat; - - InitializeTextureDataFunction dataInitializerFunction; - - typedef std::map LoadFunctionMap; - LoadFunctionMap loadFunctions; -}; -const TextureFormat &GetTextureFormatInfo(GLenum internalFormat); - -struct VertexFormat -{ - VertexFormat(); - - VertexConversionType conversionType; - DXGI_FORMAT nativeFormat; - VertexCopyFunction copyFunction; -}; -const VertexFormat &GetVertexFormatInfo(const gl::VertexFormat &vertexFormat); - -} - -} - -#endif // LIBGLESV2_RENDERER_FORMATUTILS11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp deleted file mode 100644 index 121aa3bbad..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp +++ /dev/null @@ -1,1228 +0,0 @@ -// -// Copyright (c) 2012-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// renderer11_utils.cpp: Conversion functions and other utility routines -// specific to the D3D11 renderer. - -#include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h" -#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" -#include "libGLESv2/renderer/d3d/d3d11/RenderTarget11.h" -#include "libGLESv2/renderer/Workarounds.h" -#include "libGLESv2/ProgramBinary.h" -#include "libGLESv2/Framebuffer.h" - -#include "common/debug.h" - -#include - -#ifndef D3D_FL9_1_DEFAULT_MAX_ANISOTROPY -# define D3D_FL9_1_DEFAULT_MAX_ANISOTROPY 2 -#endif -#ifndef D3D_FL9_1_SIMULTANEOUS_RENDER_TARGET_COUNT -# define D3D_FL9_1_SIMULTANEOUS_RENDER_TARGET_COUNT 1 -#endif -#ifndef D3D_FL9_3_SIMULTANEOUS_RENDER_TARGET_COUNT -# define D3D_FL9_3_SIMULTANEOUS_RENDER_TARGET_COUNT 4 -#endif -#ifndef D3D_FL9_1_IA_PRIMITIVE_MAX_COUNT -# define D3D_FL9_1_IA_PRIMITIVE_MAX_COUNT 65535 -#endif -#ifndef D3D_FL9_2_IA_PRIMITIVE_MAX_COUNT -# define D3D_FL9_2_IA_PRIMITIVE_MAX_COUNT 1048575 -#endif -#ifndef D3D_FL9_1_REQ_TEXTURECUBE_DIMENSION -# define D3D_FL9_1_REQ_TEXTURECUBE_DIMENSION 512 -#endif -#ifndef D3D_FL9_3_REQ_TEXTURECUBE_DIMENSION -# define D3D_FL9_3_REQ_TEXTURECUBE_DIMENSION 4096 -#endif -#ifndef D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION -# define D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION 2048 -#endif -#ifndef D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION -# define D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION 256 -#endif -#ifndef D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION -# define D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION 4096 -#endif -#ifndef D3D11_REQ_TEXTURECUBE_DIMENSION -# define D3D11_REQ_TEXTURECUBE_DIMENSION 16384 -#endif -#ifndef D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION -# define D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION 2048 -#endif -#ifndef D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION -# define D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION 2048 -#endif -#ifndef D3D11_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP -# define D3D11_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP 32 -#endif -#ifndef D3D11_REQ_DRAW_VERTEX_COUNT_2_TO_EXP -# define D3D11_REQ_DRAW_VERTEX_COUNT_2_TO_EXP 32 -#endif -#ifndef D3D10_1_STANDARD_VERTEX_ELEMENT_COUNT -# define D3D10_1_STANDARD_VERTEX_ELEMENT_COUNT 32 -#endif -#ifndef D3D11_STANDARD_VERTEX_ELEMENT_COUNT -# define D3D11_STANDARD_VERTEX_ELEMENT_COUNT 32 -#endif -#ifndef D3D10_1_SO_BUFFER_SLOT_COUNT -# define D3D10_1_SO_BUFFER_SLOT_COUNT 4 -#endif -#ifndef D3D11_SO_BUFFER_SLOT_COUNT -# define D3D11_SO_BUFFER_SLOT_COUNT 4 -#endif -#ifndef D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT -# define D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT 14 -#endif -#ifndef D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT -# define D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT 16 -#endif -#ifndef D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE -# define D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE -8 -#endif -#ifndef D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE -# define D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE 7 -#endif -#ifndef D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT -# define D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT 4096 -#endif -#ifndef D3D11_PS_INPUT_REGISTER_COUNT -# define D3D11_PS_INPUT_REGISTER_COUNT 32 -#endif -#ifndef D3D10_1_VS_OUTPUT_REGISTER_COUNT -# define D3D10_1_VS_OUTPUT_REGISTER_COUNT 32 -#endif - -namespace rx -{ - -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; - case GL_MIN: d3dBlendOp = D3D11_BLEND_OP_MIN; break; - case GL_MAX: d3dBlendOp = D3D11_BLEND_OP_MAX; 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, GLenum comparisonMode) -{ - bool comparison = comparisonMode != GL_NONE; - - if (maxAnisotropy > 1.0f) - { - return D3D11_ENCODE_ANISOTROPIC_FILTER(static_cast(comparison)); - } - 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, static_cast(comparison)); - } -} - -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; -} - -D3D11_QUERY ConvertQueryType(GLenum queryType) -{ - switch (queryType) - { - case GL_ANY_SAMPLES_PASSED_EXT: - case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT: return D3D11_QUERY_OCCLUSION; - case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: return D3D11_QUERY_SO_STATISTICS; - default: UNREACHABLE(); return D3D11_QUERY_EVENT; - } -} - -} - - -namespace d3d11_gl -{ - -static gl::TextureCaps GenerateTextureFormatCaps(GLenum internalFormat, ID3D11Device *device) -{ - gl::TextureCaps textureCaps; - - const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalFormat); - - UINT formatSupport; - if (SUCCEEDED(device->CheckFormatSupport(formatInfo.texFormat, &formatSupport))) - { - const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat); - if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0) - { - textureCaps.texturable = ((formatSupport & D3D11_FORMAT_SUPPORT_TEXTURE2D) != 0); - } - else - { - textureCaps.texturable = ((formatSupport & D3D11_FORMAT_SUPPORT_TEXTURE2D) != 0) && - ((formatSupport & D3D11_FORMAT_SUPPORT_TEXTURECUBE) != 0) && - ((formatSupport & D3D11_FORMAT_SUPPORT_TEXTURE3D) != 0); - } - } - - if (SUCCEEDED(device->CheckFormatSupport(formatInfo.renderFormat, &formatSupport)) && - ((formatSupport & D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET) != 0)) - { - for (size_t sampleCount = 1; sampleCount <= D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT; sampleCount++) - { - UINT qualityCount = 0; - if (SUCCEEDED(device->CheckMultisampleQualityLevels(formatInfo.renderFormat, sampleCount, &qualityCount)) && - qualityCount > 0) - { - textureCaps.sampleCounts.insert(sampleCount); - } - } - } - - textureCaps.filterable = SUCCEEDED(device->CheckFormatSupport(formatInfo.srvFormat, &formatSupport)) && - ((formatSupport & D3D11_FORMAT_SUPPORT_SHADER_SAMPLE)) != 0; - textureCaps.renderable = (SUCCEEDED(device->CheckFormatSupport(formatInfo.rtvFormat, &formatSupport)) && - ((formatSupport & D3D11_FORMAT_SUPPORT_RENDER_TARGET)) != 0) || - (SUCCEEDED(device->CheckFormatSupport(formatInfo.dsvFormat, &formatSupport)) && - ((formatSupport & D3D11_FORMAT_SUPPORT_DEPTH_STENCIL) != 0)); - - return textureCaps; -} - -static bool GetNPOTTextureSupport(D3D_FEATURE_LEVEL featureLevel) -{ - switch (featureLevel) - { -#if !defined(_MSC_VER) || (_MSC_VER >= 1800) - case D3D_FEATURE_LEVEL_11_1: -#endif - case D3D_FEATURE_LEVEL_11_0: - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: return true; - - // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876.aspx - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return true; // Provided that mipmaps & wrap modes are not used - - default: UNREACHABLE(); return false; - } -} - -static float GetMaximumAnisotropy(D3D_FEATURE_LEVEL featureLevel) -{ - switch (featureLevel) - { -#if !defined(_MSC_VER) || (_MSC_VER >= 1800) - case D3D_FEATURE_LEVEL_11_1: -#endif - 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; - - // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876.aspx - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: return 16; - - case D3D_FEATURE_LEVEL_9_1: return D3D_FL9_1_DEFAULT_MAX_ANISOTROPY; - - default: UNREACHABLE(); return 0; - } -} - -static bool GetOcclusionQuerySupport(D3D_FEATURE_LEVEL featureLevel) -{ - switch (featureLevel) - { -#if !defined(_MSC_VER) || (_MSC_VER >= 1800) - case D3D_FEATURE_LEVEL_11_1: -#endif - case D3D_FEATURE_LEVEL_11_0: - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: return true; - - // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx ID3D11Device::CreateQuery - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: return true; - case D3D_FEATURE_LEVEL_9_1: return false; - - default: UNREACHABLE(); return false; - } -} - -static bool GetEventQuerySupport(D3D_FEATURE_LEVEL featureLevel) -{ - // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx ID3D11Device::CreateQuery - - switch (featureLevel) - { -#if !defined(_MSC_VER) || (_MSC_VER >= 1800) - case D3D_FEATURE_LEVEL_11_1: -#endif - case D3D_FEATURE_LEVEL_11_0: - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return true; - - default: UNREACHABLE(); return false; - } -} - -static bool GetInstancingSupport(D3D_FEATURE_LEVEL featureLevel) -{ - // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx ID3D11Device::CreateInputLayout - - switch (featureLevel) - { -#if !defined(_MSC_VER) || (_MSC_VER >= 1800) - case D3D_FEATURE_LEVEL_11_1: -#endif - case D3D_FEATURE_LEVEL_11_0: - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: - case D3D_FEATURE_LEVEL_9_3: return true; - - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return false; - - default: UNREACHABLE(); return false; - } -} - -static bool GetDerivativeInstructionSupport(D3D_FEATURE_LEVEL featureLevel) -{ - // http://msdn.microsoft.com/en-us/library/windows/desktop/bb509588.aspx states that shader model - // ps_2_x is required for the ddx (and other derivative functions). - - // http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876.aspx states that feature level - // 9.3 supports shader model ps_2_x. - - switch (featureLevel) - { -#if !defined(_MSC_VER) || (_MSC_VER >= 1800) - case D3D_FEATURE_LEVEL_11_1: -#endif - case D3D_FEATURE_LEVEL_11_0: - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: - case D3D_FEATURE_LEVEL_9_3: return true; - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return false; - - default: UNREACHABLE(); return false; - } -} - -static size_t GetMaximumSimultaneousRenderTargets(D3D_FEATURE_LEVEL featureLevel) -{ - // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx ID3D11Device::CreateInputLayout - - switch (featureLevel) - { -#if !defined(_MSC_VER) || (_MSC_VER >= 1800) - case D3D_FEATURE_LEVEL_11_1: -#endif - case D3D_FEATURE_LEVEL_11_0: return D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; - - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: return D3D10_SIMULTANEOUS_RENDER_TARGET_COUNT; - - case D3D_FEATURE_LEVEL_9_3: return D3D_FL9_3_SIMULTANEOUS_RENDER_TARGET_COUNT; - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return D3D_FL9_1_SIMULTANEOUS_RENDER_TARGET_COUNT; - - default: UNREACHABLE(); return 0; - } -} - -static size_t GetMaximum2DTextureSize(D3D_FEATURE_LEVEL featureLevel) -{ - switch (featureLevel) - { -#if !defined(_MSC_VER) || (_MSC_VER >= 1800) - case D3D_FEATURE_LEVEL_11_1: -#endif - case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; - - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION; - - case D3D_FEATURE_LEVEL_9_3: return D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION; - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION; - - default: UNREACHABLE(); return 0; - } -} - -static size_t GetMaximumCubeMapTextureSize(D3D_FEATURE_LEVEL featureLevel) -{ - switch (featureLevel) - { -#if !defined(_MSC_VER) || (_MSC_VER >= 1800) - case D3D_FEATURE_LEVEL_11_1: -#endif - case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURECUBE_DIMENSION; - - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURECUBE_DIMENSION; - - case D3D_FEATURE_LEVEL_9_3: return D3D_FL9_3_REQ_TEXTURECUBE_DIMENSION; - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return D3D_FL9_1_REQ_TEXTURECUBE_DIMENSION; - - default: UNREACHABLE(); return 0; - } -} - -static size_t GetMaximum2DTextureArraySize(D3D_FEATURE_LEVEL featureLevel) -{ - switch (featureLevel) - { -#if !defined(_MSC_VER) || (_MSC_VER >= 1800) - case D3D_FEATURE_LEVEL_11_1: -#endif - case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION; - - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION; - - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return 0; - - default: UNREACHABLE(); return 0; - } -} - -static size_t GetMaximum3DTextureSize(D3D_FEATURE_LEVEL featureLevel) -{ - switch (featureLevel) - { -#if !defined(_MSC_VER) || (_MSC_VER >= 1800) - case D3D_FEATURE_LEVEL_11_1: -#endif - case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION; - - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE3D_U_V_OR_W_DIMENSION; - - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION; - - default: UNREACHABLE(); return 0; - } -} - -static size_t GetMaximumViewportSize(D3D_FEATURE_LEVEL featureLevel) -{ - switch (featureLevel) - { -#if !defined(_MSC_VER) || (_MSC_VER >= 1800) - case D3D_FEATURE_LEVEL_11_1: -#endif - case D3D_FEATURE_LEVEL_11_0: return D3D11_VIEWPORT_BOUNDS_MAX; - - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: return D3D10_VIEWPORT_BOUNDS_MAX; - - // No constants for D3D9 viewport size limits, use the maximum texture sizes - case D3D_FEATURE_LEVEL_9_3: return D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION; - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION; - - default: UNREACHABLE(); return 0; - } -} - -static size_t GetMaximumDrawIndexedIndexCount(D3D_FEATURE_LEVEL featureLevel) -{ - // D3D11 allows up to 2^32 elements, but we report max signed int for convenience since that's what's - // returned from glGetInteger - META_ASSERT(D3D11_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP == 32); - META_ASSERT(D3D10_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP == 32); - - switch (featureLevel) - { -#if !defined(_MSC_VER) || (_MSC_VER >= 1800) - case D3D_FEATURE_LEVEL_11_1: -#endif - case D3D_FEATURE_LEVEL_11_0: - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: return std::numeric_limits::max(); - - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: return D3D_FL9_2_IA_PRIMITIVE_MAX_COUNT; - case D3D_FEATURE_LEVEL_9_1: return D3D_FL9_1_IA_PRIMITIVE_MAX_COUNT; - - default: UNREACHABLE(); return 0; - } -} - -static size_t GetMaximumDrawVertexCount(D3D_FEATURE_LEVEL featureLevel) -{ - // D3D11 allows up to 2^32 elements, but we report max signed int for convenience since that's what's - // returned from glGetInteger - META_ASSERT(D3D11_REQ_DRAW_VERTEX_COUNT_2_TO_EXP == 32); - META_ASSERT(D3D10_REQ_DRAW_VERTEX_COUNT_2_TO_EXP == 32); - - switch (featureLevel) - { -#if !defined(_MSC_VER) || (_MSC_VER >= 1800) - case D3D_FEATURE_LEVEL_11_1: -#endif - case D3D_FEATURE_LEVEL_11_0: - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: return std::numeric_limits::max(); - - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: return D3D_FL9_2_IA_PRIMITIVE_MAX_COUNT; - case D3D_FEATURE_LEVEL_9_1: return D3D_FL9_1_IA_PRIMITIVE_MAX_COUNT; - - default: UNREACHABLE(); return 0; - } -} - -static size_t GetMaximumVertexInputSlots(D3D_FEATURE_LEVEL featureLevel) -{ - switch (featureLevel) - { -#if !defined(_MSC_VER) || (_MSC_VER >= 1800) - case D3D_FEATURE_LEVEL_11_1: -#endif - case D3D_FEATURE_LEVEL_11_0: return D3D11_STANDARD_VERTEX_ELEMENT_COUNT; - - case D3D_FEATURE_LEVEL_10_1: return D3D10_1_STANDARD_VERTEX_ELEMENT_COUNT; - case D3D_FEATURE_LEVEL_10_0: return D3D10_STANDARD_VERTEX_ELEMENT_COUNT; - - // From http://http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876.aspx "Max Input Slots" - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return 16; - - default: UNREACHABLE(); return 0; - } -} - -static size_t GetMaximumVertexUniformVectors(D3D_FEATURE_LEVEL featureLevel) -{ - // TODO(geofflang): Remove hard-coded limit once the gl-uniform-arrays test can pass - switch (featureLevel) - { -#if !defined(_MSC_VER) || (_MSC_VER >= 1800) - case D3D_FEATURE_LEVEL_11_1: -#endif - case D3D_FEATURE_LEVEL_11_0: return 1024; // D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT; - - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: return 1024; // D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT; - - // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476149.aspx ID3D11DeviceContext::VSSetConstantBuffers - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return 255; - - default: UNREACHABLE(); return 0; - } -} - -static size_t GetReservedVertexUniformBuffers() -{ - // Reserve one buffer for the application uniforms, and one for driver uniforms - return 2; -} - -static size_t GetMaximumVertexUniformBlocks(D3D_FEATURE_LEVEL featureLevel) -{ - switch (featureLevel) - { -#if !defined(_MSC_VER) || (_MSC_VER >= 1800) - case D3D_FEATURE_LEVEL_11_1: -#endif - case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - GetReservedVertexUniformBuffers(); - - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: return D3D10_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - GetReservedVertexUniformBuffers(); - - // Uniform blocks not supported in D3D9 feature levels - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return 0; - - default: UNREACHABLE(); return 0; - } -} - -static size_t GetReservedVertexOutputVectors() -{ - // We potentially reserve varyings for gl_Position, dx_Position, gl_FragCoord and gl_PointSize - return 4; -} - -static size_t GetMaximumVertexOutputVectors(D3D_FEATURE_LEVEL featureLevel) -{ - META_ASSERT(gl::IMPLEMENTATION_MAX_VARYING_VECTORS == D3D11_VS_OUTPUT_REGISTER_COUNT); - - switch (featureLevel) - { -#if !defined(_MSC_VER) || (_MSC_VER >= 1800) - case D3D_FEATURE_LEVEL_11_1: -#endif - case D3D_FEATURE_LEVEL_11_0: return D3D11_VS_OUTPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(); - - case D3D_FEATURE_LEVEL_10_1: return D3D10_1_VS_OUTPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(); - case D3D_FEATURE_LEVEL_10_0: return D3D10_VS_OUTPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(); - - // Use D3D9 SM3 and SM2 limits - case D3D_FEATURE_LEVEL_9_3: return 10 - GetReservedVertexOutputVectors(); - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return 8 - GetReservedVertexOutputVectors(); - - default: UNREACHABLE(); return 0; - } -} - -static size_t GetMaximumVertexTextureUnits(D3D_FEATURE_LEVEL featureLevel) -{ - switch (featureLevel) - { -#if !defined(_MSC_VER) || (_MSC_VER >= 1800) - case D3D_FEATURE_LEVEL_11_1: -#endif - case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT; - - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: return D3D10_COMMONSHADER_SAMPLER_SLOT_COUNT; - - // Vertex textures not supported in D3D9 feature levels according to - // http://msdn.microsoft.com/en-us/library/windows/desktop/ff476149.aspx - // ID3D11DeviceContext::VSSetSamplers and ID3D11DeviceContext::VSSetShaderResources - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return 0; - - default: UNREACHABLE(); return 0; - } -} - -static size_t GetMaximumPixelUniformVectors(D3D_FEATURE_LEVEL featureLevel) -{ - // TODO(geofflang): Remove hard-coded limit once the gl-uniform-arrays test can pass - switch (featureLevel) - { -#if !defined(_MSC_VER) || (_MSC_VER >= 1800) - case D3D_FEATURE_LEVEL_11_1: -#endif - case D3D_FEATURE_LEVEL_11_0: return 1024; // D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT; - - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: return 1024; // D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT; - - // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476149.aspx ID3D11DeviceContext::PSSetConstantBuffers - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return 32; - - default: UNREACHABLE(); return 0; - } -} - -static size_t GetReservedPixelUniformBuffers() -{ - // Reserve one buffer for the application uniforms, and one for driver uniforms - return 2; -} - -static size_t GetMaximumPixelUniformBlocks(D3D_FEATURE_LEVEL featureLevel) -{ - switch (featureLevel) - { -#if !defined(_MSC_VER) || (_MSC_VER >= 1800) - case D3D_FEATURE_LEVEL_11_1: -#endif - case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - GetReservedPixelUniformBuffers(); - - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: return D3D10_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - GetReservedPixelUniformBuffers(); - - // Uniform blocks not supported in D3D9 feature levels - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return 0; - - default: UNREACHABLE(); return 0; - } -} - -static size_t GetMaximumPixelInputVectors(D3D_FEATURE_LEVEL featureLevel) -{ - switch (featureLevel) - { -#if !defined(_MSC_VER) || (_MSC_VER >= 1800) - case D3D_FEATURE_LEVEL_11_1: -#endif - case D3D_FEATURE_LEVEL_11_0: return D3D11_PS_INPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(); - - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: return D3D10_PS_INPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(); - - // Use D3D9 SM3 and SM2 limits - case D3D_FEATURE_LEVEL_9_3: return 10 - GetReservedVertexOutputVectors(); - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return 8 - GetReservedVertexOutputVectors(); - - default: UNREACHABLE(); return 0; - } -} - -static size_t GetMaximumPixelTextureUnits(D3D_FEATURE_LEVEL featureLevel) -{ - switch (featureLevel) - { -#if !defined(_MSC_VER) || (_MSC_VER >= 1800) - case D3D_FEATURE_LEVEL_11_1: -#endif - case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT; - - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: return D3D10_COMMONSHADER_SAMPLER_SLOT_COUNT; - - // http://msdn.microsoft.com/en-us/library/windows/desktop/ff476149.aspx ID3D11DeviceContext::PSSetShaderResources - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return 16; - - default: UNREACHABLE(); return 0; - } -} - -static int GetMinimumTexelOffset(D3D_FEATURE_LEVEL featureLevel) -{ - switch (featureLevel) - { -#if !defined(_MSC_VER) || (_MSC_VER >= 1800) - case D3D_FEATURE_LEVEL_11_1: -#endif - case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE; - - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: return D3D10_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE; - - // Sampling functions with offsets are not available below shader model 4.0. - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return 0; - - default: UNREACHABLE(); return 0; - } -} - -static int GetMaximumTexelOffset(D3D_FEATURE_LEVEL featureLevel) -{ - switch (featureLevel) - { -#if !defined(_MSC_VER) || (_MSC_VER >= 1800) - case D3D_FEATURE_LEVEL_11_1: -#endif - case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE; - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: return D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE; - - // Sampling functions with offsets are not available below shader model 4.0. - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return 0; - - default: UNREACHABLE(); return 0; - } -} - -static size_t GetMaximumConstantBufferSize(D3D_FEATURE_LEVEL featureLevel) -{ - // Returns a size_t despite the limit being a GLuint64 because size_t is the maximum size of - // any buffer that could be allocated. - - const size_t bytesPerComponent = 4 * sizeof(float); - - switch (featureLevel) - { -#if !defined(_MSC_VER) || (_MSC_VER >= 1800) - case D3D_FEATURE_LEVEL_11_1: -#endif - case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * bytesPerComponent; - - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * bytesPerComponent; - - // Limits from http://msdn.microsoft.com/en-us/library/windows/desktop/ff476501.aspx remarks section - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return 4096 * bytesPerComponent; - - default: UNREACHABLE(); return 0; - } -} - -static size_t GetMaximumStreamOutputBuffers(D3D_FEATURE_LEVEL featureLevel) -{ - switch (featureLevel) - { -#if !defined(_MSC_VER) || (_MSC_VER >= 1800) - case D3D_FEATURE_LEVEL_11_1: -#endif - case D3D_FEATURE_LEVEL_11_0: return D3D11_SO_BUFFER_SLOT_COUNT; - - case D3D_FEATURE_LEVEL_10_1: return D3D10_1_SO_BUFFER_SLOT_COUNT; - case D3D_FEATURE_LEVEL_10_0: return D3D10_SO_BUFFER_SLOT_COUNT; - - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return 0; - - default: UNREACHABLE(); return 0; - } -} - -static size_t GetMaximumStreamOutputInterleavedComponents(D3D_FEATURE_LEVEL featureLevel) -{ - switch (featureLevel) - { -#if !defined(_MSC_VER) || (_MSC_VER >= 1800) - case D3D_FEATURE_LEVEL_11_1: -#endif - case D3D_FEATURE_LEVEL_11_0: - - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: return GetMaximumVertexOutputVectors(featureLevel) * 4; - - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return 0; - - default: UNREACHABLE(); return 0; - } -} - -static size_t GetMaximumStreamOutputSeparateComponents(D3D_FEATURE_LEVEL featureLevel) -{ - switch (featureLevel) - { -#if !defined(_MSC_VER) || (_MSC_VER >= 1800) - case D3D_FEATURE_LEVEL_11_1: -#endif - case D3D_FEATURE_LEVEL_11_0: return GetMaximumStreamOutputInterleavedComponents(featureLevel) / - GetMaximumStreamOutputBuffers(featureLevel); - - - // D3D 10 and 10.1 only allow one output per output slot if an output slot other than zero is used. - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: return 4; - - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return 0; - - default: UNREACHABLE(); return 0; - } -} - -void GenerateCaps(ID3D11Device *device, gl::Caps *caps, gl::TextureCapsMap *textureCapsMap, gl::Extensions *extensions) -{ - GLuint maxSamples = 0; - const gl::FormatSet &allFormats = gl::GetAllSizedInternalFormats(); - for (gl::FormatSet::const_iterator internalFormat = allFormats.begin(); internalFormat != allFormats.end(); ++internalFormat) - { - gl::TextureCaps textureCaps = GenerateTextureFormatCaps(*internalFormat, device); - textureCapsMap->insert(*internalFormat, textureCaps); - - maxSamples = std::max(maxSamples, textureCaps.getMaxSamples()); - - if (gl::GetInternalFormatInfo(*internalFormat).compressed) - { - caps->compressedTextureFormats.push_back(*internalFormat); - } - } - - D3D_FEATURE_LEVEL featureLevel = device->GetFeatureLevel(); - - // GL core feature limits - caps->maxElementIndex = static_cast(std::numeric_limits::max()); - caps->max3DTextureSize = GetMaximum3DTextureSize(featureLevel); - caps->max2DTextureSize = GetMaximum2DTextureSize(featureLevel); - caps->maxCubeMapTextureSize = GetMaximumCubeMapTextureSize(featureLevel); - caps->maxArrayTextureLayers = GetMaximum2DTextureArraySize(featureLevel); - - // Unimplemented, set to minimum required - caps->maxLODBias = 2.0f; - - // No specific limits on render target size, maximum 2D texture size is equivalent - caps->maxRenderbufferSize = caps->max2DTextureSize; - - // Maximum draw buffers and color attachments are the same, max color attachments could eventually be - // increased to 16 - caps->maxDrawBuffers = GetMaximumSimultaneousRenderTargets(featureLevel); - caps->maxColorAttachments = GetMaximumSimultaneousRenderTargets(featureLevel); - - // D3D11 has the same limit for viewport width and height - caps->maxViewportWidth = GetMaximumViewportSize(featureLevel); - caps->maxViewportHeight = caps->maxViewportWidth; - - // Choose a reasonable maximum, enforced in the shader. - caps->minAliasedPointSize = 1.0f; - caps->maxAliasedPointSize = 1024.0f; - - // Wide lines not supported - caps->minAliasedLineWidth = 1.0f; - caps->maxAliasedLineWidth = 1.0f; - - // Primitive count limits - caps->maxElementsIndices = GetMaximumDrawIndexedIndexCount(featureLevel); - caps->maxElementsVertices = GetMaximumDrawVertexCount(featureLevel); - - // Program and shader binary formats (no supported shader binary formats) - caps->programBinaryFormats.push_back(GL_PROGRAM_BINARY_ANGLE); - - // We do not wait for server fence objects internally, so report a max timeout of zero. - caps->maxServerWaitTimeout = 0; - - // Vertex shader limits - caps->maxVertexAttributes = GetMaximumVertexInputSlots(featureLevel); - caps->maxVertexUniformComponents = GetMaximumVertexUniformVectors(featureLevel) * 4; - caps->maxVertexUniformVectors = GetMaximumVertexUniformVectors(featureLevel); - caps->maxVertexUniformBlocks = GetMaximumVertexUniformBlocks(featureLevel); - caps->maxVertexOutputComponents = GetMaximumVertexOutputVectors(featureLevel) * 4; - caps->maxVertexTextureImageUnits = GetMaximumVertexTextureUnits(featureLevel); - - // Fragment shader limits - caps->maxFragmentUniformComponents = GetMaximumPixelUniformVectors(featureLevel) * 4; - caps->maxFragmentUniformVectors = GetMaximumPixelUniformVectors(featureLevel); - caps->maxFragmentUniformBlocks = GetMaximumPixelUniformBlocks(featureLevel); - caps->maxFragmentInputComponents = GetMaximumPixelInputVectors(featureLevel) * 4; - caps->maxTextureImageUnits = GetMaximumPixelTextureUnits(featureLevel); - caps->minProgramTexelOffset = GetMinimumTexelOffset(featureLevel); - caps->maxProgramTexelOffset = GetMaximumTexelOffset(featureLevel); - - // Aggregate shader limits - caps->maxUniformBufferBindings = caps->maxVertexUniformBlocks + caps->maxFragmentUniformBlocks; - caps->maxUniformBlockSize = GetMaximumConstantBufferSize(featureLevel); - - // Setting a large alignment forces uniform buffers to bind with zero offset - caps->uniformBufferOffsetAlignment = static_cast(std::numeric_limits::max()); - - caps->maxCombinedUniformBlocks = caps->maxVertexUniformBlocks + caps->maxFragmentUniformBlocks; - caps->maxCombinedVertexUniformComponents = (static_cast(caps->maxVertexUniformBlocks) * static_cast(caps->maxUniformBlockSize / 4)) + - static_cast(caps->maxVertexUniformComponents); - caps->maxCombinedFragmentUniformComponents = (static_cast(caps->maxFragmentUniformBlocks) * static_cast(caps->maxUniformBlockSize / 4)) + - static_cast(caps->maxFragmentUniformComponents); - caps->maxVaryingComponents = GetMaximumVertexOutputVectors(featureLevel) * 4; - caps->maxVaryingVectors = GetMaximumVertexOutputVectors(featureLevel); - caps->maxCombinedTextureImageUnits = caps->maxVertexTextureImageUnits + caps->maxTextureImageUnits; - - // Transform feedback limits - caps->maxTransformFeedbackInterleavedComponents = GetMaximumStreamOutputInterleavedComponents(featureLevel); - caps->maxTransformFeedbackSeparateAttributes = GetMaximumStreamOutputBuffers(featureLevel); - caps->maxTransformFeedbackSeparateComponents = GetMaximumStreamOutputSeparateComponents(featureLevel); - - // GL extension support - extensions->setTextureExtensionSupport(*textureCapsMap); - extensions->elementIndexUint = true; - extensions->packedDepthStencil = true; - extensions->getProgramBinary = true; - extensions->rgb8rgba8 = true; - extensions->readFormatBGRA = true; - extensions->pixelBufferObject = true; - extensions->mapBuffer = true; - extensions->mapBufferRange = true; - extensions->textureNPOT = GetNPOTTextureSupport(featureLevel); - extensions->drawBuffers = GetMaximumSimultaneousRenderTargets(featureLevel) > 1; - extensions->textureStorage = true; - extensions->textureFilterAnisotropic = true; - extensions->maxTextureAnisotropy = GetMaximumAnisotropy(featureLevel); - extensions->occlusionQueryBoolean = GetOcclusionQuerySupport(featureLevel); - extensions->fence = GetEventQuerySupport(featureLevel); - extensions->timerQuery = false; // Unimplemented - extensions->robustness = true; - extensions->blendMinMax = true; - extensions->framebufferBlit = true; - extensions->framebufferMultisample = true; - extensions->maxSamples = maxSamples; - extensions->instancedArrays = GetInstancingSupport(featureLevel); - extensions->packReverseRowOrder = true; - extensions->standardDerivatives = GetDerivativeInstructionSupport(featureLevel); - extensions->shaderTextureLOD = true; - extensions->fragDepth = true; - extensions->textureUsage = true; // This could be false since it has no effect in D3D11 - extensions->translatedShaderSource = true; -} - -} - -namespace d3d11 -{ - -void MakeValidSize(bool isImage, DXGI_FORMAT format, GLsizei *requestWidth, GLsizei *requestHeight, int *levelOffset) -{ - const DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(format); - - int upsampleCount = 0; - // Don't expand the size of full textures that are at least (blockWidth x blockHeight) already. - if (isImage || *requestWidth < static_cast(dxgiFormatInfo.blockWidth) || - *requestHeight < static_cast(dxgiFormatInfo.blockHeight)) - { - while (*requestWidth % dxgiFormatInfo.blockWidth != 0 || *requestHeight % dxgiFormatInfo.blockHeight != 0) - { - *requestWidth <<= 1; - *requestHeight <<= 1; - upsampleCount++; - } - } - *levelOffset = upsampleCount; -} - -void GenerateInitialTextureData(GLint internalFormat, GLuint width, GLuint height, GLuint depth, - GLuint mipLevels, std::vector *outSubresourceData, - std::vector< std::vector > *outData) -{ - const d3d11::TextureFormat &d3dFormatInfo = d3d11::GetTextureFormatInfo(internalFormat); - ASSERT(d3dFormatInfo.dataInitializerFunction != NULL); - - const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(d3dFormatInfo.texFormat); - - outSubresourceData->resize(mipLevels); - outData->resize(mipLevels); - - for (unsigned int i = 0; i < mipLevels; i++) - { - unsigned int mipWidth = std::max(width >> i, 1U); - unsigned int mipHeight = std::max(height >> i, 1U); - unsigned int mipDepth = std::max(depth >> i, 1U); - - unsigned int rowWidth = dxgiFormatInfo.pixelBytes * mipWidth; - unsigned int imageSize = rowWidth * height; - - outData->at(i).resize(rowWidth * mipHeight * mipDepth); - d3dFormatInfo.dataInitializerFunction(mipWidth, mipHeight, mipDepth, outData->at(i).data(), rowWidth, imageSize); - - outSubresourceData->at(i).pSysMem = outData->at(i).data(); - outSubresourceData->at(i).SysMemPitch = rowWidth; - outSubresourceData->at(i).SysMemSlicePitch = imageSize; - } -} - -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 SetPositionLayerTexCoord3DVertex(PositionLayerTexCoord3DVertex* vertex, float x, float y, - unsigned int layer, float u, float v, float s) -{ - vertex->x = x; - vertex->y = y; - vertex->l = layer; - vertex->u = u; - vertex->v = v; - vertex->s = s; -} - -HRESULT SetDebugName(ID3D11DeviceChild *resource, const char *name) -{ -#if defined(_DEBUG) && !defined(__MINGW32__) - return resource->SetPrivateData(WKPDID_D3DDebugObjectName, strlen(name), name); -#else - return S_OK; -#endif -} - -gl::Error GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment, RenderTarget11 **outRT) -{ - RenderTarget *renderTarget = NULL; - gl::Error error = rx::GetAttachmentRenderTarget(attachment, &renderTarget); - if (error.isError()) - { - return error; - } - *outRT = RenderTarget11::makeRenderTarget11(renderTarget); - return gl::Error(GL_NO_ERROR); -} - -Workarounds GenerateWorkarounds() -{ - Workarounds workarounds; - workarounds.mrtPerfWorkaround = true; - workarounds.setDataFasterThanImageUpload = true; - return workarounds; -} - -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.h deleted file mode 100644 index 9df9c95763..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.h +++ /dev/null @@ -1,189 +0,0 @@ -// -// Copyright (c) 2012-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// 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" -#include "libGLESv2/Caps.h" -#include "libGLESv2/Error.h" - -#include - -namespace gl -{ -class FramebufferAttachment; -} - -namespace rx -{ -class RenderTarget11; -struct Workarounds; - -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, GLenum comparisonMode); -D3D11_TEXTURE_ADDRESS_MODE ConvertTextureWrap(GLenum wrap); - -D3D11_QUERY ConvertQueryType(GLenum queryType); - -} - -namespace d3d11_gl -{ - -void GenerateCaps(ID3D11Device *device, gl::Caps *caps, gl::TextureCapsMap *textureCapsMap, gl::Extensions *extensions); - -} - -namespace d3d11 -{ - -void MakeValidSize(bool isImage, DXGI_FORMAT format, GLsizei *requestWidth, GLsizei *requestHeight, int *levelOffset); - -void GenerateInitialTextureData(GLint internalFormat, GLuint width, GLuint height, GLuint depth, - GLuint mipLevels, std::vector *outSubresourceData, - std::vector< std::vector > *outData); - -struct PositionTexCoordVertex -{ - float x, y; - float u, v; -}; -void SetPositionTexCoordVertex(PositionTexCoordVertex* vertex, float x, float y, float u, float v); - -struct PositionLayerTexCoord3DVertex -{ - float x, y; - unsigned int l; - float u, v, s; -}; -void SetPositionLayerTexCoord3DVertex(PositionLayerTexCoord3DVertex* vertex, float x, float y, - unsigned int layer, float u, float v, float s); - -template -struct PositionDepthColorVertex -{ - float x, y, z; - T r, g, b, a; -}; - -template -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; -} - -HRESULT SetDebugName(ID3D11DeviceChild *resource, const char *name); - -template -outType* DynamicCastComObject(IUnknown* object) -{ - outType *outObject = NULL; - HRESULT result = object->QueryInterface(__uuidof(outType), reinterpret_cast(&outObject)); - if (SUCCEEDED(result)) - { - return outObject; - } - else - { - SafeRelease(outObject); - return NULL; - } -} - -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; - } -} - -template -inline ID3D11VertexShader *CompileVS(ID3D11Device *device, const BYTE (&byteCode)[N], const char *name) -{ - ID3D11VertexShader *vs = NULL; - HRESULT result = device->CreateVertexShader(byteCode, N, NULL, &vs); - UNUSED_ASSERTION_VARIABLE(result); - ASSERT(SUCCEEDED(result)); - SetDebugName(vs, name); - return vs; -} - -template -inline ID3D11GeometryShader *CompileGS(ID3D11Device *device, const BYTE (&byteCode)[N], const char *name) -{ - ID3D11GeometryShader *gs = NULL; - HRESULT result = device->CreateGeometryShader(byteCode, N, NULL, &gs); - UNUSED_ASSERTION_VARIABLE(result); - ASSERT(SUCCEEDED(result)); - SetDebugName(gs, name); - return gs; -} - -template -inline ID3D11PixelShader *CompilePS(ID3D11Device *device, const BYTE (&byteCode)[N], const char *name) -{ - ID3D11PixelShader *ps = NULL; - HRESULT result = device->CreatePixelShader(byteCode, N, NULL, &ps); - UNUSED_ASSERTION_VARIABLE(result); - ASSERT(SUCCEEDED(result)); - SetDebugName(ps, name); - return ps; -} - -// Copy data to small D3D11 buffers, such as for small constant buffers, which use one struct to -// represent an entire buffer. -template -inline void SetBufferData(ID3D11DeviceContext *context, ID3D11Buffer *constantBuffer, const T &value) -{ - D3D11_MAPPED_SUBRESOURCE mappedResource; - context->Map(constantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); - - memcpy(mappedResource.pData, &value, sizeof(T)); - - context->Unmap(constantBuffer, 0); -} - -gl::Error GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment, RenderTarget11 **outRT); - -Workarounds GenerateWorkarounds(); - -} - -} - -#endif // LIBGLESV2_RENDERER_RENDERER11_UTILS_H diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/BufferToTexture11.hlsl b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/BufferToTexture11.hlsl deleted file mode 100644 index 20e6623a30..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/BufferToTexture11.hlsl +++ /dev/null @@ -1,76 +0,0 @@ -Buffer Buffer4F : register(t0); -Buffer Buffer4I : register(t0); -Buffer Buffer4UI : register(t0); - -struct VS_OUTPUT -{ - float4 position : SV_Position; - uint index : TEXCOORD0; - uint slice : LAYER; -}; - -struct GS_OUTPUT -{ - float4 position : SV_Position; - uint index : TEXCOORD0; - uint slice : SV_RenderTargetArrayIndex; -}; - -cbuffer BufferCopyParams : register(b0) -{ - uint FirstPixelOffset; - uint PixelsPerRow; - uint RowStride; - uint RowsPerSlice; - float2 PositionOffset; - float2 PositionScale; - int2 TexLocationOffset; - int2 TexLocationScale; -} - -void ComputePositionAndIndex(uint vertexID, out VS_OUTPUT outVertex) -{ - uint PixelsPerSlice = PixelsPerRow * RowsPerSlice; - uint SliceStride = RowStride * RowsPerSlice; - - uint slice = vertexID / PixelsPerSlice; - uint sliceOffset = slice * PixelsPerSlice; - uint row = (vertexID - sliceOffset) / PixelsPerRow; - uint col = vertexID - sliceOffset - (row * PixelsPerRow); - - float2 coords = float2(float(col), float(row)); - - outVertex.position = float4(PositionOffset + PositionScale * coords, 0.0f, 1.0f); - outVertex.index = FirstPixelOffset + slice * SliceStride + row * RowStride + col; - outVertex.slice = slice; -} - -void VS_BufferToTexture(in uint vertexID : SV_VertexID, out VS_OUTPUT outVertex) -{ - ComputePositionAndIndex(vertexID, outVertex); -} - -[maxvertexcount(1)] -void GS_BufferToTexture(point VS_OUTPUT inVertex[1], inout PointStream outStream) -{ - GS_OUTPUT outVertex; - outVertex.position = inVertex[0].position; - outVertex.index = inVertex[0].index; - outVertex.slice = inVertex[0].slice; - outStream.Append(outVertex); -} - -float4 PS_BufferToTexture_4F(in float4 inPosition : SV_Position, in uint inIndex : TEXCOORD0) : SV_Target -{ - return Buffer4F.Load(inIndex); -} - -int4 PS_BufferToTexture_4I(in float4 inPosition : SV_Position, in uint inIndex : TEXCOORD0) : SV_Target -{ - return Buffer4I.Load(inIndex); -} - -uint4 PS_BufferToTexture_4UI(in float4 inPosition : SV_Position, in uint inIndex : TEXCOORD0) : SV_Target -{ - return Buffer4UI.Load(inIndex); -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Clear11.hlsl b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Clear11.hlsl deleted file mode 100644 index b4cf38076e..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Clear11.hlsl +++ /dev/null @@ -1,106 +0,0 @@ -// Assume we are in SM4+, which has 8 color outputs - -void VS_ClearFloat( in float3 inPosition : POSITION, in float4 inColor : COLOR, - out float4 outPosition : SV_POSITION, out float4 outColor : COLOR) -{ - outPosition = float4(inPosition, 1.0f); - outColor = inColor; -} - -struct PS_OutputFloat -{ - float4 color0 : SV_TARGET0; - float4 color1 : SV_TARGET1; - float4 color2 : SV_TARGET2; - float4 color3 : SV_TARGET3; -#if SM4 - float4 color4 : SV_TARGET4; - float4 color5 : SV_TARGET5; - float4 color6 : SV_TARGET6; - float4 color7 : SV_TARGET7; -#endif -}; - -PS_OutputFloat PS_ClearFloat(in float4 inPosition : SV_POSITION, in float4 inColor : COLOR) -{ - PS_OutputFloat outColor; - outColor.color0 = inColor; - outColor.color1 = inColor; - outColor.color2 = inColor; - outColor.color3 = inColor; -#if SM4 - outColor.color4 = inColor; - outColor.color5 = inColor; - outColor.color6 = inColor; - outColor.color7 = inColor; -#endif - return outColor; -} - - -void VS_ClearUint( in float3 inPosition : POSITION, in uint4 inColor : COLOR, - out float4 outPosition : SV_POSITION, out uint4 outColor : COLOR) -{ - outPosition = float4(inPosition, 1.0f); - outColor = inColor; -} - -struct PS_OutputUint -{ - uint4 color0 : SV_TARGET0; - uint4 color1 : SV_TARGET1; - uint4 color2 : SV_TARGET2; - uint4 color3 : SV_TARGET3; - uint4 color4 : SV_TARGET4; - uint4 color5 : SV_TARGET5; - uint4 color6 : SV_TARGET6; - uint4 color7 : SV_TARGET7; -}; - -PS_OutputUint PS_ClearUint(in float4 inPosition : SV_POSITION, in uint4 inColor : COLOR) -{ - PS_OutputUint 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; -} - - -void VS_ClearSint( in float3 inPosition : POSITION, in int4 inColor : COLOR, - out float4 outPosition : SV_POSITION, out int4 outColor : COLOR) -{ - outPosition = float4(inPosition, 1.0f); - outColor = inColor; -} - -struct PS_OutputSint -{ - int4 color0 : SV_TARGET0; - int4 color1 : SV_TARGET1; - int4 color2 : SV_TARGET2; - int4 color3 : SV_TARGET3; - int4 color4 : SV_TARGET4; - int4 color5 : SV_TARGET5; - int4 color6 : SV_TARGET6; - int4 color7 : SV_TARGET7; -}; - -PS_OutputSint PS_ClearSint(in float4 inPosition : SV_POSITION, in int4 inColor : COLOR) -{ - PS_OutputSint 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/d3d/d3d11/shaders/Passthrough2D11.hlsl b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Passthrough2D11.hlsl deleted file mode 100644 index 8671c39fb7..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Passthrough2D11.hlsl +++ /dev/null @@ -1,111 +0,0 @@ -Texture2D TextureF : register(t0); -Texture2D TextureUI : register(t0); -Texture2D TextureI : register(t0); - -SamplerState Sampler : register(s0); - -void VS_Passthrough2D( 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; -} - -float PS_PassthroughDepth2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_DEPTH -{ - return TextureF.Sample(Sampler, inTexCoord).r; -} - -float4 PS_PassthroughRGBA2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 -{ - return TextureF.Sample(Sampler, inTexCoord).rgba; -} - -uint4 PS_PassthroughRGBA2DUI(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 -{ - uint2 size; - TextureUI.GetDimensions(size.x, size.y); - - return TextureUI.Load(int3(size * inTexCoord, 0)).rgba; -} - -int4 PS_PassthroughRGBA2DI(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 -{ - uint2 size; - TextureI.GetDimensions(size.x, size.y); - - return TextureI.Load(int3(size * inTexCoord, 0)).rgba; -} - -float4 PS_PassthroughRGB2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 -{ - return float4(TextureF.Sample(Sampler, inTexCoord).rgb, 1.0f); -} - -uint4 PS_PassthroughRGB2DUI(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 -{ - uint2 size; - TextureUI.GetDimensions(size.x, size.y); - - return uint4(TextureUI.Load(int3(size * inTexCoord, 0)).rgb, 0); -} - -int4 PS_PassthroughRGB2DI(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 -{ - uint2 size; - TextureI.GetDimensions(size.x, size.y); - - return int4(TextureI.Load(int3(size * inTexCoord, 0)).rgb, 0); -} - -float4 PS_PassthroughRG2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 -{ - return float4(TextureF.Sample(Sampler, inTexCoord).rg, 0.0f, 1.0f); -} - -uint4 PS_PassthroughRG2DUI(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 -{ - uint2 size; - TextureUI.GetDimensions(size.x, size.y); - - return uint4(TextureUI.Load(int3(size * inTexCoord, 0)).rg, 0, 0); -} - -int4 PS_PassthroughRG2DI(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 -{ - uint2 size; - TextureI.GetDimensions(size.x, size.y); - - return int4(TextureI.Load(int3(size * inTexCoord, 0)).rg, 0, 0); -} - -float4 PS_PassthroughR2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 -{ - return float4(TextureF.Sample(Sampler, inTexCoord).r, 0.0f, 0.0f, 1.0f); -} - -uint4 PS_PassthroughR2DUI(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 -{ - uint2 size; - TextureUI.GetDimensions(size.x, size.y); - - return uint4(TextureUI.Load(int3(size * inTexCoord, 0)).r, 0, 0, 0); -} - -int4 PS_PassthroughR2DI(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 -{ - uint2 size; - TextureI.GetDimensions(size.x, size.y); - - return int4(TextureI.Load(int3(size * inTexCoord, 0)).r, 0, 0, 0); -} - -float4 PS_PassthroughLum2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 -{ - return float4(TextureF.Sample(Sampler, inTexCoord).rrr, 1.0f); -} - -float4 PS_PassthroughLumAlpha2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 -{ - return TextureF.Sample(Sampler, inTexCoord).rrra; -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Passthrough3D11.hlsl b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Passthrough3D11.hlsl deleted file mode 100644 index c23c9032ec..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Passthrough3D11.hlsl +++ /dev/null @@ -1,146 +0,0 @@ -Texture3D TextureF : register(t0); -Texture3D TextureUI : register(t0); -Texture3D TextureI : register(t0); - -SamplerState Sampler : register(s0); - -struct VS_INPUT -{ - float2 Position : POSITION; - uint Layer : LAYER; - float3 TexCoord : TEXCOORD; -}; - -struct VS_OUTPUT -{ - float4 Position : SV_POSITION; - uint Layer : LAYER; - float3 TexCoord : TEXCOORD; -}; - -struct GS_OUTPUT -{ - float4 Position : SV_POSITION; - uint Layer : SV_RENDERTARGETARRAYINDEX; - float3 TexCoord : TEXCOORD; -}; - -VS_OUTPUT VS_Passthrough3D(VS_INPUT input) -{ - VS_OUTPUT output; - - output.Position = float4(input.Position, 0.0f, 1.0f); - output.Layer = input.Layer; - output.TexCoord = input.TexCoord; - - return output; -} - -[maxvertexcount(3)] -void GS_Passthrough3D(triangle VS_OUTPUT input[3], inout TriangleStream outputStream) -{ - GS_OUTPUT output; - - for (int i = 0; i < 3; i++) - { - output.Position = input[i].Position; - output.Layer = input[i].Layer; - output.TexCoord = input[i].TexCoord; - - outputStream.Append(output); - } -} - -float4 PS_PassthroughRGBA3D(GS_OUTPUT input) : SV_TARGET0 -{ - return TextureF.Sample(Sampler, input.TexCoord).rgba; -} - -uint4 PS_PassthroughRGBA3DUI(GS_OUTPUT input) : SV_TARGET0 -{ - uint3 size; - TextureUI.GetDimensions(size.x, size.y, size.z); - - return TextureUI.Load(int4(size * input.TexCoord, 0)).rgba; -} - -int4 PS_PassthroughRGBA3DI(GS_OUTPUT input) : SV_TARGET0 -{ - uint3 size; - TextureI.GetDimensions(size.x, size.y, size.z); - - return TextureI.Load(int4(size * input.TexCoord, 0)).rgba; -} - -float4 PS_PassthroughRGB3D(GS_OUTPUT input) : SV_TARGET0 -{ - return float4(TextureF.Sample(Sampler, input.TexCoord).rgb, 1.0f); -} - -uint4 PS_PassthroughRGB3DUI(GS_OUTPUT input) : SV_TARGET0 -{ - uint3 size; - TextureUI.GetDimensions(size.x, size.y, size.z); - - return uint4(TextureUI.Load(int4(size * input.TexCoord, 0)).rgb, 0); -} - -int4 PS_PassthroughRGB3DI(GS_OUTPUT input) : SV_TARGET0 -{ - uint3 size; - TextureI.GetDimensions(size.x, size.y, size.z); - - return int4(TextureI.Load(int4(size * input.TexCoord, 0)).rgb, 0); -} - -float4 PS_PassthroughRG3D(GS_OUTPUT input) : SV_TARGET0 -{ - return float4(TextureF.Sample(Sampler, input.TexCoord).rg, 0.0f, 1.0f); -} - -uint4 PS_PassthroughRG3DUI(GS_OUTPUT input) : SV_TARGET0 -{ - uint3 size; - TextureUI.GetDimensions(size.x, size.y, size.z); - - return uint4(TextureUI.Load(int4(size * input.TexCoord, 0)).rg, 0, 0); -} - -int4 PS_PassthroughRG3DI(GS_OUTPUT input) : SV_TARGET0 -{ - uint3 size; - TextureI.GetDimensions(size.x, size.y, size.z); - - return int4(TextureI.Load(int4(size * input.TexCoord, 0)).rg, 0, 0); -} - -float4 PS_PassthroughR3D(GS_OUTPUT input) : SV_TARGET0 -{ - return float4(TextureF.Sample(Sampler, input.TexCoord).r, 0.0f, 0.0f, 1.0f); -} - -uint4 PS_PassthroughR3DUI(GS_OUTPUT input) : SV_TARGET0 -{ - uint3 size; - TextureUI.GetDimensions(size.x, size.y, size.z); - - return uint4(TextureUI.Load(int4(size * input.TexCoord, 0)).r, 0, 0, 0); -} - -int4 PS_PassthroughR3DI(GS_OUTPUT input) : SV_TARGET0 -{ - uint3 size; - TextureI.GetDimensions(size.x, size.y, size.z); - - return int4(TextureI.Load(int4(size * input.TexCoord, 0)).r, 0, 0, 0); -} - -float4 PS_PassthroughLum3D(GS_OUTPUT input) : SV_TARGET0 -{ - return float4(TextureF.Sample(Sampler, input.TexCoord).rrr, 1.0f); -} - -float4 PS_PassthroughLumAlpha3D(GS_OUTPUT input) : SV_TARGET0 -{ - return TextureF.Sample(Sampler, input.TexCoord).rrra; -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Swizzle11.hlsl b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Swizzle11.hlsl deleted file mode 100644 index 505e222137..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Swizzle11.hlsl +++ /dev/null @@ -1,99 +0,0 @@ -Texture2D TextureF2D : register(t0); -Texture2D TextureUI2D : register(t0); -Texture2D TextureI2D : register(t0); - -Texture3D TextureF3D : register(t0); -Texture3D TextureUI3D : register(t0); -Texture3D TextureI3D : register(t0); - -Texture2DArray TextureF2DArray : register(t0); -Texture2DArray TextureUI2DArray : register(t0); -Texture2DArray TextureI2DArray : register(t0); - -SamplerState Sampler : register(s0); - -cbuffer SwizzleProperties : register(b0) -{ - uint4 SwizzleIndices : packoffset(c0); -} - -float4 SwizzleLookup(in float4 sample) -{ - float lookup[6] = { sample[0], sample[1], sample[2], sample[3], 0.0f, 1.0f }; - return float4(lookup[SwizzleIndices[0]], lookup[SwizzleIndices[1]], lookup[SwizzleIndices[2]], lookup[SwizzleIndices[3]]); -} - -int4 SwizzleLookup(in int4 sample) -{ - int lookup[6] = { sample[0], sample[1], sample[2], sample[3], 0.0f, 1.0f }; - return int4(lookup[SwizzleIndices[0]], lookup[SwizzleIndices[1]], lookup[SwizzleIndices[2]], lookup[SwizzleIndices[3]]); -} - -uint4 SwizzleLookup(in uint4 sample) -{ - uint lookup[6] = { sample[0], sample[1], sample[2], sample[3], 0.0f, 1.0f }; - return uint4(lookup[SwizzleIndices[0]], lookup[SwizzleIndices[1]], lookup[SwizzleIndices[2]], lookup[SwizzleIndices[3]]); -} - -float4 PS_SwizzleF2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 -{ - return SwizzleLookup(TextureF2D.Sample(Sampler, inTexCoord)); -} - -int4 PS_SwizzleI2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 -{ - uint2 size; - TextureI2D.GetDimensions(size.x, size.y); - - return SwizzleLookup(TextureI2D.Load(int3(size * inTexCoord, 0))); -} - -uint4 PS_SwizzleUI2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 -{ - uint2 size; - TextureUI2D.GetDimensions(size.x, size.y); - - return SwizzleLookup(TextureUI2D.Load(int3(size * inTexCoord, 0))); -} - -float4 PS_SwizzleF3D(in float4 inPosition : SV_POSITION, in uint inLayer : SV_RENDERTARGETARRAYINDEX, in float3 inTexCoord : TEXCOORD0) : SV_TARGET0 -{ - return SwizzleLookup(TextureF3D.Sample(Sampler, inTexCoord)); -} - -int4 PS_SwizzleI3D(in float4 inPosition : SV_POSITION, in uint inLayer : SV_RENDERTARGETARRAYINDEX, in float3 inTexCoord : TEXCOORD0) : SV_TARGET0 -{ - uint3 size; - TextureI3D.GetDimensions(size.x, size.y, size.z); - - return SwizzleLookup(TextureI3D.Load(int4(size * inTexCoord, 0))); -} - -uint4 PS_SwizzleUI3D(in float4 inPosition : SV_POSITION, in uint inLayer : SV_RENDERTARGETARRAYINDEX, in float3 inTexCoord : TEXCOORD0) : SV_TARGET0 -{ - uint3 size; - TextureUI3D.GetDimensions(size.x, size.y, size.z); - - return SwizzleLookup(TextureUI3D.Load(int4(size * inTexCoord, 0))); -} - -float4 PS_SwizzleF2DArray(in float4 inPosition : SV_POSITION, in uint inLayer : SV_RENDERTARGETARRAYINDEX, in float3 inTexCoord : TEXCOORD0) : SV_TARGET0 -{ - return SwizzleLookup(TextureF2DArray.Sample(Sampler, float3(inTexCoord.xy, inLayer))); -} - -int4 PS_SwizzleI2DArray(in float4 inPosition : SV_POSITION, in uint inLayer : SV_RENDERTARGETARRAYINDEX, in float3 inTexCoord : TEXCOORD0) : SV_TARGET0 -{ - uint3 size; - TextureI2DArray.GetDimensions(size.x, size.y, size.z); - - return SwizzleLookup(TextureI2DArray.Load(int4(size.xy * inTexCoord.xy, inLayer, 0))); -} - -uint4 PS_SwizzleUI2DArray(in float4 inPosition : SV_POSITION, in uint inLayer : SV_RENDERTARGETARRAYINDEX, in float3 inTexCoord : TEXCOORD0) : SV_TARGET0 -{ - uint3 size; - TextureUI2DArray.GetDimensions(size.x, size.y, size.z); - - return SwizzleLookup(TextureUI2DArray.Load(int4(size.xy * inTexCoord.xy, inLayer, 0))); -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.cpp deleted file mode 100644 index 2ca7a9cf8a..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.cpp +++ /dev/null @@ -1,679 +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. -// - -// Blit9.cpp: Surface copy utility class. - -#include "libGLESv2/renderer/d3d/d3d9/Blit9.h" -#include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h" -#include "libGLESv2/renderer/d3d/d3d9/formatutils9.h" -#include "libGLESv2/renderer/d3d/d3d9/TextureStorage9.h" -#include "libGLESv2/renderer/d3d/d3d9/RenderTarget9.h" -#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" -#include "libGLESv2/Framebuffer.h" -#include "libGLESv2/FramebufferAttachment.h" -#include "libGLESv2/main.h" - -namespace -{ -// Precompiled shaders -#include "libGLESv2/renderer/d3d/d3d9/shaders/compiled/standardvs.h" -#include "libGLESv2/renderer/d3d/d3d9/shaders/compiled/flipyvs.h" -#include "libGLESv2/renderer/d3d/d3d9/shaders/compiled/passthroughps.h" -#include "libGLESv2/renderer/d3d/d3d9/shaders/compiled/luminanceps.h" -#include "libGLESv2/renderer/d3d/d3d9/shaders/compiled/componentmaskps.h" - -const BYTE* const g_shaderCode[] = -{ - g_vs20_VS_standard, - g_vs20_VS_flipy, - g_ps20_PS_passthrough, - g_ps20_PS_luminance, - g_ps20_PS_componentmask -}; - -const size_t g_shaderSize[] = -{ - sizeof(g_vs20_VS_standard), - sizeof(g_vs20_VS_flipy), - sizeof(g_ps20_PS_passthrough), - sizeof(g_ps20_PS_luminance), - sizeof(g_ps20_PS_componentmask) -}; -} - -namespace rx -{ - -Blit9::Blit9(Renderer9 *renderer) - : mRenderer(renderer), - mGeometryLoaded(false), - mQuadVertexBuffer(NULL), - mQuadVertexDeclaration(NULL), - mSavedStateBlock(NULL), - mSavedRenderTarget(NULL), - mSavedDepthStencil(NULL) -{ - memset(mCompiledShaders, 0, sizeof(mCompiledShaders)); -} - -Blit9::~Blit9() -{ - SafeRelease(mSavedStateBlock); - SafeRelease(mQuadVertexBuffer); - SafeRelease(mQuadVertexDeclaration); - - for (int i = 0; i < SHADER_COUNT; i++) - { - SafeRelease(mCompiledShaders[i]); - } -} - -gl::Error Blit9::initialize() -{ - if (mGeometryLoaded) - { - return gl::Error(GL_NO_ERROR); - } - - 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, "Failed to create internal blit vertex shader, result: 0x%X.", result); - } - - void *lockPtr = NULL; - result = mQuadVertexBuffer->Lock(0, 0, &lockPtr, 0); - - if (FAILED(result) || lockPtr == NULL) - { - ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - SafeRelease(mQuadVertexBuffer); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock internal blit vertex shader, result: 0x%X.", result); - } - - 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); - SafeRelease(mQuadVertexBuffer); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock internal blit vertex declaration, result: 0x%X.", result); - } - - mGeometryLoaded = true; - return gl::Error(GL_NO_ERROR); -} - -template -gl::Error Blit9::setShader(ShaderId source, const char *profile, - gl::Error (Renderer9::*createShader)(const DWORD *, size_t length, D3DShaderType **outShader), - 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]; - - gl::Error error = (mRenderer->*createShader)(reinterpret_cast(shaderCode), shaderSize, &shader); - if (error.isError()) - { - return error; - } - - mCompiledShaders[source] = shader; - } - - HRESULT hr = (device->*setShader)(shader); - if (FAILED(hr)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to set shader for blit operation, result: 0x%X.", hr); - } - - return gl::Error(GL_NO_ERROR); -} - -gl::Error Blit9::setVertexShader(ShaderId shader) -{ - return setShader(shader, "vs_2_0", &Renderer9::createVertexShader, &IDirect3DDevice9::SetVertexShader); -} - -gl::Error Blit9::setPixelShader(ShaderId shader) -{ - return setShader(shader, "ps_2_0", &Renderer9::createPixelShader, &IDirect3DDevice9::SetPixelShader); -} - -RECT Blit9::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; -} - -gl::Error Blit9::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest) -{ - gl::Error error = initialize(); - if (error.isError()) - { - return error; - } - - IDirect3DTexture9 *texture = NULL; - error = copySurfaceToTexture(source, getSurfaceRect(source), &texture); - if (error.isError()) - { - return error; - } - - 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(); - - SafeRelease(texture); - - restoreState(); - - return gl::Error(GL_NO_ERROR); -} - -gl::Error Blit9::copy2D(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorage *storage, GLint level) -{ - gl::Error error = initialize(); - if (error.isError()) - { - return error; - } - - gl::FramebufferAttachment *colorbuffer = framebuffer->getColorbuffer(0); - ASSERT(colorbuffer); - - RenderTarget9 *renderTarget9 = NULL; - error = d3d9::GetAttachmentRenderTarget(colorbuffer, &renderTarget9); - if (error.isError()) - { - return error; - } - ASSERT(renderTarget9); - - IDirect3DSurface9 *source = renderTarget9->getSurface(); - ASSERT(source); - - IDirect3DSurface9 *destSurface = NULL; - TextureStorage9_2D *storage9 = TextureStorage9_2D::makeTextureStorage9_2D(storage); - error = storage9->getSurfaceLevel(level, true, &destSurface); - if (error.isError()) - { - return error; - } - ASSERT(destSurface); - - gl::Error result = copy(source, sourceRect, destFormat, xoffset, yoffset, destSurface); - - SafeRelease(destSurface); - SafeRelease(source); - - return result; -} - -gl::Error Blit9::copyCube(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorage *storage, GLenum target, GLint level) -{ - gl::Error error = initialize(); - if (error.isError()) - { - return error; - } - - gl::FramebufferAttachment *colorbuffer = framebuffer->getColorbuffer(0); - ASSERT(colorbuffer); - - RenderTarget9 *renderTarget9 = NULL; - error = d3d9::GetAttachmentRenderTarget(colorbuffer, &renderTarget9); - if (error.isError()) - { - return error; - } - ASSERT(renderTarget9); - - IDirect3DSurface9 *source = renderTarget9->getSurface(); - ASSERT(source); - - IDirect3DSurface9 *destSurface = NULL; - TextureStorage9_Cube *storage9 = TextureStorage9_Cube::makeTextureStorage9_Cube(storage); - error = storage9->getCubeMapSurface(target, level, true, &destSurface); - if (error.isError()) - { - return error; - } - ASSERT(destSurface); - - gl::Error result = copy(source, sourceRect, destFormat, xoffset, yoffset, destSurface); - - SafeRelease(destSurface); - SafeRelease(source); - - return result; -} - -gl::Error Blit9::copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest) -{ - ASSERT(source != NULL && dest != NULL); - - 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, "Failed to blit between textures, StretchRect result: 0x%X.", result); - } - - return gl::Error(GL_NO_ERROR); - } - else - { - return formatConvert(source, sourceRect, destFormat, xoffset, yoffset, dest); - } -} - -gl::Error Blit9::formatConvert(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest) -{ - gl::Error error = initialize(); - if (error.isError()) - { - return error; - } - - IDirect3DTexture9 *texture = NULL; - error = copySurfaceToTexture(source, sourceRect, &texture); - if (error.isError()) - { - return error; - } - - IDirect3DDevice9 *device = mRenderer->getDevice(); - - saveState(); - - device->SetTexture(0, texture); - device->SetRenderTarget(0, dest); - - setViewport(sourceRect, xoffset, yoffset); - - setCommonBlitState(); - - error = setFormatConvertShaders(destFormat); - if (!error.isError()) - { - render(); - } - - SafeRelease(texture); - - restoreState(); - - return error; -} - -gl::Error Blit9::setFormatConvertShaders(GLenum destFormat) -{ - gl::Error error = setVertexShader(SHADER_VS_STANDARD); - if (error.isError()) - { - return error; - } - - switch (destFormat) - { - default: UNREACHABLE(); - case GL_RGBA: - case GL_BGRA_EXT: - case GL_RGB: - case GL_RG_EXT: - case GL_RED_EXT: - case GL_ALPHA: - error = setPixelShader(SHADER_PS_COMPONENTMASK); - break; - - case GL_LUMINANCE: - case GL_LUMINANCE_ALPHA: - error = setPixelShader(SHADER_PS_LUMINANCE); - break; - } - - if (error.isError()) - { - return error; - } - - 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. - // Allocate one array for both registers and split it into two float4's. - float psConst[8] = { 0 }; - float *multConst = &psConst[0]; - float *addConst = &psConst[4]; - - switch (destFormat) - { - default: UNREACHABLE(); - case GL_RGBA: - case GL_BGRA_EXT: - multConst[X] = 1; - multConst[Y] = 1; - multConst[Z] = 1; - multConst[W] = 1; - addConst[X] = 0; - addConst[Y] = 0; - addConst[Z] = 0; - addConst[W] = 0; - break; - - case GL_RGB: - multConst[X] = 1; - multConst[Y] = 1; - multConst[Z] = 1; - multConst[W] = 0; - addConst[X] = 0; - addConst[Y] = 0; - addConst[Z] = 0; - addConst[W] = 1; - break; - - case GL_RG_EXT: - multConst[X] = 1; - multConst[Y] = 1; - multConst[Z] = 0; - multConst[W] = 0; - addConst[X] = 0; - addConst[Y] = 0; - addConst[Z] = 0; - addConst[W] = 1; - break; - - case GL_RED_EXT: - multConst[X] = 1; - multConst[Y] = 0; - multConst[Z] = 0; - multConst[W] = 0; - addConst[X] = 0; - addConst[Y] = 0; - addConst[Z] = 0; - addConst[W] = 1; - break; - - case GL_ALPHA: - multConst[X] = 0; - multConst[Y] = 0; - multConst[Z] = 0; - multConst[W] = 1; - addConst[X] = 0; - addConst[Y] = 0; - addConst[Z] = 0; - addConst[W] = 0; - break; - - case GL_LUMINANCE: - multConst[X] = 1; - multConst[Y] = 0; - multConst[Z] = 0; - multConst[W] = 0; - addConst[X] = 0; - addConst[Y] = 0; - addConst[Z] = 0; - addConst[W] = 1; - break; - - case GL_LUMINANCE_ALPHA: - multConst[X] = 1; - multConst[Y] = 0; - multConst[Z] = 0; - multConst[W] = 1; - addConst[X] = 0; - addConst[Y] = 0; - addConst[Z] = 0; - addConst[W] = 0; - break; - } - - mRenderer->getDevice()->SetPixelShaderConstantF(0, psConst, 2); - - return gl::Error(GL_NO_ERROR); -} - -gl::Error Blit9::copySurfaceToTexture(IDirect3DSurface9 *surface, const RECT &sourceRect, IDirect3DTexture9 **outTexture) -{ - ASSERT(surface); - - 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, "Failed to allocate internal texture for blit, result: 0x%X.", result); - } - - IDirect3DSurface9 *textureSurface; - result = texture->GetSurfaceLevel(0, &textureSurface); - - if (FAILED(result)) - { - ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - SafeRelease(texture); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to query surface of internal blit texture, result: 0x%X.", result); - } - - mRenderer->endScene(); - result = device->StretchRect(surface, &sourceRect, textureSurface, NULL, D3DTEXF_NONE); - - SafeRelease(textureSurface); - - if (FAILED(result)) - { - ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - SafeRelease(texture); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to copy between internal blit textures, result: 0x%X.", result); - } - - *outTexture = texture; - return gl::Error(GL_NO_ERROR); -} - -void Blit9::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 Blit9::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 Blit9::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 Blit9::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[8] = { 0 }; - - device->SetVertexShader(NULL); - device->SetVertexShaderConstantF(0, dummyConst, 2); - device->SetPixelShader(NULL); - device->SetPixelShaderConstantF(0, dummyConst, 2); - - 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 Blit9::restoreState() -{ - IDirect3DDevice9 *device = mRenderer->getDevice(); - - device->SetDepthStencilSurface(mSavedDepthStencil); - SafeRelease(mSavedDepthStencil); - - device->SetRenderTarget(0, mSavedRenderTarget); - SafeRelease(mSavedRenderTarget); - - ASSERT(mSavedStateBlock != NULL); - - if (mSavedStateBlock != NULL) - { - mSavedStateBlock->Apply(); - } -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.h deleted file mode 100644 index 5c7a76ce05..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.h +++ /dev/null @@ -1,97 +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. -// - -// Blit9.cpp: Surface copy utility class. - -#ifndef LIBGLESV2_BLIT9_H_ -#define LIBGLESV2_BLIT9_H_ - -#include "common/angleutils.h" -#include "libGLESv2/Error.h" - -#include - -namespace gl -{ -class Framebuffer; -} - -namespace rx -{ -class Renderer9; -class TextureStorage; - -class Blit9 -{ - public: - explicit Blit9(Renderer9 *renderer); - ~Blit9(); - - gl::Error initialize(); - - // Copy from source surface to dest surface. - // sourceRect, xoffset, yoffset are in D3D coordinates (0,0 in upper-left) - gl::Error copy2D(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorage *storage, GLint level); - gl::Error copyCube(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorage *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. - gl::Error 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. - gl::Error boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest); - - private: - Renderer9 *mRenderer; - - bool mGeometryLoaded; - IDirect3DVertexBuffer9 *mQuadVertexBuffer; - IDirect3DVertexDeclaration9 *mQuadVertexDeclaration; - - gl::Error setFormatConvertShaders(GLenum destFormat); - - gl::Error copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest); - gl::Error copySurfaceToTexture(IDirect3DSurface9 *surface, const RECT &sourceRect, IDirect3DTexture9 **outTexture); - 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 - gl::Error setShader(ShaderId source, const char *profile, - gl::Error (Renderer9::*createShader)(const DWORD *, size_t length, D3DShaderType **outShader), - HRESULT (WINAPI IDirect3DDevice9::*setShader)(D3DShaderType*)); - - gl::Error setVertexShader(ShaderId shader); - gl::Error setPixelShader(ShaderId shader); - void render(); - - void saveState(); - void restoreState(); - IDirect3DStateBlock9 *mSavedStateBlock; - IDirect3DSurface9 *mSavedRenderTarget; - IDirect3DSurface9 *mSavedDepthStencil; - - DISALLOW_COPY_AND_ASSIGN(Blit9); -}; -} - -#endif // LIBGLESV2_BLIT9_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Buffer9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Buffer9.cpp deleted file mode 100644 index 430fe81e50..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Buffer9.cpp +++ /dev/null @@ -1,122 +0,0 @@ -// -// Copyright 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Buffer9.cpp Defines the Buffer9 class. - -#include "libGLESv2/renderer/d3d/d3d9/Buffer9.h" -#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" -#include "libGLESv2/main.h" - -namespace rx -{ - -Buffer9::Buffer9(Renderer9 *renderer) - : BufferD3D(), - mRenderer(renderer), - mSize(0) -{} - -Buffer9::~Buffer9() -{ - mSize = 0; -} - -Buffer9 *Buffer9::makeBuffer9(BufferImpl *buffer) -{ - ASSERT(HAS_DYNAMIC_TYPE(Buffer9*, buffer)); - return static_cast(buffer); -} - -gl::Error Buffer9::setData(const void* data, size_t size, GLenum usage) -{ - if (size > mMemory.size()) - { - if (!mMemory.resize(size)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to resize internal buffer."); - } - } - - mSize = size; - if (data && size > 0) - { - memcpy(mMemory.data(), data, size); - } - - invalidateStaticData(); - - if (usage == GL_STATIC_DRAW) - { - initializeStaticData(); - } - - return gl::Error(GL_NO_ERROR); -} - -gl::Error Buffer9::getData(const uint8_t **outData) -{ - *outData = mMemory.data(); - return gl::Error(GL_NO_ERROR); -} - -gl::Error Buffer9::setSubData(const void* data, size_t size, size_t offset) -{ - if (offset + size > mMemory.size()) - { - if (!mMemory.resize(offset + size)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to resize internal buffer."); - } - } - - mSize = std::max(mSize, offset + size); - if (data && size > 0) - { - memcpy(mMemory.data() + offset, data, size); - } - - invalidateStaticData(); - - return gl::Error(GL_NO_ERROR); -} - -gl::Error Buffer9::copySubData(BufferImpl* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size) -{ - // Note: this method is currently unreachable - Buffer9* sourceBuffer = makeBuffer9(source); - ASSERT(sourceBuffer); - - memcpy(mMemory.data() + destOffset, sourceBuffer->mMemory.data() + sourceOffset, size); - - invalidateStaticData(); - - return gl::Error(GL_NO_ERROR); -} - -// We do not support buffer mapping in D3D9 -gl::Error Buffer9::map(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr) -{ - UNREACHABLE(); - return gl::Error(GL_INVALID_OPERATION); -} - -gl::Error Buffer9::unmap() -{ - UNREACHABLE(); - return gl::Error(GL_INVALID_OPERATION); -} - -void Buffer9::markTransformFeedbackUsage() -{ - UNREACHABLE(); -} - -RendererD3D *Buffer9::getRenderer() -{ - return mRenderer; -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Buffer9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Buffer9.h deleted file mode 100644 index c80b009738..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Buffer9.h +++ /dev/null @@ -1,52 +0,0 @@ -// -// Copyright 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Buffer9.h: Defines the rx::Buffer9 class which implements rx::BufferImpl via rx::BufferD3D. - -#ifndef LIBGLESV2_RENDERER_BUFFER9_H_ -#define LIBGLESV2_RENDERER_BUFFER9_H_ - -#include "libGLESv2/renderer/d3d/BufferD3D.h" -#include "libGLESv2/renderer/d3d/MemoryBuffer.h" -#include "libGLESv2/angletypes.h" - -namespace rx -{ -class Renderer9; - -class Buffer9 : public BufferD3D -{ - public: - Buffer9(Renderer9 *renderer); - virtual ~Buffer9(); - - static Buffer9 *makeBuffer9(BufferImpl *buffer); - - // BufferD3D implementation - virtual size_t getSize() const { return mSize; } - virtual bool supportsDirectBinding() const { return false; } - RendererD3D *getRenderer() override; - - // BufferImpl implementation - virtual gl::Error setData(const void* data, size_t size, GLenum usage); - gl::Error getData(const uint8_t **outData) override; - virtual gl::Error setSubData(const void* data, size_t size, size_t offset); - virtual gl::Error copySubData(BufferImpl* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size); - virtual gl::Error map(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr); - virtual gl::Error unmap(); - virtual void markTransformFeedbackUsage(); - - private: - DISALLOW_COPY_AND_ASSIGN(Buffer9); - - Renderer9 *mRenderer; - MemoryBuffer mMemory; - size_t mSize; -}; - -} - -#endif // LIBGLESV2_RENDERER_BUFFER9_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Fence9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Fence9.cpp deleted file mode 100644 index 66263fe110..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Fence9.cpp +++ /dev/null @@ -1,91 +0,0 @@ -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Fence9.cpp: Defines the rx::FenceNV9 class. - -#include "libGLESv2/renderer/d3d/d3d9/Fence9.h" -#include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h" -#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" -#include "libGLESv2/main.h" - -namespace rx -{ - -FenceNV9::FenceNV9(Renderer9 *renderer) - : FenceNVImpl(), - mRenderer(renderer), - mQuery(NULL) -{ -} - -FenceNV9::~FenceNV9() -{ - SafeRelease(mQuery); -} - -gl::Error FenceNV9::set() -{ - if (!mQuery) - { - gl::Error error = mRenderer->allocateEventQuery(&mQuery); - if (error.isError()) - { - return error; - } - } - - HRESULT result = mQuery->Issue(D3DISSUE_END); - if (FAILED(result)) - { - ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - SafeRelease(mQuery); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to end event query, result: 0x%X.", result); - } - - return gl::Error(GL_NO_ERROR); -} - -gl::Error FenceNV9::test(bool flushCommandBuffer, GLboolean *outFinished) -{ - ASSERT(mQuery); - - DWORD getDataFlags = (flushCommandBuffer ? D3DGETDATA_FLUSH : 0); - HRESULT result = mQuery->GetData(NULL, 0, getDataFlags); - - if (d3d9::isDeviceLostError(result)) - { - mRenderer->notifyDeviceLost(); - return gl::Error(GL_OUT_OF_MEMORY, "Device was lost while querying result of an event query."); - } - else if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to get query data, result: 0x%X.", result); - } - - ASSERT(result == S_OK || result == S_FALSE); - *outFinished = ((result == S_OK) ? GL_TRUE : GL_FALSE); - return gl::Error(GL_NO_ERROR); -} - -gl::Error FenceNV9::finishFence(GLboolean *outFinished) -{ - ASSERT(outFinished); - - while (*outFinished != GL_TRUE) - { - gl::Error error = test(true, outFinished); - if (error.isError()) - { - return error; - } - - Sleep(0); - } - - return gl::Error(GL_NO_ERROR); -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Fence9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Fence9.h deleted file mode 100644 index d7873d5264..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Fence9.h +++ /dev/null @@ -1,37 +0,0 @@ -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Fence9.h: Defines the rx::FenceNV9 class which implements rx::FenceNVImpl. - -#ifndef LIBGLESV2_RENDERER_FENCE9_H_ -#define LIBGLESV2_RENDERER_FENCE9_H_ - -#include "libGLESv2/renderer/FenceImpl.h" - -namespace rx -{ -class Renderer9; - -class FenceNV9 : public FenceNVImpl -{ - public: - explicit FenceNV9(Renderer9 *renderer); - virtual ~FenceNV9(); - - gl::Error set(); - gl::Error test(bool flushCommandBuffer, GLboolean *outFinished); - gl::Error finishFence(GLboolean *outFinished); - - private: - DISALLOW_COPY_AND_ASSIGN(FenceNV9); - - Renderer9 *mRenderer; - IDirect3DQuery9 *mQuery; -}; - -} - -#endif // LIBGLESV2_RENDERER_FENCE9_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Image9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Image9.cpp deleted file mode 100644 index 2a06d12942..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Image9.cpp +++ /dev/null @@ -1,792 +0,0 @@ -// -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Image9.cpp: Implements the rx::Image9 class, which acts as the interface to -// the actual underlying surfaces of a Texture. - -#include "libGLESv2/renderer/d3d/d3d9/Image9.h" -#include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h" -#include "libGLESv2/renderer/d3d/d3d9/formatutils9.h" -#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" -#include "libGLESv2/renderer/d3d/d3d9/RenderTarget9.h" -#include "libGLESv2/renderer/d3d/d3d9/TextureStorage9.h" -#include "libGLESv2/main.h" -#include "libGLESv2/Framebuffer.h" -#include "libGLESv2/FramebufferAttachment.h" -#include "libGLESv2/Renderbuffer.h" -#include "common/utilities.h" - -namespace rx -{ - -Image9::Image9() -{ - mSurface = NULL; - mRenderer = NULL; - - mD3DPool = D3DPOOL_SYSTEMMEM; - mD3DFormat = D3DFMT_UNKNOWN; -} - -Image9::~Image9() -{ - SafeRelease(mSurface); -} - -gl::Error Image9::generateMip(IDirect3DSurface9 *destSurface, IDirect3DSurface9 *sourceSurface) -{ - D3DSURFACE_DESC destDesc; - HRESULT result = destSurface->GetDesc(&destDesc); - ASSERT(SUCCEEDED(result)); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to query the source surface description for mipmap generation, result: 0x%X.", result); - } - - D3DSURFACE_DESC sourceDesc; - result = sourceSurface->GetDesc(&sourceDesc); - ASSERT(SUCCEEDED(result)); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to query the destination surface description for mipmap generation, result: 0x%X.", result); - } - - ASSERT(sourceDesc.Format == destDesc.Format); - ASSERT(sourceDesc.Width == 1 || sourceDesc.Width / 2 == destDesc.Width); - ASSERT(sourceDesc.Height == 1 || sourceDesc.Height / 2 == destDesc.Height); - - const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(sourceDesc.Format); - ASSERT(d3dFormatInfo.mipGenerationFunction != NULL); - - D3DLOCKED_RECT sourceLocked = {0}; - result = sourceSurface->LockRect(&sourceLocked, NULL, D3DLOCK_READONLY); - ASSERT(SUCCEEDED(result)); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock the source surface for mipmap generation, result: 0x%X.", result); - } - - D3DLOCKED_RECT destLocked = {0}; - result = destSurface->LockRect(&destLocked, NULL, 0); - ASSERT(SUCCEEDED(result)); - if (FAILED(result)) - { - sourceSurface->UnlockRect(); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock the destination surface for mipmap generation, result: 0x%X.", result); - } - - const uint8_t *sourceData = reinterpret_cast(sourceLocked.pBits); - uint8_t *destData = reinterpret_cast(destLocked.pBits); - - ASSERT(sourceData && destData); - - d3dFormatInfo.mipGenerationFunction(sourceDesc.Width, sourceDesc.Height, 1, sourceData, sourceLocked.Pitch, 0, - destData, destLocked.Pitch, 0); - - destSurface->UnlockRect(); - sourceSurface->UnlockRect(); - - return gl::Error(GL_NO_ERROR); -} - -Image9 *Image9::makeImage9(Image *img) -{ - ASSERT(HAS_DYNAMIC_TYPE(Image9*, img)); - return static_cast(img); -} - -gl::Error Image9::generateMipmap(Image9 *dest, Image9 *source) -{ - IDirect3DSurface9 *sourceSurface = NULL; - gl::Error error = source->getSurface(&sourceSurface); - if (error.isError()) - { - return error; - } - - IDirect3DSurface9 *destSurface = NULL; - error = dest->getSurface(&destSurface); - if (error.isError()) - { - return error; - } - - error = generateMip(destSurface, sourceSurface); - if (error.isError()) - { - return error; - } - - dest->markDirty(); - - return gl::Error(GL_NO_ERROR); -} - -gl::Error Image9::copyLockableSurfaces(IDirect3DSurface9 *dest, IDirect3DSurface9 *source) -{ - D3DLOCKED_RECT sourceLock = {0}; - D3DLOCKED_RECT destLock = {0}; - - HRESULT result; - - result = source->LockRect(&sourceLock, NULL, 0); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock source surface for copy, result: 0x%X.", result); - } - - result = dest->LockRect(&destLock, NULL, 0); - if (FAILED(result)) - { - source->UnlockRect(); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock source surface for copy, result: 0x%X.", result); - } - - ASSERT(sourceLock.pBits && destLock.pBits); - - D3DSURFACE_DESC desc; - source->GetDesc(&desc); - - const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(desc.Format); - unsigned int rows = desc.Height / d3dFormatInfo.blockHeight; - - unsigned int bytes = d3d9::ComputeBlockSize(desc.Format, desc.Width, d3dFormatInfo.blockHeight); - ASSERT(bytes <= static_cast(sourceLock.Pitch) && - bytes <= static_cast(destLock.Pitch)); - - for(unsigned int i = 0; i < rows; i++) - { - memcpy((char*)destLock.pBits + destLock.Pitch * i, (char*)sourceLock.pBits + sourceLock.Pitch * i, bytes); - } - - source->UnlockRect(); - dest->UnlockRect(); - - return gl::Error(GL_NO_ERROR); -} - -bool Image9::redefine(RendererD3D *renderer, GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, bool forceRelease) -{ - // 3D textures are not supported by the D3D9 backend. - ASSERT(depth <= 1); - - // Only 2D and cube texture are supported by the D3D9 backend. - ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP); - - if (mWidth != width || - mHeight != height || - mDepth != depth || - mInternalFormat != internalformat || - forceRelease) - { - mRenderer = Renderer9::makeRenderer9(renderer); - - mWidth = width; - mHeight = height; - mDepth = depth; - mInternalFormat = internalformat; - - // compute the d3d format that will be used - const d3d9::TextureFormat &d3d9FormatInfo = d3d9::GetTextureFormatInfo(internalformat); - const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(d3d9FormatInfo.texFormat); - mD3DFormat = d3d9FormatInfo.texFormat; - mActualFormat = d3dFormatInfo.internalFormat; - mRenderable = (d3d9FormatInfo.renderFormat != D3DFMT_UNKNOWN); - - SafeRelease(mSurface); - mDirty = (d3d9FormatInfo.dataInitializerFunction != NULL); - - return true; - } - - return false; -} - -gl::Error Image9::createSurface() -{ - if (mSurface) - { - return gl::Error(GL_NO_ERROR); - } - - IDirect3DTexture9 *newTexture = NULL; - IDirect3DSurface9 *newSurface = NULL; - const D3DPOOL poolToUse = D3DPOOL_SYSTEMMEM; - const D3DFORMAT d3dFormat = getD3DFormat(); - - if (mWidth != 0 && mHeight != 0) - { - int levelToFetch = 0; - GLsizei requestWidth = mWidth; - GLsizei requestHeight = mHeight; - d3d9::MakeValidSize(true, d3dFormat, &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); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create image surface, result: 0x%X.", result); - } - - newTexture->GetSurfaceLevel(levelToFetch, &newSurface); - SafeRelease(newTexture); - - const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(mInternalFormat); - if (d3dFormatInfo.dataInitializerFunction != NULL) - { - RECT entireRect; - entireRect.left = 0; - entireRect.right = mWidth; - entireRect.top = 0; - entireRect.bottom = mHeight; - - D3DLOCKED_RECT lockedRect; - result = newSurface->LockRect(&lockedRect, &entireRect, 0); - ASSERT(SUCCEEDED(result)); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock image surface, result: 0x%X.", result); - } - - d3dFormatInfo.dataInitializerFunction(mWidth, mHeight, 1, reinterpret_cast(lockedRect.pBits), - lockedRect.Pitch, 0); - - result = newSurface->UnlockRect(); - ASSERT(SUCCEEDED(result)); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to unlock image surface, result: 0x%X.", result); - } - } - } - - mSurface = newSurface; - mDirty = false; - mD3DPool = poolToUse; - - return gl::Error(GL_NO_ERROR); -} - -gl::Error Image9::lock(D3DLOCKED_RECT *lockedRect, const RECT &rect) -{ - gl::Error error = createSurface(); - if (error.isError()) - { - return error; - } - - if (mSurface) - { - HRESULT result = mSurface->LockRect(lockedRect, &rect, 0); - ASSERT(SUCCEEDED(result)); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock image surface, result: 0x%X.", result); - } - - mDirty = true; - } - - return gl::Error(GL_NO_ERROR); -} - -void Image9::unlock() -{ - if (mSurface) - { - HRESULT result = mSurface->UnlockRect(); - UNUSED_ASSERTION_VARIABLE(result); - ASSERT(SUCCEEDED(result)); - } -} - -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; -} - -bool Image9::isDirty() const -{ - // Make sure to that this image is marked as dirty even if the staging texture hasn't been created yet - // if initialization is required before use. - return (mSurface || d3d9::GetTextureFormatInfo(mInternalFormat).dataInitializerFunction != NULL) && mDirty; -} - -gl::Error Image9::getSurface(IDirect3DSurface9 **outSurface) -{ - gl::Error error = createSurface(); - if (error.isError()) - { - return error; - } - - *outSurface = mSurface; - return gl::Error(GL_NO_ERROR); -} - -gl::Error Image9::setManagedSurface2D(TextureStorage *storage, int level) -{ - IDirect3DSurface9 *surface = NULL; - TextureStorage9_2D *storage9 = TextureStorage9_2D::makeTextureStorage9_2D(storage); - gl::Error error = storage9->getSurfaceLevel(level, false, &surface); - if (error.isError()) - { - return error; - } - return setManagedSurface(surface); -} - -gl::Error Image9::setManagedSurfaceCube(TextureStorage *storage, int face, int level) -{ - IDirect3DSurface9 *surface = NULL; - TextureStorage9_Cube *storage9 = TextureStorage9_Cube::makeTextureStorage9_Cube(storage); - gl::Error error = storage9->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, false, &surface); - if (error.isError()) - { - return error; - } - return setManagedSurface(surface); -} - -gl::Error 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) - { - gl::Error error = copyLockableSurfaces(surface, mSurface); - SafeRelease(mSurface); - if (error.isError()) - { - return error; - } - } - - mSurface = surface; - mD3DPool = desc.Pool; - } - - return gl::Error(GL_NO_ERROR); -} - -gl::Error Image9::copyToStorage(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box ®ion) -{ - gl::Error error = createSurface(); - if (error.isError()) - { - return error; - } - - IDirect3DSurface9 *destSurface = NULL; - - if (index.type == GL_TEXTURE_2D) - { - TextureStorage9_2D *storage9 = TextureStorage9_2D::makeTextureStorage9_2D(storage); - gl::Error error = storage9->getSurfaceLevel(index.mipIndex, true, &destSurface); - if (error.isError()) - { - return error; - } - } - else - { - ASSERT(gl::IsCubemapTextureTarget(index.type)); - TextureStorage9_Cube *storage9 = TextureStorage9_Cube::makeTextureStorage9_Cube(storage); - gl::Error error = storage9->getCubeMapSurface(index.type, index.mipIndex, true, &destSurface); - if (error.isError()) - { - return error; - } - } - - error = copyToSurface(destSurface, region.x, region.y, region.width, region.height); - SafeRelease(destSurface); - return error; -} - -gl::Error Image9::copyToSurface(IDirect3DSurface9 *destSurface, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) -{ - ASSERT(width > 0 && height > 0); - ASSERT(destSurface); - - IDirect3DSurface9 *sourceSurface = NULL; - gl::Error error = getSurface(&sourceSurface); - if (error.isError()) - { - return error; - } - - ASSERT(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 (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Internal CreateOffscreenPlainSurface call failed, result: 0x%X.", result); - } - - copyLockableSurfaces(surf, sourceSurface); - result = device->UpdateSurface(surf, &rect, destSurface, &point); - SafeRelease(surf); - ASSERT(SUCCEEDED(result)); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Internal UpdateSurface call failed, result: 0x%X.", result); - } - } - else - { - // UpdateSurface: source must be SYSTEMMEM, dest must be DEFAULT pools - HRESULT result = device->UpdateSurface(sourceSurface, &rect, destSurface, &point); - ASSERT(SUCCEEDED(result)); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Internal UpdateSurface call failed, result: 0x%X.", result); - } - } - - return gl::Error(GL_NO_ERROR); -} - -// Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as format/type at input -// into the target pixel rectangle. -gl::Error Image9::loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, - GLint unpackAlignment, GLenum type, const void *input) -{ - // 3D textures are not supported by the D3D9 backend. - ASSERT(zoffset == 0 && depth == 1); - - const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat); - GLsizei inputRowPitch = formatInfo.computeRowPitch(type, width, unpackAlignment); - - const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(mInternalFormat); - ASSERT(d3dFormatInfo.loadFunction != NULL); - - RECT lockRect = - { - xoffset, yoffset, - xoffset + width, yoffset + height - }; - - D3DLOCKED_RECT locked; - gl::Error error = lock(&locked, lockRect); - if (error.isError()) - { - return error; - } - - d3dFormatInfo.loadFunction(width, height, depth, - reinterpret_cast(input), inputRowPitch, 0, - reinterpret_cast(locked.pBits), locked.Pitch, 0); - - unlock(); - - return gl::Error(GL_NO_ERROR); -} - -gl::Error Image9::loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, - const void *input) -{ - // 3D textures are not supported by the D3D9 backend. - ASSERT(zoffset == 0 && depth == 1); - - const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat); - GLsizei inputRowPitch = formatInfo.computeRowPitch(GL_UNSIGNED_BYTE, width, 1); - GLsizei inputDepthPitch = formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, width, height, 1); - - const d3d9::TextureFormat &d3d9FormatInfo = d3d9::GetTextureFormatInfo(mInternalFormat); - - ASSERT(xoffset % d3d9::GetD3DFormatInfo(d3d9FormatInfo.texFormat).blockWidth == 0); - ASSERT(yoffset % d3d9::GetD3DFormatInfo(d3d9FormatInfo.texFormat).blockHeight == 0); - - ASSERT(d3d9FormatInfo.loadFunction != NULL); - - RECT lockRect = - { - xoffset, yoffset, - xoffset + width, yoffset + height - }; - - D3DLOCKED_RECT locked; - gl::Error error = lock(&locked, lockRect); - if (error.isError()) - { - return error; - } - - d3d9FormatInfo.loadFunction(width, height, depth, - reinterpret_cast(input), inputRowPitch, inputDepthPitch, - reinterpret_cast(locked.pBits), locked.Pitch, 0); - - unlock(); - - return gl::Error(GL_NO_ERROR); -} - -// This implements glCopyTex[Sub]Image2D for non-renderable internal texture formats and incomplete textures -gl::Error Image9::copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea, RenderTarget *source) -{ - ASSERT(source); - - // ES3.0 only behaviour to copy into a 3d texture - ASSERT(zoffset == 0); - - RenderTarget9 *renderTarget = RenderTarget9::makeRenderTarget9(source); - - IDirect3DSurface9 *surface = renderTarget->getSurface(); - ASSERT(surface); - - 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)) - { - SafeRelease(surface); - return gl::Error(GL_OUT_OF_MEMORY, "Could not create matching destination surface, result: 0x%X.", result); - } - - result = device->GetRenderTargetData(surface, renderTargetData); - - if (FAILED(result)) - { - SafeRelease(renderTargetData); - SafeRelease(surface); - return gl::Error(GL_OUT_OF_MEMORY, "GetRenderTargetData unexpectedly failed, result: 0x%X.", result); - } - - int width = sourceArea.width; - int height = sourceArea.height; - - RECT sourceRect = { sourceArea.x, sourceArea.y, sourceArea.x + width, sourceArea.y + height }; - RECT destRect = { xoffset, yoffset, xoffset + width, yoffset + height }; - - D3DLOCKED_RECT sourceLock = {0}; - result = renderTargetData->LockRect(&sourceLock, &sourceRect, 0); - - if (FAILED(result)) - { - SafeRelease(renderTargetData); - SafeRelease(surface); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock the source surface (rectangle might be invalid), result: 0x%X.", result); - } - - D3DLOCKED_RECT destLock = {0}; - gl::Error error = lock(&destLock, destRect); - if (error.isError()) - { - renderTargetData->UnlockRect(); - SafeRelease(renderTargetData); - SafeRelease(surface); - return error; - } - - ASSERT(destLock.pBits && sourceLock.pBits); - - unsigned char *sourcePixels = (unsigned char*)sourceLock.pBits; - unsigned char *destPixels = (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(destPixels, sourcePixels, 4 * width); - sourcePixels += sourceLock.Pitch; - destPixels += destLock.Pitch; - } - break; - case D3DFMT_L8: - for (int y = 0; y < height; y++) - { - for (int x = 0; x < width; x++) - { - destPixels[x] = sourcePixels[x * 4 + 2]; - } - sourcePixels += sourceLock.Pitch; - destPixels += destLock.Pitch; - } - break; - case D3DFMT_A8L8: - for (int y = 0; y < height; y++) - { - for (int x = 0; x < width; x++) - { - destPixels[x * 2 + 0] = sourcePixels[x * 4 + 2]; - destPixels[x * 2 + 1] = sourcePixels[x * 4 + 3]; - } - sourcePixels += sourceLock.Pitch; - destPixels += 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*)sourcePixels)[x]; - unsigned char red = (rgb & 0xF800) >> 8; - unsigned char green = (rgb & 0x07E0) >> 3; - unsigned char blue = (rgb & 0x001F) << 3; - destPixels[x + 0] = blue | (blue >> 5); - destPixels[x + 1] = green | (green >> 6); - destPixels[x + 2] = red | (red >> 5); - destPixels[x + 3] = 0xFF; - } - sourcePixels += sourceLock.Pitch; - destPixels += destLock.Pitch; - } - break; - case D3DFMT_L8: - for (int y = 0; y < height; y++) - { - for (int x = 0; x < width; x++) - { - unsigned char red = sourcePixels[x * 2 + 1] & 0xF8; - destPixels[x] = red | (red >> 5); - } - sourcePixels += sourceLock.Pitch; - destPixels += 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*)sourcePixels)[x]; - unsigned char red = (argb & 0x7C00) >> 7; - unsigned char green = (argb & 0x03E0) >> 2; - unsigned char blue = (argb & 0x001F) << 3; - destPixels[x + 0] = blue | (blue >> 5); - destPixels[x + 1] = green | (green >> 5); - destPixels[x + 2] = red | (red >> 5); - destPixels[x + 3] = 0xFF; - } - sourcePixels += sourceLock.Pitch; - destPixels += 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*)sourcePixels)[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; - destPixels[x + 0] = blue | (blue >> 5); - destPixels[x + 1] = green | (green >> 5); - destPixels[x + 2] = red | (red >> 5); - destPixels[x + 3] = alpha; - } - sourcePixels += sourceLock.Pitch; - destPixels += destLock.Pitch; - } - break; - case D3DFMT_L8: - for (int y = 0; y < height; y++) - { - for (int x = 0; x < width; x++) - { - unsigned char red = sourcePixels[x * 2 + 1] & 0x7C; - destPixels[x] = (red << 1) | (red >> 4); - } - sourcePixels += sourceLock.Pitch; - destPixels += destLock.Pitch; - } - break; - case D3DFMT_A8L8: - for (int y = 0; y < height; y++) - { - for (int x = 0; x < width; x++) - { - unsigned char red = sourcePixels[x * 2 + 1] & 0x7C; - destPixels[x * 2 + 0] = (red << 1) | (red >> 4); - destPixels[x * 2 + 1] = (signed char)sourcePixels[x * 2 + 1] >> 7; - } - sourcePixels += sourceLock.Pitch; - destPixels += destLock.Pitch; - } - break; - default: - UNREACHABLE(); - } - break; - default: - UNREACHABLE(); - } - - unlock(); - renderTargetData->UnlockRect(); - - SafeRelease(renderTargetData); - SafeRelease(surface); - - mDirty = true; - return gl::Error(GL_NO_ERROR); -} - -gl::Error Image9::copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &area, const gl::ImageIndex &srcIndex, TextureStorage *srcStorage) -{ - // Currently unreachable, due to only being used in a D3D11-only workaround - UNIMPLEMENTED(); - return gl::Error(GL_INVALID_OPERATION); -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Image9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Image9.h deleted file mode 100644 index 8cc2258859..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Image9.h +++ /dev/null @@ -1,77 +0,0 @@ -// -// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// 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/d3d/ImageD3D.h" -#include "common/debug.h" - -namespace gl -{ -class Framebuffer; -} - -namespace rx -{ -class Renderer9; - -class Image9 : public ImageD3D -{ - public: - Image9(); - ~Image9(); - - static Image9 *makeImage9(Image *img); - - static gl::Error generateMipmap(Image9 *dest, Image9 *source); - static gl::Error generateMip(IDirect3DSurface9 *destSurface, IDirect3DSurface9 *sourceSurface); - static gl::Error copyLockableSurfaces(IDirect3DSurface9 *dest, IDirect3DSurface9 *source); - - bool redefine(RendererD3D *renderer, GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, bool forceRelease) override; - - D3DFORMAT getD3DFormat() const; - - virtual bool isDirty() const; - - virtual gl::Error setManagedSurface2D(TextureStorage *storage, int level); - virtual gl::Error setManagedSurfaceCube(TextureStorage *storage, int face, int level); - virtual gl::Error copyToStorage(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box ®ion); - - virtual gl::Error loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, - GLint unpackAlignment, GLenum type, const void *input); - virtual gl::Error loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, - const void *input); - - virtual gl::Error copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea, RenderTarget *source); - virtual gl::Error copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea, - const gl::ImageIndex &sourceIndex, TextureStorage *source); - - private: - DISALLOW_COPY_AND_ASSIGN(Image9); - - gl::Error getSurface(IDirect3DSurface9 **outSurface); - - gl::Error createSurface(); - gl::Error setManagedSurface(IDirect3DSurface9 *surface); - gl::Error copyToSurface(IDirect3DSurface9 *dest, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); - - gl::Error 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/d3d/d3d9/IndexBuffer9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/IndexBuffer9.cpp deleted file mode 100644 index 1c51b9e985..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/IndexBuffer9.cpp +++ /dev/null @@ -1,173 +0,0 @@ -// -// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Indexffer9.cpp: Defines the D3D9 IndexBuffer implementation. - -#include "libGLESv2/renderer/d3d/d3d9/IndexBuffer9.h" -#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" - -namespace rx -{ - -IndexBuffer9::IndexBuffer9(Renderer9 *const renderer) : mRenderer(renderer) -{ - mIndexBuffer = NULL; - mBufferSize = 0; - mIndexType = 0; - mDynamic = false; -} - -IndexBuffer9::~IndexBuffer9() -{ - SafeRelease(mIndexBuffer); -} - -gl::Error IndexBuffer9::initialize(unsigned int bufferSize, GLenum indexType, bool dynamic) -{ - SafeRelease(mIndexBuffer); - - updateSerial(); - - if (bufferSize > 0) - { - D3DFORMAT format = D3DFMT_UNKNOWN; - if (indexType == GL_UNSIGNED_SHORT || indexType == GL_UNSIGNED_BYTE) - { - format = D3DFMT_INDEX16; - } - else if (indexType == GL_UNSIGNED_INT) - { - ASSERT(mRenderer->getRendererExtensions().elementIndexUint); - format = D3DFMT_INDEX32; - } - else UNREACHABLE(); - - DWORD usageFlags = D3DUSAGE_WRITEONLY; - if (dynamic) - { - usageFlags |= D3DUSAGE_DYNAMIC; - } - - HRESULT result = mRenderer->createIndexBuffer(bufferSize, usageFlags, format, &mIndexBuffer); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal index buffer of size, %lu.", bufferSize); - } - } - - mBufferSize = bufferSize; - mIndexType = indexType; - mDynamic = dynamic; - - return gl::Error(GL_NO_ERROR); -} - -IndexBuffer9 *IndexBuffer9::makeIndexBuffer9(IndexBuffer *indexBuffer) -{ - ASSERT(HAS_DYNAMIC_TYPE(IndexBuffer9*, indexBuffer)); - return static_cast(indexBuffer); -} - -gl::Error IndexBuffer9::mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory) -{ - if (!mIndexBuffer) - { - return gl::Error(GL_OUT_OF_MEMORY, "Internal index buffer is not initialized."); - } - - DWORD lockFlags = mDynamic ? D3DLOCK_NOOVERWRITE : 0; - - void *mapPtr = NULL; - HRESULT result = mIndexBuffer->Lock(offset, size, &mapPtr, lockFlags); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock internal index buffer, HRESULT: 0x%08x.", result); - } - - *outMappedMemory = mapPtr; - return gl::Error(GL_NO_ERROR); -} - -gl::Error IndexBuffer9::unmapBuffer() -{ - if (!mIndexBuffer) - { - return gl::Error(GL_OUT_OF_MEMORY, "Internal index buffer is not initialized."); - } - - HRESULT result = mIndexBuffer->Unlock(); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to unlock internal index buffer, HRESULT: 0x%08x.", result); - } - - return gl::Error(GL_NO_ERROR); -} - -GLenum IndexBuffer9::getIndexType() const -{ - return mIndexType; -} - -unsigned int IndexBuffer9::getBufferSize() const -{ - return mBufferSize; -} - -gl::Error IndexBuffer9::setSize(unsigned int bufferSize, GLenum indexType) -{ - if (bufferSize > mBufferSize || indexType != mIndexType) - { - return initialize(bufferSize, indexType, mDynamic); - } - else - { - return gl::Error(GL_NO_ERROR); - } -} - -gl::Error IndexBuffer9::discard() -{ - if (!mIndexBuffer) - { - return gl::Error(GL_OUT_OF_MEMORY, "Internal index buffer is not initialized."); - } - - void *dummy; - HRESULT result; - - result = mIndexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock internal index buffer, HRESULT: 0x%08x.", result); - } - - result = mIndexBuffer->Unlock(); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to unlock internal index buffer, HRESULT: 0x%08x.", result); - } - - return gl::Error(GL_NO_ERROR); -} - -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; -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/IndexBuffer9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/IndexBuffer9.h deleted file mode 100644 index 2375fcf4b0..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/IndexBuffer9.h +++ /dev/null @@ -1,53 +0,0 @@ -// -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Indexffer9.h: Defines the D3D9 IndexBuffer implementation. - -#ifndef LIBGLESV2_RENDERER_INDEXBUFFER9_H_ -#define LIBGLESV2_RENDERER_INDEXBUFFER9_H_ - -#include "libGLESv2/renderer/d3d/IndexBuffer.h" - -namespace rx -{ -class Renderer9; - -class IndexBuffer9 : public IndexBuffer -{ - public: - explicit IndexBuffer9(Renderer9 *const renderer); - virtual ~IndexBuffer9(); - - virtual gl::Error initialize(unsigned int bufferSize, GLenum indexType, bool dynamic); - - static IndexBuffer9 *makeIndexBuffer9(IndexBuffer *indexBuffer); - - virtual gl::Error mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory); - virtual gl::Error unmapBuffer(); - - virtual GLenum getIndexType() const; - virtual unsigned int getBufferSize() const; - virtual gl::Error setSize(unsigned int bufferSize, GLenum indexType); - - virtual gl::Error discard(); - - D3DFORMAT getIndexFormat() const; - IDirect3DIndexBuffer9 *getBuffer() const; - - private: - DISALLOW_COPY_AND_ASSIGN(IndexBuffer9); - - 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/d3d/d3d9/Query9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Query9.cpp deleted file mode 100644 index a3cab578be..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Query9.cpp +++ /dev/null @@ -1,144 +0,0 @@ -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Query9.cpp: Defines the rx::Query9 class which implements rx::QueryImpl. - -#include "libGLESv2/renderer/d3d/d3d9/Query9.h" -#include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h" -#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" -#include "libGLESv2/main.h" - -#include - -namespace rx -{ -Query9::Query9(Renderer9 *renderer, GLenum type) - : QueryImpl(type), - mResult(GL_FALSE), - mQueryFinished(false), - mRenderer(renderer), - mQuery(NULL) -{ -} - -Query9::~Query9() -{ - SafeRelease(mQuery); -} - -gl::Error Query9::begin() -{ - if (mQuery == NULL) - { - HRESULT result = mRenderer->getDevice()->CreateQuery(D3DQUERYTYPE_OCCLUSION, &mQuery); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Internal query creation failed, result: 0x%X.", result); - } - } - - HRESULT result = mQuery->Issue(D3DISSUE_BEGIN); - ASSERT(SUCCEEDED(result)); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to begin internal query, result: 0x%X.", result); - } - - return gl::Error(GL_NO_ERROR); -} - -gl::Error Query9::end() -{ - ASSERT(mQuery); - - HRESULT result = mQuery->Issue(D3DISSUE_END); - ASSERT(SUCCEEDED(result)); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to end internal query, result: 0x%X.", result); - } - - mQueryFinished = false; - mResult = GL_FALSE; - - return gl::Error(GL_NO_ERROR); -} - -gl::Error Query9::getResult(GLuint *params) -{ - while (!mQueryFinished) - { - gl::Error error = testQuery(); - if (error.isError()) - { - return error; - } - - if (!mQueryFinished) - { - Sleep(0); - } - } - - ASSERT(mQueryFinished); - *params = mResult; - - return gl::Error(GL_NO_ERROR); -} - -gl::Error Query9::isResultAvailable(GLuint *available) -{ - gl::Error error = testQuery(); - if (error.isError()) - { - return error; - } - - *available = (mQueryFinished ? GL_TRUE : GL_FALSE); - - return gl::Error(GL_NO_ERROR); -} - -gl::Error Query9::testQuery() -{ - if (!mQueryFinished) - { - ASSERT(mQuery); - - DWORD numPixels = 0; - - HRESULT hres = mQuery->GetData(&numPixels, sizeof(DWORD), D3DGETDATA_FLUSH); - if (hres == S_OK) - { - mQueryFinished = 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(); - break; - } - } - else if (d3d9::isDeviceLostError(hres)) - { - mRenderer->notifyDeviceLost(); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to test get query result, device is lost."); - } - else if (mRenderer->testDeviceLost(true)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to test get query result, device is lost."); - } - } - - return gl::Error(GL_NO_ERROR); -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Query9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Query9.h deleted file mode 100644 index 36851c6c6c..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Query9.h +++ /dev/null @@ -1,43 +0,0 @@ -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Query9.h: Defines the rx::Query9 class which implements rx::QueryImpl. - -#ifndef LIBGLESV2_RENDERER_QUERY9_H_ -#define LIBGLESV2_RENDERER_QUERY9_H_ - -#include "libGLESv2/renderer/QueryImpl.h" - -namespace rx -{ -class Renderer9; - -class Query9 : public QueryImpl -{ - public: - Query9(Renderer9 *renderer, GLenum type); - virtual ~Query9(); - - virtual gl::Error begin(); - virtual gl::Error end(); - virtual gl::Error getResult(GLuint *params); - virtual gl::Error isResultAvailable(GLuint *available); - - private: - DISALLOW_COPY_AND_ASSIGN(Query9); - - gl::Error testQuery(); - - GLuint mResult; - bool mQueryFinished; - - Renderer9 *mRenderer; - IDirect3DQuery9 *mQuery; -}; - -} - -#endif // LIBGLESV2_RENDERER_QUERY9_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/RenderTarget9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/RenderTarget9.cpp deleted file mode 100644 index 53d1f752fa..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/RenderTarget9.cpp +++ /dev/null @@ -1,148 +0,0 @@ -// -// Copyright (c) 2012-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// RenderTarget9.cpp: Implements a D3D9-specific wrapper for IDirect3DSurface9 -// pointers retained by renderbuffers. - -#include "libGLESv2/renderer/d3d/d3d9/RenderTarget9.h" -#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" -#include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h" -#include "libGLESv2/renderer/d3d/d3d9/SwapChain9.h" -#include "libGLESv2/renderer/d3d/d3d9/formatutils9.h" -#include "libGLESv2/main.h" - -namespace rx -{ - -RenderTarget9 *RenderTarget9::makeRenderTarget9(RenderTarget *target) -{ - ASSERT(HAS_DYNAMIC_TYPE(RenderTarget9*, target)); - return static_cast(target); -} - -void RenderTarget9::invalidate(GLint x, GLint y, GLsizei width, GLsizei height) -{ - // Currently a no-op -} - -// TODO: AddRef the incoming surface to take ownership instead of expecting that its ref is being given. -TextureRenderTarget9::TextureRenderTarget9(IDirect3DSurface9 *surface, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, - GLsizei samples) - : mWidth(width), - mHeight(height), - mDepth(depth), - mInternalFormat(internalFormat), - mActualFormat(internalFormat), - mSamples(samples), - mRenderTarget(surface) -{ - ASSERT(mDepth == 1); - - if (mRenderTarget) - { - D3DSURFACE_DESC description; - mRenderTarget->GetDesc(&description); - - const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(description.Format); - mActualFormat = d3dFormatInfo.internalFormat; - } -} - -TextureRenderTarget9::~TextureRenderTarget9() -{ - SafeRelease(mRenderTarget); -} - -GLsizei TextureRenderTarget9::getWidth() const -{ - return mWidth; -} - -GLsizei TextureRenderTarget9::getHeight() const -{ - return mHeight; -} - -GLsizei TextureRenderTarget9::getDepth() const -{ - return mDepth; -} - -GLenum TextureRenderTarget9::getInternalFormat() const -{ - return mInternalFormat; -} - -GLenum TextureRenderTarget9::getActualFormat() const -{ - return mActualFormat; -} - -GLsizei TextureRenderTarget9::getSamples() const -{ - return mSamples; -} - -IDirect3DSurface9 *TextureRenderTarget9::getSurface() -{ - // Caller is responsible for releasing the returned surface reference. - // TODO: remove the AddRef to match RenderTarget11 - if (mRenderTarget) - { - mRenderTarget->AddRef(); - } - - return mRenderTarget; -} - - -SurfaceRenderTarget9::SurfaceRenderTarget9(SwapChain9 *swapChain, bool depth) - : mSwapChain(swapChain), - mDepth(depth) -{ -} - -SurfaceRenderTarget9::~SurfaceRenderTarget9() -{ -} - -GLsizei SurfaceRenderTarget9::getWidth() const -{ - return mSwapChain->getWidth(); -} - -GLsizei SurfaceRenderTarget9::getHeight() const -{ - return mSwapChain->getHeight(); -} - -GLsizei SurfaceRenderTarget9::getDepth() const -{ - return 1; -} - -GLenum SurfaceRenderTarget9::getInternalFormat() const -{ - return (mDepth ? mSwapChain->GetDepthBufferInternalFormat() : mSwapChain->GetBackBufferInternalFormat()); -} - -GLenum SurfaceRenderTarget9::getActualFormat() const -{ - return d3d9::GetD3DFormatInfo(d3d9::GetTextureFormatInfo(getInternalFormat()).texFormat).internalFormat; -} - -GLsizei SurfaceRenderTarget9::getSamples() const -{ - // Our EGL surfaces do not support multisampling. - return 0; -} - -IDirect3DSurface9 *SurfaceRenderTarget9::getSurface() -{ - return (mDepth ? mSwapChain->getDepthStencil() : mSwapChain->getRenderTarget()); -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/RenderTarget9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/RenderTarget9.h deleted file mode 100644 index 4585697f4c..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/RenderTarget9.h +++ /dev/null @@ -1,89 +0,0 @@ -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// RenderTarget9.h: Defines a D3D9-specific wrapper for IDirect3DSurface9 pointers -// retained by Renderbuffers. - -#ifndef LIBGLESV2_RENDERER_RENDERTARGET9_H_ -#define LIBGLESV2_RENDERER_RENDERTARGET9_H_ - -#include "libGLESv2/renderer/RenderTarget.h" - -namespace rx -{ -class Renderer9; -class SwapChain9; - -class RenderTarget9 : public RenderTarget -{ - public: - RenderTarget9() { } - virtual ~RenderTarget9() { } - - static RenderTarget9 *makeRenderTarget9(RenderTarget *renderTarget); - - void invalidate(GLint x, GLint y, GLsizei width, GLsizei height) override; - - virtual IDirect3DSurface9 *getSurface() = 0; - - private: - DISALLOW_COPY_AND_ASSIGN(RenderTarget9); -}; - -class TextureRenderTarget9 : public RenderTarget9 -{ - public: - TextureRenderTarget9(IDirect3DSurface9 *surface, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, - GLsizei samples); - virtual ~TextureRenderTarget9(); - - GLsizei getWidth() const override; - GLsizei getHeight() const override; - GLsizei getDepth() const override; - GLenum getInternalFormat() const override; - GLenum getActualFormat() const override; - GLsizei getSamples() const override; - - IDirect3DSurface9 *getSurface() override; - - private: - DISALLOW_COPY_AND_ASSIGN(TextureRenderTarget9); - - GLsizei mWidth; - GLsizei mHeight; - GLsizei mDepth; - GLenum mInternalFormat; - GLenum mActualFormat; - GLsizei mSamples; - - IDirect3DSurface9 *mRenderTarget; -}; - -class SurfaceRenderTarget9 : public RenderTarget9 -{ - public: - SurfaceRenderTarget9(SwapChain9 *swapChain, bool depth); - virtual ~SurfaceRenderTarget9(); - - GLsizei getWidth() const override; - GLsizei getHeight() const override; - GLsizei getDepth() const override; - GLenum getInternalFormat() const override; - GLenum getActualFormat() const override; - GLsizei getSamples() const override; - - IDirect3DSurface9 *getSurface() override; - - private: - DISALLOW_COPY_AND_ASSIGN(SurfaceRenderTarget9); - - SwapChain9 *mSwapChain; - bool mDepth; -}; - -} - -#endif // LIBGLESV2_RENDERER_RENDERTARGET9_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp deleted file mode 100644 index 18e6e2d7f0..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp +++ /dev/null @@ -1,3171 +0,0 @@ -// -// Copyright (c) 2012-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Renderer9.cpp: Implements a back-end specific class for the D3D9 renderer. - -#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" -#include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h" -#include "libGLESv2/renderer/d3d/d3d9/formatutils9.h" -#include "libGLESv2/renderer/d3d/d3d9/ShaderExecutable9.h" -#include "libGLESv2/renderer/d3d/d3d9/SwapChain9.h" -#include "libGLESv2/renderer/d3d/d3d9/TextureStorage9.h" -#include "libGLESv2/renderer/d3d/d3d9/Image9.h" -#include "libGLESv2/renderer/d3d/d3d9/Blit9.h" -#include "libGLESv2/renderer/d3d/d3d9/RenderTarget9.h" -#include "libGLESv2/renderer/d3d/d3d9/VertexBuffer9.h" -#include "libGLESv2/renderer/d3d/d3d9/IndexBuffer9.h" -#include "libGLESv2/renderer/d3d/d3d9/Buffer9.h" -#include "libGLESv2/renderer/d3d/d3d9/Query9.h" -#include "libGLESv2/renderer/d3d/d3d9/Fence9.h" -#include "libGLESv2/renderer/d3d/d3d9/VertexArray9.h" -#include "libGLESv2/renderer/d3d/IndexDataManager.h" -#include "libGLESv2/renderer/d3d/ProgramD3D.h" -#include "libGLESv2/renderer/d3d/ShaderD3D.h" -#include "libGLESv2/renderer/d3d/TextureD3D.h" -#include "libGLESv2/renderer/d3d/TransformFeedbackD3D.h" -#include "libGLESv2/renderer/d3d/RenderbufferD3D.h" -#include "libGLESv2/main.h" -#include "libGLESv2/Buffer.h" -#include "libGLESv2/Texture.h" -#include "libGLESv2/Framebuffer.h" -#include "libGLESv2/FramebufferAttachment.h" -#include "libGLESv2/Renderbuffer.h" -#include "libGLESv2/ProgramBinary.h" -#include "libGLESv2/State.h" -#include "libGLESv2/angletypes.h" - -#include "libEGL/Display.h" - -#include "common/features.h" -#include "common/utilities.h" - -#include - -// Can also be enabled by defining FORCE_REF_RAST in the project's predefined macros -#define REF_RAST 0 - -#if !defined(ANGLE_COMPILE_OPTIMIZATION_LEVEL) -#define ANGLE_COMPILE_OPTIMIZATION_LEVEL D3DCOMPILE_OPTIMIZATION_LEVEL3 -#endif - -const D3DFORMAT D3DFMT_INTZ = ((D3DFORMAT)(MAKEFOURCC('I','N','T','Z'))); -const D3DFORMAT D3DFMT_NULL = ((D3DFORMAT)(MAKEFOURCC('N','U','L','L'))); - -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, EGLNativeDisplayType hDc, const egl::AttributeMap &attributes) - : RendererD3D(display), - mDc(hDc) -{ - 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; - - mMaskedClearSavedState = NULL; - - mVertexDataManager = NULL; - mIndexDataManager = NULL; - mLineLoopIB = NULL; - mCountingIB = 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; - } - - mAppliedVertexShader = NULL; - mAppliedPixelShader = NULL; - mAppliedProgramSerial = 0; -} - -Renderer9::~Renderer9() -{ - if (mDevice) - { - // If the device is lost, reset it first to prevent leaving the driver in an unstable state - if (testDeviceLost(false)) - { - resetDevice(); - } - } - - release(); -} - -void Renderer9::release() -{ - RendererD3D::cleanup(); - - releaseShaderCompiler(); - releaseDeviceResources(); - - SafeRelease(mDevice); - SafeRelease(mDeviceEx); - SafeRelease(mD3d9); - SafeRelease(mD3d9Ex); - - mCompiler.release(); - - if (mDeviceWindow) - { - DestroyWindow(mDeviceWindow); - mDeviceWindow = NULL; - } - - mD3d9Module = NULL; -} - -Renderer9 *Renderer9::makeRenderer9(Renderer *renderer) -{ - ASSERT(HAS_DYNAMIC_TYPE(Renderer9*, renderer)); - return static_cast(renderer); -} - -EGLint Renderer9::initialize() -{ - if (!mCompiler.initialize()) - { - return EGL_NOT_INITIALIZED; - } - - 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_D3D9EX == ANGLE_ENABLED && 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::ensureRenderTarget. - 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); - } - - 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); - } - - 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; - - static wchar_t *qt_d3dcreate_multihreaded_var = _wgetenv(L"QT_D3DCREATE_MULTITHREADED"); - if (qt_d3dcreate_multihreaded_var && wcsstr(qt_d3dcreate_multihreaded_var, L"1")) - behaviorFlags |= D3DCREATE_MULTITHREADED; - - { - 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); - } - - 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)); - - 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 - } - - const gl::Caps &rendererCaps = getRendererCaps(); - - mForceSetVertexSamplerStates.resize(rendererCaps.maxVertexTextureImageUnits); - mCurVertexSamplerStates.resize(rendererCaps.maxVertexTextureImageUnits); - - mForceSetPixelSamplerStates.resize(rendererCaps.maxTextureImageUnits); - mCurPixelSamplerStates.resize(rendererCaps.maxTextureImageUnits); - - mCurVertexTextureSerials.resize(rendererCaps.maxVertexTextureImageUnits); - mCurPixelTextureSerials.resize(rendererCaps.maxTextureImageUnits); - - markAllStateDirty(); - - mSceneStarted = false; - - ASSERT(!mBlit); - mBlit = new Blit9(this); - mBlit->initialize(); - - ASSERT(!mVertexDataManager && !mIndexDataManager); - mVertexDataManager = new VertexDataManager(this); - mIndexDataManager = new 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++) - { - const d3d9::D3DFormat &renderTargetFormatInfo = d3d9::GetD3DFormatInfo(RenderTargetFormats[formatIndex]); - const gl::TextureCaps &renderTargetFormatCaps = getRendererTextureCaps().get(renderTargetFormatInfo.internalFormat); - if (renderTargetFormatCaps.renderable) - { - for (unsigned int depthStencilIndex = 0; depthStencilIndex < numDepthFormats; depthStencilIndex++) - { - const d3d9::D3DFormat &depthStencilFormatInfo = d3d9::GetD3DFormatInfo(DepthStencilFormats[depthStencilIndex]); - const gl::TextureCaps &depthStencilFormatCaps = getRendererTextureCaps().get(depthStencilFormatInfo.internalFormat); - if (depthStencilFormatCaps.renderable || DepthStencilFormats[depthStencilIndex] == D3DFMT_UNKNOWN) - { - ConfigDesc newConfig; - newConfig.renderTargetFormat = renderTargetFormatInfo.internalFormat; - newConfig.depthStencilFormat = depthStencilFormatInfo.internalFormat; - newConfig.multiSample = 0; // FIXME: enumerate multi-sampling - newConfig.fastConfig = (currentDisplayMode.Format == RenderTargetFormats[formatIndex]); - newConfig.es3Capable = false; - - (*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; - } -} - -gl::Error Renderer9::sync(bool block) -{ - IDirect3DQuery9* query = NULL; - gl::Error error = allocateEventQuery(&query); - if (error.isError()) - { - return error; - } - - HRESULT result = query->Issue(D3DISSUE_END); - if (FAILED(result)) - { - ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to issue event query, result: 0x%X.", result); - } - - // Grab the query data once in blocking and non-blocking case - result = query->GetData(NULL, 0, D3DGETDATA_FLUSH); - if (FAILED(result)) - { - if (d3d9::isDeviceLostError(result)) - { - notifyDeviceLost(); - } - - freeEventQuery(query); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to get event query data, result: 0x%X.", result); - } - - // If blocking, loop until the query completes - while (block && result == S_FALSE) - { - // Keep polling, but allow other threads to do something useful first - Sleep(0); - - result = query->GetData(NULL, 0, D3DGETDATA_FLUSH); - - // 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 (result == S_FALSE && testDeviceLost(false)) - { - result = D3DERR_DEVICELOST; - } - - if (FAILED(result)) - { - if (d3d9::isDeviceLostError(result)) - { - notifyDeviceLost(); - } - - freeEventQuery(query); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to get event query data, result: 0x%X.", result); - } - - } - - freeEventQuery(query); - - return gl::Error(GL_NO_ERROR); -} - -SwapChain *Renderer9::createSwapChain(NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) -{ - return new SwapChain9(this, nativeWindow, shareHandle, backBufferFormat, depthBufferFormat); -} - -gl::Error Renderer9::allocateEventQuery(IDirect3DQuery9 **outQuery) -{ - if (mEventQueryPool.empty()) - { - HRESULT result = mDevice->CreateQuery(D3DQUERYTYPE_EVENT, outQuery); - if (FAILED(result)) - { - ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate event query, result: 0x%X.", result); - } - } - else - { - *outQuery = mEventQueryPool.back(); - mEventQueryPool.pop_back(); - } - - return gl::Error(GL_NO_ERROR); -} - -void Renderer9::freeEventQuery(IDirect3DQuery9* query) -{ - if (mEventQueryPool.size() > 1000) - { - SafeRelease(query); - } - else - { - mEventQueryPool.push_back(query); - } -} - -gl::Error Renderer9::createVertexShader(const DWORD *function, size_t length, IDirect3DVertexShader9 **outShader) -{ - return mVertexShaderCache.create(function, length, outShader); -} - -gl::Error Renderer9::createPixelShader(const DWORD *function, size_t length, IDirect3DPixelShader9 **outShader) -{ - return mPixelShaderCache.create(function, length, outShader); -} - -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); -} - -BufferImpl *Renderer9::createBuffer() -{ - return new Buffer9(this); -} - -VertexArrayImpl *Renderer9::createVertexArray() -{ - return new VertexArray9(this); -} - -QueryImpl *Renderer9::createQuery(GLenum type) -{ - return new Query9(this, type); -} - -FenceNVImpl *Renderer9::createFenceNV() -{ - return new FenceNV9(this); -} - -FenceSyncImpl *Renderer9::createFenceSync() -{ - // Renderer9 doesn't support ES 3.0 and its sync objects. - UNREACHABLE(); - return NULL; -} - -TransformFeedbackImpl* Renderer9::createTransformFeedback() -{ - return new TransformFeedbackD3D(); -} - -bool Renderer9::supportsFastCopyBufferToTexture(GLenum internalFormat) const -{ - // Pixel buffer objects are not supported in D3D9, since D3D9 is ES2-only and PBOs are ES3. - return false; -} - -gl::Error Renderer9::fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget, - GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea) -{ - // Pixel buffer objects are not supported in D3D9, since D3D9 is ES2-only and PBOs are ES3. - UNREACHABLE(); - return gl::Error(GL_INVALID_OPERATION); -} - -gl::Error Renderer9::generateSwizzle(gl::Texture *texture) -{ - // Swizzled textures are not available in ES2 or D3D9 - UNREACHABLE(); - return gl::Error(GL_INVALID_OPERATION); -} - -gl::Error Renderer9::setSamplerState(gl::SamplerType type, int index, gl::Texture *texture, const gl::SamplerState &samplerState) -{ - std::vector &forceSetSamplers = (type == gl::SAMPLER_PIXEL) ? mForceSetPixelSamplerStates : mForceSetVertexSamplerStates; - std::vector &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; - - // Make sure to add the level offset for our tiny compressed texture workaround - TextureD3D *textureD3D = TextureD3D::makeTextureD3D(texture->getImplementation()); - DWORD baseLevel = samplerState.baseLevel + textureD3D->getNativeTexture()->getTopLevel(); - - 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, baseLevel); - if (getRendererExtensions().textureFilterAnisotropic) - { - mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAXANISOTROPY, (DWORD)samplerState.maxAnisotropy); - } - } - - forceSetSamplers[index] = false; - appliedSamplers[index] = samplerState; - - return gl::Error(GL_NO_ERROR); -} - -gl::Error 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; - - std::vector &appliedSerials = (type == gl::SAMPLER_PIXEL) ? mCurPixelTextureSerials : mCurVertexTextureSerials; - - if (texture) - { - TextureD3D* textureImpl = TextureD3D::makeTextureD3D(texture->getImplementation()); - - TextureStorage *texStorage = textureImpl->getNativeTexture(); - if (texStorage) - { - TextureStorage9 *storage9 = TextureStorage9::makeTextureStorage9(texStorage); - - gl::Error error = storage9->getBaseTexture(&d3dTexture); - if (error.isError()) - { - return error; - } - } - // 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 = textureImpl->hasDirtyImages(); - textureImpl->resetDirty(); - } - - if (forceSetTexture || appliedSerials[index] != serial) - { - mDevice->SetTexture(d3dSampler, d3dTexture); - } - - appliedSerials[index] = serial; - - return gl::Error(GL_NO_ERROR); -} - -gl::Error Renderer9::setUniformBuffers(const gl::Buffer* /*vertexUniformBuffers*/[], const gl::Buffer* /*fragmentUniformBuffers*/[]) -{ - // No effect in ES2/D3D9 - return gl::Error(GL_NO_ERROR); -} - -gl::Error 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; - - return gl::Error(GL_NO_ERROR); -} - -gl::Error Renderer9::setBlendState(const gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::ColorF &blendColor, - unsigned int sampleMask) -{ - bool blendStateChanged = mForceSetBlendState || memcmp(&blendState, &mCurBlendState, sizeof(gl::BlendState)) != 0; - bool blendColorChanged = mForceSetBlendState || memcmp(&blendColor, &mCurBlendColor, sizeof(gl::ColorF)) != 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."); - } - - gl::FramebufferAttachment *attachment = framebuffer->getFirstColorbuffer(); - GLenum internalFormat = attachment ? attachment->getInternalFormat() : GL_NONE; - - // 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 - - const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat); - DWORD colorMask = gl_d3d9::ConvertColorMask(formatInfo.redBits > 0 && blendState.colorMaskRed, - formatInfo.greenBits > 0 && blendState.colorMaskGreen, - formatInfo.blueBits > 0 && blendState.colorMaskBlue, - formatInfo.alphaBits > 0 && 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; - - return gl::Error(GL_NO_ERROR); -} - -gl::Error 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; - - ASSERT(depthStencilState.stencilWritemask == depthStencilState.stencilBackWritemask); - ASSERT(stencilRef == stencilBackRef); - ASSERT(depthStencilState.stencilMask == depthStencilState.stencilBackMask); - - // 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; - - return gl::Error(GL_NO_ERROR); -} - -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; -} - -void 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; - - float depthFront = !gl::IsTriangleMode(drawMode) ? 0.0f : (frontFace == GL_CCW ? 1.0f : -1.0f); - - bool viewportChanged = mForceSetViewport || memcmp(&actualViewport, &mCurViewport, sizeof(gl::Rectangle)) != 0 || - actualZNear != mCurNear || actualZFar != mCurFar || mCurDepthFront != depthFront; - if (viewportChanged) - { - mDevice->SetViewport(&dxViewport); - - mCurViewport = actualViewport; - mCurNear = actualZNear; - mCurFar = actualZFar; - mCurDepthFront = depthFront; - - dx_VertexConstants vc = {0}; - dx_PixelConstants pc = {0}; - - vc.viewAdjust[0] = (float)((actualViewport.width - (int)dxViewport.Width) + 2 * (actualViewport.x - (int)dxViewport.X) - 1) / dxViewport.Width; - vc.viewAdjust[1] = (float)((actualViewport.height - (int)dxViewport.Height) + 2 * (actualViewport.y - (int)dxViewport.Y) - 1) / dxViewport.Height; - vc.viewAdjust[2] = (float)actualViewport.width / dxViewport.Width; - vc.viewAdjust[3] = (float)actualViewport.height / dxViewport.Height; - - pc.viewCoords[0] = actualViewport.width * 0.5f; - pc.viewCoords[1] = actualViewport.height * 0.5f; - pc.viewCoords[2] = actualViewport.x + (actualViewport.width * 0.5f); - pc.viewCoords[3] = actualViewport.y + (actualViewport.height * 0.5f); - - pc.depthFront[0] = (actualZFar - actualZNear) * 0.5f; - pc.depthFront[1] = (actualZNear + actualZFar) * 0.5f; - pc.depthFront[2] = depthFront; - - vc.depthRange[0] = actualZNear; - vc.depthRange[1] = actualZFar; - vc.depthRange[2] = actualZFar - actualZNear; - - pc.depthRange[0] = actualZNear; - pc.depthRange[1] = actualZFar; - pc.depthRange[2] = actualZFar - actualZNear; - - if (memcmp(&vc, &mVertexConstants, sizeof(dx_VertexConstants)) != 0) - { - mVertexConstants = vc; - mDxUniformsDirty = true; - } - - if (memcmp(&pc, &mPixelConstants, sizeof(dx_PixelConstants)) != 0) - { - mPixelConstants = pc; - mDxUniformsDirty = true; - } - } - - mForceSetViewport = false; -} - -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: - UNREACHABLE(); - return false; - } - - return mPrimitiveCount > 0; -} - - -gl::Error Renderer9::getNullColorbuffer(gl::FramebufferAttachment *depthbuffer, gl::FramebufferAttachment **outColorBuffer) -{ - ASSERT(depthbuffer); - - 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; - *outColorBuffer = mNullColorbufferCache[i].buffer; - return gl::Error(GL_NO_ERROR); - } - } - - gl::Renderbuffer *nullRenderbuffer = new gl::Renderbuffer(createRenderbuffer(), 0); - gl::Error error = nullRenderbuffer->setStorage(width, height, GL_NONE, 0); - if (error.isError()) - { - SafeDelete(nullRenderbuffer); - return error; - } - - gl::RenderbufferAttachment *nullbuffer = new gl::RenderbufferAttachment(GL_NONE, nullRenderbuffer); - - // 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; - - *outColorBuffer = nullbuffer; - return gl::Error(GL_NO_ERROR); -} - -gl::Error Renderer9::applyRenderTarget(const 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::FramebufferAttachment *attachment = framebuffer->getColorbuffer(0); - if (!attachment) - { - gl::Error error = getNullColorbuffer(framebuffer->getDepthbuffer(), &attachment); - if (error.isError()) - { - return error; - } - } - ASSERT(attachment); - - bool renderTargetChanged = false; - unsigned int renderTargetSerial = GetAttachmentSerial(attachment); - if (renderTargetSerial != mAppliedRenderTargetSerial) - { - // Apply the render target on the device - RenderTarget9 *renderTarget = NULL; - gl::Error error = d3d9::GetAttachmentRenderTarget(attachment, &renderTarget); - if (error.isError()) - { - return error; - } - ASSERT(renderTarget); - - IDirect3DSurface9 *renderTargetSurface = renderTarget->getSurface(); - ASSERT(renderTargetSurface); - - mDevice->SetRenderTarget(0, renderTargetSurface); - SafeRelease(renderTargetSurface); - - mAppliedRenderTargetSerial = renderTargetSerial; - renderTargetChanged = true; - } - - gl::FramebufferAttachment *depthStencil = framebuffer->getDepthbuffer(); - unsigned int depthbufferSerial = 0; - unsigned int stencilbufferSerial = 0; - if (depthStencil) - { - depthbufferSerial = GetAttachmentSerial(depthStencil); - } - else if (framebuffer->getStencilbuffer()) - { - depthStencil = framebuffer->getStencilbuffer(); - stencilbufferSerial = GetAttachmentSerial(depthStencil); - } - - if (depthbufferSerial != mAppliedDepthbufferSerial || - stencilbufferSerial != mAppliedStencilbufferSerial || - !mDepthStencilInitialized) - { - unsigned int depthSize = 0; - unsigned int stencilSize = 0; - - // Apply the depth stencil on the device - if (depthStencil) - { - RenderTarget9 *depthStencilRenderTarget = NULL; - gl::Error error = d3d9::GetAttachmentRenderTarget(depthStencil, &depthStencilRenderTarget); - if (error.isError()) - { - return error; - } - ASSERT(depthStencilRenderTarget); - - IDirect3DSurface9 *depthStencilSurface = depthStencilRenderTarget->getSurface(); - ASSERT(depthStencilSurface); - - mDevice->SetDepthStencilSurface(depthStencilSurface); - SafeRelease(depthStencilSurface); - - 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; - mForceSetBlendState = true; - - mRenderTargetDesc.width = attachment->getWidth(); - mRenderTargetDesc.height = attachment->getHeight(); - mRenderTargetDesc.format = attachment->getActualFormat(); - mRenderTargetDescInitialized = true; - } - - return gl::Error(GL_NO_ERROR); -} - -gl::Error Renderer9::applyVertexBuffer(const gl::State &state, GLint first, GLsizei count, GLsizei instances) -{ - TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS]; - gl::Error error = mVertexDataManager->prepareVertexData(state, first, count, attributes, instances); - if (error.isError()) - { - return error; - } - - return mVertexDeclarationCache.applyDeclaration(mDevice, attributes, state.getCurrentProgramBinary(), instances, &mRepeatDraw); -} - -// Applies the indices and element array bindings to the Direct3D 9 device -gl::Error Renderer9::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo) -{ - gl::Error error = mIndexDataManager->prepareIndexData(type, count, elementArrayBuffer, indices, indexInfo); - if (error.isError()) - { - return 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 gl::Error(GL_NO_ERROR); -} - -void Renderer9::applyTransformFeedbackBuffers(const gl::State& state) -{ - UNREACHABLE(); -} - -gl::Error Renderer9::drawArrays(GLenum mode, GLsizei count, GLsizei instances, bool transformFeedbackActive) -{ - ASSERT(!transformFeedbackActive); - - startScene(); - - if (mode == GL_LINE_LOOP) - { - return drawLineLoop(count, GL_NONE, NULL, 0, NULL); - } - else if (instances > 0) - { - StaticIndexBufferInterface *countingIB = NULL; - gl::Error error = getCountingIB(count, &countingIB); - if (error.isError()) - { - return error; - } - - 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); - } - - return gl::Error(GL_NO_ERROR); - } - else // Regular case - { - mDevice->DrawPrimitive(mPrimitiveType, 0, mPrimitiveCount); - return gl::Error(GL_NO_ERROR); - } -} - -gl::Error Renderer9::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, - gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei /*instances*/) -{ - startScene(); - - int minIndex = static_cast(indexInfo.indexRange.start); - - if (mode == GL_POINTS) - { - return drawIndexedPoints(count, type, indices, minIndex, elementArrayBuffer); - } - else if (mode == GL_LINE_LOOP) - { - return drawLineLoop(count, type, indices, minIndex, elementArrayBuffer); - } - else - { - for (int i = 0; i < mRepeatDraw; i++) - { - GLsizei vertexCount = static_cast(indexInfo.indexRange.length()) + 1; - mDevice->DrawIndexedPrimitive(mPrimitiveType, -minIndex, minIndex, vertexCount, indexInfo.startIndex, mPrimitiveCount); - } - return gl::Error(GL_NO_ERROR); - } -} - -gl::Error 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) - { - BufferD3D *storage = BufferD3D::makeFromBuffer(elementArrayBuffer); - intptr_t offset = reinterpret_cast(indices); - const uint8_t *bufferData = NULL; - gl::Error error = storage->getData(&bufferData); - if (error.isError()) - { - return error; - } - indices = bufferData + offset; - } - - unsigned int startIndex = 0; - - if (getRendererExtensions().elementIndexUint) - { - if (!mLineLoopIB) - { - mLineLoopIB = new StreamingIndexBufferInterface(this); - gl::Error error = mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT); - if (error.isError()) - { - SafeDelete(mLineLoopIB); - return error; - } - } - - // Checked by Renderer9::applyPrimitiveType - ASSERT(count >= 0); - - if (static_cast(count) + 1 > (std::numeric_limits::max() / sizeof(unsigned int))) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create a 32-bit looping index buffer for GL_LINE_LOOP, too many indices required."); - } - - const unsigned int spaceNeeded = (static_cast(count)+1) * sizeof(unsigned int); - gl::Error error = mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT); - if (error.isError()) - { - return error; - } - - void* mappedMemory = NULL; - unsigned int offset = 0; - error = mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset); - if (error.isError()) - { - return error; - } - - 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(); - } - - error = mLineLoopIB->unmapBuffer(); - if (error.isError()) - { - return error; - } - } - else - { - if (!mLineLoopIB) - { - mLineLoopIB = new StreamingIndexBufferInterface(this); - gl::Error error = mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_SHORT); - if (error.isError()) - { - SafeDelete(mLineLoopIB); - return error; - } - } - - // Checked by Renderer9::applyPrimitiveType - ASSERT(count >= 0); - - if (static_cast(count) + 1 > (std::numeric_limits::max() / sizeof(unsigned short))) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create a 16-bit looping index buffer for GL_LINE_LOOP, too many indices required."); - } - - const unsigned int spaceNeeded = (static_cast(count) + 1) * sizeof(unsigned short); - gl::Error error = mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_SHORT); - if (error.isError()) - { - return error; - } - - void* mappedMemory = NULL; - unsigned int offset; - error = mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset); - if (error.isError()) - { - return error; - } - - 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(); - } - - error = mLineLoopIB->unmapBuffer(); - if (error.isError()) - { - return error; - } - } - - 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); - - return gl::Error(GL_NO_ERROR); -} - -template -static gl::Error drawPoints(IDirect3DDevice9* device, GLsizei count, const GLvoid *indices, int minIndex) -{ - for (int i = 0; i < count; i++) - { - unsigned int indexValue = static_cast(static_cast(indices)[i]) - minIndex; - device->DrawPrimitive(D3DPT_POINTLIST, indexValue, 1); - } - - return gl::Error(GL_NO_ERROR); -} - -gl::Error Renderer9::drawIndexedPoints(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer) -{ - // Drawing index point lists is unsupported in d3d9, fall back to a regular DrawPrimitive call - // for each individual point. This call is not expected to happen often. - - if (elementArrayBuffer) - { - BufferD3D *storage = BufferD3D::makeFromBuffer(elementArrayBuffer); - intptr_t offset = reinterpret_cast(indices); - - const uint8_t *bufferData = NULL; - gl::Error error = storage->getData(&bufferData); - if (error.isError()) - { - return error; - } - - indices = bufferData + offset; - } - - switch (type) - { - case GL_UNSIGNED_BYTE: return drawPoints(mDevice, count, indices, minIndex); - case GL_UNSIGNED_SHORT: return drawPoints(mDevice, count, indices, minIndex); - case GL_UNSIGNED_INT: return drawPoints(mDevice, count, indices, minIndex); - default: UNREACHABLE(); return gl::Error(GL_INVALID_OPERATION); - } -} - -gl::Error Renderer9::getCountingIB(size_t count, StaticIndexBufferInterface **outIB) -{ - // Update the counting index buffer if it is not large enough or has not been created yet. - if (count <= 65536) // 16-bit indices - { - const unsigned int spaceNeeded = count * sizeof(unsigned short); - - if (!mCountingIB || mCountingIB->getBufferSize() < spaceNeeded) - { - SafeDelete(mCountingIB); - mCountingIB = new StaticIndexBufferInterface(this); - mCountingIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_SHORT); - - void *mappedMemory = NULL; - gl::Error error = mCountingIB->mapBuffer(spaceNeeded, &mappedMemory, NULL); - if (error.isError()) - { - return error; - } - - unsigned short *data = reinterpret_cast(mappedMemory); - for (size_t i = 0; i < count; i++) - { - data[i] = i; - } - - error = mCountingIB->unmapBuffer(); - if (error.isError()) - { - return error; - } - } - } - else if (getRendererExtensions().elementIndexUint) - { - const unsigned int spaceNeeded = count * sizeof(unsigned int); - - if (!mCountingIB || mCountingIB->getBufferSize() < spaceNeeded) - { - SafeDelete(mCountingIB); - mCountingIB = new StaticIndexBufferInterface(this); - mCountingIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT); - - void *mappedMemory = NULL; - gl::Error error = mCountingIB->mapBuffer(spaceNeeded, &mappedMemory, NULL); - if (error.isError()) - { - return error; - } - - unsigned int *data = reinterpret_cast(mappedMemory); - for (size_t i = 0; i < count; i++) - { - data[i] = i; - } - - error = mCountingIB->unmapBuffer(); - if (error.isError()) - { - return error; - } - } - } - else - { - return gl::Error(GL_OUT_OF_MEMORY, "Could not create a counting index buffer for glDrawArraysInstanced."); - } - - *outIB = mCountingIB; - return gl::Error(GL_NO_ERROR); -} - -gl::Error Renderer9::applyShaders(gl::ProgramBinary *programBinary, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer, - bool rasterizerDiscard, bool transformFeedbackActive) -{ - ASSERT(!transformFeedbackActive); - ASSERT(!rasterizerDiscard); - - ProgramD3D *programD3D = ProgramD3D::makeProgramD3D(programBinary->getImplementation()); - - ShaderExecutable *vertexExe = NULL; - gl::Error error = programD3D->getVertexExecutableForInputLayout(inputLayout, &vertexExe); - if (error.isError()) - { - return error; - } - - ShaderExecutable *pixelExe = NULL; - error = programD3D->getPixelExecutableForFramebuffer(framebuffer, &pixelExe); - if (error.isError()) - { - return error; - } - - IDirect3DVertexShader9 *vertexShader = (vertexExe ? ShaderExecutable9::makeShaderExecutable9(vertexExe)->getVertexShader() : NULL); - IDirect3DPixelShader9 *pixelShader = (pixelExe ? ShaderExecutable9::makeShaderExecutable9(pixelExe)->getPixelShader() : NULL); - - if (vertexShader != mAppliedVertexShader) - { - mDevice->SetVertexShader(vertexShader); - mAppliedVertexShader = vertexShader; - } - - if (pixelShader != mAppliedPixelShader) - { - mDevice->SetPixelShader(pixelShader); - mAppliedPixelShader = pixelShader; - } - - // D3D9 has a quirk where creating multiple shaders with the same content - // can return the same shader pointer. Because GL programs store different data - // per-program, checking the program serial guarantees we upload fresh - // uniform data even if our shader pointers are the same. - // https://code.google.com/p/angleproject/issues/detail?id=661 - unsigned int programSerial = programBinary->getSerial(); - if (programSerial != mAppliedProgramSerial) - { - programD3D->dirtyAllUniforms(); - mDxUniformsDirty = true; - mAppliedProgramSerial = programSerial; - } - - return gl::Error(GL_NO_ERROR); -} - -gl::Error Renderer9::applyUniforms(const ProgramImpl &program, const std::vector &uniformArray) -{ - for (size_t uniformIndex = 0; uniformIndex < uniformArray.size(); uniformIndex++) - { - gl::LinkedUniform *targetUniform = uniformArray[uniformIndex]; - - 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(); - } - } - } - - // 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; - } - - return gl::Error(GL_NO_ERROR); -} - -void Renderer9::applyUniformnfv(gl::LinkedUniform *targetUniform, const GLfloat *v) -{ - if (targetUniform->isReferencedByFragmentShader()) - { - mDevice->SetPixelShaderConstantF(targetUniform->psRegisterIndex, v, targetUniform->registerCount); - } - - if (targetUniform->isReferencedByVertexShader()) - { - mDevice->SetVertexShaderConstantF(targetUniform->vsRegisterIndex, v, targetUniform->registerCount); - } -} - -void Renderer9::applyUniformniv(gl::LinkedUniform *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::LinkedUniform *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); -} - -gl::Error Renderer9::clear(const gl::ClearParameters &clearParams, const gl::Framebuffer *frameBuffer) -{ - if (clearParams.colorClearType != GL_FLOAT) - { - // Clearing buffers with non-float values is not supported by Renderer9 and ES 2.0 - UNREACHABLE(); - return gl::Error(GL_INVALID_OPERATION); - } - - bool clearColor = clearParams.clearColor[0]; - for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++) - { - if (clearParams.clearColor[i] != clearColor) - { - // Clearing individual buffers other than buffer zero is not supported by Renderer9 and ES 2.0 - UNREACHABLE(); - return gl::Error(GL_INVALID_OPERATION); - } - } - - float depth = gl::clamp01(clearParams.depthClearValue); - DWORD stencil = clearParams.stencilClearValue & 0x000000FF; - - unsigned int stencilUnmasked = 0x0; - if (clearParams.clearStencil && frameBuffer->hasStencil()) - { - unsigned int stencilSize = gl::GetInternalFormatInfo((frameBuffer->getStencilbuffer()->getActualFormat())).stencilBits; - stencilUnmasked = (0x1 << stencilSize) - 1; - } - - const bool needMaskedStencilClear = clearParams.clearStencil && - (clearParams.stencilWriteMask & stencilUnmasked) != stencilUnmasked; - - bool needMaskedColorClear = false; - D3DCOLOR color = D3DCOLOR_ARGB(255, 0, 0, 0); - if (clearColor) - { - const gl::FramebufferAttachment *attachment = frameBuffer->getFirstColorbuffer(); - const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(attachment->getInternalFormat()); - const gl::InternalFormat &actualFormatInfo = gl::GetInternalFormatInfo(attachment->getActualFormat()); - - color = D3DCOLOR_ARGB(gl::unorm<8>((formatInfo.alphaBits == 0 && actualFormatInfo.alphaBits > 0) ? 1.0f : clearParams.colorFClearValue.alpha), - gl::unorm<8>((formatInfo.redBits == 0 && actualFormatInfo.redBits > 0) ? 0.0f : clearParams.colorFClearValue.red), - gl::unorm<8>((formatInfo.greenBits == 0 && actualFormatInfo.greenBits > 0) ? 0.0f : clearParams.colorFClearValue.green), - gl::unorm<8>((formatInfo.blueBits == 0 && actualFormatInfo.blueBits > 0) ? 0.0f : clearParams.colorFClearValue.blue)); - - if ((formatInfo.redBits > 0 && !clearParams.colorMaskRed) || - (formatInfo.greenBits > 0 && !clearParams.colorMaskGreen) || - (formatInfo.blueBits > 0 && !clearParams.colorMaskBlue) || - (formatInfo.alphaBits > 0 && !clearParams.colorMaskAlpha)) - { - needMaskedColorClear = true; - } - } - - 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 (clearColor) - { - 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.clearStencil) - { - 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.clearDepth) - { - 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 (clearColor || clearParams.clearDepth || clearParams.clearStencil) - { - DWORD dxClearFlags = 0; - if (clearColor) - { - dxClearFlags |= D3DCLEAR_TARGET; - } - if (clearParams.clearDepth) - { - dxClearFlags |= D3DCLEAR_ZBUFFER; - } - if (clearParams.clearStencil) - { - dxClearFlags |= D3DCLEAR_STENCIL; - } - - mDevice->Clear(0, NULL, dxClearFlags, color, depth, stencil); - } - - return gl::Error(GL_NO_ERROR); -} - -void Renderer9::markAllStateDirty() -{ - mAppliedRenderTargetSerial = 0; - mAppliedDepthbufferSerial = 0; - mAppliedStencilbufferSerial = 0; - mDepthStencilInitialized = false; - mRenderTargetDescInitialized = false; - - mForceSetDepthStencilState = true; - mForceSetRasterState = true; - mForceSetScissor = true; - mForceSetViewport = true; - mForceSetBlendState = true; - - ASSERT(mForceSetVertexSamplerStates.size() == mCurVertexTextureSerials.size()); - for (unsigned int i = 0; i < mForceSetVertexSamplerStates.size(); i++) - { - mForceSetVertexSamplerStates[i] = true; - mCurVertexTextureSerials[i] = 0; - } - - ASSERT(mForceSetPixelSamplerStates.size() == mCurPixelTextureSerials.size()); - for (unsigned int i = 0; i < mForceSetPixelSamplerStates.size(); i++) - { - mForceSetPixelSamplerStates[i] = true; - mCurPixelTextureSerials[i] = 0; - } - - mAppliedIBSerial = 0; - mAppliedVertexShader = NULL; - mAppliedPixelShader = NULL; - mAppliedProgramSerial = 0; - mDxUniformsDirty = true; - - mVertexDeclarationCache.markStateDirty(); -} - -void Renderer9::releaseDeviceResources() -{ - for (size_t i = 0; i < mEventQueryPool.size(); i++) - { - SafeRelease(mEventQueryPool[i]); - } - mEventQueryPool.clear(); - - SafeRelease(mMaskedClearSavedState); - - mVertexShaderCache.clear(); - mPixelShaderCache.clear(); - - SafeDelete(mBlit); - SafeDelete(mVertexDataManager); - SafeDelete(mIndexDataManager); - SafeDelete(mLineLoopIB); - SafeDelete(mCountingIB); - - for (int i = 0; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++) - { - SafeDelete(mNullColorbufferCache[i].buffer); - } -} - -void Renderer9::notifyDeviceLost() -{ - mDeviceLost = true; - mDisplay->notifyDeviceLost(); -} - -bool Renderer9::isDeviceLost() -{ - return mDeviceLost; -} - -// set notify to true to broadcast a message to all contexts of the device loss -bool Renderer9::testDeviceLost(bool notify) -{ - HRESULT status = getDeviceStatusCode(); - bool isLost = FAILED(status); - - if (isLost) - { - // ensure we note the device loss -- - // we'll probably get this done again by notifyDeviceLost - // but best to remember it! - // Note that we don't want to clear the device loss status here - // -- this needs to be done by resetDevice - mDeviceLost = true; - if (notify) - { - notifyDeviceLost(); - } - } - - return isLost; -} - -HRESULT Renderer9::getDeviceStatusCode() -{ - HRESULT status = D3D_OK; - - if (mDeviceEx) - { - status = mDeviceEx->CheckDeviceState(NULL); - } - else if (mDevice) - { - status = mDevice->TestCooperativeLevel(); - } - - return status; -} - -bool Renderer9::testDeviceResettable() -{ - // On D3D9Ex, DEVICELOST represents a hung device that needs to be restarted - // DEVICEREMOVED indicates the device has been stopped and must be recreated - switch (getDeviceStatusCode()) - { - case D3DERR_DEVICENOTRESET: - case D3DERR_DEVICEHUNG: - return true; - case D3DERR_DEVICELOST: - return (mDeviceEx != NULL); - case D3DERR_DEVICEREMOVED: - ASSERT(mDeviceEx != NULL); - return isRemovedDeviceResettable(); - default: - return false; - } -} - -bool Renderer9::resetDevice() -{ - releaseDeviceResources(); - - D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters(); - - HRESULT result = D3D_OK; - bool lost = testDeviceLost(false); - bool removedDevice = (getDeviceStatusCode() == D3DERR_DEVICEREMOVED); - - // Device Removed is a feature which is only present with D3D9Ex - ASSERT(mDeviceEx != NULL || !removedDevice); - - for (int attempts = 3; lost && attempts > 0; attempts--) - { - if (removedDevice) - { - // Device removed, which may trigger on driver reinstallation, - // may cause a longer wait other reset attempts before the - // system is ready to handle creating a new device. - Sleep(800); - lost = !resetRemovedDevice(); - } - else if (mDeviceEx) - { - Sleep(500); // Give the graphics driver some CPU time - result = mDeviceEx->ResetEx(&presentParameters, NULL); - lost = testDeviceLost(false); - } - else - { - result = mDevice->TestCooperativeLevel(); - while (result == D3DERR_DEVICELOST) - { - Sleep(100); // Give the graphics driver some CPU time - result = mDevice->TestCooperativeLevel(); - } - - if (result == D3DERR_DEVICENOTRESET) - { - result = mDevice->Reset(&presentParameters); - } - lost = testDeviceLost(false); - } - } - - if (FAILED(result)) - { - ERR("Reset/ResetEx failed multiple times: 0x%08X", result); - return false; - } - - if (removedDevice && lost) - { - ERR("Device lost reset failed multiple times"); - return false; - } - - // If the device was removed, we already finished re-initialization in resetRemovedDevice - if (!removedDevice) - { - // reset device defaults - initializeDevice(); - } - - mDeviceLost = false; - - return true; -} - -bool Renderer9::isRemovedDeviceResettable() const -{ - bool success = false; - -#if ANGLE_D3D9EX == ANGLE_ENABLED - IDirect3D9Ex *d3d9Ex = NULL; - typedef HRESULT (WINAPI *Direct3DCreate9ExFunc)(UINT, IDirect3D9Ex**); - Direct3DCreate9ExFunc Direct3DCreate9ExPtr = reinterpret_cast(GetProcAddress(mD3d9Module, "Direct3DCreate9Ex")); - - if (Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &d3d9Ex))) - { - D3DCAPS9 deviceCaps; - HRESULT result = d3d9Ex->GetDeviceCaps(mAdapter, mDeviceType, &deviceCaps); - success = SUCCEEDED(result); - } - - SafeRelease(d3d9Ex); -#else - ASSERT(UNREACHABLE()); -#endif - - return success; -} - -bool Renderer9::resetRemovedDevice() -{ - // From http://msdn.microsoft.com/en-us/library/windows/desktop/bb172554(v=vs.85).aspx: - // The hardware adapter has been removed. Application must destroy the device, do enumeration of - // adapters and create another Direct3D device. If application continues rendering without - // calling Reset, the rendering calls will succeed. Applies to Direct3D 9Ex only. - release(); - return (initialize() == EGL_SUCCESS); -} - -DWORD Renderer9::getAdapterVendor() const -{ - return mAdapterIdentifier.VendorId; -} - -std::string Renderer9::getRendererDescription() const -{ - std::ostringstream rendererString; - - rendererString << mAdapterIdentifier.Description; - if (getShareHandleSupport()) - { - rendererString << " Direct3D9Ex"; - } - else - { - rendererString << " Direct3D9"; - } - - rendererString << " vs_" << D3DSHADER_VERSION_MAJOR(mDeviceCaps.VertexShaderVersion) << "_" << D3DSHADER_VERSION_MINOR(mDeviceCaps.VertexShaderVersion); - rendererString << " ps_" << D3DSHADER_VERSION_MAJOR(mDeviceCaps.PixelShaderVersion) << "_" << D3DSHADER_VERSION_MINOR(mDeviceCaps.PixelShaderVersion); - - return rendererString.str(); -} - -GUID Renderer9::getAdapterIdentifier() const -{ - return mAdapterIdentifier.DeviceIdentifier; -} - -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::getReservedVertexUniformBuffers() const -{ - return 0; -} - -unsigned int Renderer9::getReservedFragmentUniformBuffers() const -{ - return 0; -} - -bool Renderer9::getShareHandleSupport() const -{ - // PIX doesn't seem to support using share handles, so disable them. - return (mD3d9Ex != NULL) && !gl::perfActive(); -} - -bool Renderer9::getPostSubBufferSupport() const -{ - return true; -} - -int Renderer9::getMajorShaderModel() const -{ - return D3DSHADER_VERSION_MAJOR(mDeviceCaps.PixelShaderVersion); -} - -DWORD Renderer9::getCapsDeclTypes() const -{ - return mDeviceCaps.DeclTypes; -} - -int Renderer9::getMinSwapInterval() const -{ - return mMinSwapInterval; -} - -int Renderer9::getMaxSwapInterval() const -{ - return mMaxSwapInterval; -} - -D3DPOOL Renderer9::getBufferPool(DWORD usage) const -{ - if (mD3d9Ex != NULL) - { - return D3DPOOL_DEFAULT; - } - else - { - if (!(usage & D3DUSAGE_DYNAMIC)) - { - return D3DPOOL_MANAGED; - } - } - - return D3DPOOL_DEFAULT; -} - -gl::Error Renderer9::copyImage2D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, TextureStorage *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->copy2D(framebuffer, rect, destFormat, xoffset, yoffset, storage, level); -} - -gl::Error Renderer9::copyImageCube(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, TextureStorage *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->copyCube(framebuffer, rect, destFormat, xoffset, yoffset, storage, target, level); -} - -gl::Error Renderer9::copyImage3D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level) -{ - // 3D textures are not available in the D3D9 backend. - UNREACHABLE(); - return gl::Error(GL_INVALID_OPERATION); -} - -gl::Error Renderer9::copyImage2DArray(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level) -{ - // 2D array textures are not available in the D3D9 backend. - UNREACHABLE(); - return gl::Error(GL_INVALID_OPERATION); -} - -gl::Error Renderer9::blitRect(const gl::Framebuffer *readFramebuffer, const gl::Rectangle &readRect, - const gl::Framebuffer *drawFramebuffer, const gl::Rectangle &drawRect, - const gl::Rectangle *scissor, bool blitRenderTarget, - bool blitDepth, bool blitStencil, GLenum filter) -{ - ASSERT(filter == GL_NEAREST); - - endScene(); - - if (blitRenderTarget) - { - gl::FramebufferAttachment *readBuffer = readFramebuffer->getColorbuffer(0); - ASSERT(readBuffer); - - RenderTarget9 *readRenderTarget = NULL; - gl::Error error = d3d9::GetAttachmentRenderTarget(readBuffer, &readRenderTarget); - if (error.isError()) - { - return error; - } - ASSERT(readRenderTarget); - - gl::FramebufferAttachment *drawBuffer = drawFramebuffer->getColorbuffer(0); - ASSERT(drawBuffer); - - RenderTarget9 *drawRenderTarget = NULL; - error = d3d9::GetAttachmentRenderTarget(drawBuffer, &drawRenderTarget); - if (error.isError()) - { - return error; - } - ASSERT(drawRenderTarget); - - // The getSurface calls do an AddRef so save them until after no errors are possible - IDirect3DSurface9* readSurface = readRenderTarget->getSurface(); - ASSERT(readSurface); - - IDirect3DSurface9* drawSurface = drawRenderTarget->getSurface(); - ASSERT(drawSurface); - - gl::Extents srcSize(readRenderTarget->getWidth(), readRenderTarget->getHeight(), 1); - gl::Extents dstSize(drawRenderTarget->getWidth(), drawRenderTarget->getHeight(), 1); - - 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; - - // Clip the rectangles to the scissor rectangle - if (scissor) - { - if (dstRect.left < scissor->x) - { - srcRect.left += (scissor->x - dstRect.left); - dstRect.left = scissor->x; - } - if (dstRect.top < scissor->y) - { - srcRect.top += (scissor->y - dstRect.top); - dstRect.top = scissor->y; - } - if (dstRect.right > scissor->x + scissor->width) - { - srcRect.right -= (dstRect.right - (scissor->x + scissor->width)); - dstRect.right = scissor->x + scissor->width; - } - if (dstRect.bottom > scissor->y + scissor->height) - { - srcRect.bottom -= (dstRect.bottom - (scissor->y + scissor->height)); - dstRect.bottom = scissor->y + scissor->height; - } - } - - // Clip the rectangles to the destination size - if (dstRect.left < 0) - { - srcRect.left += -dstRect.left; - dstRect.left = 0; - } - if (dstRect.right > dstSize.width) - { - srcRect.right -= (dstRect.right - dstSize.width); - dstRect.right = dstSize.width; - } - if (dstRect.top < 0) - { - srcRect.top += -dstRect.top; - dstRect.top = 0; - } - if (dstRect.bottom > dstSize.height) - { - srcRect.bottom -= (dstRect.bottom - dstSize.height); - dstRect.bottom = dstSize.height; - } - - // Clip the rectangles to the source size - if (srcRect.left < 0) - { - dstRect.left += -srcRect.left; - srcRect.left = 0; - } - if (srcRect.right > srcSize.width) - { - dstRect.right -= (srcRect.right - srcSize.width); - srcRect.right = srcSize.width; - } - if (srcRect.top < 0) - { - dstRect.top += -srcRect.top; - srcRect.top = 0; - } - if (srcRect.bottom > srcSize.height) - { - dstRect.bottom -= (srcRect.bottom - srcSize.height); - srcRect.bottom = srcSize.height; - } - - HRESULT result = mDevice->StretchRect(readSurface, &srcRect, drawSurface, &dstRect, D3DTEXF_NONE); - - SafeRelease(readSurface); - SafeRelease(drawSurface); - - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Internal blit failed, StretchRect returned 0x%X.", result); - } - } - - if (blitDepth || blitStencil) - { - gl::FramebufferAttachment *readBuffer = readFramebuffer->getDepthOrStencilbuffer(); - ASSERT(readBuffer); - - RenderTarget9 *readDepthStencil = NULL; - gl::Error error = d3d9::GetAttachmentRenderTarget(readBuffer, &readDepthStencil); - if (error.isError()) - { - return error; - } - ASSERT(readDepthStencil); - - gl::FramebufferAttachment *drawBuffer = drawFramebuffer->getDepthOrStencilbuffer(); - ASSERT(drawBuffer); - - RenderTarget9 *drawDepthStencil = NULL; - error = d3d9::GetAttachmentRenderTarget(drawBuffer, &drawDepthStencil); - if (error.isError()) - { - return error; - } - ASSERT(drawDepthStencil); - - // The getSurface calls do an AddRef so save them until after no errors are possible - IDirect3DSurface9* readSurface = readDepthStencil->getSurface(); - ASSERT(readDepthStencil); - - IDirect3DSurface9* drawSurface = drawDepthStencil->getSurface(); - ASSERT(drawDepthStencil); - - HRESULT result = mDevice->StretchRect(readSurface, NULL, drawSurface, NULL, D3DTEXF_NONE); - - SafeRelease(readSurface); - SafeRelease(drawSurface); - - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Internal blit failed, StretchRect returned 0x%X.", result); - } - } - - return gl::Error(GL_NO_ERROR); -} - -gl::Error Renderer9::readPixels(const gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, - GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, uint8_t *pixels) -{ - ASSERT(pack.pixelBuffer.get() == NULL); - - gl::FramebufferAttachment *colorbuffer = framebuffer->getColorbuffer(0); - ASSERT(colorbuffer); - - RenderTarget9 *renderTarget = NULL; - gl::Error error = d3d9::GetAttachmentRenderTarget(colorbuffer, &renderTarget); - if (error.isError()) - { - return error; - } - ASSERT(renderTarget); - - IDirect3DSurface9 *surface = renderTarget->getSurface(); - ASSERT(surface); - - D3DSURFACE_DESC desc; - surface->GetDesc(&desc); - - if (desc.MultiSampleType != D3DMULTISAMPLE_NONE) - { - UNIMPLEMENTED(); // FIXME: Requires resolve using StretchRect into non-multisampled render target - SafeRelease(surface); - return gl::Error(GL_OUT_OF_MEMORY, "ReadPixels is unimplemented for multisampled framebuffer attachments."); - } - - HRESULT result; - IDirect3DSurface9 *systemSurface = NULL; - bool directToPixels = !pack.reverseRowOrder && pack.alignment <= 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, reinterpret_cast(&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); - SafeRelease(surface); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal texture for ReadPixels."); - } - } - - result = mDevice->GetRenderTargetData(surface, systemSurface); - SafeRelease(surface); - - if (FAILED(result)) - { - SafeRelease(systemSurface); - - // It turns out that D3D will sometimes produce more error - // codes than those documented. - if (d3d9::isDeviceLostError(result)) - { - notifyDeviceLost(); - } - else - { - UNREACHABLE(); - } - - return gl::Error(GL_OUT_OF_MEMORY, "Failed to read internal render target data."); - } - - if (directToPixels) - { - SafeRelease(systemSurface); - return gl::Error(GL_NO_ERROR); - } - - 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(); - SafeRelease(systemSurface); - - return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock internal render target."); - } - - uint8_t *source; - int inputPitch; - if (pack.reverseRowOrder) - { - source = reinterpret_cast(lock.pBits) + lock.Pitch * (rect.bottom - rect.top - 1); - inputPitch = -lock.Pitch; - } - else - { - source = reinterpret_cast(lock.pBits); - inputPitch = lock.Pitch; - } - - const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(desc.Format); - const gl::InternalFormat &sourceFormatInfo = gl::GetInternalFormatInfo(d3dFormatInfo.internalFormat); - if (sourceFormatInfo.format == format && sourceFormatInfo.type == type) - { - // Direct copy possible - for (int y = 0; y < rect.bottom - rect.top; y++) - { - memcpy(pixels + y * outputPitch, source + y * inputPitch, (rect.right - rect.left) * sourceFormatInfo.pixelBytes); - } - } - else - { - const d3d9::D3DFormat &sourceD3DFormatInfo = d3d9::GetD3DFormatInfo(desc.Format); - ColorCopyFunction fastCopyFunc = sourceD3DFormatInfo.getFastCopyFunction(format, type); - - const gl::FormatType &destFormatTypeInfo = gl::GetFormatTypeInfo(format, type); - const gl::InternalFormat &destFormatInfo = gl::GetInternalFormatInfo(destFormatTypeInfo.internalFormat); - - if (fastCopyFunc) - { - // Fast copy is possible through some special function - for (int y = 0; y < rect.bottom - rect.top; y++) - { - for (int x = 0; x < rect.right - rect.left; x++) - { - uint8_t *dest = pixels + y * outputPitch + x * destFormatInfo.pixelBytes; - const uint8_t *src = source + y * inputPitch + x * sourceFormatInfo.pixelBytes; - - fastCopyFunc(src, dest); - } - } - } - else - { - uint8_t temp[sizeof(gl::ColorF)]; - for (int y = 0; y < rect.bottom - rect.top; y++) - { - for (int x = 0; x < rect.right - rect.left; x++) - { - uint8_t *dest = pixels + y * outputPitch + x * destFormatInfo.pixelBytes; - const uint8_t *src = source + y * inputPitch + x * sourceFormatInfo.pixelBytes; - - // readFunc and writeFunc will be using the same type of color, CopyTexImage - // will not allow the copy otherwise. - sourceD3DFormatInfo.colorReadFunction(src, temp); - destFormatTypeInfo.colorWriteFunction(temp, dest); - } - } - } - } - - systemSurface->UnlockRect(); - SafeRelease(systemSurface); - - return gl::Error(GL_NO_ERROR); -} - -gl::Error Renderer9::createRenderTarget(SwapChain *swapChain, bool depth, RenderTarget **outRT) -{ - SwapChain9 *swapChain9 = SwapChain9::makeSwapChain9(swapChain); - *outRT = new SurfaceRenderTarget9(swapChain9, depth); - return gl::Error(GL_NO_ERROR); -} - -gl::Error Renderer9::createRenderTarget(int width, int height, GLenum format, GLsizei samples, RenderTarget **outRT) -{ - const d3d9::TextureFormat &d3d9FormatInfo = d3d9::GetTextureFormatInfo(format); - - const gl::TextureCaps &textureCaps = getRendererTextureCaps().get(format); - GLuint supportedSamples = textureCaps.getNearestSamples(samples); - - IDirect3DSurface9 *renderTarget = NULL; - if (width > 0 && height > 0) - { - bool requiresInitialization = false; - HRESULT result = D3DERR_INVALIDCALL; - - const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format); - if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0) - { - result = mDevice->CreateDepthStencilSurface(width, height, d3d9FormatInfo.renderFormat, - gl_d3d9::GetMultisampleType(supportedSamples), - 0, FALSE, &renderTarget, NULL); - } - else - { - requiresInitialization = (d3d9FormatInfo.dataInitializerFunction != NULL); - result = mDevice->CreateRenderTarget(width, height, d3d9FormatInfo.renderFormat, - gl_d3d9::GetMultisampleType(supportedSamples), - 0, FALSE, &renderTarget, NULL); - } - - if (FAILED(result)) - { - ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create render target, result: 0x%X.", result); - } - - if (requiresInitialization) - { - // This format requires that the data be initialized before the render target can be used - // Unfortunately this requires a Get call on the d3d device but it is far better than having - // to mark the render target as lockable and copy data to the gpu. - IDirect3DSurface9 *prevRenderTarget = NULL; - mDevice->GetRenderTarget(0, &prevRenderTarget); - mDevice->SetRenderTarget(0, renderTarget); - mDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_RGBA(0, 0, 0, 255), 0.0f, 0); - mDevice->SetRenderTarget(0, prevRenderTarget); - } - } - - *outRT = new TextureRenderTarget9(renderTarget, format, width, height, 1, supportedSamples); - return gl::Error(GL_NO_ERROR); -} - -ShaderImpl *Renderer9::createShader(const gl::Data &data, GLenum type) -{ - return new ShaderD3D(data, type, this); -} - -ProgramImpl *Renderer9::createProgram() -{ - return new ProgramD3D(this); -} - -void Renderer9::releaseShaderCompiler() -{ - ShaderD3D::releaseCompiler(); -} - -gl::Error Renderer9::loadExecutable(const void *function, size_t length, ShaderType type, - const std::vector &transformFeedbackVaryings, - bool separatedOutputBuffers, ShaderExecutable **outExecutable) -{ - // Transform feedback is not supported in ES2 or D3D9 - ASSERT(transformFeedbackVaryings.size() == 0); - - switch (type) - { - case SHADER_VERTEX: - { - IDirect3DVertexShader9 *vshader = NULL; - gl::Error error = createVertexShader((DWORD*)function, length, &vshader); - if (error.isError()) - { - return error; - } - *outExecutable = new ShaderExecutable9(function, length, vshader); - } - break; - case SHADER_PIXEL: - { - IDirect3DPixelShader9 *pshader = NULL; - gl::Error error = createPixelShader((DWORD*)function, length, &pshader); - if (error.isError()) - { - return error; - } - *outExecutable = new ShaderExecutable9(function, length, pshader); - } - break; - default: - UNREACHABLE(); - return gl::Error(GL_INVALID_OPERATION); - } - - return gl::Error(GL_NO_ERROR); -} - -gl::Error Renderer9::compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, ShaderType type, - const std::vector &transformFeedbackVaryings, - bool separatedOutputBuffers, D3DWorkaroundType workaround, - ShaderExecutable **outExectuable) -{ - // Transform feedback is not supported in ES2 or D3D9 - ASSERT(transformFeedbackVaryings.size() == 0); - - const char *profileType = NULL; - switch (type) - { - case SHADER_VERTEX: - profileType = "vs"; - break; - case SHADER_PIXEL: - profileType = "ps"; - break; - default: - UNREACHABLE(); - return gl::Error(GL_INVALID_OPERATION); - } - unsigned int profileMajorVersion = (getMajorShaderModel() >= 3) ? 3 : 2; - unsigned int profileMinorVersion = 0; - std::string profile = FormatString("%s_%u_%u", profileType, profileMajorVersion, profileMinorVersion); - - UINT flags = ANGLE_COMPILE_OPTIMIZATION_LEVEL; - - if (workaround == ANGLE_D3D_WORKAROUND_SKIP_OPTIMIZATION) - { - flags = D3DCOMPILE_SKIP_OPTIMIZATION; - } - else if (workaround == ANGLE_D3D_WORKAROUND_MAX_OPTIMIZATION) - { - flags = D3DCOMPILE_OPTIMIZATION_LEVEL3; - } - else ASSERT(workaround == ANGLE_D3D_WORKAROUND_NONE); - - if (gl::perfActive()) - { -#ifndef NDEBUG - flags = D3DCOMPILE_SKIP_OPTIMIZATION; -#endif - - flags |= D3DCOMPILE_DEBUG; - } - - // 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. - std::vector configs; - configs.push_back(CompileConfig(flags, "default" )); - configs.push_back(CompileConfig(flags | D3DCOMPILE_AVOID_FLOW_CONTROL, "avoid flow control" )); - configs.push_back(CompileConfig(flags | D3DCOMPILE_PREFER_FLOW_CONTROL, "prefer flow control")); - - ID3DBlob *binary = NULL; - std::string debugInfo; - gl::Error error = mCompiler.compileToBinary(infoLog, shaderHLSL, profile, configs, NULL, &binary, &debugInfo); - if (error.isError()) - { - return error; - } - - // It's possible that binary is NULL if the compiler failed in all configurations. Set the executable to NULL - // and return GL_NO_ERROR to signify that there was a link error but the internal state is still OK. - if (!binary) - { - *outExectuable = NULL; - return gl::Error(GL_NO_ERROR); - } - - error = loadExecutable(binary->GetBufferPointer(), binary->GetBufferSize(), type, - transformFeedbackVaryings, separatedOutputBuffers, outExectuable); - - SafeRelease(binary); - if (error.isError()) - { - return error; - } - - if (!debugInfo.empty()) - { - (*outExectuable)->appendDebugInfo(debugInfo); - } - - return gl::Error(GL_NO_ERROR); -} - -UniformStorage *Renderer9::createUniformStorage(size_t storageSize) -{ - return new UniformStorage(storageSize); -} - -gl::Error 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; -} - -gl::Error Renderer9::copyToRenderTarget(IDirect3DSurface9 *dest, IDirect3DSurface9 *source, bool fromManaged) -{ - ASSERT(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); - SafeRelease(surf); - } - } - else - { - endScene(); - result = mDevice->StretchRect(source, NULL, dest, NULL, D3DTEXF_NONE); - } - - if (FAILED(result)) - { - ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to blit internal texture, result: 0x%X.", result); - } - - return gl::Error(GL_NO_ERROR); -} - -Image *Renderer9::createImage() -{ - return new Image9(); -} - -gl::Error Renderer9::generateMipmap(Image *dest, Image *src) -{ - Image9 *src9 = Image9::makeImage9(src); - Image9 *dst9 = Image9::makeImage9(dest); - return Image9::generateMipmap(dst9, src9); -} - -TextureStorage *Renderer9::createTextureStorage2D(SwapChain *swapChain) -{ - SwapChain9 *swapChain9 = SwapChain9::makeSwapChain9(swapChain); - return new TextureStorage9_2D(this, swapChain9); -} - -TextureStorage *Renderer9::createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels) -{ - return new TextureStorage9_2D(this, internalformat, renderTarget, width, height, levels); -} - -TextureStorage *Renderer9::createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels) -{ - return new TextureStorage9_Cube(this, internalformat, renderTarget, size, levels); -} - -TextureStorage *Renderer9::createTextureStorage3D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) -{ - // 3D textures are not supported by the D3D9 backend. - UNREACHABLE(); - - return NULL; -} - -TextureStorage *Renderer9::createTextureStorage2DArray(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) -{ - // 2D array textures are not supported by the D3D9 backend. - UNREACHABLE(); - - return NULL; -} - -TextureImpl *Renderer9::createTexture(GLenum target) -{ - switch(target) - { - case GL_TEXTURE_2D: return new TextureD3D_2D(this); - case GL_TEXTURE_CUBE_MAP: return new TextureD3D_Cube(this); - default: UNREACHABLE(); - } - - return NULL; -} - -RenderbufferImpl *Renderer9::createRenderbuffer() -{ - RenderbufferD3D *renderbuffer = new RenderbufferD3D(this); - return renderbuffer; -} - -RenderbufferImpl *Renderer9::createRenderbuffer(SwapChain *swapChain, bool depth) -{ - RenderbufferD3D *renderbuffer = new RenderbufferD3D(this); - renderbuffer->setStorage(swapChain, depth); - return renderbuffer; -} - -bool Renderer9::getLUID(LUID *adapterLuid) const -{ - adapterLuid->HighPart = 0; - adapterLuid->LowPart = 0; - - if (mD3d9Ex) - { - mD3d9Ex->GetAdapterLUID(mAdapter, adapterLuid); - return true; - } - - return false; -} - -VertexConversionType Renderer9::getVertexConversionType(const gl::VertexFormat &vertexFormat) const -{ - return d3d9::GetVertexFormatInfo(getCapsDeclTypes(), vertexFormat).conversionType; -} - -GLenum Renderer9::getVertexComponentType(const gl::VertexFormat &vertexFormat) const -{ - return d3d9::GetVertexFormatInfo(getCapsDeclTypes(), vertexFormat).componentType; -} - -void Renderer9::generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureCaps, gl::Extensions *outExtensions) const -{ - d3d9_gl::GenerateCaps(mD3d9, mDevice, mDeviceType, mAdapter, outCaps, outTextureCaps, outExtensions); -} - -Workarounds Renderer9::generateWorkarounds() const -{ - return d3d9::GenerateWorkarounds(); -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.h deleted file mode 100644 index 10d2fb11e8..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.h +++ /dev/null @@ -1,352 +0,0 @@ -// -// Copyright (c) 2012-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// 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 "common/mathutil.h" -#include "libGLESv2/renderer/d3d/d3d9/ShaderCache.h" -#include "libGLESv2/renderer/d3d/d3d9/VertexDeclarationCache.h" -#include "libGLESv2/renderer/d3d/HLSLCompiler.h" -#include "libGLESv2/renderer/d3d/RendererD3D.h" -#include "libGLESv2/renderer/RenderTarget.h" - -namespace gl -{ -class FramebufferAttachment; -} - -namespace egl -{ -class AttributeMap; -} - -namespace rx -{ -class VertexDataManager; -class IndexDataManager; -class StreamingIndexBufferInterface; -class StaticIndexBufferInterface; -struct TranslatedAttribute; -class Blit9; - -class Renderer9 : public RendererD3D -{ - public: - Renderer9(egl::Display *display, EGLNativeDisplayType hDc, const egl::AttributeMap &attributes); - 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 gl::Error sync(bool block); - - virtual SwapChain *createSwapChain(NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat); - - gl::Error allocateEventQuery(IDirect3DQuery9 **outQuery); - void freeEventQuery(IDirect3DQuery9* query); - - // resource creation - gl::Error createVertexShader(const DWORD *function, size_t length, IDirect3DVertexShader9 **outShader); - gl::Error createPixelShader(const DWORD *function, size_t length, IDirect3DPixelShader9 **outShader); - HRESULT createVertexBuffer(UINT Length, DWORD Usage, IDirect3DVertexBuffer9 **ppVertexBuffer); - HRESULT createIndexBuffer(UINT Length, DWORD Usage, D3DFORMAT Format, IDirect3DIndexBuffer9 **ppIndexBuffer); - virtual gl::Error generateSwizzle(gl::Texture *texture); - virtual gl::Error setSamplerState(gl::SamplerType type, int index, gl::Texture *texture, const gl::SamplerState &sampler); - virtual gl::Error setTexture(gl::SamplerType type, int index, gl::Texture *texture); - - virtual gl::Error setUniformBuffers(const gl::Buffer *vertexUniformBuffers[], const gl::Buffer *fragmentUniformBuffers[]); - - virtual gl::Error setRasterizerState(const gl::RasterizerState &rasterState); - gl::Error setBlendState(const gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::ColorF &blendColor, - unsigned int sampleMask) override; - virtual gl::Error setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef, - int stencilBackRef, bool frontFaceCCW); - - virtual void setScissorRectangle(const gl::Rectangle &scissor, bool enabled); - virtual void setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace, - bool ignoreViewport); - - gl::Error applyRenderTarget(const gl::Framebuffer *frameBuffer) override; - virtual gl::Error applyShaders(gl::ProgramBinary *programBinary, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer, - bool rasterizerDiscard, bool transformFeedbackActive); - virtual gl::Error applyUniforms(const ProgramImpl &program, const std::vector &uniformArray); - virtual bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount); - virtual gl::Error applyVertexBuffer(const gl::State &state, GLint first, GLsizei count, GLsizei instances); - virtual gl::Error applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo); - - virtual void applyTransformFeedbackBuffers(const gl::State& state); - - virtual gl::Error drawArrays(GLenum mode, GLsizei count, GLsizei instances, bool transformFeedbackActive); - virtual gl::Error drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, - gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances); - - gl::Error clear(const gl::ClearParameters &clearParams, const gl::Framebuffer *frameBuffer) override; - - virtual void markAllStateDirty(); - - // lost device - void notifyDeviceLost() override; - bool isDeviceLost() override; - bool testDeviceLost(bool notify) override; - bool testDeviceResettable() override; - - DWORD getAdapterVendor() const override; - std::string getRendererDescription() const override; - GUID getAdapterIdentifier() const override; - - IDirect3DDevice9 *getDevice() { return mDevice; } - - virtual unsigned int getReservedVertexUniformVectors() const; - virtual unsigned int getReservedFragmentUniformVectors() const; - virtual unsigned int getReservedVertexUniformBuffers() const; - virtual unsigned int getReservedFragmentUniformBuffers() const; - virtual bool getShareHandleSupport() const; - virtual bool getPostSubBufferSupport() const; - - virtual int getMajorShaderModel() const; - DWORD getCapsDeclTypes() const; - virtual int getMinSwapInterval() const; - virtual int getMaxSwapInterval() const; - - // Pixel operations - virtual gl::Error copyImage2D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, TextureStorage *storage, GLint level); - virtual gl::Error copyImageCube(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, TextureStorage *storage, GLenum target, GLint level); - virtual gl::Error copyImage3D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level); - virtual gl::Error copyImage2DArray(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level); - - gl::Error blitRect(const gl::Framebuffer *readTarget, const gl::Rectangle &readRect, - const gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect, - const gl::Rectangle *scissor, bool blitRenderTarget, - bool blitDepth, bool blitStencil, GLenum filter) override; - - virtual gl::Error readPixels(const gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, - GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, uint8_t *pixels); - - // RenderTarget creation - virtual gl::Error createRenderTarget(SwapChain *swapChain, bool depth, RenderTarget **outRT); - virtual gl::Error createRenderTarget(int width, int height, GLenum format, GLsizei samples, RenderTarget **outRT); - - // Shader creation - virtual ShaderImpl *createShader(const gl::Data &data, GLenum type); - virtual ProgramImpl *createProgram(); - - // Shader operations - void releaseShaderCompiler() override; - virtual gl::Error loadExecutable(const void *function, size_t length, ShaderType type, - const std::vector &transformFeedbackVaryings, - bool separatedOutputBuffers, ShaderExecutable **outExecutable); - virtual gl::Error compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, ShaderType type, - const std::vector &transformFeedbackVaryings, - bool separatedOutputBuffers, D3DWorkaroundType workaround, - ShaderExecutable **outExectuable); - virtual UniformStorage *createUniformStorage(size_t storageSize); - - // Image operations - virtual Image *createImage(); - gl::Error generateMipmap(Image *dest, Image *source) override; - virtual TextureStorage *createTextureStorage2D(SwapChain *swapChain); - virtual TextureStorage *createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels); - virtual TextureStorage *createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels); - virtual TextureStorage *createTextureStorage3D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels); - virtual TextureStorage *createTextureStorage2DArray(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels); - - // Texture creation - virtual TextureImpl *createTexture(GLenum target); - - // Renderbuffer creation - virtual RenderbufferImpl *createRenderbuffer(); - virtual RenderbufferImpl *createRenderbuffer(SwapChain *swapChain, bool depth); - - // Buffer creation - virtual BufferImpl *createBuffer(); - virtual VertexBuffer *createVertexBuffer(); - virtual IndexBuffer *createIndexBuffer(); - - // Vertex Array creation - virtual VertexArrayImpl *createVertexArray(); - - // Query and Fence creation - virtual QueryImpl *createQuery(GLenum type); - virtual FenceNVImpl *createFenceNV(); - virtual FenceSyncImpl *createFenceSync(); - - // Transform Feedback creation - virtual TransformFeedbackImpl* createTransformFeedback(); - - // Buffer-to-texture and Texture-to-buffer copies - virtual bool supportsFastCopyBufferToTexture(GLenum internalFormat) const; - virtual gl::Error fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget, - GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea); - - // D3D9-renderer specific methods - gl::Error boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest); - - D3DPOOL getTexturePool(DWORD usage) const; - - virtual bool getLUID(LUID *adapterLuid) const; - virtual VertexConversionType getVertexConversionType(const gl::VertexFormat &vertexFormat) const; - virtual GLenum getVertexComponentType(const gl::VertexFormat &vertexFormat) const; - - gl::Error copyToRenderTarget(IDirect3DSurface9 *dest, IDirect3DSurface9 *source, bool fromManaged); - - private: - DISALLOW_COPY_AND_ASSIGN(Renderer9); - - void generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureCaps, gl::Extensions *outExtensions) const override; - Workarounds generateWorkarounds() const override; - - void release(); - - void applyUniformnfv(gl::LinkedUniform *targetUniform, const GLfloat *v); - void applyUniformniv(gl::LinkedUniform *targetUniform, const GLint *v); - void applyUniformnbv(gl::LinkedUniform *targetUniform, const GLint *v); - - gl::Error drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer); - gl::Error drawIndexedPoints(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer); - - gl::Error getCountingIB(size_t count, StaticIndexBufferInterface **outIB); - - gl::Error getNullColorbuffer(gl::FramebufferAttachment *depthbuffer, gl::FramebufferAttachment **outColorBuffer); - - D3DPOOL getBufferPool(DWORD usage) const; - - HMODULE mD3d9Module; - HDC mDc; - - void initializeDevice(); - D3DPRESENT_PARAMETERS getDefaultPresentParameters(); - void releaseDeviceResources(); - - HRESULT getDeviceStatusCode(); - bool isRemovedDeviceResettable() const; - bool resetRemovedDevice(); - - UINT mAdapter; - D3DDEVTYPE mDeviceType; - 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. - - HLSLCompiler mCompiler; - - Blit9 *mBlit; - - HWND mDeviceWindow; - - bool mDeviceLost; - D3DCAPS9 mDeviceCaps; - D3DADAPTER_IDENTIFIER9 mAdapterIdentifier; - - D3DPRIMITIVETYPE mPrimitiveType; - int mPrimitiveCount; - GLsizei mRepeatDraw; - - bool mSceneStarted; - int mMinSwapInterval; - int mMaxSwapInterval; - - bool mVertexTextureSupport; - - // current render target states - unsigned int mAppliedRenderTargetSerial; - unsigned int mAppliedDepthbufferSerial; - unsigned int mAppliedStencilbufferSerial; - bool mDepthStencilInitialized; - bool mRenderTargetDescInitialized; - RenderTarget::Desc mRenderTargetDesc; - unsigned int mCurStencilSize; - unsigned int mCurDepthSize; - - IDirect3DStateBlock9 *mMaskedClearSavedState; - - // previously set render states - bool mForceSetDepthStencilState; - gl::DepthStencilState mCurDepthStencilState; - int mCurStencilRef; - int mCurStencilBackRef; - bool mCurFrontFaceCCW; - - bool mForceSetRasterState; - gl::RasterizerState mCurRasterState; - - bool mForceSetScissor; - gl::Rectangle mCurScissor; - bool mScissorEnabled; - - bool mForceSetViewport; - gl::Rectangle mCurViewport; - float mCurNear; - float mCurFar; - float mCurDepthFront; - - bool mForceSetBlendState; - gl::BlendState mCurBlendState; - gl::ColorF mCurBlendColor; - GLuint mCurSampleMask; - - // Currently applied sampler states - std::vector mForceSetVertexSamplerStates; - std::vector mCurVertexSamplerStates; - - std::vector mForceSetPixelSamplerStates; - std::vector mCurPixelSamplerStates; - - // Currently applied textures - std::vector mCurVertexTextureSerials; - std::vector mCurPixelTextureSerials; - - unsigned int mAppliedIBSerial; - IDirect3DVertexShader9 *mAppliedVertexShader; - IDirect3DPixelShader9 *mAppliedPixelShader; - unsigned int mAppliedProgramSerial; - - dx_VertexConstants mVertexConstants; - 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; - StaticIndexBufferInterface *mCountingIB; - - enum { NUM_NULL_COLORBUFFER_CACHE_ENTRIES = 12 }; - struct NullColorbufferCacheEntry - { - UINT lruCount; - int width; - int height; - gl::FramebufferAttachment *buffer; - } mNullColorbufferCache[NUM_NULL_COLORBUFFER_CACHE_ENTRIES]; - UINT mMaxNullColorbufferLRU; - -}; - -} -#endif // LIBGLESV2_RENDERER_RENDERER9_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderCache.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderCache.h deleted file mode 100644 index 6d7d2d648f..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderCache.h +++ /dev/null @@ -1,110 +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. -// - -// 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 "libGLESv2/Error.h" - -#include "common/debug.h" - -#include -#include -#include - -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; - } - - gl::Error create(const DWORD *function, size_t length, ShaderObject **outShaderObject) - { - std::string key(reinterpret_cast(function), length); - typename Map::iterator it = mMap.find(key); - if (it != mMap.end()) - { - it->second->AddRef(); - *outShaderObject = it->second; - return gl::Error(GL_NO_ERROR); - } - - ShaderObject *shader; - HRESULT result = createShader(function, &shader); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create shader, result: 0x%X.", result); - } - - // Random eviction policy. - if (mMap.size() >= kMaxMapSize) - { - SafeRelease(mMap.begin()->second); - mMap.erase(mMap.begin()); - } - - shader->AddRef(); - mMap[key] = shader; - - *outShaderObject = shader; - return gl::Error(GL_NO_ERROR); - } - - void clear() - { - for (typename Map::iterator it = mMap.begin(); it != mMap.end(); ++it) - { - SafeRelease(it->second); - } - - 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); - } - - typedef std::unordered_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/d3d/d3d9/ShaderExecutable9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderExecutable9.cpp deleted file mode 100644 index bc7120461b..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderExecutable9.cpp +++ /dev/null @@ -1,53 +0,0 @@ -// -// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// ShaderExecutable9.cpp: Implements a D3D9-specific class to contain shader -// executable implementation details. - -#include "libGLESv2/renderer/d3d/d3d9/ShaderExecutable9.h" - -#include "common/debug.h" - -namespace rx -{ - -ShaderExecutable9::ShaderExecutable9(const void *function, size_t length, IDirect3DPixelShader9 *executable) - : ShaderExecutable(function, length) -{ - mPixelExecutable = executable; - mVertexExecutable = NULL; -} - -ShaderExecutable9::ShaderExecutable9(const void *function, size_t length, IDirect3DVertexShader9 *executable) - : ShaderExecutable(function, length) -{ - mVertexExecutable = executable; - mPixelExecutable = NULL; -} - -ShaderExecutable9::~ShaderExecutable9() -{ - SafeRelease(mVertexExecutable); - SafeRelease(mPixelExecutable); -} - -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/d3d/d3d9/ShaderExecutable9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderExecutable9.h deleted file mode 100644 index fa1e6c2844..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderExecutable9.h +++ /dev/null @@ -1,39 +0,0 @@ -// -// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// ShaderExecutable9.h: Defines a D3D9-specific class to contain shader -// executable implementation details. - -#ifndef LIBGLESV2_RENDERER_SHADEREXECUTABLE9_H_ -#define LIBGLESV2_RENDERER_SHADEREXECUTABLE9_H_ - -#include "libGLESv2/renderer/ShaderExecutable.h" - -namespace rx -{ - -class ShaderExecutable9 : public ShaderExecutable -{ - public: - ShaderExecutable9(const void *function, size_t length, IDirect3DPixelShader9 *executable); - ShaderExecutable9(const void *function, size_t length, IDirect3DVertexShader9 *executable); - virtual ~ShaderExecutable9(); - - static ShaderExecutable9 *makeShaderExecutable9(ShaderExecutable *executable); - - IDirect3DPixelShader9 *getPixelShader() const; - IDirect3DVertexShader9 *getVertexShader() const; - - private: - DISALLOW_COPY_AND_ASSIGN(ShaderExecutable9); - - IDirect3DPixelShader9 *mPixelExecutable; - IDirect3DVertexShader9 *mVertexExecutable; -}; - -} - -#endif // LIBGLESV2_RENDERER_SHADEREXECUTABLE9_H_ \ No newline at end of file diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.cpp deleted file mode 100644 index 95eb1a4371..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.cpp +++ /dev/null @@ -1,422 +0,0 @@ -// -// Copyright (c) 2012-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// SwapChain9.cpp: Implements a back-end specific class for the D3D9 swap chain. - -#include "libGLESv2/renderer/d3d/d3d9/SwapChain9.h" -#include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h" -#include "libGLESv2/renderer/d3d/d3d9/formatutils9.h" -#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" - -#include "common/features.h" - -namespace rx -{ - -SwapChain9::SwapChain9(Renderer9 *renderer, NativeWindow nativeWindow, HANDLE shareHandle, - GLenum backBufferFormat, GLenum depthBufferFormat) - : mRenderer(renderer), - SwapChain(nativeWindow, 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() -{ - SafeRelease(mSwapChain); - SafeRelease(mBackBuffer); - SafeRelease(mDepthStencil); - SafeRelease(mRenderTarget); - SafeRelease(mOffscreenTexture); - - if (mNativeWindow.getNativeWindow()) - { - mShareHandle = NULL; - } -} - -static DWORD convertInterval(EGLint interval) -{ -#if ANGLE_VSYNC == ANGLE_DISABLED - return D3DPRESENT_INTERVAL_IMMEDIATE; -#else - switch(interval) - { - case 0: return D3DPRESENT_INTERVAL_IMMEDIATE; - case 1: return D3DPRESENT_INTERVAL_ONE; - case 2: return D3DPRESENT_INTERVAL_TWO; - case 3: return D3DPRESENT_INTERVAL_THREE; - case 4: return D3DPRESENT_INTERVAL_FOUR; - default: UNREACHABLE(); - } - - return D3DPRESENT_INTERVAL_DEFAULT; -#endif -} - -EGLint SwapChain9::resize(int backbufferWidth, int backbufferHeight) -{ - // D3D9 does not support resizing swap chains without recreating them - return reset(backbufferWidth, backbufferHeight, mSwapInterval); -} - -EGLint SwapChain9::reset(int backbufferWidth, int backbufferHeight, EGLint swapInterval) -{ - IDirect3DDevice9 *device = mRenderer->getDevice(); - - if (device == NULL) - { - return EGL_BAD_ACCESS; - } - - // Evict all non-render target textures to system memory and release all resources - // before reallocating them to free up as much video memory as possible. - device->EvictManagedResources(); - - HRESULT result; - - // Release specific resources to free up memory for the new render target, while the - // old render target still exists for the purpose of preserving its contents. - SafeRelease(mSwapChain); - SafeRelease(mBackBuffer); - SafeRelease(mOffscreenTexture); - SafeRelease(mDepthStencil); - - HANDLE *pShareHandle = NULL; - if (!mNativeWindow.getNativeWindow() && mRenderer->getShareHandleSupport()) - { - pShareHandle = &mShareHandle; - } - - const d3d9::TextureFormat &backBufferd3dFormatInfo = d3d9::GetTextureFormatInfo(mBackBufferFormat); - result = device->CreateTexture(backbufferWidth, backbufferHeight, 1, D3DUSAGE_RENDERTARGET, - backBufferd3dFormatInfo.texFormat, 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)); - - SafeRelease(oldRenderTarget); - } - - const d3d9::TextureFormat &depthBufferd3dFormatInfo = d3d9::GetTextureFormatInfo(mDepthBufferFormat); - - EGLNativeWindowType window = mNativeWindow.getNativeWindow(); - if (window) - { - D3DPRESENT_PARAMETERS presentParameters = {0}; - presentParameters.AutoDepthStencilFormat = depthBufferd3dFormatInfo.renderFormat; - presentParameters.BackBufferCount = 1; - presentParameters.BackBufferFormat = backBufferd3dFormatInfo.renderFormat; - presentParameters.EnableAutoDepthStencil = FALSE; - presentParameters.Flags = 0; - presentParameters.hDeviceWindow = window; - 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(window, NULL, FALSE); - } - - if (mDepthBufferFormat != GL_NONE) - { - result = device->CreateDepthStencilSurface(backbufferWidth, backbufferHeight, - depthBufferd3dFormatInfo.renderFormat, - D3DMULTISAMPLE_NONE, 0, FALSE, &mDepthStencil, NULL); - - if (FAILED(result)) - { - ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_INVALIDCALL); - - ERR("Could not create depthstencil surface for new swap chain: 0x%08X", result); - release(); - - if (d3d9::isDeviceLostError(result)) - { - return EGL_CONTEXT_LOST; - } - else - { - return EGL_BAD_ALLOC; - } - } - } - - mWidth = backbufferWidth; - mHeight = backbufferHeight; - mSwapInterval = swapInterval; - - return EGL_SUCCESS; -} - -// parameters should be validated/clamped by caller -EGLint SwapChain9::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) -{ - if (!mSwapChain) - { - return EGL_SUCCESS; - } - - IDirect3DDevice9 *device = mRenderer->getDevice(); - - // Disable all pipeline operations - device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE); - device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); - device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); - device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); - device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); - device->SetRenderState(D3DRS_STENCILENABLE, FALSE); - device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0); - device->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA | D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_RED); - device->SetRenderState(D3DRS_SRGBWRITEENABLE, FALSE); - device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE); - device->SetPixelShader(NULL); - device->SetVertexShader(NULL); - - device->SetRenderTarget(0, mBackBuffer); - device->SetDepthStencilSurface(NULL); - - device->SetTexture(0, mOffscreenTexture); - device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); - device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); - device->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); - device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT); - device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT); - device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); - device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); - device->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1); - - for (UINT streamIndex = 0; streamIndex < gl::MAX_VERTEX_ATTRIBS; streamIndex++) - { - device->SetStreamSourceFreq(streamIndex, 1); - } - - D3DVIEWPORT9 viewport = {0, 0, mWidth, mHeight, 0.0f, 1.0f}; - device->SetViewport(&viewport); - - float x1 = x - 0.5f; - float y1 = (mHeight - y - height) - 0.5f; - float x2 = (x + width) - 0.5f; - float y2 = (mHeight - y) - 0.5f; - - float u1 = x / float(mWidth); - float v1 = y / float(mHeight); - float u2 = (x + width) / float(mWidth); - float v2 = (y + height) / float(mHeight); - - float quad[4][6] = {{x1, y1, 0.0f, 1.0f, u1, v2}, - {x2, y1, 0.0f, 1.0f, u2, v2}, - {x2, y2, 0.0f, 1.0f, u2, v1}, - {x1, y2, 0.0f, 1.0f, u1, v1}}; // x, y, z, rhw, u, v - - mRenderer->startScene(); - device->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, quad, 6 * sizeof(float)); - mRenderer->endScene(); - - device->SetTexture(0, NULL); - - RECT rect = - { - x, mHeight - y - height, - x + width, mHeight - y - }; - - HRESULT result = mSwapChain->Present(&rect, &rect, NULL, NULL, 0); - - mRenderer->markAllStateDirty(); - - if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DRIVERINTERNALERROR) - { - return EGL_BAD_ALLOC; - } - - // On Windows 8 systems, IDirect3DSwapChain9::Present sometimes returns 0x88760873 when the windows is - // in the process of entering/exiting fullscreen. This code doesn't seem to have any documentation. The - // device appears to be ok after emitting this error so simply return a failure to swap. - if (result == 0x88760873) - { - return EGL_BAD_MATCH; - } - - // http://crbug.com/313210 - // If our swap failed, trigger a device lost event. Resetting will work around an AMD-specific - // device removed bug with lost contexts when reinstalling drivers. - if (FAILED(result)) - { - mRenderer->notifyDeviceLost(); - return EGL_CONTEXT_LOST; - } - - return EGL_SUCCESS; -} - -// Increments refcount on surface. -// caller must Release() the returned surface -// TODO: remove the AddRef to match SwapChain11 -IDirect3DSurface9 *SwapChain9::getRenderTarget() -{ - if (mRenderTarget) - { - mRenderTarget->AddRef(); - } - - return mRenderTarget; -} - -// Increments refcount on surface. -// caller must Release() the returned surface -// TODO: remove the AddRef to match SwapChain11 -IDirect3DSurface9 *SwapChain9::getDepthStencil() -{ - if (mDepthStencil) - { - mDepthStencil->AddRef(); - } - - return mDepthStencil; -} - -// Increments refcount on texture. -// caller must Release() the returned texture -// TODO: remove the AddRef to match SwapChain11 -IDirect3DTexture9 *SwapChain9::getOffscreenTexture() -{ - if (mOffscreenTexture) - { - mOffscreenTexture->AddRef(); - } - - return mOffscreenTexture; -} - -SwapChain9 *SwapChain9::makeSwapChain9(SwapChain *swapChain) -{ - ASSERT(HAS_DYNAMIC_TYPE(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; - } - - SafeRelease(mSwapChain); - mSwapChain = newSwapChain; - - SafeRelease(mBackBuffer); - result = mSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &mBackBuffer); - ASSERT(SUCCEEDED(result)); -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.h deleted file mode 100644 index cb33bfbc0c..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.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. -// - -// 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, NativeWindow nativeWindow, 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(); - - EGLint getWidth() const { return mWidth; } - EGLint getHeight() const { return mHeight; } - - 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/d3d/d3d9/TextureStorage9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.cpp deleted file mode 100644 index 0ff4fd3b0f..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.cpp +++ /dev/null @@ -1,472 +0,0 @@ -// -// Copyright (c) 2012-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// 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/renderer/d3d/d3d9/TextureStorage9.h" -#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" -#include "libGLESv2/renderer/d3d/d3d9/SwapChain9.h" -#include "libGLESv2/renderer/d3d/d3d9/RenderTarget9.h" -#include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h" -#include "libGLESv2/renderer/d3d/d3d9/formatutils9.h" -#include "libGLESv2/renderer/d3d/TextureD3D.h" -#include "libGLESv2/Texture.h" -#include "libGLESv2/main.h" - -namespace rx -{ -TextureStorage9::TextureStorage9(Renderer9 *renderer, DWORD usage) - : mTopLevel(0), - mMipLevels(0), - mTextureWidth(0), - mTextureHeight(0), - mInternalFormat(GL_NONE), - mTextureFormat(D3DFMT_UNKNOWN), - 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(GLenum internalformat, bool renderTarget) -{ - DWORD d3dusage = 0; - - const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat); - const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(internalformat); - if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0) - { - d3dusage |= D3DUSAGE_DEPTHSTENCIL; - } - else if (renderTarget && (d3dFormatInfo.renderFormat != D3DFMT_UNKNOWN)) - { - d3dusage |= D3DUSAGE_RENDERTARGET; - } - - return d3dusage; -} - - -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::getTopLevel() const -{ - return mTopLevel; -} - -int TextureStorage9::getLevelCount() const -{ - return mMipLevels - mTopLevel; -} - -gl::Error TextureStorage9::setData(const gl::ImageIndex &index, Image *image, const gl::Box *destBox, GLenum type, - const gl::PixelUnpackState &unpack, const uint8_t *pixelData) -{ - UNREACHABLE(); - return gl::Error(GL_INVALID_OPERATION); -} - -TextureStorage9_2D::TextureStorage9_2D(Renderer9 *renderer, SwapChain9 *swapchain) - : TextureStorage9(renderer, D3DUSAGE_RENDERTARGET) -{ - IDirect3DTexture9 *surfaceTexture = swapchain->getOffscreenTexture(); - mTexture = surfaceTexture; - mMipLevels = surfaceTexture->GetLevelCount(); - - mInternalFormat = swapchain->GetBackBufferInternalFormat(); - - D3DSURFACE_DESC surfaceDesc; - surfaceTexture->GetLevelDesc(0, &surfaceDesc); - mTextureWidth = surfaceDesc.Width; - mTextureHeight = surfaceDesc.Height; - mTextureFormat = surfaceDesc.Format; - - mRenderTarget = NULL; - - initializeSerials(1, 1); -} - -TextureStorage9_2D::TextureStorage9_2D(Renderer9 *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels) - : TextureStorage9(renderer, GetTextureUsage(internalformat, renderTarget)) -{ - mTexture = NULL; - mRenderTarget = NULL; - - mInternalFormat = internalformat; - - const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(internalformat); - mTextureFormat = d3dFormatInfo.texFormat; - - d3d9::MakeValidSize(false, d3dFormatInfo.texFormat, &width, &height, &mTopLevel); - mTextureWidth = width; - mTextureHeight = height; - mMipLevels = mTopLevel + levels; - - initializeSerials(getLevelCount(), 1); -} - -TextureStorage9_2D::~TextureStorage9_2D() -{ - SafeRelease(mTexture); - SafeDelete(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 -gl::Error TextureStorage9_2D::getSurfaceLevel(int level, bool dirty, IDirect3DSurface9 **outSurface) -{ - IDirect3DBaseTexture9 *baseTexture = NULL; - gl::Error error = getBaseTexture(&baseTexture); - if (error.isError()) - { - return error; - } - - IDirect3DTexture9 *texture = static_cast(baseTexture); - - HRESULT result = texture->GetSurfaceLevel(level + mTopLevel, outSurface); - - ASSERT(SUCCEEDED(result)); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to get the surface from a texture, result: 0x%X.", result); - } - - // With managed textures the driver needs to be informed of updates to the lower mipmap levels - if (level + mTopLevel != 0 && isManaged() && dirty) - { - texture->AddDirtyRect(NULL); - } - - return gl::Error(GL_NO_ERROR); -} - -gl::Error TextureStorage9_2D::getRenderTarget(const gl::ImageIndex &/*index*/, RenderTarget **outRT) -{ - if (!mRenderTarget && isRenderTarget()) - { - IDirect3DSurface9 *surface = NULL; - gl::Error error = getSurfaceLevel(0, false, &surface); - if (error.isError()) - { - return error; - } - - mRenderTarget = new TextureRenderTarget9(surface, mInternalFormat, mTextureWidth, mTextureHeight, 1, 0); - } - - ASSERT(outRT); - *outRT = mRenderTarget; - return gl::Error(GL_NO_ERROR); -} - -gl::Error TextureStorage9_2D::generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex) -{ - IDirect3DSurface9 *upper = NULL; - gl::Error error = getSurfaceLevel(sourceIndex.mipIndex, false, &upper); - if (error.isError()) - { - return error; - } - - IDirect3DSurface9 *lower = NULL; - error = getSurfaceLevel(destIndex.mipIndex, true, &lower); - if (error.isError()) - { - SafeRelease(upper); - return error; - } - - ASSERT(upper && lower); - error = mRenderer->boxFilter(upper, lower); - - SafeRelease(upper); - SafeRelease(lower); - - return error; -} - -gl::Error TextureStorage9_2D::getBaseTexture(IDirect3DBaseTexture9 **outTexture) -{ - // 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 (mTexture == NULL && mTextureWidth > 0 && mTextureHeight > 0) - { - ASSERT(mMipLevels > 0); - - IDirect3DDevice9 *device = mRenderer->getDevice(); - HRESULT result = device->CreateTexture(mTextureWidth, mTextureHeight, mMipLevels, getUsage(), mTextureFormat, - getPool(), &mTexture, NULL); - - if (FAILED(result)) - { - ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create 2D storage texture, result: 0x%X.", result); - } - } - - *outTexture = mTexture; - return gl::Error(GL_NO_ERROR); -} - -gl::Error TextureStorage9_2D::copyToStorage(TextureStorage *destStorage) -{ - ASSERT(destStorage); - - TextureStorage9_2D *dest9 = TextureStorage9_2D::makeTextureStorage9_2D(destStorage); - - int levels = getLevelCount(); - for (int i = 0; i < levels; ++i) - { - IDirect3DSurface9 *srcSurf = NULL; - gl::Error error = getSurfaceLevel(i, false, &srcSurf); - if (error.isError()) - { - return error; - } - - IDirect3DSurface9 *dstSurf = NULL; - error = dest9->getSurfaceLevel(i, true, &dstSurf); - if (error.isError()) - { - SafeRelease(srcSurf); - return error; - } - - error = mRenderer->copyToRenderTarget(dstSurf, srcSurf, isManaged()); - - SafeRelease(srcSurf); - SafeRelease(dstSurf); - - if (error.isError()) - { - return error; - } - } - - return gl::Error(GL_NO_ERROR); -} - -TextureStorage9_Cube::TextureStorage9_Cube(Renderer9 *renderer, GLenum internalformat, bool renderTarget, int size, int levels) - : TextureStorage9(renderer, GetTextureUsage(internalformat, renderTarget)) -{ - mTexture = NULL; - for (int i = 0; i < CUBE_FACE_COUNT; ++i) - { - mRenderTarget[i] = NULL; - } - - mInternalFormat = internalformat; - - const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(internalformat); - mTextureFormat = d3dFormatInfo.texFormat; - - int height = size; - d3d9::MakeValidSize(false, d3dFormatInfo.texFormat, &size, &height, &mTopLevel); - mTextureWidth = size; - mTextureHeight = size; - mMipLevels = mTopLevel + levels; - - initializeSerials(getLevelCount() * CUBE_FACE_COUNT, CUBE_FACE_COUNT); -} - -TextureStorage9_Cube::~TextureStorage9_Cube() -{ - SafeRelease(mTexture); - - for (int i = 0; i < CUBE_FACE_COUNT; ++i) - { - SafeDelete(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 -gl::Error TextureStorage9_Cube::getCubeMapSurface(GLenum faceTarget, int level, bool dirty, IDirect3DSurface9 **outSurface) -{ - IDirect3DBaseTexture9 *baseTexture = NULL; - gl::Error error = getBaseTexture(&baseTexture); - if (error.isError()) - { - return error; - } - - IDirect3DCubeTexture9 *texture = static_cast(baseTexture); - - D3DCUBEMAP_FACES face = gl_d3d9::ConvertCubeFace(faceTarget); - HRESULT result = texture->GetCubeMapSurface(face, level + mTopLevel, outSurface); - - ASSERT(SUCCEEDED(result)); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to get the surface from a texture, result: 0x%X.", result); - } - - // With managed textures the driver needs to be informed of updates to the lower mipmap levels - if (level != 0 && isManaged() && dirty) - { - texture->AddDirtyRect(face, NULL); - } - - return gl::Error(GL_NO_ERROR); -} - -gl::Error TextureStorage9_Cube::getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT) -{ - ASSERT(outRT); - ASSERT(index.mipIndex == 0); - ASSERT(index.layerIndex >= 0 && index.layerIndex < CUBE_FACE_COUNT); - - if (mRenderTarget[index.layerIndex] == NULL && isRenderTarget()) - { - IDirect3DSurface9 *surface = NULL; - gl::Error error = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + index.layerIndex, 0, false, &surface); - if (error.isError()) - { - return error; - } - - mRenderTarget[index.layerIndex] = new TextureRenderTarget9(surface, mInternalFormat, mTextureWidth, mTextureHeight, 1, 0); - } - - *outRT = mRenderTarget[index.layerIndex]; - return gl::Error(GL_NO_ERROR); -} - -gl::Error TextureStorage9_Cube::generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex) -{ - IDirect3DSurface9 *upper = NULL; - gl::Error error = getCubeMapSurface(sourceIndex.type, sourceIndex.mipIndex, false, &upper); - if (error.isError()) - { - return error; - } - - IDirect3DSurface9 *lower = NULL; - error = getCubeMapSurface(destIndex.type, destIndex.mipIndex, true, &lower); - if (error.isError()) - { - SafeRelease(upper); - return error; - } - - ASSERT(upper && lower); - error = mRenderer->boxFilter(upper, lower); - - SafeRelease(upper); - SafeRelease(lower); - - return error; -} - -gl::Error TextureStorage9_Cube::getBaseTexture(IDirect3DBaseTexture9 **outTexture) -{ - // 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 (mTexture == NULL && mTextureWidth > 0 && mTextureHeight > 0) - { - ASSERT(mMipLevels > 0); - ASSERT(mTextureWidth == mTextureHeight); - - IDirect3DDevice9 *device = mRenderer->getDevice(); - HRESULT result = device->CreateCubeTexture(mTextureWidth, mMipLevels, getUsage(), mTextureFormat, getPool(), - &mTexture, NULL); - - if (FAILED(result)) - { - ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create cube storage texture, result: 0x%X.", result); - } - } - - *outTexture = mTexture; - return gl::Error(GL_NO_ERROR); -} - -gl::Error TextureStorage9_Cube::copyToStorage(TextureStorage *destStorage) -{ - ASSERT(destStorage); - - TextureStorage9_Cube *dest9 = TextureStorage9_Cube::makeTextureStorage9_Cube(destStorage); - - int levels = getLevelCount(); - for (int f = 0; f < CUBE_FACE_COUNT; f++) - { - for (int i = 0; i < levels; i++) - { - IDirect3DSurface9 *srcSurf = NULL; - gl::Error error = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, false, &srcSurf); - if (error.isError()) - { - return error; - } - - IDirect3DSurface9 *dstSurf = NULL; - error = dest9->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, true, &dstSurf); - if (error.isError()) - { - SafeRelease(srcSurf); - return error; - } - - error = mRenderer->copyToRenderTarget(dstSurf, srcSurf, isManaged()); - - SafeRelease(srcSurf); - SafeRelease(dstSurf); - - if (error.isError()) - { - return error; - } - } - } - - return gl::Error(GL_NO_ERROR); -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.h deleted file mode 100644 index da0e1f2f18..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.h +++ /dev/null @@ -1,114 +0,0 @@ -// -// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// 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/d3d/TextureStorage.h" -#include "common/debug.h" - -namespace rx -{ -class Renderer9; -class SwapChain9; -class RenderTarget; -class RenderTarget9; - -class TextureStorage9 : public TextureStorage -{ - public: - virtual ~TextureStorage9(); - - static TextureStorage9 *makeTextureStorage9(TextureStorage *storage); - - static DWORD GetTextureUsage(GLenum internalformat, bool renderTarget); - - D3DPOOL getPool() const; - DWORD getUsage() const; - - virtual gl::Error getBaseTexture(IDirect3DBaseTexture9 **outTexture) = 0; - virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT) = 0; - - virtual int getTopLevel() const; - virtual bool isRenderTarget() const; - virtual bool isManaged() const; - virtual int getLevelCount() const; - - virtual gl::Error setData(const gl::ImageIndex &index, Image *image, const gl::Box *destBox, GLenum type, - const gl::PixelUnpackState &unpack, const uint8_t *pixelData); - - protected: - int mTopLevel; - size_t mMipLevels; - size_t mTextureWidth; - size_t mTextureHeight; - GLenum mInternalFormat; - D3DFORMAT mTextureFormat; - - Renderer9 *mRenderer; - - TextureStorage9(Renderer9 *renderer, DWORD usage); - - private: - DISALLOW_COPY_AND_ASSIGN(TextureStorage9); - - const DWORD mD3DUsage; - const D3DPOOL mD3DPool; -}; - -class TextureStorage9_2D : public TextureStorage9 -{ - public: - TextureStorage9_2D(Renderer9 *renderer, SwapChain9 *swapchain); - TextureStorage9_2D(Renderer9 *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels); - virtual ~TextureStorage9_2D(); - - static TextureStorage9_2D *makeTextureStorage9_2D(TextureStorage *storage); - - gl::Error getSurfaceLevel(int level, bool dirty, IDirect3DSurface9 **outSurface); - virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT); - virtual gl::Error getBaseTexture(IDirect3DBaseTexture9 **outTexture); - virtual gl::Error generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex); - virtual gl::Error copyToStorage(TextureStorage *destStorage); - - private: - DISALLOW_COPY_AND_ASSIGN(TextureStorage9_2D); - - IDirect3DTexture9 *mTexture; - RenderTarget9 *mRenderTarget; -}; - -class TextureStorage9_Cube : public TextureStorage9 -{ - public: - TextureStorage9_Cube(Renderer9 *renderer, GLenum internalformat, bool renderTarget, int size, int levels); - virtual ~TextureStorage9_Cube(); - - static TextureStorage9_Cube *makeTextureStorage9_Cube(TextureStorage *storage); - - gl::Error getCubeMapSurface(GLenum faceTarget, int level, bool dirty, IDirect3DSurface9 **outSurface); - virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT); - virtual gl::Error getBaseTexture(IDirect3DBaseTexture9 **outTexture); - virtual gl::Error generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex); - virtual gl::Error copyToStorage(TextureStorage *destStorage); - - private: - DISALLOW_COPY_AND_ASSIGN(TextureStorage9_Cube); - - static const size_t CUBE_FACE_COUNT = 6; - - IDirect3DCubeTexture9 *mTexture; - RenderTarget9 *mRenderTarget[CUBE_FACE_COUNT]; -}; - -} - -#endif // LIBGLESV2_RENDERER_TEXTURESTORAGE9_H_ - diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexArray9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexArray9.h deleted file mode 100644 index 791c108462..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexArray9.h +++ /dev/null @@ -1,43 +0,0 @@ -// -// Copyright 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// VertexArray9.h: Defines the rx::VertexArray9 class which implements rx::VertexArrayImpl. - -#ifndef LIBGLESV2_RENDERER_VERTEXARRAY9_H_ -#define LIBGLESV2_RENDERER_VERTEXARRAY9_H_ - -#include "libGLESv2/renderer/VertexArrayImpl.h" -#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" - -namespace rx -{ -class Renderer9; - -class VertexArray9 : public VertexArrayImpl -{ - public: - VertexArray9(Renderer9 *renderer) - : VertexArrayImpl(), - mRenderer(renderer) - { - } - - virtual ~VertexArray9() { } - - virtual void setElementArrayBuffer(const gl::Buffer *buffer) { } - virtual void setAttribute(size_t idx, const gl::VertexAttribute &attr) { } - virtual void setAttributeDivisor(size_t idx, GLuint divisor) { } - virtual void enableAttribute(size_t idx, bool enabledState) { } - - private: - DISALLOW_COPY_AND_ASSIGN(VertexArray9); - - Renderer9 *mRenderer; -}; - -} - -#endif // LIBGLESV2_RENDERER_VERTEXARRAY9_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexBuffer9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexBuffer9.cpp deleted file mode 100644 index b90133097c..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexBuffer9.cpp +++ /dev/null @@ -1,239 +0,0 @@ -// -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// VertexBuffer9.cpp: Defines the D3D9 VertexBuffer implementation. - -#include "libGLESv2/renderer/d3d/d3d9/VertexBuffer9.h" -#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" -#include "libGLESv2/renderer/d3d/d3d9/formatutils9.h" -#include "libGLESv2/renderer/vertexconversion.h" -#include "libGLESv2/renderer/d3d/BufferD3D.h" -#include "libGLESv2/VertexAttribute.h" -#include "libGLESv2/Buffer.h" - -namespace rx -{ - -VertexBuffer9::VertexBuffer9(Renderer9 *renderer) : mRenderer(renderer) -{ - mVertexBuffer = NULL; - mBufferSize = 0; - mDynamicUsage = false; -} - -VertexBuffer9::~VertexBuffer9() -{ - SafeRelease(mVertexBuffer); -} - -gl::Error VertexBuffer9::initialize(unsigned int size, bool dynamicUsage) -{ - SafeRelease(mVertexBuffer); - - updateSerial(); - - if (size > 0) - { - DWORD flags = D3DUSAGE_WRITEONLY; - if (dynamicUsage) - { - flags |= D3DUSAGE_DYNAMIC; - } - - HRESULT result = mRenderer->createVertexBuffer(size, flags, &mVertexBuffer); - - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal vertex buffer of size, %lu.", size); - } - } - - mBufferSize = size; - mDynamicUsage = dynamicUsage; - return gl::Error(GL_NO_ERROR); -} - -VertexBuffer9 *VertexBuffer9::makeVertexBuffer9(VertexBuffer *vertexBuffer) -{ - ASSERT(HAS_DYNAMIC_TYPE(VertexBuffer9*, vertexBuffer)); - return static_cast(vertexBuffer); -} - -gl::Error VertexBuffer9::storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData ¤tValue, - GLint start, GLsizei count, GLsizei instances, unsigned int offset) -{ - if (!mVertexBuffer) - { - return gl::Error(GL_OUT_OF_MEMORY, "Internal vertex buffer is not initialized."); - } - - gl::Buffer *buffer = attrib.buffer.get(); - - int inputStride = gl::ComputeVertexAttributeStride(attrib); - int elementSize = gl::ComputeVertexAttributeTypeSize(attrib); - - DWORD lockFlags = mDynamicUsage ? D3DLOCK_NOOVERWRITE : 0; - - uint8_t *mapPtr = NULL; - - unsigned int mapSize; - gl::Error error = spaceRequired(attrib, count, instances, &mapSize); - if (error.isError()) - { - return error; - } - - HRESULT result = mVertexBuffer->Lock(offset, mapSize, reinterpret_cast(&mapPtr), lockFlags); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock internal vertex buffer, HRESULT: 0x%08x.", result); - } - - const uint8_t *input = NULL; - if (attrib.enabled) - { - if (buffer) - { - BufferD3D *storage = BufferD3D::makeFromBuffer(buffer); - ASSERT(storage); - gl::Error error = storage->getData(&input); - if (error.isError()) - { - return error; - } - input += static_cast(attrib.offset); - } - else - { - input = static_cast(attrib.pointer); - } - } - else - { - input = reinterpret_cast(currentValue.FloatValues); - } - - if (instances == 0 || attrib.divisor == 0) - { - input += inputStride * start; - } - - gl::VertexFormat vertexFormat(attrib, currentValue.Type); - const d3d9::VertexFormat &d3dVertexInfo = d3d9::GetVertexFormatInfo(mRenderer->getCapsDeclTypes(), vertexFormat); - bool needsConversion = (d3dVertexInfo.conversionType & VERTEX_CONVERT_CPU) > 0; - - if (!needsConversion && inputStride == elementSize) - { - size_t copySize = static_cast(count) * static_cast(inputStride); - memcpy(mapPtr, input, copySize); - } - else - { - d3dVertexInfo.copyFunction(input, inputStride, count, mapPtr); - } - - mVertexBuffer->Unlock(); - - return gl::Error(GL_NO_ERROR); -} - -gl::Error VertexBuffer9::getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances, - unsigned int *outSpaceRequired) const -{ - return spaceRequired(attrib, count, instances, outSpaceRequired); -} - -unsigned int VertexBuffer9::getBufferSize() const -{ - return mBufferSize; -} - -gl::Error VertexBuffer9::setBufferSize(unsigned int size) -{ - if (size > mBufferSize) - { - return initialize(size, mDynamicUsage); - } - else - { - return gl::Error(GL_NO_ERROR); - } -} - -gl::Error VertexBuffer9::discard() -{ - if (!mVertexBuffer) - { - return gl::Error(GL_OUT_OF_MEMORY, "Internal vertex buffer is not initialized."); - } - - void *dummy; - HRESULT result; - - result = mVertexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock internal buffer for discarding, HRESULT: 0x%08x", result); - } - - result = mVertexBuffer->Unlock(); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to unlock internal buffer for discarding, HRESULT: 0x%08x", result); - } - - return gl::Error(GL_NO_ERROR); -} - -IDirect3DVertexBuffer9 * VertexBuffer9::getBuffer() const -{ - return mVertexBuffer; -} - -gl::Error VertexBuffer9::spaceRequired(const gl::VertexAttribute &attrib, std::size_t count, GLsizei instances, - unsigned int *outSpaceRequired) const -{ - gl::VertexFormat vertexFormat(attrib, GL_FLOAT); - const d3d9::VertexFormat &d3d9VertexInfo = d3d9::GetVertexFormatInfo(mRenderer->getCapsDeclTypes(), vertexFormat); - - if (attrib.enabled) - { - unsigned int elementCount = 0; - if (instances == 0 || attrib.divisor == 0) - { - elementCount = count; - } - else - { - // Round up to divisor, if possible - elementCount = UnsignedCeilDivide(static_cast(instances), attrib.divisor); - } - - if (d3d9VertexInfo.outputElementSize <= std::numeric_limits::max() / elementCount) - { - if (outSpaceRequired) - { - *outSpaceRequired = d3d9VertexInfo.outputElementSize * elementCount; - } - return gl::Error(GL_NO_ERROR); - } - else - { - return gl::Error(GL_OUT_OF_MEMORY, "New vertex buffer size would result in an overflow."); - } - } - else - { - const unsigned int elementSize = 4; - if (outSpaceRequired) - { - *outSpaceRequired = elementSize * 4; - } - return gl::Error(GL_NO_ERROR); - } -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexBuffer9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexBuffer9.h deleted file mode 100644 index 9af2b98a6e..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexBuffer9.h +++ /dev/null @@ -1,54 +0,0 @@ -// -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// VertexBuffer9.h: Defines the D3D9 VertexBuffer implementation. - -#ifndef LIBGLESV2_RENDERER_VERTEXBUFFER9_H_ -#define LIBGLESV2_RENDERER_VERTEXBUFFER9_H_ - -#include "libGLESv2/renderer/d3d/VertexBuffer.h" - -namespace rx -{ -class Renderer9; - -class VertexBuffer9 : public VertexBuffer -{ - public: - explicit VertexBuffer9(Renderer9 *renderer); - virtual ~VertexBuffer9(); - - virtual gl::Error initialize(unsigned int size, bool dynamicUsage); - - static VertexBuffer9 *makeVertexBuffer9(VertexBuffer *vertexBuffer); - - virtual gl::Error storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData ¤tValue, - GLint start, GLsizei count, GLsizei instances, unsigned int offset); - - virtual gl::Error getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances, unsigned int *outSpaceRequired) const; - - virtual unsigned int getBufferSize() const; - virtual gl::Error setBufferSize(unsigned int size); - virtual gl::Error discard(); - - IDirect3DVertexBuffer9 *getBuffer() const; - - private: - DISALLOW_COPY_AND_ASSIGN(VertexBuffer9); - - Renderer9 *mRenderer; - - IDirect3DVertexBuffer9 *mVertexBuffer; - unsigned int mBufferSize; - bool mDynamicUsage; - - gl::Error spaceRequired(const gl::VertexAttribute &attrib, std::size_t count, GLsizei instances, - unsigned int *outSpaceRequired) const; -}; - -} - -#endif // LIBGLESV2_RENDERER_VERTEXBUFFER9_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexDeclarationCache.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexDeclarationCache.cpp deleted file mode 100644 index cefd786f11..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexDeclarationCache.cpp +++ /dev/null @@ -1,237 +0,0 @@ -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// VertexDeclarationCache.cpp: Implements a helper class to construct and cache vertex declarations. - -#include "libGLESv2/renderer/d3d/d3d9/VertexDeclarationCache.h" -#include "libGLESv2/renderer/d3d/d3d9/VertexBuffer9.h" -#include "libGLESv2/renderer/d3d/d3d9/formatutils9.h" -#include "libGLESv2/ProgramBinary.h" -#include "libGLESv2/VertexAttribute.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++) - { - SafeRelease(mVertexDeclCache[i].vertexDeclaration); - } -} - -gl::Error 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) - { - for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; ++i) - { - if (attributes[i].divisor != 0) - { - // If a divisor is set, it still applies even if an instanced draw was not used, so treat - // as a single-instance draw. - instances = 1; - break; - } - } - } - - 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 - } - } - - // The validation layer checks that there is at least one active attribute with a zero divisor as per - // the GL_ANGLE_instanced_arrays spec. - ASSERT(indexedAttribute != gl::MAX_VERTEX_ATTRIBS); - } - - D3DCAPS9 caps; - device->GetDeviceCaps(&caps); - - 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; - } - - gl::VertexFormat vertexFormat(*attributes[i].attribute, GL_FLOAT); - const d3d9::VertexFormat &d3d9VertexInfo = d3d9::GetVertexFormatInfo(caps.DeclTypes, vertexFormat); - - element->Stream = stream; - element->Offset = 0; - element->Type = d3d9VertexInfo.nativeFormat; - 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::Error(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) - { - SafeRelease(lastCache->vertexDeclaration); - // mLastSetVDecl is set to the replacement, so we don't have to worry - // about it. - } - - memcpy(lastCache->cachedElements, elements, (element - elements) * sizeof(D3DVERTEXELEMENT9)); - HRESULT result = device->CreateVertexDeclaration(elements, &lastCache->vertexDeclaration); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal vertex declaration, result: 0x%X.", result); - } - - device->SetVertexDeclaration(lastCache->vertexDeclaration); - mLastSetVDecl = lastCache->vertexDeclaration; - lastCache->lruCount = ++mMaxLru; - - return gl::Error(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/d3d/d3d9/VertexDeclarationCache.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexDeclarationCache.h deleted file mode 100644 index 9af36e0d7a..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexDeclarationCache.h +++ /dev/null @@ -1,59 +0,0 @@ -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// VertexDeclarationCache.h: Defines a helper class to construct and cache vertex declarations. - -#ifndef LIBGLESV2_RENDERER_VERTEXDECLARATIONCACHE_H_ -#define LIBGLESV2_RENDERER_VERTEXDECLARATIONCACHE_H_ - -#include "libGLESv2/Error.h" -#include "libGLESv2/renderer/d3d/VertexDataManager.h" - -namespace gl -{ -class VertexDataManager; -} - -namespace rx -{ - -class VertexDeclarationCache -{ - public: - VertexDeclarationCache(); - ~VertexDeclarationCache(); - - gl::Error 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/d3d/d3d9/formatutils9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/formatutils9.cpp deleted file mode 100644 index f3acaf7987..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/formatutils9.cpp +++ /dev/null @@ -1,588 +0,0 @@ -// -// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// formatutils9.cpp: Queries for GL image formats and their translations to D3D9 -// formats. - -#include "libGLESv2/renderer/d3d/d3d9/formatutils9.h" -#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" -#include "libGLESv2/renderer/generatemip.h" -#include "libGLESv2/renderer/loadimage.h" -#include "libGLESv2/renderer/copyimage.h" -#include "libGLESv2/renderer/vertexconversion.h" - -namespace rx -{ - -namespace d3d9 -{ - -const D3DFORMAT D3DFMT_INTZ = ((D3DFORMAT)(MAKEFOURCC('I', 'N', 'T', 'Z'))); -const D3DFORMAT D3DFMT_NULL = ((D3DFORMAT)(MAKEFOURCC('N', 'U', 'L', 'L'))); - -struct D3D9FastCopyFormat -{ - GLenum destFormat; - GLenum destType; - ColorCopyFunction copyFunction; - - D3D9FastCopyFormat(GLenum destFormat, GLenum destType, ColorCopyFunction copyFunction) - : destFormat(destFormat), destType(destType), copyFunction(copyFunction) - { } - - bool operator<(const D3D9FastCopyFormat& other) const - { - return memcmp(this, &other, sizeof(D3D9FastCopyFormat)) < 0; - } -}; - -typedef std::multimap D3D9FastCopyMap; - -static D3D9FastCopyMap BuildFastCopyMap() -{ - D3D9FastCopyMap map; - - map.insert(std::make_pair(D3DFMT_A8R8G8B8, D3D9FastCopyFormat(GL_RGBA, GL_UNSIGNED_BYTE, CopyBGRA8ToRGBA8))); - - return map; -} - -// A map to determine the pixel size and mip generation function of a given D3D format -typedef std::map D3D9FormatInfoMap; - -D3DFormat::D3DFormat() - : pixelBytes(0), - blockWidth(0), - blockHeight(0), - internalFormat(GL_NONE), - mipGenerationFunction(NULL), - colorReadFunction(NULL), - fastCopyFunctions() -{ -} - -ColorCopyFunction D3DFormat::getFastCopyFunction(GLenum format, GLenum type) const -{ - FastCopyFunctionMap::const_iterator iter = fastCopyFunctions.find(std::make_pair(format, type)); - return (iter != fastCopyFunctions.end()) ? iter->second : NULL; -} - -static inline void InsertD3DFormatInfo(D3D9FormatInfoMap *map, D3DFORMAT format, GLuint bits, GLuint blockWidth, - GLuint blockHeight, GLenum internalFormat, MipGenerationFunction mipFunc, - ColorReadFunction colorReadFunc) -{ - D3DFormat info; - info.pixelBytes = bits / 8; - info.blockWidth = blockWidth; - info.blockHeight = blockHeight; - info.internalFormat = internalFormat; - info.mipGenerationFunction = mipFunc; - info.colorReadFunction = colorReadFunc; - - static const D3D9FastCopyMap fastCopyMap = BuildFastCopyMap(); - std::pair fastCopyIter = fastCopyMap.equal_range(format); - for (D3D9FastCopyMap::const_iterator i = fastCopyIter.first; i != fastCopyIter.second; i++) - { - info.fastCopyFunctions.insert(std::make_pair(std::make_pair(i->second.destFormat, i->second.destType), i->second.copyFunction)); - } - - map->insert(std::make_pair(format, info)); -} - -static D3D9FormatInfoMap BuildD3D9FormatInfoMap() -{ - D3D9FormatInfoMap map; - - // | D3DFORMAT | S |W |H | Internal format | Mip generation function | Color read function | - InsertD3DFormatInfo(&map, D3DFMT_NULL, 0, 0, 0, GL_NONE, NULL, NULL ); - InsertD3DFormatInfo(&map, D3DFMT_UNKNOWN, 0, 0, 0, GL_NONE, NULL, NULL ); - - InsertD3DFormatInfo(&map, D3DFMT_L8, 8, 1, 1, GL_LUMINANCE8_EXT, GenerateMip, ReadColor ); - InsertD3DFormatInfo(&map, D3DFMT_A8, 8, 1, 1, GL_ALPHA8_EXT, GenerateMip, ReadColor ); - InsertD3DFormatInfo(&map, D3DFMT_A8L8, 16, 1, 1, GL_LUMINANCE8_ALPHA8_EXT, GenerateMip, ReadColor ); - InsertD3DFormatInfo(&map, D3DFMT_A4R4G4B4, 16, 1, 1, GL_BGRA4_ANGLEX, GenerateMip, ReadColor ); - InsertD3DFormatInfo(&map, D3DFMT_A1R5G5B5, 16, 1, 1, GL_BGR5_A1_ANGLEX, GenerateMip, ReadColor ); - InsertD3DFormatInfo(&map, D3DFMT_R5G6B5, 16, 1, 1, GL_RGB565, GenerateMip, ReadColor ); - InsertD3DFormatInfo(&map, D3DFMT_X8R8G8B8, 32, 1, 1, GL_BGRA8_EXT, GenerateMip, ReadColor ); - InsertD3DFormatInfo(&map, D3DFMT_A8R8G8B8, 32, 1, 1, GL_BGRA8_EXT, GenerateMip, ReadColor ); - InsertD3DFormatInfo(&map, D3DFMT_R16F, 16, 1, 1, GL_R16F_EXT, GenerateMip, ReadColor ); - InsertD3DFormatInfo(&map, D3DFMT_G16R16F, 32, 1, 1, GL_RG16F_EXT, GenerateMip, ReadColor ); - InsertD3DFormatInfo(&map, D3DFMT_A16B16G16R16F, 64, 1, 1, GL_RGBA16F_EXT, GenerateMip, ReadColor); - InsertD3DFormatInfo(&map, D3DFMT_R32F, 32, 1, 1, GL_R32F_EXT, GenerateMip, ReadColor ); - InsertD3DFormatInfo(&map, D3DFMT_G32R32F, 64, 1, 1, GL_RG32F_EXT, GenerateMip, ReadColor ); - InsertD3DFormatInfo(&map, D3DFMT_A32B32G32R32F, 128, 1, 1, GL_RGBA32F_EXT, GenerateMip, ReadColor); - - InsertD3DFormatInfo(&map, D3DFMT_D16, 16, 1, 1, GL_DEPTH_COMPONENT16, NULL, NULL ); - InsertD3DFormatInfo(&map, D3DFMT_D24S8, 32, 1, 1, GL_DEPTH24_STENCIL8_OES, NULL, NULL ); - InsertD3DFormatInfo(&map, D3DFMT_D24X8, 32, 1, 1, GL_DEPTH_COMPONENT16, NULL, NULL ); - InsertD3DFormatInfo(&map, D3DFMT_D32, 32, 1, 1, GL_DEPTH_COMPONENT32_OES, NULL, NULL ); - - InsertD3DFormatInfo(&map, D3DFMT_INTZ, 32, 1, 1, GL_DEPTH24_STENCIL8_OES, NULL, NULL ); - - InsertD3DFormatInfo(&map, D3DFMT_DXT1, 64, 4, 4, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, NULL, NULL ); - InsertD3DFormatInfo(&map, D3DFMT_DXT3, 128, 4, 4, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, NULL, NULL ); - InsertD3DFormatInfo(&map, D3DFMT_DXT5, 128, 4, 4, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, NULL, NULL ); - - return map; -} - -const D3DFormat &GetD3DFormatInfo(D3DFORMAT format) -{ - static const D3D9FormatInfoMap infoMap = BuildD3D9FormatInfoMap(); - D3D9FormatInfoMap::const_iterator iter = infoMap.find(format); - if (iter != infoMap.end()) - { - return iter->second; - } - else - { - static const D3DFormat defaultInfo; - return defaultInfo; - } -} - - - -typedef std::pair InternalFormatInitialzerPair; -typedef std::map InternalFormatInitialzerMap; - -static InternalFormatInitialzerMap BuildInternalFormatInitialzerMap() -{ - InternalFormatInitialzerMap map; - - map.insert(InternalFormatInitialzerPair(GL_RGB16F, Initialize4ComponentData)); - map.insert(InternalFormatInitialzerPair(GL_RGB32F, Initialize4ComponentData)); - - return map; -} - -// Each GL internal format corresponds to one D3D format and data loading function. -// Due to not all formats being available all the time, some of the function/format types are wrapped -// in templates that perform format support queries on a Renderer9 object which is supplied -// when requesting the function or format. - -typedef bool(*FallbackPredicateFunction)(); - -template -static void FallbackLoad(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) -{ - if (pred()) - { - prefered(width, height, depth, input, inputRowPitch, inputDepthPitch, output, outputRowPitch, outputDepthPitch); - } - else - { - fallback(width, height, depth, input, inputRowPitch, inputDepthPitch, output, outputRowPitch, outputDepthPitch); - } -} - -static void UnreachableLoad(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) -{ - UNREACHABLE(); -} - -typedef std::pair D3D9FormatPair; -typedef std::map D3D9FormatMap; - -TextureFormat::TextureFormat() - : texFormat(D3DFMT_NULL), - renderFormat(D3DFMT_NULL), - dataInitializerFunction(NULL), - loadFunction(UnreachableLoad) -{ -} - -static inline void InsertD3D9FormatInfo(D3D9FormatMap *map, GLenum internalFormat, D3DFORMAT texFormat, - D3DFORMAT renderFormat, LoadImageFunction loadFunction) -{ - TextureFormat info; - info.texFormat = texFormat; - info.renderFormat = renderFormat; - - static const InternalFormatInitialzerMap dataInitializationMap = BuildInternalFormatInitialzerMap(); - InternalFormatInitialzerMap::const_iterator dataInitIter = dataInitializationMap.find(internalFormat); - info.dataInitializerFunction = (dataInitIter != dataInitializationMap.end()) ? dataInitIter->second : NULL; - - info.loadFunction = loadFunction; - - map->insert(std::make_pair(internalFormat, info)); -} - -static D3D9FormatMap BuildD3D9FormatMap() -{ - D3D9FormatMap map; - - // | Internal format | Texture format | Render format | Load function | - InsertD3D9FormatInfo(&map, GL_NONE, D3DFMT_NULL, D3DFMT_NULL, UnreachableLoad ); - - // We choose to downsample the GL_DEPTH_COMPONENT32_OES format to a 24-bit format because D3DFMT_D32 is not widely - // supported. We're allowed to do this because: - // - The ES spec 2.0.25 sec 3.7.1 states that we're allowed to store texture formats with internal format - // resolutions of our own choosing. - // - OES_depth_texture states that downsampling of the depth formats is allowed. - // - ANGLE_depth_texture does not state minimum required resolutions of the depth texture formats it - // introduces. - // In ES3 however, there are minimum resolutions for the texture formats and this would not be allowed. - - InsertD3D9FormatInfo(&map, GL_DEPTH_COMPONENT16, D3DFMT_INTZ, D3DFMT_D24S8, UnreachableLoad ); - InsertD3D9FormatInfo(&map, GL_DEPTH_COMPONENT32_OES, D3DFMT_INTZ, D3DFMT_D24X8, UnreachableLoad ); - InsertD3D9FormatInfo(&map, GL_DEPTH24_STENCIL8_OES, D3DFMT_INTZ, D3DFMT_D24S8, UnreachableLoad ); - InsertD3D9FormatInfo(&map, GL_STENCIL_INDEX8, D3DFMT_UNKNOWN, D3DFMT_D24S8, UnreachableLoad ); // TODO: What's the texture format? - - InsertD3D9FormatInfo(&map, GL_RGBA32F_EXT, D3DFMT_A32B32G32R32F, D3DFMT_A32B32G32R32F, LoadToNative ); - InsertD3D9FormatInfo(&map, GL_RGB32F_EXT, D3DFMT_A32B32G32R32F, D3DFMT_A32B32G32R32F, LoadToNative3To4); - InsertD3D9FormatInfo(&map, GL_RG32F_EXT, D3DFMT_G32R32F, D3DFMT_G32R32F, LoadToNative ); - InsertD3D9FormatInfo(&map, GL_R32F_EXT, D3DFMT_R32F, D3DFMT_R32F, LoadToNative ); - InsertD3D9FormatInfo(&map, GL_ALPHA32F_EXT, D3DFMT_A32B32G32R32F, D3DFMT_UNKNOWN, LoadA32FToRGBA32F ); - InsertD3D9FormatInfo(&map, GL_LUMINANCE32F_EXT, D3DFMT_A32B32G32R32F, D3DFMT_UNKNOWN, LoadL32FToRGBA32F ); - InsertD3D9FormatInfo(&map, GL_LUMINANCE_ALPHA32F_EXT, D3DFMT_A32B32G32R32F, D3DFMT_UNKNOWN, LoadLA32FToRGBA32F ); - - InsertD3D9FormatInfo(&map, GL_RGBA16F_EXT, D3DFMT_A16B16G16R16F, D3DFMT_A16B16G16R16F, LoadToNative ); - InsertD3D9FormatInfo(&map, GL_RGB16F_EXT, D3DFMT_A16B16G16R16F, D3DFMT_A16B16G16R16F, LoadToNative3To4 ); - InsertD3D9FormatInfo(&map, GL_RG16F_EXT, D3DFMT_G16R16F, D3DFMT_G16R16F, LoadToNative ); - InsertD3D9FormatInfo(&map, GL_R16F_EXT, D3DFMT_R16F, D3DFMT_R16F, LoadToNative ); - InsertD3D9FormatInfo(&map, GL_ALPHA16F_EXT, D3DFMT_A16B16G16R16F, D3DFMT_UNKNOWN, LoadA16FToRGBA16F ); - InsertD3D9FormatInfo(&map, GL_LUMINANCE16F_EXT, D3DFMT_A16B16G16R16F, D3DFMT_UNKNOWN, LoadL16FToRGBA16F ); - InsertD3D9FormatInfo(&map, GL_LUMINANCE_ALPHA16F_EXT, D3DFMT_A16B16G16R16F, D3DFMT_UNKNOWN, LoadLA16FToRGBA16F ); - - InsertD3D9FormatInfo(&map, GL_ALPHA8_EXT, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, FallbackLoad); - - InsertD3D9FormatInfo(&map, GL_RGB8_OES, D3DFMT_X8R8G8B8, D3DFMT_X8R8G8B8, LoadRGB8ToBGRX8 ); - InsertD3D9FormatInfo(&map, GL_RGB565, D3DFMT_X8R8G8B8, D3DFMT_X8R8G8B8, LoadR5G6B5ToBGRA8 ); - InsertD3D9FormatInfo(&map, GL_RGBA8_OES, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, FallbackLoad); - InsertD3D9FormatInfo(&map, GL_RGBA4, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, LoadRGBA4ToBGRA8 ); - InsertD3D9FormatInfo(&map, GL_RGB5_A1, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, LoadRGB5A1ToBGRA8 ); - InsertD3D9FormatInfo(&map, GL_R8_EXT, D3DFMT_X8R8G8B8, D3DFMT_X8R8G8B8, LoadR8ToBGRX8 ); - InsertD3D9FormatInfo(&map, GL_RG8_EXT, D3DFMT_X8R8G8B8, D3DFMT_X8R8G8B8, LoadRG8ToBGRX8 ); - - InsertD3D9FormatInfo(&map, GL_BGRA8_EXT, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, LoadToNative ); - InsertD3D9FormatInfo(&map, GL_BGRA4_ANGLEX, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, LoadBGRA4ToBGRA8 ); - InsertD3D9FormatInfo(&map, GL_BGR5_A1_ANGLEX, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, LoadBGR5A1ToBGRA8 ); - - InsertD3D9FormatInfo(&map, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, D3DFMT_DXT1, D3DFMT_UNKNOWN, LoadCompressedToNative<4, 4, 8> ); - InsertD3D9FormatInfo(&map, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, D3DFMT_DXT1, D3DFMT_UNKNOWN, LoadCompressedToNative<4, 4, 8> ); - InsertD3D9FormatInfo(&map, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, D3DFMT_DXT3, D3DFMT_UNKNOWN, LoadCompressedToNative<4, 4, 16> ); - InsertD3D9FormatInfo(&map, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, D3DFMT_DXT5, D3DFMT_UNKNOWN, LoadCompressedToNative<4, 4, 16> ); - - // These formats require checking if the renderer supports D3DFMT_L8 or D3DFMT_A8L8 and - // then changing the format and loading function appropriately. - InsertD3D9FormatInfo(&map, GL_LUMINANCE8_EXT, D3DFMT_L8, D3DFMT_UNKNOWN, LoadToNative ); - InsertD3D9FormatInfo(&map, GL_LUMINANCE8_ALPHA8_EXT, D3DFMT_A8L8, D3DFMT_UNKNOWN, LoadToNative ); - - return map; -} - -const TextureFormat &GetTextureFormatInfo(GLenum internalFormat) -{ - static const D3D9FormatMap formatMap = BuildD3D9FormatMap(); - D3D9FormatMap::const_iterator iter = formatMap.find(internalFormat); - if (iter != formatMap.end()) - { - return iter->second; - } - else - { - static const TextureFormat defaultInfo; - return defaultInfo; - } -} - -static GLenum GetDeclTypeComponentType(D3DDECLTYPE declType) -{ - switch (declType) - { - case D3DDECLTYPE_FLOAT1: return GL_FLOAT; - case D3DDECLTYPE_FLOAT2: return GL_FLOAT; - case D3DDECLTYPE_FLOAT3: return GL_FLOAT; - case D3DDECLTYPE_FLOAT4: return GL_FLOAT; - case D3DDECLTYPE_UBYTE4: return GL_UNSIGNED_INT; - case D3DDECLTYPE_SHORT2: return GL_INT; - case D3DDECLTYPE_SHORT4: return GL_INT; - case D3DDECLTYPE_UBYTE4N: return GL_UNSIGNED_NORMALIZED; - case D3DDECLTYPE_SHORT4N: return GL_SIGNED_NORMALIZED; - case D3DDECLTYPE_USHORT4N: return GL_UNSIGNED_NORMALIZED; - case D3DDECLTYPE_SHORT2N: return GL_SIGNED_NORMALIZED; - case D3DDECLTYPE_USHORT2N: return GL_UNSIGNED_NORMALIZED; - default: UNREACHABLE(); return GL_NONE; - } -} - -// Attribute format conversion -enum { NUM_GL_VERTEX_ATTRIB_TYPES = 6 }; - -struct TranslationDescription -{ - DWORD capsFlag; - VertexFormat preferredConversion; - VertexFormat fallbackConversion; -}; - -// 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 }; -}; - -VertexFormat::VertexFormat() - : conversionType(VERTEX_CONVERT_NONE), - outputElementSize(0), - copyFunction(NULL), - nativeFormat(D3DDECLTYPE_UNUSED), - componentType(GL_NONE) -{ -} - -// Initialize a TranslationInfo -VertexFormat CreateVertexFormatInfo(bool identity, size_t elementSize, VertexCopyFunction copyFunc, D3DDECLTYPE nativeFormat) -{ - VertexFormat formatInfo; - formatInfo.conversionType = identity ? VERTEX_CONVERT_NONE : VERTEX_CONVERT_CPU; - formatInfo.outputElementSize = elementSize; - formatInfo.copyFunction = copyFunc; - formatInfo.nativeFormat = nativeFormat; - formatInfo.componentType = GetDeclTypeComponentType(nativeFormat); - return formatInfo; -} - -#define TRANSLATION(type, norm, size, preferred) \ - CreateVertexFormatInfo \ - ( \ - 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) }, \ - } - -static inline unsigned int ComputeTypeIndex(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 VertexFormat &GetVertexFormatInfo(DWORD supportedDeclTypes, const gl::VertexFormat &vertexFormat) -{ - static bool initialized = false; - static DWORD intializedDeclTypes = 0; - static VertexFormat formatConverters[NUM_GL_VERTEX_ATTRIB_TYPES][2][4]; - if (!initialized) - { - const TranslationDescription translations[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) - }; - 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 (translations[i][j][k].capsFlag == 0 || (supportedDeclTypes & translations[i][j][k].capsFlag) != 0) - { - formatConverters[i][j][k] = translations[i][j][k].preferredConversion; - } - else - { - formatConverters[i][j][k] = translations[i][j][k].fallbackConversion; - } - } - } - } - initialized = true; - intializedDeclTypes = supportedDeclTypes; - } - - ASSERT(intializedDeclTypes == supportedDeclTypes); - - // Pure integer attributes only supported in ES3.0 - ASSERT(!vertexFormat.mPureInteger); - return formatConverters[ComputeTypeIndex(vertexFormat.mType)][vertexFormat.mNormalized][vertexFormat.mComponents - 1]; -} - -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/formatutils9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/formatutils9.h deleted file mode 100644 index f26fe43b36..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/formatutils9.h +++ /dev/null @@ -1,74 +0,0 @@ -// -// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// formatutils9.h: Queries for GL image formats and their translations to D3D9 -// formats. - -#ifndef LIBGLESV2_RENDERER_FORMATUTILS9_H_ -#define LIBGLESV2_RENDERER_FORMATUTILS9_H_ - -#include "libGLESv2/formatutils.h" - -#include - -namespace rx -{ - -class Renderer9; - -namespace d3d9 -{ - -typedef std::map, ColorCopyFunction> FastCopyFunctionMap; - -struct D3DFormat -{ - D3DFormat(); - - GLuint pixelBytes; - GLuint blockWidth; - GLuint blockHeight; - - GLenum internalFormat; - - MipGenerationFunction mipGenerationFunction; - ColorReadFunction colorReadFunction; - - FastCopyFunctionMap fastCopyFunctions; - ColorCopyFunction getFastCopyFunction(GLenum format, GLenum type) const; -}; -const D3DFormat &GetD3DFormatInfo(D3DFORMAT format); - -struct VertexFormat -{ - VertexFormat(); - - VertexConversionType conversionType; - size_t outputElementSize; - VertexCopyFunction copyFunction; - D3DDECLTYPE nativeFormat; - GLenum componentType; -}; -const VertexFormat &GetVertexFormatInfo(DWORD supportedDeclTypes, const gl::VertexFormat &vertexFormat); - -struct TextureFormat -{ - TextureFormat(); - - D3DFORMAT texFormat; - D3DFORMAT renderFormat; - - InitializeTextureDataFunction dataInitializerFunction; - - LoadImageFunction loadFunction; -}; -const TextureFormat &GetTextureFormatInfo(GLenum internalFormat); - -} - -} - -#endif // LIBGLESV2_RENDERER_FORMATUTILS9_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.cpp deleted file mode 100644 index a98b2081f3..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.cpp +++ /dev/null @@ -1,558 +0,0 @@ -// -// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// renderer9_utils.cpp: Conversion functions and other utility routines -// specific to the D3D9 renderer. - -#include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h" -#include "libGLESv2/renderer/d3d/d3d9/formatutils9.h" -#include "libGLESv2/renderer/Workarounds.h" -#include "libGLESv2/formatutils.h" -#include "libGLESv2/Framebuffer.h" -#include "libGLESv2/renderer/d3d/d3d9/RenderTarget9.h" - -#include "common/mathutil.h" -#include "common/debug.h" - -#include "third_party/systeminfo/SystemInfo.h" - -namespace rx -{ - -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::ColorF 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; - case GL_MIN_EXT: d3dBlendOp = D3DBLENDOP_MIN; break; - case GL_MAX_EXT: d3dBlendOp = D3DBLENDOP_MAX; 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; - } -} - -D3DMULTISAMPLE_TYPE GetMultisampleType(GLuint samples) -{ - return (samples > 1) ? static_cast(samples) : D3DMULTISAMPLE_NONE; -} - -} - -namespace d3d9_gl -{ - -GLsizei GetSamplesCount(D3DMULTISAMPLE_TYPE type) -{ - return (type != D3DMULTISAMPLE_NONMASKABLE) ? type : 0; -} - -bool IsFormatChannelEquivalent(D3DFORMAT d3dformat, GLenum format) -{ - GLenum internalFormat = d3d9::GetD3DFormatInfo(d3dformat).internalFormat; - GLenum convertedFormat = gl::GetInternalFormatInfo(internalFormat).format; - return convertedFormat == format; -} - -static gl::TextureCaps GenerateTextureFormatCaps(GLenum internalFormat, IDirect3D9 *d3d9, D3DDEVTYPE deviceType, - UINT adapter, D3DFORMAT adapterFormat) -{ - gl::TextureCaps textureCaps; - - const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(internalFormat); - const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat); - if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0) - { - textureCaps.texturable = SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, 0, D3DRTYPE_TEXTURE, d3dFormatInfo.texFormat)); - } - else - { - textureCaps.texturable = SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, 0, D3DRTYPE_TEXTURE, d3dFormatInfo.texFormat)) && - SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, 0, D3DRTYPE_CUBETEXTURE, d3dFormatInfo.texFormat)); - } - - textureCaps.filterable = SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, D3DUSAGE_QUERY_FILTER, D3DRTYPE_TEXTURE, d3dFormatInfo.texFormat)); - textureCaps.renderable = SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_TEXTURE, d3dFormatInfo.renderFormat)) || - SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, d3dFormatInfo.renderFormat)); - - textureCaps.sampleCounts.insert(1); - for (size_t i = D3DMULTISAMPLE_2_SAMPLES; i <= D3DMULTISAMPLE_16_SAMPLES; i++) - { - D3DMULTISAMPLE_TYPE multisampleType = D3DMULTISAMPLE_TYPE(i); - - HRESULT result = d3d9->CheckDeviceMultiSampleType(adapter, deviceType, d3dFormatInfo.renderFormat, TRUE, multisampleType, NULL); - if (SUCCEEDED(result)) - { - textureCaps.sampleCounts.insert(i); - } - } - - return textureCaps; -} - -void GenerateCaps(IDirect3D9 *d3d9, IDirect3DDevice9 *device, D3DDEVTYPE deviceType, UINT adapter, gl::Caps *caps, - gl::TextureCapsMap *textureCapsMap, gl::Extensions *extensions) -{ - D3DCAPS9 deviceCaps; - if (FAILED(d3d9->GetDeviceCaps(adapter, deviceType, &deviceCaps))) - { - // Can't continue with out device caps - return; - } - - D3DDISPLAYMODE currentDisplayMode; - d3d9->GetAdapterDisplayMode(adapter, ¤tDisplayMode); - - GLuint maxSamples = 0; - const gl::FormatSet &allFormats = gl::GetAllSizedInternalFormats(); - for (gl::FormatSet::const_iterator internalFormat = allFormats.begin(); internalFormat != allFormats.end(); ++internalFormat) - { - gl::TextureCaps textureCaps = GenerateTextureFormatCaps(*internalFormat, d3d9, deviceType, adapter, - currentDisplayMode.Format); - textureCapsMap->insert(*internalFormat, textureCaps); - - maxSamples = std::max(maxSamples, textureCaps.getMaxSamples()); - - if (gl::GetInternalFormatInfo(*internalFormat).compressed) - { - caps->compressedTextureFormats.push_back(*internalFormat); - } - } - - // GL core feature limits - caps->maxElementIndex = static_cast(std::numeric_limits::max()); - - // 3D textures are unimplemented in D3D9 - caps->max3DTextureSize = 1; - - // Only one limit in GL, use the minimum dimension - caps->max2DTextureSize = std::min(deviceCaps.MaxTextureWidth, deviceCaps.MaxTextureHeight); - - // D3D treats cube maps as a special case of 2D textures - caps->maxCubeMapTextureSize = caps->max2DTextureSize; - - // Array textures are not available in D3D9 - caps->maxArrayTextureLayers = 1; - - // ES3-only feature - caps->maxLODBias = 0.0f; - - // No specific limits on render target size, maximum 2D texture size is equivalent - caps->maxRenderbufferSize = caps->max2DTextureSize; - - // Draw buffers are not supported in D3D9 - caps->maxDrawBuffers = 1; - caps->maxColorAttachments = 1; - - // No specific limits on viewport size, maximum 2D texture size is equivalent - caps->maxViewportWidth = caps->max2DTextureSize; - caps->maxViewportHeight = caps->maxViewportWidth; - - // Point size is clamped to 1.0f when the shader model is less than 3 - caps->minAliasedPointSize = 1.0f; - caps->maxAliasedPointSize = ((D3DSHADER_VERSION_MAJOR(deviceCaps.PixelShaderVersion) >= 3) ? deviceCaps.MaxPointSize : 1.0f); - - // Wide lines not supported - caps->minAliasedLineWidth = 1.0f; - caps->maxAliasedLineWidth = 1.0f; - - // Primitive count limits (unused in ES2) - caps->maxElementsIndices = 0; - caps->maxElementsVertices = 0; - - // Program and shader binary formats (no supported shader binary formats) - caps->programBinaryFormats.push_back(GL_PROGRAM_BINARY_ANGLE); - - // WaitSync is ES3-only, set to zero - caps->maxServerWaitTimeout = 0; - - // Vertex shader limits - caps->maxVertexAttributes = 16; - - const size_t reservedVertexUniformVectors = 2; // dx_ViewAdjust and dx_DepthRange. - const size_t MAX_VERTEX_CONSTANT_VECTORS_D3D9 = 256; - caps->maxVertexUniformVectors = MAX_VERTEX_CONSTANT_VECTORS_D3D9 - reservedVertexUniformVectors; - caps->maxVertexUniformComponents = caps->maxVertexUniformVectors * 4; - - caps->maxVertexUniformBlocks = 0; - - // SM3 only supports 11 output variables, with a special 12th register for PSIZE. - const size_t MAX_VERTEX_OUTPUT_VECTORS_SM3 = 9; - const size_t MAX_VERTEX_OUTPUT_VECTORS_SM2 = 7; - caps->maxVertexOutputComponents = ((deviceCaps.VertexShaderVersion >= D3DVS_VERSION(3, 0)) ? MAX_VERTEX_OUTPUT_VECTORS_SM3 - : MAX_VERTEX_OUTPUT_VECTORS_SM2) * 4; - - // Only Direct3D 10 ready devices support all the necessary vertex texture formats. - // We test this using D3D9 by checking support for the R16F format. - if (deviceCaps.VertexShaderVersion >= D3DVS_VERSION(3, 0) && - SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, currentDisplayMode.Format, - D3DUSAGE_QUERY_VERTEXTEXTURE, D3DRTYPE_TEXTURE, D3DFMT_R16F))) - { - const size_t MAX_TEXTURE_IMAGE_UNITS_VTF_SM3 = 4; - caps->maxVertexTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS_VTF_SM3; - } - else - { - caps->maxVertexTextureImageUnits = 0; - } - - // Fragment shader limits - const size_t reservedPixelUniformVectors = 3; // dx_ViewCoords, dx_DepthFront and dx_DepthRange. - - const size_t MAX_PIXEL_CONSTANT_VECTORS_SM3 = 224; - const size_t MAX_PIXEL_CONSTANT_VECTORS_SM2 = 32; - caps->maxFragmentUniformVectors = ((deviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0)) ? MAX_PIXEL_CONSTANT_VECTORS_SM3 - : MAX_PIXEL_CONSTANT_VECTORS_SM2) - reservedPixelUniformVectors; - caps->maxFragmentUniformComponents = caps->maxFragmentUniformVectors * 4; - caps->maxFragmentUniformBlocks = 0; - caps->maxFragmentInputComponents = caps->maxVertexOutputComponents; - caps->maxTextureImageUnits = 16; - caps->minProgramTexelOffset = 0; - caps->maxProgramTexelOffset = 0; - - // Aggregate shader limits (unused in ES2) - caps->maxUniformBufferBindings = 0; - caps->maxUniformBlockSize = 0; - caps->uniformBufferOffsetAlignment = 0; - caps->maxCombinedUniformBlocks = 0; - caps->maxCombinedVertexUniformComponents = 0; - caps->maxCombinedFragmentUniformComponents = 0; - caps->maxVaryingComponents = 0; - - // Aggregate shader limits - caps->maxVaryingVectors = caps->maxVertexOutputComponents / 4; - caps->maxCombinedTextureImageUnits = caps->maxVertexTextureImageUnits + caps->maxTextureImageUnits; - - // Transform feedback limits - caps->maxTransformFeedbackInterleavedComponents = 0; - caps->maxTransformFeedbackSeparateAttributes = 0; - caps->maxTransformFeedbackSeparateComponents = 0; - - // GL extension support - extensions->setTextureExtensionSupport(*textureCapsMap); - extensions->elementIndexUint = deviceCaps.MaxVertexIndex >= (1 << 16); - extensions->packedDepthStencil = true; - extensions->getProgramBinary = true; - extensions->rgb8rgba8 = true; - extensions->readFormatBGRA = true; - extensions->pixelBufferObject = false; - extensions->mapBuffer = false; - extensions->mapBufferRange = false; - - // ATI cards on XP have problems with non-power-of-two textures. - D3DADAPTER_IDENTIFIER9 adapterId = { 0 }; - if (SUCCEEDED(d3d9->GetAdapterIdentifier(adapter, 0, &adapterId))) - { - extensions->textureNPOT = !(deviceCaps.TextureCaps & D3DPTEXTURECAPS_POW2) && - !(deviceCaps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2) && - !(deviceCaps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL) && - !(!isWindowsVistaOrGreater() && adapterId.VendorId == VENDOR_ID_AMD); - } - else - { - extensions->textureNPOT = false; - } - - extensions->drawBuffers = false; - extensions->textureStorage = true; - - // Must support a minimum of 2:1 anisotropy for max anisotropy to be considered supported, per the spec - extensions->textureFilterAnisotropic = (deviceCaps.RasterCaps & D3DPRASTERCAPS_ANISOTROPY) != 0 && deviceCaps.MaxAnisotropy >= 2; - extensions->maxTextureAnisotropy = static_cast(deviceCaps.MaxAnisotropy); - - // Check occlusion query support by trying to create one - IDirect3DQuery9 *occlusionQuery = NULL; - extensions->occlusionQueryBoolean = SUCCEEDED(device->CreateQuery(D3DQUERYTYPE_OCCLUSION, &occlusionQuery)) && occlusionQuery; - SafeRelease(occlusionQuery); - - // Check event query support by trying to create one - IDirect3DQuery9 *eventQuery = NULL; - extensions->fence = SUCCEEDED(device->CreateQuery(D3DQUERYTYPE_EVENT, &eventQuery)) && eventQuery; - SafeRelease(eventQuery); - - extensions->timerQuery = false; // Unimplemented - extensions->robustness = true; - extensions->blendMinMax = true; - extensions->framebufferBlit = true; - extensions->framebufferMultisample = true; - extensions->maxSamples = maxSamples; - extensions->instancedArrays = deviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0); - extensions->packReverseRowOrder = true; - extensions->standardDerivatives = (deviceCaps.PS20Caps.Caps & D3DPS20CAPS_GRADIENTINSTRUCTIONS) != 0; - extensions->shaderTextureLOD = true; - extensions->fragDepth = true; - extensions->textureUsage = true; - extensions->translatedShaderSource = true; - extensions->colorBufferFloat = false; -} - -} - -namespace d3d9 -{ - -GLuint ComputeBlockSize(D3DFORMAT format, GLuint width, GLuint height) -{ - const D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(format); - GLuint numBlocksWide = (width + d3dFormatInfo.blockWidth - 1) / d3dFormatInfo.blockWidth; - GLuint numBlocksHight = (height + d3dFormatInfo.blockHeight - 1) / d3dFormatInfo.blockHeight; - return (d3dFormatInfo.pixelBytes * numBlocksWide * numBlocksHight); -} - -void MakeValidSize(bool isImage, D3DFORMAT format, GLsizei *requestWidth, GLsizei *requestHeight, int *levelOffset) -{ - const D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(format); - - int upsampleCount = 0; - // Don't expand the size of full textures that are at least (blockWidth x blockHeight) already. - if (isImage || *requestWidth < static_cast(d3dFormatInfo.blockWidth) || - *requestHeight < static_cast(d3dFormatInfo.blockHeight)) - { - while (*requestWidth % d3dFormatInfo.blockWidth != 0 || *requestHeight % d3dFormatInfo.blockHeight != 0) - { - *requestWidth <<= 1; - *requestHeight <<= 1; - upsampleCount++; - } - } - *levelOffset = upsampleCount; -} - -gl::Error GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment, RenderTarget9 **outRT) -{ - RenderTarget *renderTarget = NULL; - gl::Error error = rx::GetAttachmentRenderTarget(attachment, &renderTarget); - if (error.isError()) - { - return error; - } - *outRT = RenderTarget9::makeRenderTarget9(renderTarget); - return gl::Error(GL_NO_ERROR); -} - -Workarounds GenerateWorkarounds() -{ - Workarounds workarounds; - workarounds.mrtPerfWorkaround = true; - workarounds.setDataFasterThanImageUpload = false; - return workarounds; -} - -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.h deleted file mode 100644 index 9760b9735a..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.h +++ /dev/null @@ -1,86 +0,0 @@ -// -// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// 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/angletypes.h" -#include "libGLESv2/Caps.h" -#include "libGLESv2/Error.h" - -namespace gl -{ -class FramebufferAttachment; -} - -namespace rx -{ -class RenderTarget9; -struct Workarounds; - -namespace gl_d3d9 -{ - -D3DCMPFUNC ConvertComparison(GLenum comparison); -D3DCOLOR ConvertColor(gl::ColorF 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); - -D3DMULTISAMPLE_TYPE GetMultisampleType(GLuint samples); - -} - -namespace d3d9_gl -{ - -GLsizei GetSamplesCount(D3DMULTISAMPLE_TYPE type); - -bool IsFormatChannelEquivalent(D3DFORMAT d3dformat, GLenum format); - -void GenerateCaps(IDirect3D9 *d3d9, IDirect3DDevice9 *device, D3DDEVTYPE deviceType, UINT adapter, gl::Caps *caps, - gl::TextureCapsMap *textureCapsMap, gl::Extensions *extensions); - -} - -namespace d3d9 -{ - -GLuint ComputeBlockSize(D3DFORMAT format, GLuint width, GLuint height); - -void MakeValidSize(bool isImage, D3DFORMAT format, GLsizei *requestWidth, GLsizei *requestHeight, int *levelOffset); - -inline bool isDeviceLostError(HRESULT errorCode) -{ - switch (errorCode) - { - case D3DERR_DRIVERINTERNALERROR: - case D3DERR_DEVICELOST: - case D3DERR_DEVICEHUNG: - case D3DERR_DEVICEREMOVED: - return true; - default: - return false; - } -} - -gl::Error GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment, RenderTarget9 **outRT); -Workarounds GenerateWorkarounds(); - -} - -} - -#endif // LIBGLESV2_RENDERER_RENDERER9_UTILS_H diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/shaders/Blit.ps b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/shaders/Blit.ps deleted file mode 100644 index eb43eb3e7a..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/shaders/Blit.ps +++ /dev/null @@ -1,33 +0,0 @@ -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -sampler2D tex : s0; - -uniform float4 mult : c0; -uniform float4 add : c1; - -// Passthrough Pixel Shader -// Outputs texture 0 sampled at texcoord 0. -float4 PS_passthrough(float4 texcoord : TEXCOORD0) : COLOR -{ - return tex2D(tex, texcoord.xy); -}; - -// Luminance Conversion Pixel Shader -// Performs a mad operation using the LA data from the texture with mult.xw and add.xw. -// Returns data in the form of llla -float4 PS_luminance(float4 texcoord : TEXCOORD0) : COLOR -{ - return (tex2D(tex, texcoord.xy).xw * mult.xw + add.xw).xxxy; -}; - -// RGB/A Component Mask Pixel Shader -// Performs a mad operation using the texture's RGBA data with mult.xyzw and add.xyzw. -// Returns data in the form of rgba -float4 PS_componentmask(float4 texcoord : TEXCOORD0) : COLOR -{ - return tex2D(tex, texcoord.xy) * mult + add; -}; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/shaders/Blit.vs b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/shaders/Blit.vs deleted file mode 100644 index 3bd611ba5d..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/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 VS_standard(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 VS_flipy(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/generatemip.h b/src/3rdparty/angle/src/libGLESv2/renderer/generatemip.h deleted file mode 100644 index a57b00d444..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/generatemip.h +++ /dev/null @@ -1,28 +0,0 @@ -// -// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// 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/renderer/imageformats.h" -#include "libGLESv2/angletypes.h" - -namespace rx -{ - -template -inline void GenerateMip(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth, - const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch, - uint8_t *destData, size_t destRowPitch, size_t destDepthPitch); - -} - -#include "generatemip.inl" - -#endif // LIBGLESV2_RENDERER_GENERATEMIP_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/generatemip.inl b/src/3rdparty/angle/src/libGLESv2/renderer/generatemip.inl deleted file mode 100644 index 6788a42f03..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/generatemip.inl +++ /dev/null @@ -1,266 +0,0 @@ -// -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// generatemip.inl: Defines the GenerateMip function, templated on the format -// type of the image for which mip levels are being generated. - -#include "common/mathutil.h" - -namespace rx -{ - -namespace priv -{ - -template -static inline T *GetPixel(uint8_t *data, size_t x, size_t y, size_t z, size_t rowPitch, size_t depthPitch) -{ - return reinterpret_cast(data + (x * sizeof(T)) + (y * rowPitch) + (z * depthPitch)); -} - -template -static inline const T *GetPixel(const uint8_t *data, size_t x, size_t y, size_t z, size_t rowPitch, size_t depthPitch) -{ - return reinterpret_cast(data + (x * sizeof(T)) + (y * rowPitch) + (z * depthPitch)); -} - -template -static void GenerateMip_Y(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth, - const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch, - size_t destWidth, size_t destHeight, size_t destDepth, - uint8_t *destData, size_t destRowPitch, size_t destDepthPitch) -{ - ASSERT(sourceWidth == 1); - ASSERT(sourceHeight > 1); - ASSERT(sourceDepth == 1); - - for (size_t y = 0; y < destHeight; y++) - { - const T *src0 = GetPixel(sourceData, 0, y * 2, 0, sourceRowPitch, sourceDepthPitch); - const T *src1 = GetPixel(sourceData, 0, y * 2 + 1, 0, sourceRowPitch, sourceDepthPitch); - T *dst = GetPixel(destData, 0, y, 0, destRowPitch, destDepthPitch); - - T::average(dst, src0, src1); - } -} - -template -static void GenerateMip_X(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth, - const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch, - size_t destWidth, size_t destHeight, size_t destDepth, - uint8_t *destData, size_t destRowPitch, size_t destDepthPitch) -{ - ASSERT(sourceWidth > 1); - ASSERT(sourceHeight == 1); - ASSERT(sourceDepth == 1); - - for (size_t x = 0; x < destWidth; x++) - { - const T *src0 = GetPixel(sourceData, x * 2, 0, 0, sourceRowPitch, sourceDepthPitch); - const T *src1 = GetPixel(sourceData, x * 2 + 1, 0, 0, sourceRowPitch, sourceDepthPitch); - T *dst = GetPixel(destData, x, 0, 0, destRowPitch, destDepthPitch); - - T::average(dst, src0, src1); - } -} - -template -static void GenerateMip_Z(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth, - const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch, - size_t destWidth, size_t destHeight, size_t destDepth, - uint8_t *destData, size_t destRowPitch, size_t destDepthPitch) -{ - ASSERT(sourceWidth == 1); - ASSERT(sourceHeight == 1); - ASSERT(sourceDepth > 1); - - for (size_t z = 0; z < destDepth; z++) - { - const T *src0 = GetPixel(sourceData, 0, 0, z * 2, sourceRowPitch, sourceDepthPitch); - const T *src1 = GetPixel(sourceData, 0, 0, z * 2 + 1, sourceRowPitch, sourceDepthPitch); - T *dst = GetPixel(destData, 0, 0, z, destRowPitch, destDepthPitch); - - T::average(dst, src0, src1); - } -} - -template -static void GenerateMip_XY(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth, - const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch, - size_t destWidth, size_t destHeight, size_t destDepth, - uint8_t *destData, size_t destRowPitch, size_t destDepthPitch) -{ - ASSERT(sourceWidth > 1); - ASSERT(sourceHeight > 1); - ASSERT(sourceDepth == 1); - - for (size_t y = 0; y < destHeight; y++) - { - for (size_t x = 0; x < destWidth; x++) - { - const T *src0 = GetPixel(sourceData, x * 2, y * 2, 0, sourceRowPitch, sourceDepthPitch); - const T *src1 = GetPixel(sourceData, x * 2, y * 2 + 1, 0, sourceRowPitch, sourceDepthPitch); - const T *src2 = GetPixel(sourceData, x * 2 + 1, y * 2, 0, sourceRowPitch, sourceDepthPitch); - const T *src3 = GetPixel(sourceData, x * 2 + 1, y * 2 + 1, 0, sourceRowPitch, sourceDepthPitch); - T *dst = GetPixel(destData, x, y, 0, destRowPitch, destDepthPitch); - - T tmp0, tmp1; - - T::average(&tmp0, src0, src1); - T::average(&tmp1, src2, src3); - T::average(dst, &tmp0, &tmp1); - } - } -} - -template -static void GenerateMip_YZ(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth, - const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch, - size_t destWidth, size_t destHeight, size_t destDepth, - uint8_t *destData, size_t destRowPitch, size_t destDepthPitch) -{ - ASSERT(sourceWidth == 1); - ASSERT(sourceHeight > 1); - ASSERT(sourceDepth > 1); - - for (size_t z = 0; z < destDepth; z++) - { - for (size_t y = 0; y < destHeight; y++) - { - const T *src0 = GetPixel(sourceData, 0, y * 2, z * 2, sourceRowPitch, sourceDepthPitch); - const T *src1 = GetPixel(sourceData, 0, y * 2, z * 2 + 1, sourceRowPitch, sourceDepthPitch); - const T *src2 = GetPixel(sourceData, 0, y * 2 + 1, z * 2, sourceRowPitch, sourceDepthPitch); - const T *src3 = GetPixel(sourceData, 0, y * 2 + 1, z * 2 + 1, sourceRowPitch, sourceDepthPitch); - T *dst = GetPixel(destData, 0, y, z, destRowPitch, destDepthPitch); - - T tmp0, tmp1; - - T::average(&tmp0, src0, src1); - T::average(&tmp1, src2, src3); - T::average(dst, &tmp0, &tmp1); - } - } -} - -template -static void GenerateMip_XZ(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth, - const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch, - size_t destWidth, size_t destHeight, size_t destDepth, - uint8_t *destData, size_t destRowPitch, size_t destDepthPitch) -{ - ASSERT(sourceWidth > 1); - ASSERT(sourceHeight == 1); - ASSERT(sourceDepth > 1); - - for (size_t z = 0; z < destDepth; z++) - { - for (size_t x = 0; x < destWidth; x++) - { - const T *src0 = GetPixel(sourceData, x * 2, 0, z * 2, sourceRowPitch, sourceDepthPitch); - const T *src1 = GetPixel(sourceData, x * 2, 0, z * 2 + 1, sourceRowPitch, sourceDepthPitch); - const T *src2 = GetPixel(sourceData, x * 2 + 1, 0, z * 2, sourceRowPitch, sourceDepthPitch); - const T *src3 = GetPixel(sourceData, x * 2 + 1, 0, z * 2 + 1, sourceRowPitch, sourceDepthPitch); - T *dst = GetPixel(destData, x, 0, z, destRowPitch, destDepthPitch); - - T tmp0, tmp1; - - T::average(&tmp0, src0, src1); - T::average(&tmp1, src2, src3); - T::average(dst, &tmp0, &tmp1); - } - } -} - -template -static void GenerateMip_XYZ(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth, - const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch, - size_t destWidth, size_t destHeight, size_t destDepth, - uint8_t *destData, size_t destRowPitch, size_t destDepthPitch) -{ - ASSERT(sourceWidth > 1); - ASSERT(sourceHeight > 1); - ASSERT(sourceDepth > 1); - - for (size_t z = 0; z < destDepth; z++) - { - for (size_t y = 0; y < destHeight; y++) - { - for (size_t x = 0; x < destWidth; x++) - { - const T *src0 = GetPixel(sourceData, x * 2, y * 2, z * 2, sourceRowPitch, sourceDepthPitch); - const T *src1 = GetPixel(sourceData, x * 2, y * 2, z * 2 + 1, sourceRowPitch, sourceDepthPitch); - const T *src2 = GetPixel(sourceData, x * 2, y * 2 + 1, z * 2, sourceRowPitch, sourceDepthPitch); - const T *src3 = GetPixel(sourceData, x * 2, y * 2 + 1, z * 2 + 1, sourceRowPitch, sourceDepthPitch); - const T *src4 = GetPixel(sourceData, x * 2 + 1, y * 2, z * 2, sourceRowPitch, sourceDepthPitch); - const T *src5 = GetPixel(sourceData, x * 2 + 1, y * 2, z * 2 + 1, sourceRowPitch, sourceDepthPitch); - const T *src6 = GetPixel(sourceData, x * 2 + 1, y * 2 + 1, z * 2, sourceRowPitch, sourceDepthPitch); - const T *src7 = GetPixel(sourceData, x * 2 + 1, y * 2 + 1, z * 2 + 1, sourceRowPitch, sourceDepthPitch); - T *dst = GetPixel(destData, x, y, z, destRowPitch, destDepthPitch); - - T tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; - - T::average(&tmp0, src0, src1); - T::average(&tmp1, src2, src3); - T::average(&tmp2, src4, src5); - T::average(&tmp3, src6, src7); - - T::average(&tmp4, &tmp0, &tmp1); - T::average(&tmp5, &tmp2, &tmp3); - - T::average(dst, &tmp4, &tmp5); - } - } - } -} - - -typedef void (*MipGenerationFunction)(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth, - const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch, - size_t destWidth, size_t destHeight, size_t destDepth, - uint8_t *destData, size_t destRowPitch, size_t destDepthPitch); - -template -static MipGenerationFunction GetMipGenerationFunction(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth) -{ - uint8_t index = ((sourceWidth > 1) ? 1 : 0) | - ((sourceHeight > 1) ? 2 : 0) | - ((sourceDepth > 1) ? 4 : 0); - - switch (index) - { - case 0: return NULL; - case 1: return GenerateMip_X; // W x 1 x 1 - case 2: return GenerateMip_Y; // 1 x H x 1 - case 3: return GenerateMip_XY; // W x H x 1 - case 4: return GenerateMip_Z; // 1 x 1 x D - case 5: return GenerateMip_XZ; // W x 1 x D - case 6: return GenerateMip_YZ; // 1 x H x D - case 7: return GenerateMip_XYZ; // W x H x D - } - - UNREACHABLE(); - return NULL; -} - -} - -template -inline void GenerateMip(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth, - const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch, - uint8_t *destData, size_t destRowPitch, size_t destDepthPitch) -{ - size_t mipWidth = std::max(1, sourceWidth >> 1); - size_t mipHeight = std::max(1, sourceHeight >> 1); - size_t mipDepth = std::max(1, sourceDepth >> 1); - - priv::MipGenerationFunction generationFunction = priv::GetMipGenerationFunction(sourceWidth, sourceHeight, sourceDepth); - ASSERT(generationFunction != NULL); - - generationFunction(sourceWidth, sourceHeight, sourceDepth, sourceData, sourceRowPitch, sourceDepthPitch, - mipWidth, mipHeight, mipDepth, destData, destRowPitch, destDepthPitch); -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/imageformats.h b/src/3rdparty/angle/src/libGLESv2/renderer/imageformats.h deleted file mode 100644 index 2140a9ee72..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/imageformats.h +++ /dev/null @@ -1,2029 +0,0 @@ -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// imageformats.h: Defines image format types with functions for mip generation -// and copying. - -#ifndef LIBGLESV2_RENDERER_IMAGEFORMATS_H_ -#define LIBGLESV2_RENDERER_IMAGEFORMATS_H_ - -#include "common/mathutil.h" - -namespace rx -{ - -// Several structures share functionality for reading, writing or mipmapping but the layout -// must match the texture format which the structure represents. If collapsing or typedefing -// structs in this header, make sure the functionality and memory layout is exactly the same. - -struct L8 -{ - unsigned char L; - - static void readColor(gl::ColorF *dst, const L8 *src) - { - const float lum = gl::normalizedToFloat(src->L); - dst->red = lum; - dst->green = lum; - dst->blue = lum; - dst->alpha = 1.0f; - } - - static void writeColor(L8 *dst, const gl::ColorF *src) - { - dst->L = gl::floatToNormalized((src->red + src->green + src->blue) / 3.0f); - } - - static void average(L8 *dst, const L8 *src1, const L8 *src2) - { - dst->L = gl::average(src1->L, src2->L); - } -}; - -struct R8 -{ - unsigned char R; - - static void readColor(gl::ColorF *dst, const R8 *src) - { - dst->red = gl::normalizedToFloat(src->R); - dst->green = 0.0f; - dst->blue = 0.0f; - dst->alpha = 1.0f; - } - - static void readColor(gl::ColorUI *dst, const R8 *src) - { - dst->red = src->R; - dst->green = 0; - dst->blue = 0; - dst->alpha = 1; - } - - static void writeColor(R8 *dst, const gl::ColorF *src) - { - dst->R = gl::floatToNormalized(src->red); - } - - static void writeColor(R8 *dst, const gl::ColorUI *src) - { - dst->R = static_cast(src->red); - } - - static void average(R8 *dst, const R8 *src1, const R8 *src2) - { - dst->R = gl::average(src1->R, src2->R); - } -}; - -struct A8 -{ - unsigned char A; - - static void readColor(gl::ColorF *dst, const A8 *src) - { - dst->red = 0.0f; - dst->green = 0.0f; - dst->blue = 0.0f; - dst->alpha = gl::normalizedToFloat(src->A); - } - - static void writeColor(A8 *dst, const gl::ColorF *src) - { - dst->A = gl::floatToNormalized(src->alpha); - } - - static void average(A8 *dst, const A8 *src1, const A8 *src2) - { - dst->A = gl::average(src1->A, src2->A); - } -}; - -struct L8A8 -{ - unsigned char L; - unsigned char A; - - static void readColor(gl::ColorF *dst, const L8A8 *src) - { - const float lum = gl::normalizedToFloat(src->L); - dst->red = lum; - dst->green = lum; - dst->blue = lum; - dst->alpha = gl::normalizedToFloat(src->A); - } - - static void writeColor(L8A8 *dst, const gl::ColorF *src) - { - dst->L = gl::floatToNormalized((src->red + src->green + src->blue) / 3.0f); - dst->A = gl::floatToNormalized(src->alpha); - } - - static void average(L8A8 *dst, const L8A8 *src1, const L8A8 *src2) - { - *(unsigned short*)dst = (((*(unsigned short*)src1 ^ *(unsigned short*)src2) & 0xFEFE) >> 1) + (*(unsigned short*)src1 & *(unsigned short*)src2); - } -}; - -struct A8L8 -{ - unsigned char A; - unsigned char L; - - static void readColor(gl::ColorF *dst, const A8L8 *src) - { - const float lum = gl::normalizedToFloat(src->L); - dst->red = lum; - dst->green = lum; - dst->blue = lum; - dst->alpha = gl::normalizedToFloat(src->A); - } - - static void writeColor(A8L8 *dst, const gl::ColorF *src) - { - dst->L = gl::floatToNormalized((src->red + src->green + src->blue) / 3.0f); - dst->A = gl::floatToNormalized(src->alpha); - } - - 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 R8G8 -{ - unsigned char R; - unsigned char G; - - static void readColor(gl::ColorF *dst, const R8G8 *src) - { - dst->red = gl::normalizedToFloat(src->R); - dst->green = gl::normalizedToFloat(src->G); - dst->blue = 0.0f; - dst->alpha = 1.0f; - } - - static void readColor(gl::ColorUI *dst, const R8G8 *src) - { - dst->red = src->R; - dst->green = src->G; - dst->blue = 0; - dst->alpha = 1; - } - - static void writeColor(R8G8 *dst, const gl::ColorF *src) - { - dst->R = gl::floatToNormalized(src->red); - dst->G = gl::floatToNormalized(src->green); - } - - static void writeColor(R8G8 *dst, const gl::ColorUI *src) - { - dst->R = static_cast(src->red); - dst->G = static_cast(src->green); - } - - static void average(R8G8 *dst, const R8G8 *src1, const R8G8 *src2) - { - *(unsigned short*)dst = (((*(unsigned short*)src1 ^ *(unsigned short*)src2) & 0xFEFE) >> 1) + (*(unsigned short*)src1 & *(unsigned short*)src2); - } -}; - -struct R8G8B8 -{ - unsigned char R; - unsigned char G; - unsigned char B; - - static void readColor(gl::ColorF *dst, const R8G8B8 *src) - { - dst->red = gl::normalizedToFloat(src->R); - dst->green = gl::normalizedToFloat(src->G); - dst->blue = gl::normalizedToFloat(src->B); - dst->alpha = 1.0f; - } - - static void readColor(gl::ColorUI *dst, const R8G8B8 *src) - { - dst->red = src->R; - dst->green = src->G; - dst->blue = src->G; - dst->alpha = 1; - } - - static void writeColor(R8G8B8 *dst, const gl::ColorF *src) - { - dst->R = gl::floatToNormalized(src->red); - dst->G = gl::floatToNormalized(src->green); - dst->B = gl::floatToNormalized(src->blue); - } - - static void writeColor(R8G8B8 *dst, const gl::ColorUI *src) - { - dst->R = static_cast(src->red); - dst->G = static_cast(src->green); - dst->B = static_cast(src->blue); - } - - static void average(R8G8B8 *dst, const R8G8B8 *src1, const R8G8B8 *src2) - { - dst->R = gl::average(src1->R, src2->R); - dst->G = gl::average(src1->G, src2->G); - dst->B = gl::average(src1->B, src2->B); - } -}; - -struct B8G8R8 -{ - unsigned char B; - unsigned char G; - unsigned char R; - - static void readColor(gl::ColorF *dst, const B8G8R8 *src) - { - dst->red = gl::normalizedToFloat(src->R); - dst->green = gl::normalizedToFloat(src->G); - dst->blue = gl::normalizedToFloat(src->B); - dst->alpha = 1.0f; - } - - static void readColor(gl::ColorUI *dst, const B8G8R8 *src) - { - dst->red = src->R; - dst->green = src->G; - dst->blue = src->G; - dst->alpha = 1; - } - - static void writeColor(B8G8R8 *dst, const gl::ColorF *src) - { - dst->R = gl::floatToNormalized(src->red); - dst->G = gl::floatToNormalized(src->green); - dst->B = gl::floatToNormalized(src->blue); - } - - static void writeColor(B8G8R8 *dst, const gl::ColorUI *src) - { - dst->R = static_cast(src->red); - dst->G = static_cast(src->green); - dst->B = static_cast(src->blue); - } - - static void average(B8G8R8 *dst, const B8G8R8 *src1, const B8G8R8 *src2) - { - dst->R = gl::average(src1->R, src2->R); - dst->G = gl::average(src1->G, src2->G); - dst->B = gl::average(src1->B, src2->B); - } -}; - -struct R5G6B5 -{ - unsigned short RGB; - - static void readColor(gl::ColorF *dst, const R5G6B5 *src) - { - dst->red = gl::normalizedToFloat<5>(gl::getShiftedData<5, 11>(src->RGB)); - dst->green = gl::normalizedToFloat<6>(gl::getShiftedData<6, 5>(src->RGB)); - dst->blue = gl::normalizedToFloat<5>(gl::getShiftedData<5, 0>(src->RGB)); - dst->alpha = 1.0f; - } - - static void writeColor(R5G6B5 *dst, const gl::ColorF *src) - { - dst->RGB = gl::shiftData<5, 11>(gl::floatToNormalized<5, unsigned short>(src->red)) | - gl::shiftData<6, 5>(gl::floatToNormalized<6, unsigned short>(src->green)) | - gl::shiftData<5, 0>(gl::floatToNormalized<5, unsigned short>(src->blue)); - } - - static void average(R5G6B5 *dst, const R5G6B5 *src1, const R5G6B5 *src2) - { - dst->RGB = gl::shiftData<5, 11>(gl::average(gl::getShiftedData<5, 11>(src1->RGB), gl::getShiftedData<5, 11>(src2->RGB))) | - gl::shiftData<6, 5>(gl::average(gl::getShiftedData<6, 5>(src1->RGB), gl::getShiftedData<6, 5>(src2->RGB))) | - gl::shiftData<5, 0>(gl::average(gl::getShiftedData<5, 0>(src1->RGB), gl::getShiftedData<5, 0>(src2->RGB))); - } -}; - -struct A8R8G8B8 -{ - unsigned char A; - unsigned char R; - unsigned char G; - unsigned char B; - - static void readColor(gl::ColorF *dst, const A8R8G8B8 *src) - { - dst->red = gl::normalizedToFloat(src->R); - dst->green = gl::normalizedToFloat(src->G); - dst->blue = gl::normalizedToFloat(src->B); - dst->alpha = gl::normalizedToFloat(src->A); - } - - static void readColor(gl::ColorUI *dst, const A8R8G8B8 *src) - { - dst->red = src->R; - dst->green = src->G; - dst->blue = src->B; - dst->alpha = src->A; - } - - static void writeColor(A8R8G8B8 *dst, const gl::ColorF *src) - { - dst->R = gl::floatToNormalized(src->red); - dst->G = gl::floatToNormalized(src->green); - dst->B = gl::floatToNormalized(src->blue); - dst->A = gl::floatToNormalized(src->alpha); - } - - static void writeColor(A8R8G8B8 *dst, const gl::ColorUI *src) - { - dst->R = static_cast(src->red); - dst->G = static_cast(src->green); - dst->B = static_cast(src->blue); - dst->A = static_cast(src->alpha); - } - - 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 R8G8B8A8 -{ - unsigned char R; - unsigned char G; - unsigned char B; - unsigned char A; - - static void readColor(gl::ColorF *dst, const R8G8B8A8 *src) - { - dst->red = gl::normalizedToFloat(src->R); - dst->green = gl::normalizedToFloat(src->G); - dst->blue = gl::normalizedToFloat(src->B); - dst->alpha = gl::normalizedToFloat(src->A); - } - - static void readColor(gl::ColorUI *dst, const R8G8B8A8 *src) - { - dst->red = src->R; - dst->green = src->G; - dst->blue = src->B; - dst->alpha = src->A; - } - - static void writeColor(R8G8B8A8 *dst, const gl::ColorF *src) - { - dst->R = gl::floatToNormalized(src->red); - dst->G = gl::floatToNormalized(src->green); - dst->B = gl::floatToNormalized(src->blue); - dst->A = gl::floatToNormalized(src->alpha); - } - - static void writeColor(R8G8B8A8 *dst, const gl::ColorUI *src) - { - dst->R = static_cast(src->red); - dst->G = static_cast(src->green); - dst->B = static_cast(src->blue); - dst->A = static_cast(src->alpha); - } - - static void average(R8G8B8A8 *dst, const R8G8B8A8 *src1, const R8G8B8A8 *src2) - { - *(unsigned int*)dst = (((*(unsigned int*)src1 ^ *(unsigned int*)src2) & 0xFEFEFEFE) >> 1) + (*(unsigned int*)src1 & *(unsigned int*)src2); - } -}; - -struct B8G8R8A8 -{ - unsigned char B; - unsigned char G; - unsigned char R; - unsigned char A; - - static void readColor(gl::ColorF *dst, const B8G8R8A8 *src) - { - dst->red = gl::normalizedToFloat(src->R); - dst->green = gl::normalizedToFloat(src->G); - dst->blue = gl::normalizedToFloat(src->B); - dst->alpha = gl::normalizedToFloat(src->A); - } - - static void readColor(gl::ColorUI *dst, const B8G8R8A8 *src) - { - dst->red = src->R; - dst->green = src->G; - dst->blue = src->B; - dst->alpha = src->A; - } - - static void writeColor(B8G8R8A8 *dst, const gl::ColorF *src) - { - dst->R = gl::floatToNormalized(src->red); - dst->G = gl::floatToNormalized(src->green); - dst->B = gl::floatToNormalized(src->blue); - dst->A = gl::floatToNormalized(src->alpha); - } - - static void writeColor(B8G8R8A8 *dst, const gl::ColorUI *src) - { - dst->R = static_cast(src->red); - dst->G = static_cast(src->green); - dst->B = static_cast(src->blue); - dst->A = static_cast(src->alpha); - } - - static void average(B8G8R8A8 *dst, const B8G8R8A8 *src1, const B8G8R8A8 *src2) - { - *(unsigned int*)dst = (((*(unsigned int*)src1 ^ *(unsigned int*)src2) & 0xFEFEFEFE) >> 1) + (*(unsigned int*)src1 & *(unsigned int*)src2); - } -}; - -struct B8G8R8X8 -{ - unsigned char B; - unsigned char G; - unsigned char R; - unsigned char X; - - static void readColor(gl::ColorF *dst, const B8G8R8X8 *src) - { - dst->red = gl::normalizedToFloat(src->R); - dst->green = gl::normalizedToFloat(src->G); - dst->blue = gl::normalizedToFloat(src->B); - dst->alpha = 1.0f; - } - - static void readColor(gl::ColorUI *dst, const B8G8R8X8 *src) - { - dst->red = src->R; - dst->green = src->G; - dst->blue = src->B; - dst->alpha = 1; - } - - static void writeColor(B8G8R8X8 *dst, const gl::ColorF *src) - { - dst->R = gl::floatToNormalized(src->red); - dst->G = gl::floatToNormalized(src->green); - dst->B = gl::floatToNormalized(src->blue); - dst->X = 255; - } - - static void writeColor(B8G8R8X8 *dst, const gl::ColorUI *src) - { - dst->R = static_cast(src->red); - dst->G = static_cast(src->green); - dst->B = static_cast(src->blue); - dst->X = 255; - } - - static void average(B8G8R8X8 *dst, const B8G8R8X8 *src1, const B8G8R8X8 *src2) - { - *(unsigned int*)dst = (((*(unsigned int*)src1 ^ *(unsigned int*)src2) & 0xFEFEFEFE) >> 1) + (*(unsigned int*)src1 & *(unsigned int*)src2); - dst->X = 255; - } -}; - -struct B5G5R5A1 -{ - unsigned short BGRA; - - static void readColor(gl::ColorF *dst, const B5G5R5A1 *src) - { - dst->alpha = gl::normalizedToFloat<1>(gl::getShiftedData<1, 15>(src->BGRA)); - dst->red = gl::normalizedToFloat<5>(gl::getShiftedData<5, 10>(src->BGRA)); - dst->green = gl::normalizedToFloat<5>(gl::getShiftedData<5, 5>(src->BGRA)); - dst->blue = gl::normalizedToFloat<5>(gl::getShiftedData<5, 0>(src->BGRA)); - } - - static void writeColor(B5G5R5A1 *dst, const gl::ColorF *src) - { - dst->BGRA = gl::shiftData<1, 15>(gl::floatToNormalized<1, unsigned short>(src->alpha)) | - gl::shiftData<5, 10>(gl::floatToNormalized<5, unsigned short>(src->red)) | - gl::shiftData<5, 5>(gl::floatToNormalized<5, unsigned short>(src->green)) | - gl::shiftData<5, 0>(gl::floatToNormalized<5, unsigned short>(src->blue)); - } - - static void average(B5G5R5A1 *dst, const B5G5R5A1 *src1, const B5G5R5A1 *src2) - { - dst->BGRA = gl::shiftData<1, 15>(gl::average(gl::getShiftedData<1, 15>(src1->BGRA), gl::getShiftedData<1, 15>(src2->BGRA))) | - gl::shiftData<5, 10>(gl::average(gl::getShiftedData<5, 10>(src1->BGRA), gl::getShiftedData<5, 10>(src2->BGRA))) | - gl::shiftData<5, 5>(gl::average(gl::getShiftedData<5, 5>(src1->BGRA), gl::getShiftedData<5, 5>(src2->BGRA))) | - gl::shiftData<5, 0>(gl::average(gl::getShiftedData<5, 0>(src1->BGRA), gl::getShiftedData<5, 0>(src2->BGRA))); - } -}; - -struct R5G5B5A1 -{ - unsigned short RGBA; - - static void readColor(gl::ColorF *dst, const R5G5B5A1 *src) - { - dst->alpha = gl::normalizedToFloat<1>(gl::getShiftedData<1, 15>(src->RGBA)); - dst->blue = gl::normalizedToFloat<5>(gl::getShiftedData<5, 10>(src->RGBA)); - dst->green = gl::normalizedToFloat<5>(gl::getShiftedData<5, 5>(src->RGBA)); - dst->red = gl::normalizedToFloat<5>(gl::getShiftedData<5, 0>(src->RGBA)); - } - - static void writeColor(R5G5B5A1 *dst, const gl::ColorF *src) - { - dst->RGBA = gl::shiftData<1, 15>(gl::floatToNormalized<1, unsigned short>(src->alpha)) | - gl::shiftData<5, 10>(gl::floatToNormalized<5, unsigned short>(src->blue)) | - gl::shiftData<5, 5>(gl::floatToNormalized<5, unsigned short>(src->green)) | - gl::shiftData<5, 0>(gl::floatToNormalized<5, unsigned short>(src->red)); - } - - static void average(R5G5B5A1 *dst, const R5G5B5A1 *src1, const R5G5B5A1 *src2) - { - dst->RGBA = gl::shiftData<1, 15>(gl::average(gl::getShiftedData<1, 15>(src1->RGBA), gl::getShiftedData<1, 15>(src2->RGBA))) | - gl::shiftData<5, 10>(gl::average(gl::getShiftedData<5, 10>(src1->RGBA), gl::getShiftedData<5, 10>(src2->RGBA))) | - gl::shiftData<5, 5>(gl::average(gl::getShiftedData<5, 5>(src1->RGBA), gl::getShiftedData<5, 5>(src2->RGBA))) | - gl::shiftData<5, 0>(gl::average(gl::getShiftedData<5, 0>(src1->RGBA), gl::getShiftedData<5, 0>(src2->RGBA))); - } -}; - -struct R4G4B4A4 -{ - unsigned char R : 4; - unsigned char G : 4; - unsigned char B : 4; - unsigned char A : 4; - - static void readColor(gl::ColorF *dst, const R4G4B4A4 *src) - { - dst->red = gl::normalizedToFloat<4>(src->R); - dst->green = gl::normalizedToFloat<4>(src->G); - dst->blue = gl::normalizedToFloat<4>(src->B); - dst->alpha = gl::normalizedToFloat<4>(src->A); - } - - static void writeColor(R4G4B4A4 *dst, const gl::ColorF *src) - { - dst->R = gl::floatToNormalized<4, unsigned char>(src->red); - dst->G = gl::floatToNormalized<4, unsigned char>(src->green); - dst->B = gl::floatToNormalized<4, unsigned char>(src->blue); - dst->A = gl::floatToNormalized<4, unsigned char>(src->alpha); - } - - static void average(R4G4B4A4 *dst, const R4G4B4A4 *src1, const R4G4B4A4 *src2) - { - dst->R = gl::average(src1->R, src2->R); - dst->G = gl::average(src1->G, src2->G); - dst->B = gl::average(src1->B, src2->B); - dst->A = gl::average(src1->A, src2->A); - } -}; - -struct A4R4G4B4 -{ - unsigned char A : 4; - unsigned char R : 4; - unsigned char G : 4; - unsigned char B : 4; - - static void readColor(gl::ColorF *dst, const A4R4G4B4 *src) - { - dst->red = gl::normalizedToFloat<4>(src->R); - dst->green = gl::normalizedToFloat<4>(src->G); - dst->blue = gl::normalizedToFloat<4>(src->B); - dst->alpha = gl::normalizedToFloat<4>(src->A); - } - - static void writeColor(A4R4G4B4 *dst, const gl::ColorF *src) - { - dst->R = gl::floatToNormalized<4, unsigned char>(src->red); - dst->G = gl::floatToNormalized<4, unsigned char>(src->green); - dst->B = gl::floatToNormalized<4, unsigned char>(src->blue); - dst->A = gl::floatToNormalized<4, unsigned char>(src->alpha); - } - - static void average(A4R4G4B4 *dst, const A4R4G4B4 *src1, const A4R4G4B4 *src2) - { - dst->R = gl::average(src1->R, src2->R); - dst->G = gl::average(src1->G, src2->G); - dst->B = gl::average(src1->B, src2->B); - dst->A = gl::average(src1->A, src2->A); - } -}; - -struct B4G4R4A4 -{ - unsigned char B : 4; - unsigned char G : 4; - unsigned char R : 4; - unsigned char A : 4; - - static void readColor(gl::ColorF *dst, const B4G4R4A4 *src) - { - dst->red = gl::normalizedToFloat<4>(src->R); - dst->green = gl::normalizedToFloat<4>(src->G); - dst->blue = gl::normalizedToFloat<4>(src->B); - dst->alpha = gl::normalizedToFloat<4>(src->A); - } - - static void writeColor(B4G4R4A4 *dst, const gl::ColorF *src) - { - dst->R = gl::floatToNormalized<4, unsigned char>(src->red); - dst->G = gl::floatToNormalized<4, unsigned char>(src->green); - dst->B = gl::floatToNormalized<4, unsigned char>(src->blue); - dst->A = gl::floatToNormalized<4, unsigned char>(src->alpha); - } - - static void average(B4G4R4A4 *dst, const B4G4R4A4 *src1, const B4G4R4A4 *src2) - { - dst->R = gl::average(src1->R, src2->R); - dst->G = gl::average(src1->G, src2->G); - dst->B = gl::average(src1->B, src2->B); - dst->A = gl::average(src1->A, src2->A); - } -}; - -struct R16 -{ - unsigned short R; - - static void readColor(gl::ColorF *dst, const R16 *src) - { - dst->red = gl::normalizedToFloat(src->R); - dst->green = 0.0f; - dst->blue = 0.0f; - dst->alpha = 1.0f; - } - - static void readColor(gl::ColorUI *dst, const R16 *src) - { - dst->red = src->R; - dst->green = 0; - dst->blue = 0; - dst->alpha = 1; - } - - static void writeColor(R16 *dst, const gl::ColorF *src) - { - dst->R = gl::floatToNormalized(src->red); - } - - static void writeColor(R16 *dst, const gl::ColorUI *src) - { - dst->R = static_cast(src->red); - } - - static void average(R16 *dst, const R16 *src1, const R16 *src2) - { - dst->R = gl::average(src1->R, src2->R); - } -}; - -struct R16G16 -{ - unsigned short R; - unsigned short G; - - static void readColor(gl::ColorF *dst, const R16G16 *src) - { - dst->red = gl::normalizedToFloat(src->R); - dst->green = gl::normalizedToFloat(src->G); - dst->blue = 0.0f; - dst->alpha = 1.0f; - } - - static void readColor(gl::ColorUI *dst, const R16G16 *src) - { - dst->red = src->R; - dst->green = src->G; - dst->blue = 0; - dst->alpha = 1; - } - - static void writeColor(R16G16 *dst, const gl::ColorF *src) - { - dst->R = gl::floatToNormalized(src->red); - dst->G = gl::floatToNormalized(src->green); - } - - static void writeColor(R16G16 *dst, const gl::ColorUI *src) - { - dst->R = static_cast(src->red); - dst->G = static_cast(src->green); - } - - static void average(R16G16 *dst, const R16G16 *src1, const R16G16 *src2) - { - dst->R = gl::average(src1->R, src2->R); - dst->G = gl::average(src1->G, src2->G); - } -}; - -struct R16G16B16 -{ - unsigned short R; - unsigned short G; - unsigned short B; - - static void readColor(gl::ColorF *dst, const R16G16B16 *src) - { - dst->red = gl::normalizedToFloat(src->R); - dst->green = gl::normalizedToFloat(src->G); - dst->blue = gl::normalizedToFloat(src->B); - dst->alpha = 1.0f; - } - - static void readColor(gl::ColorUI *dst, const R16G16B16 *src) - { - dst->red = src->R; - dst->green = src->G; - dst->blue = src->B; - dst->alpha = 1; - } - - static void writeColor(R16G16B16 *dst, const gl::ColorF *src) - { - dst->R = gl::floatToNormalized(src->red); - dst->G = gl::floatToNormalized(src->green); - dst->B = gl::floatToNormalized(src->blue); - } - - static void writeColor(R16G16B16 *dst, const gl::ColorUI *src) - { - dst->R = static_cast(src->red); - dst->G = static_cast(src->green); - dst->B = static_cast(src->blue); - } - - static void average(R16G16B16 *dst, const R16G16B16 *src1, const R16G16B16 *src2) - { - dst->R = gl::average(src1->R, src2->R); - dst->G = gl::average(src1->G, src2->G); - dst->B = gl::average(src1->B, src2->B); - } -}; - -struct R16G16B16A16 -{ - unsigned short R; - unsigned short G; - unsigned short B; - unsigned short A; - - static void readColor(gl::ColorF *dst, const R16G16B16A16 *src) - { - dst->red = gl::normalizedToFloat(src->R); - dst->green = gl::normalizedToFloat(src->G); - dst->blue = gl::normalizedToFloat(src->B); - dst->alpha = gl::normalizedToFloat(src->A); - } - - static void readColor(gl::ColorUI *dst, const R16G16B16A16 *src) - { - dst->red = src->R; - dst->green = src->G; - dst->blue = src->B; - dst->alpha = src->A; - } - - static void writeColor(R16G16B16A16 *dst, const gl::ColorF *src) - { - dst->R = gl::floatToNormalized(src->red); - dst->G = gl::floatToNormalized(src->green); - dst->B = gl::floatToNormalized(src->blue); - dst->A = gl::floatToNormalized(src->alpha); - } - - static void writeColor(R16G16B16A16 *dst, const gl::ColorUI *src) - { - dst->R = static_cast(src->red); - dst->G = static_cast(src->green); - dst->B = static_cast(src->blue); - dst->A = static_cast(src->alpha); - } - - static void average(R16G16B16A16 *dst, const R16G16B16A16 *src1, const R16G16B16A16 *src2) - { - dst->R = gl::average(src1->R, src2->R); - dst->G = gl::average(src1->G, src2->G); - dst->B = gl::average(src1->B, src2->B); - dst->A = gl::average(src1->A, src2->A); - } -}; - -struct R32 -{ - unsigned int R; - - static void readColor(gl::ColorF *dst, const R32 *src) - { - dst->red = gl::normalizedToFloat(src->R); - dst->green = 0.0f; - dst->blue = 0.0f; - dst->alpha = 1.0f; - } - - static void readColor(gl::ColorUI *dst, const R32 *src) - { - dst->red = src->R; - dst->green = 0; - dst->blue = 0; - dst->alpha = 1; - } - - static void writeColor(R32 *dst, const gl::ColorF *src) - { - dst->R = gl::floatToNormalized(src->red); - } - - static void writeColor(R32 *dst, const gl::ColorUI *src) - { - dst->R = static_cast(src->red); - } - - static void average(R32 *dst, const R32 *src1, const R32 *src2) - { - dst->R = gl::average(src1->R, src2->R); - } -}; - -struct R32G32 -{ - unsigned int R; - unsigned int G; - - static void readColor(gl::ColorF *dst, const R32G32 *src) - { - dst->red = gl::normalizedToFloat(src->R); - dst->green = gl::normalizedToFloat(src->G); - dst->blue = 0.0f; - dst->alpha = 1.0f; - } - - static void readColor(gl::ColorUI *dst, const R32G32 *src) - { - dst->red = src->R; - dst->green = src->G; - dst->blue = 0; - dst->alpha = 1; - } - - static void writeColor(R32G32 *dst, const gl::ColorF *src) - { - dst->R = gl::floatToNormalized(src->red); - dst->G = gl::floatToNormalized(src->green); - } - - static void writeColor(R32G32 *dst, const gl::ColorUI *src) - { - dst->R = static_cast(src->red); - dst->G = static_cast(src->green); - } - - static void average(R32G32 *dst, const R32G32 *src1, const R32G32 *src2) - { - dst->R = gl::average(src1->R, src2->R); - dst->G = gl::average(src1->G, src2->G); - } -}; - -struct R32G32B32 -{ - unsigned int R; - unsigned int G; - unsigned int B; - - static void readColor(gl::ColorF *dst, const R32G32B32 *src) - { - dst->red = gl::normalizedToFloat(src->R); - dst->green = gl::normalizedToFloat(src->G); - dst->blue = gl::normalizedToFloat(src->B); - dst->alpha = 1.0f; - } - - static void readColor(gl::ColorUI *dst, const R32G32B32 *src) - { - dst->red = src->R; - dst->green = src->G; - dst->blue = src->B; - dst->alpha = 1; - } - - static void writeColor(R32G32B32 *dst, const gl::ColorF *src) - { - dst->R = gl::floatToNormalized(src->red); - dst->G = gl::floatToNormalized(src->green); - dst->B = gl::floatToNormalized(src->blue); - } - - static void writeColor(R32G32B32 *dst, const gl::ColorUI *src) - { - dst->R = static_cast(src->red); - dst->G = static_cast(src->green); - dst->B = static_cast(src->blue); - } - - static void average(R32G32B32 *dst, const R32G32B32 *src1, const R32G32B32 *src2) - { - dst->R = gl::average(src1->R, src2->R); - dst->G = gl::average(src1->G, src2->G); - dst->B = gl::average(src1->B, src2->B); - } -}; - -struct R32G32B32A32 -{ - unsigned int R; - unsigned int G; - unsigned int B; - unsigned int A; - - static void readColor(gl::ColorF *dst, const R32G32B32A32 *src) - { - dst->red = gl::normalizedToFloat(src->R); - dst->green = gl::normalizedToFloat(src->G); - dst->blue = gl::normalizedToFloat(src->B); - dst->alpha = gl::normalizedToFloat(src->A); - } - - static void readColor(gl::ColorUI *dst, const R32G32B32A32 *src) - { - dst->red = src->R; - dst->green = src->G; - dst->blue = src->B; - dst->alpha = src->A; - } - - static void writeColor(R32G32B32A32 *dst, const gl::ColorF *src) - { - dst->R = gl::floatToNormalized(src->red); - dst->G = gl::floatToNormalized(src->green); - dst->B = gl::floatToNormalized(src->blue); - dst->A = gl::floatToNormalized(src->alpha); - } - - static void writeColor(R32G32B32A32 *dst, const gl::ColorUI *src) - { - dst->R = static_cast(src->red); - dst->G = static_cast(src->green); - dst->B = static_cast(src->blue); - dst->A = static_cast(src->alpha); - } - - static void average(R32G32B32A32 *dst, const R32G32B32A32 *src1, const R32G32B32A32 *src2) - { - dst->R = gl::average(src1->R, src2->R); - dst->G = gl::average(src1->G, src2->G); - dst->B = gl::average(src1->B, src2->B); - dst->A = gl::average(src1->A, src2->A); - } -}; - -struct R8S -{ - char R; - - static void readColor(gl::ColorF *dst, const R8S *src) - { - dst->red = gl::normalizedToFloat(src->R); - dst->green = 0.0f; - dst->blue = 0.0f; - dst->alpha = 1.0f; - } - - static void readColor(gl::ColorI *dst, const R8S *src) - { - dst->red = src->R; - dst->green = 0; - dst->blue = 0; - dst->alpha = 1; - } - - static void writeColor(R8S *dst, const gl::ColorF *src) - { - dst->R = gl::floatToNormalized(src->red); - } - - static void writeColor(R8S *dst, const gl::ColorI *src) - { - dst->R = static_cast(src->red); - } - - static void average(R8S *dst, const R8S *src1, const R8S *src2) - { - dst->R = gl::average(src1->R, src2->R); - } -}; - -struct R8G8S -{ - char R; - char G; - - static void readColor(gl::ColorF *dst, const R8G8S *src) - { - dst->red = gl::normalizedToFloat(src->R); - dst->green = gl::normalizedToFloat(src->G); - dst->blue = 0.0f; - dst->alpha = 1.0f; - } - - static void readColor(gl::ColorI *dst, const R8G8S *src) - { - dst->red = src->R; - dst->green = src->G; - dst->blue = 0; - dst->alpha = 1; - } - - static void writeColor(R8G8S *dst, const gl::ColorF *src) - { - dst->R = gl::floatToNormalized(src->red); - dst->G = gl::floatToNormalized(src->green); - } - - static void writeColor(R8G8S *dst, const gl::ColorI *src) - { - dst->R = static_cast(src->red); - dst->G = static_cast(src->green); - } - - static void average(R8G8S *dst, const R8G8S *src1, const R8G8S *src2) - { - dst->R = gl::average(src1->R, src2->R); - dst->G = gl::average(src1->G, src2->G); - } -}; - -struct R8G8B8S -{ - char R; - char G; - char B; - - static void readColor(gl::ColorF *dst, const R8G8B8S *src) - { - dst->red = gl::normalizedToFloat(src->R); - dst->green = gl::normalizedToFloat(src->G); - dst->blue = gl::normalizedToFloat(src->B); - dst->alpha = 1.0f; - } - - static void readColor(gl::ColorI *dst, const R8G8B8S *src) - { - dst->red = src->R; - dst->green = src->G; - dst->blue = src->B; - dst->alpha = 1; - } - - static void writeColor(R8G8B8S *dst, const gl::ColorF *src) - { - dst->R = gl::floatToNormalized(src->red); - dst->G = gl::floatToNormalized(src->green); - dst->B = gl::floatToNormalized(src->blue); - } - - static void writeColor(R8G8B8S *dst, const gl::ColorI *src) - { - dst->R = static_cast(src->red); - dst->G = static_cast(src->green); - dst->B = static_cast(src->blue); - } - - static void average(R8G8B8S *dst, const R8G8B8S *src1, const R8G8B8S *src2) - { - dst->R = gl::average(src1->R, src2->R); - dst->G = gl::average(src1->G, src2->G); - dst->B = gl::average(src1->B, src2->B); - } -}; - -struct R8G8B8A8S -{ - char R; - char G; - char B; - char A; - - static void readColor(gl::ColorF *dst, const R8G8B8A8S *src) - { - dst->red = gl::normalizedToFloat(src->R); - dst->green = gl::normalizedToFloat(src->G); - dst->blue = gl::normalizedToFloat(src->B); - dst->alpha = gl::normalizedToFloat(src->A); - } - - static void readColor(gl::ColorI *dst, const R8G8B8A8S *src) - { - dst->red = src->R; - dst->green = src->G; - dst->blue = src->B; - dst->alpha = src->A; - } - - static void writeColor(R8G8B8A8S *dst, const gl::ColorF *src) - { - dst->R = gl::floatToNormalized(src->red); - dst->G = gl::floatToNormalized(src->green); - dst->B = gl::floatToNormalized(src->blue); - dst->A = gl::floatToNormalized(src->alpha); - } - - static void writeColor(R8G8B8A8S *dst, const gl::ColorI *src) - { - dst->R = static_cast(src->red); - dst->G = static_cast(src->green); - dst->B = static_cast(src->blue); - dst->A = static_cast(src->alpha); - } - - static void average(R8G8B8A8S *dst, const R8G8B8A8S *src1, const R8G8B8A8S *src2) - { - dst->R = gl::average(src1->R, src2->R); - dst->G = gl::average(src1->G, src2->G); - dst->B = gl::average(src1->B, src2->B); - dst->A = gl::average(src1->A, src2->A); - } -}; - -struct R16S -{ - short R; - - static void readColor(gl::ColorF *dst, const R16S *src) - { - dst->red = gl::normalizedToFloat(src->R); - dst->green = 0.0f; - dst->blue = 0.0f; - dst->alpha = 1.0f; - } - - static void readColor(gl::ColorI *dst, const R16S *src) - { - dst->red = src->R; - dst->green = 0; - dst->blue = 0; - dst->alpha = 1; - } - - static void writeColor(R16S *dst, const gl::ColorF *src) - { - dst->R = gl::floatToNormalized(src->red); - } - - static void writeColor(R16S *dst, const gl::ColorI *src) - { - dst->R = static_cast(src->red); - } - - static void average(R16S *dst, const R16S *src1, const R16S *src2) - { - dst->R = gl::average(src1->R, src2->R); - } -}; - -struct R16G16S -{ - short R; - short G; - - static void readColor(gl::ColorF *dst, const R16G16S *src) - { - dst->red = gl::normalizedToFloat(src->R); - dst->green = gl::normalizedToFloat(src->G); - dst->blue = 0.0f; - dst->alpha = 1.0f; - } - - static void readColor(gl::ColorI *dst, const R16G16S *src) - { - dst->red = src->R; - dst->green = src->G; - dst->blue = 0; - dst->alpha = 1; - } - - static void writeColor(R16G16S *dst, const gl::ColorF *src) - { - dst->R = gl::floatToNormalized(src->red); - dst->G = gl::floatToNormalized(src->green); - } - - static void writeColor(R16G16S *dst, const gl::ColorI *src) - { - dst->R = static_cast(src->red); - dst->G = static_cast(src->green); - } - - static void average(R16G16S *dst, const R16G16S *src1, const R16G16S *src2) - { - dst->R = gl::average(src1->R, src2->R); - dst->G = gl::average(src1->G, src2->G); - } -}; - -struct R16G16B16S -{ - short R; - short G; - short B; - - static void readColor(gl::ColorF *dst, const R16G16B16S *src) - { - dst->red = gl::normalizedToFloat(src->R); - dst->green = gl::normalizedToFloat(src->G); - dst->blue = gl::normalizedToFloat(src->B); - dst->alpha = 1.0f; - } - - static void readColor(gl::ColorI *dst, const R16G16B16S *src) - { - dst->red = src->R; - dst->green = src->G; - dst->blue = src->B; - dst->alpha = 1; - } - - static void writeColor(R16G16B16S *dst, const gl::ColorF *src) - { - dst->R = gl::floatToNormalized(src->red); - dst->G = gl::floatToNormalized(src->green); - dst->B = gl::floatToNormalized(src->blue); - } - - static void writeColor(R16G16B16S *dst, const gl::ColorI *src) - { - dst->R = static_cast(src->red); - dst->G = static_cast(src->green); - dst->B = static_cast(src->blue); - } - - static void average(R16G16B16S *dst, const R16G16B16S *src1, const R16G16B16S *src2) - { - dst->R = gl::average(src1->R, src2->R); - dst->G = gl::average(src1->G, src2->G); - dst->B = gl::average(src1->B, src2->B); - } -}; - -struct R16G16B16A16S -{ - short R; - short G; - short B; - short A; - - static void readColor(gl::ColorF *dst, const R16G16B16A16S *src) - { - dst->red = gl::normalizedToFloat(src->R); - dst->green = gl::normalizedToFloat(src->G); - dst->blue = gl::normalizedToFloat(src->B); - dst->alpha = gl::normalizedToFloat(src->A); - } - - static void readColor(gl::ColorI *dst, const R16G16B16A16S *src) - { - dst->red = src->R; - dst->green = src->G; - dst->blue = src->B; - dst->alpha = src->A; - } - - static void writeColor(R16G16B16A16S *dst, const gl::ColorF *src) - { - dst->R = gl::floatToNormalized(src->red); - dst->G = gl::floatToNormalized(src->green); - dst->B = gl::floatToNormalized(src->blue); - dst->A = gl::floatToNormalized(src->alpha); - } - - static void writeColor(R16G16B16A16S *dst, const gl::ColorI *src) - { - dst->R = static_cast(src->red); - dst->G = static_cast(src->green); - dst->B = static_cast(src->blue); - dst->A = static_cast(src->alpha); - } - - static void average(R16G16B16A16S *dst, const R16G16B16A16S *src1, const R16G16B16A16S *src2) - { - dst->R = gl::average(src1->R, src2->R); - dst->G = gl::average(src1->G, src2->G); - dst->B = gl::average(src1->B, src2->B); - dst->A = gl::average(src1->A, src2->A); - } -}; - -struct R32S -{ - int R; - - static void readColor(gl::ColorF *dst, const R32S *src) - { - dst->red = gl::normalizedToFloat(src->R); - dst->green = 0.0f; - dst->blue = 0.0f; - dst->alpha = 1.0f; - } - - static void readColor(gl::ColorI *dst, const R32S *src) - { - dst->red = src->R; - dst->green = 0; - dst->blue = 0; - dst->alpha = 1; - } - - static void writeColor(R32S *dst, const gl::ColorF *src) - { - dst->R = gl::floatToNormalized(src->red); - } - - static void writeColor(R32S *dst, const gl::ColorI *src) - { - dst->R = static_cast(src->red); - } - - static void average(R32S *dst, const R32S *src1, const R32S *src2) - { - dst->R = gl::average(src1->R, src2->R); - } -}; - -struct R32G32S -{ - int R; - int G; - - static void readColor(gl::ColorF *dst, const R32G32S *src) - { - dst->red = gl::normalizedToFloat(src->R); - dst->green = gl::normalizedToFloat(src->G); - dst->blue = 0.0f; - dst->alpha = 1.0f; - } - - static void readColor(gl::ColorI *dst, const R32G32S *src) - { - dst->red = src->R; - dst->green = src->G; - dst->blue = 0; - dst->alpha = 1; - } - - static void writeColor(R32G32S *dst, const gl::ColorF *src) - { - dst->R = gl::floatToNormalized(src->red); - dst->G = gl::floatToNormalized(src->green); - } - - static void writeColor(R32G32S *dst, const gl::ColorI *src) - { - dst->R = static_cast(src->red); - dst->G = static_cast(src->green); - } - - static void average(R32G32S *dst, const R32G32S *src1, const R32G32S *src2) - { - dst->R = gl::average(src1->R, src2->R); - dst->G = gl::average(src1->G, src2->G); - } -}; - -struct R32G32B32S -{ - int R; - int G; - int B; - - static void readColor(gl::ColorF *dst, const R32G32B32S *src) - { - dst->red = gl::normalizedToFloat(src->R); - dst->green = gl::normalizedToFloat(src->G); - dst->blue = gl::normalizedToFloat(src->B); - dst->alpha = 1.0f; - } - - static void readColor(gl::ColorI *dst, const R32G32B32S *src) - { - dst->red = src->R; - dst->green = src->G; - dst->blue = src->B; - dst->alpha = 1; - } - - static void writeColor(R32G32B32S *dst, const gl::ColorF *src) - { - dst->R = gl::floatToNormalized(src->red); - dst->G = gl::floatToNormalized(src->green); - dst->B = gl::floatToNormalized(src->blue); - } - - static void writeColor(R32G32B32S *dst, const gl::ColorI *src) - { - dst->R = static_cast(src->red); - dst->G = static_cast(src->green); - dst->B = static_cast(src->blue); - } - - static void average(R32G32B32S *dst, const R32G32B32S *src1, const R32G32B32S *src2) - { - dst->R = gl::average(src1->R, src2->R); - dst->G = gl::average(src1->G, src2->G); - dst->B = gl::average(src1->B, src2->B); - } -}; - -struct R32G32B32A32S -{ - int R; - int G; - int B; - int A; - - static void readColor(gl::ColorF *dst, const R32G32B32A32S *src) - { - dst->red = gl::normalizedToFloat(src->R); - dst->green = gl::normalizedToFloat(src->G); - dst->blue = gl::normalizedToFloat(src->B); - dst->alpha = gl::normalizedToFloat(src->A); - } - - static void readColor(gl::ColorI *dst, const R32G32B32A32S *src) - { - dst->red = src->R; - dst->green = src->G; - dst->blue = src->B; - dst->alpha = src->A; - } - - static void writeColor(R32G32B32A32S *dst, const gl::ColorF *src) - { - dst->R = gl::floatToNormalized(src->red); - dst->G = gl::floatToNormalized(src->green); - dst->B = gl::floatToNormalized(src->blue); - dst->A = gl::floatToNormalized(src->alpha); - } - - static void writeColor(R32G32B32A32S *dst, const gl::ColorI *src) - { - dst->R = static_cast(src->red); - dst->G = static_cast(src->green); - dst->B = static_cast(src->blue); - dst->A = static_cast(src->alpha); - } - - static void average(R32G32B32A32S *dst, const R32G32B32A32S *src1, const R32G32B32A32S *src2) - { - dst->R = gl::average(src1->R, src2->R); - dst->G = gl::average(src1->G, src2->G); - dst->B = gl::average(src1->B, src2->B); - dst->A = gl::average(src1->A, src2->A); - } -}; - -struct A16B16G16R16F -{ - unsigned short A; - unsigned short R; - unsigned short G; - unsigned short B; - - static void readColor(gl::ColorF *dst, const A16B16G16R16F *src) - { - dst->red = gl::float16ToFloat32(src->R); - dst->green = gl::float16ToFloat32(src->G); - dst->blue = gl::float16ToFloat32(src->B); - dst->alpha = gl::float16ToFloat32(src->A); - } - - static void writeColor(A16B16G16R16F *dst, const gl::ColorF *src) - { - dst->R = gl::float32ToFloat16(src->red); - dst->G = gl::float32ToFloat16(src->green); - dst->B = gl::float32ToFloat16(src->blue); - dst->A = gl::float32ToFloat16(src->alpha); - } - - static void average(A16B16G16R16F *dst, const A16B16G16R16F *src1, const A16B16G16R16F *src2) - { - dst->R = gl::averageHalfFloat(src1->R, src2->R); - dst->G = gl::averageHalfFloat(src1->G, src2->G); - dst->B = gl::averageHalfFloat(src1->B, src2->B); - dst->A = gl::averageHalfFloat(src1->A, src2->A); - } -}; - -struct R16G16B16A16F -{ - unsigned short R; - unsigned short G; - unsigned short B; - unsigned short A; - - static void readColor(gl::ColorF *dst, const R16G16B16A16F *src) - { - dst->red = gl::float16ToFloat32(src->R); - dst->green = gl::float16ToFloat32(src->G); - dst->blue = gl::float16ToFloat32(src->B); - dst->alpha = gl::float16ToFloat32(src->A); - } - - static void writeColor(R16G16B16A16F *dst, const gl::ColorF *src) - { - dst->R = gl::float32ToFloat16(src->red); - dst->G = gl::float32ToFloat16(src->green); - dst->B = gl::float32ToFloat16(src->blue); - dst->A = gl::float32ToFloat16(src->alpha); - } - - static void average(R16G16B16A16F *dst, const R16G16B16A16F *src1, const R16G16B16A16F *src2) - { - dst->R = gl::averageHalfFloat(src1->R, src2->R); - dst->G = gl::averageHalfFloat(src1->G, src2->G); - dst->B = gl::averageHalfFloat(src1->B, src2->B); - dst->A = gl::averageHalfFloat(src1->A, src2->A); - } -}; - -struct R16F -{ - unsigned short R; - - static void readColor(gl::ColorF *dst, const R16F *src) - { - dst->red = gl::float16ToFloat32(src->R); - dst->green = 0.0f; - dst->blue = 0.0f; - dst->alpha = 1.0f; - } - - static void writeColor(R16F *dst, const gl::ColorF *src) - { - dst->R = gl::float32ToFloat16(src->red); - } - - static void average(R16F *dst, const R16F *src1, const R16F *src2) - { - dst->R = gl::averageHalfFloat(src1->R, src2->R); - } -}; - -struct A16F -{ - unsigned short A; - - static void readColor(gl::ColorF *dst, const A16F *src) - { - dst->red = 0.0f; - dst->green = 0.0f; - dst->blue = 0.0f; - dst->alpha = gl::float16ToFloat32(src->A); - } - - static void writeColor(A16F *dst, const gl::ColorF *src) - { - dst->A = gl::float32ToFloat16(src->alpha); - } - - static void average(A16F *dst, const A16F *src1, const A16F *src2) - { - dst->A = gl::averageHalfFloat(src1->A, src2->A); - } -}; - -struct L16F -{ - unsigned short L; - - static void readColor(gl::ColorF *dst, const L16F *src) - { - float lum = gl::float16ToFloat32(src->L); - dst->red = lum; - dst->green = lum; - dst->blue = lum; - dst->alpha = 1.0f; - } - - static void writeColor(L16F *dst, const gl::ColorF *src) - { - dst->L = gl::float32ToFloat16((src->red + src->green + src->blue) / 3.0f); - } - - static void average(L16F *dst, const L16F *src1, const L16F *src2) - { - dst->L = gl::averageHalfFloat(src1->L, src2->L); - } -}; - -struct L16A16F -{ - unsigned short L; - unsigned short A; - - static void readColor(gl::ColorF *dst, const L16A16F *src) - { - float lum = gl::float16ToFloat32(src->L); - dst->red = lum; - dst->green = lum; - dst->blue = lum; - dst->alpha = gl::float16ToFloat32(src->A); - } - - static void writeColor(L16A16F *dst, const gl::ColorF *src) - { - dst->L = gl::float32ToFloat16((src->red + src->green + src->blue) / 3.0f); - dst->A = gl::float32ToFloat16(src->alpha); - } - - static void average(L16A16F *dst, const L16A16F *src1, const L16A16F *src2) - { - dst->L = gl::averageHalfFloat(src1->L, src2->L); - dst->A = gl::averageHalfFloat(src1->A, src2->A); - } -}; - -struct R16G16F -{ - unsigned short R; - unsigned short G; - - static void readColor(gl::ColorF *dst, const R16G16F *src) - { - dst->red = gl::float16ToFloat32(src->R); - dst->green = gl::float16ToFloat32(src->G); - dst->blue = 0.0f; - dst->alpha = 1.0f; - } - - static void writeColor(R16G16F *dst, const gl::ColorF *src) - { - dst->R = gl::float32ToFloat16(src->red); - dst->G = gl::float32ToFloat16(src->green); - } - - static void average(R16G16F *dst, const R16G16F *src1, const R16G16F *src2) - { - dst->R = gl::averageHalfFloat(src1->R, src2->R); - dst->G = gl::averageHalfFloat(src1->G, src2->G); - } -}; - -struct R16G16B16F -{ - unsigned short R; - unsigned short G; - unsigned short B; - - static void readColor(gl::ColorF *dst, const R16G16B16F *src) - { - dst->red = gl::float16ToFloat32(src->R); - dst->green = gl::float16ToFloat32(src->G); - dst->blue = gl::float16ToFloat32(src->B); - dst->alpha = 1.0f; - } - - static void writeColor(R16G16B16F *dst, const gl::ColorF *src) - { - dst->R = gl::float32ToFloat16(src->red); - dst->G = gl::float32ToFloat16(src->green); - dst->B = gl::float32ToFloat16(src->blue); - } - - static void average(R16G16B16F *dst, const R16G16B16F *src1, const R16G16B16F *src2) - { - dst->R = gl::averageHalfFloat(src1->R, src2->R); - dst->G = gl::averageHalfFloat(src1->G, src2->G); - dst->B = gl::averageHalfFloat(src1->B, src2->B); - } -}; - -struct A32B32G32R32F -{ - float A; - float R; - float G; - float B; - - static void readColor(gl::ColorF *dst, const A32B32G32R32F *src) - { - dst->red = src->R; - dst->green = src->G; - dst->blue = src->B; - dst->alpha = src->A; - } - - static void writeColor(A32B32G32R32F *dst, const gl::ColorF *src) - { - dst->R = src->red; - dst->G = src->green; - dst->B = src->blue; - dst->A = src->alpha; - } - - static void average(A32B32G32R32F *dst, const A32B32G32R32F *src1, const A32B32G32R32F *src2) - { - dst->R = gl::average(src1->R, src2->R); - dst->G = gl::average(src1->G, src2->G); - dst->B = gl::average(src1->B, src2->B); - dst->A = gl::average(src1->A, src2->A); - } -}; - -struct R32G32B32A32F -{ - float R; - float G; - float B; - float A; - - static void readColor(gl::ColorF *dst, const R32G32B32A32F *src) - { - dst->red = src->R; - dst->green = src->G; - dst->blue = src->B; - dst->alpha = src->A; - } - - static void writeColor(R32G32B32A32F *dst, const gl::ColorF *src) - { - dst->R = src->red; - dst->G = src->green; - dst->B = src->blue; - dst->A = src->alpha; - } - - static void average(R32G32B32A32F *dst, const R32G32B32A32F *src1, const R32G32B32A32F *src2) - { - dst->R = gl::average(src1->R, src2->R); - dst->G = gl::average(src1->G, src2->G); - dst->B = gl::average(src1->B, src2->B); - dst->A = gl::average(src1->A, src2->A); - } -}; - -struct R32F -{ - float R; - - static void readColor(gl::ColorF *dst, const R32F *src) - { - dst->red = src->R; - dst->green = 0.0f; - dst->blue = 0.0f; - dst->alpha = 1.0f; - } - - static void writeColor(R32F *dst, const gl::ColorF *src) - { - dst->R = src->red; - } - - static void average(R32F *dst, const R32F *src1, const R32F *src2) - { - dst->R = gl::average(src1->R, src2->R); - } -}; - -struct A32F -{ - float A; - - static void readColor(gl::ColorF *dst, const A32F *src) - { - dst->red = 0.0f; - dst->green = 0.0f; - dst->blue = 0.0f; - dst->alpha = src->A; - } - - static void writeColor(A32F *dst, const gl::ColorF *src) - { - dst->A = src->alpha; - } - - static void average(A32F *dst, const A32F *src1, const A32F *src2) - { - dst->A = gl::average(src1->A, src2->A); - } -}; - -struct L32F -{ - float L; - - static void readColor(gl::ColorF *dst, const L32F *src) - { - dst->red = src->L; - dst->green = src->L; - dst->blue = src->L; - dst->alpha = 1.0f; - } - - static void writeColor(L32F *dst, const gl::ColorF *src) - { - dst->L = (src->red + src->green + src->blue) / 3.0f; - } - - static void average(L32F *dst, const L32F *src1, const L32F *src2) - { - dst->L = gl::average(src1->L, src2->L); - } -}; - -struct L32A32F -{ - float L; - float A; - - static void readColor(gl::ColorF *dst, const L32A32F *src) - { - dst->red = src->L; - dst->green = src->L; - dst->blue = src->L; - dst->alpha = src->A; - } - - static void writeColor(L32A32F *dst, const gl::ColorF *src) - { - dst->L = (src->red + src->green + src->blue) / 3.0f; - dst->A = src->alpha; - } - - static void average(L32A32F *dst, const L32A32F *src1, const L32A32F *src2) - { - dst->L = gl::average(src1->L, src2->L); - dst->A = gl::average(src1->A, src2->A); - } -}; - -struct R32G32F -{ - float R; - float G; - - static void readColor(gl::ColorF *dst, const R32G32F *src) - { - dst->red = src->R; - dst->green = src->G; - dst->blue = 0.0f; - dst->alpha = 1.0f; - } - - static void writeColor(R32G32F *dst, const gl::ColorF *src) - { - dst->R = src->red; - dst->G = src->green; - } - - static void average(R32G32F *dst, const R32G32F *src1, const R32G32F *src2) - { - dst->R = gl::average(src1->R, src2->R); - dst->G = gl::average(src1->G, src2->G); - } -}; - -struct R32G32B32F -{ - float R; - float G; - float B; - - static void readColor(gl::ColorF *dst, const R32G32B32F *src) - { - dst->red = src->R; - dst->green = src->G; - dst->blue = src->B; - dst->alpha = 1.0f; - } - - static void writeColor(R32G32B32F *dst, const gl::ColorF *src) - { - dst->R = src->red; - dst->G = src->green; - dst->B = src->blue; - } - - static void average(R32G32B32F *dst, const R32G32B32F *src1, const R32G32B32F *src2) - { - dst->R = gl::average(src1->R, src2->R); - dst->G = gl::average(src1->G, src2->G); - dst->B = gl::average(src1->B, src2->B); - } -}; - -struct R10G10B10A2 -{ - unsigned int R : 10; - unsigned int G : 10; - unsigned int B : 10; - unsigned int A : 2; - - static void readColor(gl::ColorF *dst, const R10G10B10A2 *src) - { - dst->red = gl::normalizedToFloat<10>(src->R); - dst->green = gl::normalizedToFloat<10>(src->G); - dst->blue = gl::normalizedToFloat<10>(src->B); - dst->alpha = gl::normalizedToFloat< 2>(src->A); - } - - static void readColor(gl::ColorUI *dst, const R10G10B10A2 *src) - { - dst->red = src->R; - dst->green = src->G; - dst->blue = src->B; - dst->alpha = src->A; - } - - static void writeColor(R10G10B10A2 *dst, const gl::ColorF *src) - { - dst->R = gl::floatToNormalized<10, unsigned int>(src->red); - dst->G = gl::floatToNormalized<10, unsigned int>(src->green); - dst->B = gl::floatToNormalized<10, unsigned int>(src->blue); - dst->A = gl::floatToNormalized< 2, unsigned int>(src->alpha); - } - - static void writeColor(R10G10B10A2 *dst, const gl::ColorUI *src) - { - dst->R = static_cast(src->red); - dst->G = static_cast(src->green); - dst->B = static_cast(src->blue); - dst->A = static_cast(src->alpha); - } - - static void average(R10G10B10A2 *dst, const R10G10B10A2 *src1, const R10G10B10A2 *src2) - { - dst->R = gl::average(src1->R, src2->R); - dst->G = gl::average(src1->G, src2->G); - dst->B = gl::average(src1->B, src2->B); - dst->A = gl::average(src1->A, src2->A); - } -}; - -struct R9G9B9E5 -{ - unsigned int R : 9; - unsigned int G : 9; - unsigned int B : 9; - unsigned int E : 5; - - static void readColor(gl::ColorF *dst, const R9G9B9E5 *src) - { - gl::convert999E5toRGBFloats(gl::bitCast(*src), &dst->red, &dst->green, &dst->blue); - dst->alpha = 1.0f; - } - - static void writeColor(R9G9B9E5 *dst, const gl::ColorF *src) - { - *reinterpret_cast(dst) = gl::convertRGBFloatsTo999E5(src->red, - src->green, - src->blue); - } - - static void average(R9G9B9E5 *dst, const R9G9B9E5 *src1, const R9G9B9E5 *src2) - { - float r1, g1, b1; - gl::convert999E5toRGBFloats(*reinterpret_cast(src1), &r1, &g1, &b1); - - float r2, g2, b2; - gl::convert999E5toRGBFloats(*reinterpret_cast(src2), &r2, &g2, &b2); - - *reinterpret_cast(dst) = gl::convertRGBFloatsTo999E5(gl::average(r1, r2), - gl::average(g1, g2), - gl::average(b1, b2)); - } -}; - -struct R11G11B10F -{ - unsigned int R : 11; - unsigned int G : 11; - unsigned int B : 10; - - static void readColor(gl::ColorF *dst, const R11G11B10F *src) - { - dst->red = gl::float11ToFloat32(src->R); - dst->green = gl::float11ToFloat32(src->G); - dst->blue = gl::float10ToFloat32(src->B); - dst->alpha = 1.0f; - } - - static void writeColor(R11G11B10F *dst, const gl::ColorF *src) - { - dst->R = gl::float32ToFloat11(src->red); - dst->G = gl::float32ToFloat11(src->green); - dst->B = gl::float32ToFloat10(src->blue); - } - - static void average(R11G11B10F *dst, const R11G11B10F *src1, const R11G11B10F *src2) - { - dst->R = gl::averageFloat11(src1->R, src2->R); - dst->G = gl::averageFloat11(src1->G, src2->G); - dst->B = gl::averageFloat10(src1->B, src2->B); - } -}; - -} - -#endif // LIBGLESV2_RENDERER_IMAGEFORMATS_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/loadimage.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/loadimage.cpp deleted file mode 100644 index 1986191a75..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/loadimage.cpp +++ /dev/null @@ -1,661 +0,0 @@ -// -// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// loadimage.cpp: Defines image loading functions. - -#include "libGLESv2/renderer/loadimage.h" - -namespace rx -{ - -void LoadA8ToRGBA8(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) -{ - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y++) - { - const uint8_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - uint32_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - for (size_t x = 0; x < width; x++) - { - dest[x] = static_cast(source[x]) << 24; - } - } - } -} - -void LoadA8ToBGRA8(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) -{ - // Same as loading to RGBA - LoadA8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output, outputRowPitch, outputDepthPitch); -} - -void LoadA32FToRGBA32F(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) -{ - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y++) - { - const float *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - float *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - for (size_t x = 0; x < width; x++) - { - dest[4 * x + 0] = 0.0f; - dest[4 * x + 1] = 0.0f; - dest[4 * x + 2] = 0.0f; - dest[4 * x + 3] = source[x]; - } - } - } -} - -void LoadA16FToRGBA16F(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) -{ - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y++) - { - const uint16_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - uint16_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - for (size_t 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 LoadL8ToRGBA8(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) -{ - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y++) - { - const uint8_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - uint8_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - for (size_t x = 0; x < width; x++) - { - dest[4 * x + 0] = source[x]; - dest[4 * x + 1] = source[x]; - dest[4 * x + 2] = source[x]; - dest[4 * x + 3] = 0xFF; - } - } - } -} - -void LoadL8ToBGRA8(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) -{ - // Same as loading to RGBA - LoadL8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output, outputRowPitch, outputDepthPitch); -} - -void LoadL32FToRGBA32F(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) -{ - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y++) - { - const float *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - float *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - for (size_t 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 LoadL16FToRGBA16F(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) -{ - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y++) - { - const uint16_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - uint16_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - for (size_t 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] = gl::Float16One; - } - } - } -} - -void LoadLA8ToRGBA8(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) -{ - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y++) - { - const uint8_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - uint8_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - for (size_t 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 LoadLA8ToBGRA8(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) -{ - // Same as loading to RGBA - LoadLA8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output, outputRowPitch, outputDepthPitch); -} - -void LoadLA32FToRGBA32F(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) -{ - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y++) - { - const float *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - float *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - for (size_t 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 LoadLA16FToRGBA16F(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) -{ - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y++) - { - const uint16_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - uint16_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - for (size_t 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 LoadRGB8ToBGRX8(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) -{ - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y++) - { - const uint8_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - uint8_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - for (size_t 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 LoadRG8ToBGRX8(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) -{ - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y++) - { - const uint8_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - uint8_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - for (size_t x = 0; x < width; x++) - { - dest[4 * x + 0] = 0x00; - dest[4 * x + 1] = source[x * 2 + 1]; - dest[4 * x + 2] = source[x * 2 + 0]; - dest[4 * x + 3] = 0xFF; - } - } - } -} - -void LoadR8ToBGRX8(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) -{ - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y++) - { - const uint8_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - uint8_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - for (size_t x = 0; x < width; x++) - { - dest[4 * x + 0] = 0x00; - dest[4 * x + 1] = 0x00; - dest[4 * x + 2] = source[x]; - dest[4 * x + 3] = 0xFF; - } - } - } -} - -void LoadR5G6B5ToBGRA8(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) -{ - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y++) - { - const uint16_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - uint8_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - for (size_t x = 0; x < width; x++) - { - uint16_t rgb = source[x]; - dest[4 * x + 0] = ((rgb & 0x001F) << 3) | ((rgb & 0x001F) >> 2); - dest[4 * x + 1] = ((rgb & 0x07E0) >> 3) | ((rgb & 0x07E0) >> 9); - dest[4 * x + 2] = ((rgb & 0xF800) >> 8) | ((rgb & 0xF800) >> 13); - dest[4 * x + 3] = 0xFF; - } - } - } -} - -void LoadR5G6B5ToRGBA8(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) -{ - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y++) - { - const uint16_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - uint8_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - for (size_t x = 0; x < width; x++) - { - uint16_t rgb = source[x]; - dest[4 * x + 0] = ((rgb & 0xF800) >> 8) | ((rgb & 0xF800) >> 13); - dest[4 * x + 1] = ((rgb & 0x07E0) >> 3) | ((rgb & 0x07E0) >> 9); - dest[4 * x + 2] = ((rgb & 0x001F) << 3) | ((rgb & 0x001F) >> 2); - dest[4 * x + 3] = 0xFF; - } - } - } -} - -void LoadRGBA8ToBGRA8(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) -{ - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y++) - { - const uint32_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - uint32_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - for (size_t x = 0; x < width; x++) - { - uint32_t rgba = source[x]; - dest[x] = (_rotl(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00); - } - } - } -} - -void LoadRGBA4ToBGRA8(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) -{ - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y++) - { - const uint16_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - uint8_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - for (size_t x = 0; x < width; x++) - { - uint16_t 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 LoadRGBA4ToRGBA8(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) -{ - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y++) - { - const uint16_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - uint8_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - for (size_t x = 0; x < width; x++) - { - uint16_t 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 LoadBGRA4ToBGRA8(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) -{ - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y++) - { - const uint16_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - uint8_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - for (size_t x = 0; x < width; x++) - { - uint16_t bgra = source[x]; - dest[4 * x + 0] = ((bgra & 0xF000) >> 8) | ((bgra & 0xF000) >> 12); - dest[4 * x + 1] = ((bgra & 0x0F00) >> 4) | ((bgra & 0x0F00) >> 8); - dest[4 * x + 2] = ((bgra & 0x00F0) << 0) | ((bgra & 0x00F0) >> 4); - dest[4 * x + 3] = ((bgra & 0x000F) << 4) | ((bgra & 0x000F) >> 0); - } - } - } -} - -void LoadRGB5A1ToBGRA8(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) -{ - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y++) - { - const uint16_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - uint8_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - for (size_t x = 0; x < width; x++) - { - uint16_t 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 LoadRGB5A1ToRGBA8(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) -{ - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y++) - { - const uint16_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - uint8_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - for (size_t x = 0; x < width; x++) - { - uint16_t 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 LoadBGR5A1ToBGRA8(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) -{ - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y++) - { - const uint16_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - uint8_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - for (size_t x = 0; x < width; x++) - { - uint16_t bgra = source[x]; - dest[4 * x + 0] = ((bgra & 0xF800) >> 8) | ((bgra & 0xF800) >> 13); - dest[4 * x + 1] = ((bgra & 0x07C0) >> 3) | ((bgra & 0x07C0) >> 8); - dest[4 * x + 2] = ((bgra & 0x003E) << 2) | ((bgra & 0x003E) >> 3); - dest[4 * x + 3] = (bgra & 0x0001) ? 0xFF : 0; - } - } - } -} - -void LoadRGB10A2ToRGBA8(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) -{ - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y++) - { - const uint32_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - uint8_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - for (size_t x = 0; x < width; x++) - { - uint32_t rgba = source[x]; - dest[4 * x + 0] = (rgba & 0x000003FF) >> 2; - dest[4 * x + 1] = (rgba & 0x000FFC00) >> 12; - dest[4 * x + 2] = (rgba & 0x3FF00000) >> 22; - dest[4 * x + 3] = ((rgba & 0xC0000000) >> 30) * 0x55; - } - } - } -} - -void LoadRGB16FToRGB9E5(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) -{ - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y++) - { - const uint16_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - uint32_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - for (size_t x = 0; x < width; x++) - { - dest[x] = gl::convertRGBFloatsTo999E5(gl::float16ToFloat32(source[x * 3 + 0]), - gl::float16ToFloat32(source[x * 3 + 1]), - gl::float16ToFloat32(source[x * 3 + 2])); - } - } - } -} - -void LoadRGB32FToRGB9E5(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) -{ - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y++) - { - const float *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - uint32_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - for (size_t x = 0; x < width; x++) - { - dest[x] = gl::convertRGBFloatsTo999E5(source[x * 3 + 0], source[x * 3 + 1], source[x * 3 + 2]); - } - } - } -} - -void LoadRGB16FToRG11B10F(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) -{ - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y++) - { - const uint16_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - uint32_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - for (size_t x = 0; x < width; x++) - { - dest[x] = (gl::float32ToFloat11(gl::float16ToFloat32(source[x * 3 + 0])) << 0) | - (gl::float32ToFloat11(gl::float16ToFloat32(source[x * 3 + 1])) << 11) | - (gl::float32ToFloat10(gl::float16ToFloat32(source[x * 3 + 2])) << 22); - } - } - } -} - -void LoadRGB32FToRG11B10F(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) -{ - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y++) - { - const float *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - uint32_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - for (size_t x = 0; x < width; x++) - { - dest[x] = (gl::float32ToFloat11(source[x * 3 + 0]) << 0) | - (gl::float32ToFloat11(source[x * 3 + 1]) << 11) | - (gl::float32ToFloat10(source[x * 3 + 2]) << 22); - } - } - } -} - -void LoadG8R24ToR24G8(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) -{ - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y++) - { - const uint32_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - uint32_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - for (size_t x = 0; x < width; x++) - { - uint32_t d = source[x] >> 8; - uint8_t s = source[x] & 0xFF; - dest[x] = d | (s << 24); - } - } - } -} - -void LoadRGB32FToRGBA16F(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) -{ - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y++) - { - const float *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - uint16_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - for (size_t x = 0; x < width; x++) - { - dest[x * 4 + 0] = gl::float32ToFloat16(source[x * 3 + 0]); - dest[x * 4 + 1] = gl::float32ToFloat16(source[x * 3 + 1]); - dest[x * 4 + 2] = gl::float32ToFloat16(source[x * 3 + 2]); - dest[x * 4 + 3] = gl::Float16One; - } - } - } -} - -void LoadR32ToR16(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) -{ - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y++) - { - const uint32_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - uint16_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - for (size_t x = 0; x < width; x++) - { - dest[x] = source[x] >> 16; - } - } - } -} - -void LoadR32ToR24G8(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) -{ - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y++) - { - const uint32_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - uint32_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - - for (size_t x = 0; x < width; x++) - { - dest[x] = source[x] >> 8; - } - } - } -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/loadimage.h b/src/3rdparty/angle/src/libGLESv2/renderer/loadimage.h deleted file mode 100644 index bcdff24a66..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/loadimage.h +++ /dev/null @@ -1,193 +0,0 @@ -// -// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// loadimage.h: Defines image loading functions - -#ifndef LIBGLESV2_RENDERER_LOADIMAGE_H_ -#define LIBGLESV2_RENDERER_LOADIMAGE_H_ - -#include "libGLESv2/angletypes.h" - -#include - -namespace rx -{ - -void LoadA8ToRGBA8(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); - -void LoadA8ToBGRA8(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); - -void LoadA8ToBGRA8_SSE2(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); - -void LoadA32FToRGBA32F(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); - -void LoadA16FToRGBA16F(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); - -void LoadL8ToRGBA8(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); - -void LoadL8ToBGRA8(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); - -void LoadL32FToRGBA32F(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); - -void LoadL16FToRGBA16F(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); - -void LoadLA8ToRGBA8(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); - -void LoadLA8ToBGRA8(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); - -void LoadLA32FToRGBA32F(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); - -void LoadLA16FToRGBA16F(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); - -void LoadRGB8ToBGRX8(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); - -void LoadRG8ToBGRX8(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); - -void LoadR8ToBGRX8(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); - -void LoadR5G6B5ToBGRA8(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); - -void LoadR5G6B5ToRGBA8(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); - -void LoadRGBA8ToBGRA8_SSE2(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); - -void LoadRGBA8ToBGRA8(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); - -void LoadRGBA4ToBGRA8(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); - -void LoadRGBA4ToRGBA8(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); - -void LoadBGRA4ToBGRA8(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); - -void LoadRGB5A1ToBGRA8(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); - -void LoadRGB5A1ToRGBA8(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); - -void LoadBGR5A1ToBGRA8(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); - -void LoadRGB10A2ToRGBA8(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); - -void LoadRGB16FToRGB9E5(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); - -void LoadRGB32FToRGB9E5(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); - -void LoadRGB16FToRG11B10F(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); - -void LoadRGB32FToRG11B10F(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); - -void LoadG8R24ToR24G8(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); - -template -inline void LoadToNative(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); - -template -inline void LoadToNative3To4(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); - -template -inline void Load32FTo16F(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); - -void LoadRGB32FToRGBA16F(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); - -template -inline void LoadCompressedToNative(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); - -void LoadR32ToR16(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); - -template -inline void Initialize4ComponentData(size_t width, size_t height, size_t depth, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); - -void LoadR32ToR24G8(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); - -template -inline T *OffsetDataPointer(uint8_t *data, size_t y, size_t z, size_t rowPitch, size_t depthPitch); - -template -inline const T *OffsetDataPointer(const uint8_t *data, size_t y, size_t z, size_t rowPitch, size_t depthPitch); - -} - -#include "loadimage.inl" - -#endif // LIBGLESV2_RENDERER_LOADIMAGE_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/loadimage.inl b/src/3rdparty/angle/src/libGLESv2/renderer/loadimage.inl deleted file mode 100644 index abd0a3673c..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/loadimage.inl +++ /dev/null @@ -1,156 +0,0 @@ -// -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "common/mathutil.h" - -namespace rx -{ - -template -inline T *OffsetDataPointer(uint8_t *data, size_t y, size_t z, size_t rowPitch, size_t depthPitch) -{ - return reinterpret_cast(data + (y * rowPitch) + (z * depthPitch)); -} - -template -inline const T *OffsetDataPointer(const uint8_t *data, size_t y, size_t z, size_t rowPitch, size_t depthPitch) -{ - return reinterpret_cast(data + (y * rowPitch) + (z * depthPitch)); -} - -template -inline void LoadToNative(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) -{ - const size_t rowSize = width * sizeof(type) * componentCount; - const size_t layerSize = rowSize * height; - const size_t imageSize = layerSize * depth; - - if (layerSize == inputDepthPitch && layerSize == outputDepthPitch) - { - ASSERT(rowSize == inputRowPitch && rowSize == outputRowPitch); - memcpy(output, input, imageSize); - } - else if (rowSize == inputRowPitch && rowSize == outputRowPitch) - { - for (size_t z = 0; z < depth; z++) - { - const type *source = OffsetDataPointer(input, 0, z, inputRowPitch, inputDepthPitch); - type *dest = OffsetDataPointer(output, 0, z, outputRowPitch, outputDepthPitch); - - memcpy(dest, source, layerSize); - } - } - else - { - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y++) - { - const type *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - type *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - memcpy(dest, source, width * sizeof(type) * componentCount); - } - } - } -} - -template -inline void LoadToNative3To4(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) -{ - const type fourthValue = gl::bitCast(fourthComponentBits); - - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y++) - { - const type *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - type *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - for (size_t x = 0; x < width; x++) - { - dest[x * 4 + 0] = source[x * 3 + 0]; - dest[x * 4 + 1] = source[x * 3 + 1]; - dest[x * 4 + 2] = source[x * 3 + 2]; - dest[x * 4 + 3] = fourthValue; - } - } - } -} - -template -inline void Load32FTo16F(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) -{ - const size_t elementWidth = componentCount * width; - - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y++) - { - const float *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - uint16_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - - for (size_t x = 0; x < elementWidth; x++) - { - dest[x] = gl::float32ToFloat16(source[x]); - } - } - } -} - -template -inline void LoadCompressedToNative(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) -{ - const size_t columns = (width + (blockWidth - 1)) / blockWidth; - const size_t rows = (height + (blockHeight - 1)) / blockHeight; - - for (size_t z = 0; z < depth; ++z) - { - for (size_t y = 0; y < rows; ++y) - { - const uint8_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - uint8_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - memcpy(dest, source, columns * blockSize); - } - } -} - -template -inline void Initialize4ComponentData(size_t width, size_t height, size_t depth, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) -{ - type writeValues[4] = - { - gl::bitCast(firstBits), - gl::bitCast(secondBits), - gl::bitCast(thirdBits), - gl::bitCast(fourthBits), - }; - - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y++) - { - type *destRow = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - for (size_t x = 0; x < width; x++) - { - type* destPixel = destRow + x * 4; - - // This could potentially be optimized by generating an entire row of initialization - // data and copying row by row instead of pixel by pixel. - memcpy(destPixel, writeValues, sizeof(type) * 4); - } - } - } -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/loadimageSSE2.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/loadimageSSE2.cpp deleted file mode 100644 index 159b4c7e9f..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/loadimageSSE2.cpp +++ /dev/null @@ -1,118 +0,0 @@ -// -// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// loadimageSSE2.cpp: Defines image loading functions. 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/renderer/loadimage.h" - -namespace rx -{ - -void LoadA8ToBGRA8_SSE2(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) -{ -#if defined(_M_ARM) - // Ensure that this function is reported as not implemented for ARM builds because - // the instructions below are not present for that architecture. - UNIMPLEMENTED(); - return; -#else - __m128i zeroWide = _mm_setzero_si128(); - - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y++) - { - const uint8_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - uint32_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - - size_t x = 0; - - // Make output writes aligned - for (; ((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; - } - } - } -#endif -} - -void LoadRGBA8ToBGRA8_SSE2(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) -{ -#if defined(_M_ARM) - // Ensure that this function is reported as not implemented for ARM builds because - // the instructions below are not present for that architecture. - UNIMPLEMENTED(); - return; -#else - __m128i brMask = _mm_set1_epi32(0x00ff00ff); - - for (size_t z = 0; z < depth; z++) - { - for (size_t y = 0; y < height; y++) - { - const uint32_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); - uint32_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); - - size_t x = 0; - - // Make output writes aligned - for (; ((reinterpret_cast(&dest[x]) & 15) != 0) && x < width; x++) - { - uint32_t 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++) - { - uint32_t rgba = source[x]; - dest[x] = (_rotl(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00); - } - } - } -#endif -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/vertexconversion.h b/src/3rdparty/angle/src/libGLESv2/renderer/vertexconversion.h deleted file mode 100644 index 81ba8a0767..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/vertexconversion.h +++ /dev/null @@ -1,197 +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 - -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 uint8_t *input, size_t stride, size_t n, uint8_t *output) - { - OutputType *out = reinterpret_cast(output); - - for (std::size_t i = 0; i < n; i++) - { - const InputType *ein = reinterpret_cast(input + 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; - } - } - - private: - 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/validationES.cpp b/src/3rdparty/angle/src/libGLESv2/validationES.cpp deleted file mode 100644 index 265f4b4fba..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/validationES.cpp +++ /dev/null @@ -1,1954 +0,0 @@ -// -// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// validationES.h: Validation functions for generic OpenGL ES entry point parameters - -#include "libGLESv2/validationES.h" -#include "libGLESv2/validationES2.h" -#include "libGLESv2/validationES3.h" -#include "libGLESv2/Context.h" -#include "libGLESv2/Texture.h" -#include "libGLESv2/Framebuffer.h" -#include "libGLESv2/FramebufferAttachment.h" -#include "libGLESv2/formatutils.h" -#include "libGLESv2/main.h" -#include "libGLESv2/Query.h" -#include "libGLESv2/ProgramBinary.h" -#include "libGLESv2/TransformFeedback.h" -#include "libGLESv2/VertexArray.h" -#include "libGLESv2/renderer/BufferImpl.h" - -#include "common/mathutil.h" -#include "common/utilities.h" - -// FIXME(jmadill): remove this when we support buffer data caching -#include "libGLESv2/renderer/d3d/BufferD3D.h" - -namespace gl -{ - -bool ValidCap(const Context *context, GLenum cap) -{ - switch (cap) - { - case GL_CULL_FACE: - case GL_POLYGON_OFFSET_FILL: - case GL_SAMPLE_ALPHA_TO_COVERAGE: - case GL_SAMPLE_COVERAGE: - case GL_SCISSOR_TEST: - case GL_STENCIL_TEST: - case GL_DEPTH_TEST: - case GL_BLEND: - case GL_DITHER: - return true; - case GL_PRIMITIVE_RESTART_FIXED_INDEX: - case GL_RASTERIZER_DISCARD: - return (context->getClientVersion() >= 3); - default: - return false; - } -} - -bool ValidTextureTarget(const Context *context, GLenum target) -{ - switch (target) - { - case GL_TEXTURE_2D: - case GL_TEXTURE_CUBE_MAP: - return true; - - case GL_TEXTURE_3D: - case GL_TEXTURE_2D_ARRAY: - return (context->getClientVersion() >= 3); - - default: - return false; - } -} - -// This function differs from ValidTextureTarget in that the target must be -// usable as the destination of a 2D operation-- so a cube face is valid, but -// GL_TEXTURE_CUBE_MAP is not. -// Note: duplicate of IsInternalTextureTarget -bool ValidTexture2DDestinationTarget(const Context *context, GLenum target) -{ - switch (target) - { - case GL_TEXTURE_2D: - case GL_TEXTURE_CUBE_MAP_POSITIVE_X: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: - return true; - case GL_TEXTURE_2D_ARRAY: - case GL_TEXTURE_3D: - return (context->getClientVersion() >= 3); - default: - return false; - } -} - -bool ValidFramebufferTarget(GLenum target) -{ - META_ASSERT(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER && GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER); - - switch (target) - { - case GL_FRAMEBUFFER: return true; - case GL_READ_FRAMEBUFFER: return true; - case GL_DRAW_FRAMEBUFFER: return true; - default: return false; - } -} - -bool ValidBufferTarget(const Context *context, GLenum target) -{ - switch (target) - { - case GL_ARRAY_BUFFER: - case GL_ELEMENT_ARRAY_BUFFER: - return true; - - case GL_PIXEL_PACK_BUFFER: - case GL_PIXEL_UNPACK_BUFFER: - return context->getExtensions().pixelBufferObject; - - case GL_COPY_READ_BUFFER: - case GL_COPY_WRITE_BUFFER: - case GL_TRANSFORM_FEEDBACK_BUFFER: - case GL_UNIFORM_BUFFER: - return (context->getClientVersion() >= 3); - - default: - return false; - } -} - -bool ValidBufferParameter(const Context *context, GLenum pname) -{ - switch (pname) - { - case GL_BUFFER_USAGE: - case GL_BUFFER_SIZE: - return true; - - // GL_BUFFER_MAP_POINTER is a special case, and may only be - // queried with GetBufferPointerv - case GL_BUFFER_ACCESS_FLAGS: - case GL_BUFFER_MAPPED: - case GL_BUFFER_MAP_OFFSET: - case GL_BUFFER_MAP_LENGTH: - return (context->getClientVersion() >= 3); - - default: - return false; - } -} - -bool ValidMipLevel(const Context *context, GLenum target, GLint level) -{ - size_t maxDimension = 0; - switch (target) - { - case GL_TEXTURE_2D: maxDimension = context->getCaps().max2DTextureSize; break; - case GL_TEXTURE_CUBE_MAP: - case GL_TEXTURE_CUBE_MAP_POSITIVE_X: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: maxDimension = context->getCaps().maxCubeMapTextureSize; break; - case GL_TEXTURE_3D: maxDimension = context->getCaps().max3DTextureSize; break; - case GL_TEXTURE_2D_ARRAY: maxDimension = context->getCaps().max2DTextureSize; break; - default: UNREACHABLE(); - } - - return level <= gl::log2(maxDimension); -} - -bool ValidImageSize(const Context *context, GLenum target, GLint level, - GLsizei width, GLsizei height, GLsizei depth) -{ - if (level < 0 || width < 0 || height < 0 || depth < 0) - { - return false; - } - - if (!context->getExtensions().textureNPOT && - (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth)))) - { - return false; - } - - if (!ValidMipLevel(context, target, level)) - { - return false; - } - - return true; -} - -bool ValidCompressedImageSize(const Context *context, GLenum internalFormat, GLsizei width, GLsizei height) -{ - const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat); - if (!formatInfo.compressed) - { - return false; - } - - if (width < 0 || (static_cast(width) > formatInfo.compressedBlockWidth && width % formatInfo.compressedBlockWidth != 0) || - height < 0 || (static_cast(height) > formatInfo.compressedBlockHeight && height % formatInfo.compressedBlockHeight != 0)) - { - return false; - } - - return true; -} - -bool ValidQueryType(const Context *context, GLenum queryType) -{ - META_ASSERT(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT); - META_ASSERT(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT); - - switch (queryType) - { - case GL_ANY_SAMPLES_PASSED: - case GL_ANY_SAMPLES_PASSED_CONSERVATIVE: - return true; - case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: - return (context->getClientVersion() >= 3); - default: - return false; - } -} - -bool ValidProgram(Context *context, GLuint id) -{ - // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will generate the - // error INVALID_VALUE if the provided name is not the name of either a shader or program object and - // INVALID_OPERATION if the provided name identifies an object that is not the expected type." - - if (context->getProgram(id) != NULL) - { - return true; - } - else if (context->getShader(id) != NULL) - { - // ID is the wrong type - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - else - { - // No shader/program object has this ID - context->recordError(Error(GL_INVALID_VALUE)); - return false; - } -} - -bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment) -{ - if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT) - { - const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT); - - if (colorAttachment >= context->getCaps().maxColorAttachments) - { - context->recordError(Error(GL_INVALID_VALUE)); - return false; - } - } - else - { - switch (attachment) - { - case GL_DEPTH_ATTACHMENT: - case GL_STENCIL_ATTACHMENT: - break; - - case GL_DEPTH_STENCIL_ATTACHMENT: - if (context->getClientVersion() < 3) - { - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - break; - - default: - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - } - - return true; -} - -bool ValidateRenderbufferStorageParameters(gl::Context *context, GLenum target, GLsizei samples, - GLenum internalformat, GLsizei width, GLsizei height, - bool angleExtension) -{ - switch (target) - { - case GL_RENDERBUFFER: - break; - default: - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - - if (width < 0 || height < 0 || samples < 0) - { - context->recordError(Error(GL_INVALID_VALUE)); - return false; - } - - const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat); - if (!formatCaps.renderable) - { - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - - // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be - // sized but it does state that the format must be in the ES2.0 spec table 4.5 which contains - // only sized internal formats. The ES3 spec (section 4.4.2) does, however, state that the - // internal format must be sized and not an integer format if samples is greater than zero. - const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat); - if (formatInfo.pixelBytes == 0) - { - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - - if ((formatInfo.componentType == GL_UNSIGNED_INT || formatInfo.componentType == GL_INT) && samples > 0) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - if (static_cast(std::max(width, height)) > context->getCaps().maxRenderbufferSize) - { - context->recordError(Error(GL_INVALID_VALUE)); - return false; - } - - // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal - // to MAX_SAMPLES_ANGLE (Context::getMaxSupportedSamples) while the ES3.0 spec (section 4.4.2) - // states that samples must be less than or equal to the maximum samples for the specified - // internal format. - if (angleExtension) - { - ASSERT(context->getExtensions().framebufferMultisample); - if (static_cast(samples) > context->getExtensions().maxSamples) - { - context->recordError(Error(GL_INVALID_VALUE)); - return false; - } - - // Check if this specific format supports enough samples - if (static_cast(samples) > formatCaps.getMaxSamples()) - { - context->recordError(Error(GL_OUT_OF_MEMORY)); - return false; - } - } - else - { - if (static_cast(samples) > formatCaps.getMaxSamples()) - { - context->recordError(Error(GL_INVALID_VALUE)); - return false; - } - } - - GLuint handle = context->getState().getRenderbufferId(); - if (handle == 0) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - return true; -} - -bool ValidateFramebufferRenderbufferParameters(gl::Context *context, GLenum target, GLenum attachment, - GLenum renderbuffertarget, GLuint renderbuffer) -{ - if (!ValidFramebufferTarget(target)) - { - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - - gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target); - GLuint framebufferHandle = context->getState().getTargetFramebuffer(target)->id(); - - if (!framebuffer || (framebufferHandle == 0 && renderbuffer != 0)) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - if (!ValidateAttachmentTarget(context, attachment)) - { - return false; - } - - // [OpenGL ES 2.0.25] Section 4.4.3 page 112 - // [OpenGL ES 3.0.2] Section 4.4.2 page 201 - // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of - // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated. - if (renderbuffer != 0) - { - if (!context->getRenderbuffer(renderbuffer)) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - } - - return true; -} - -static bool IsPartialBlit(gl::Context *context, gl::FramebufferAttachment *readBuffer, gl::FramebufferAttachment *writeBuffer, - GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, - GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1) -{ - if (srcX0 != 0 || srcY0 != 0 || dstX0 != 0 || dstY0 != 0 || - dstX1 != writeBuffer->getWidth() || dstY1 != writeBuffer->getHeight() || - srcX1 != readBuffer->getWidth() || srcY1 != readBuffer->getHeight()) - { - return true; - } - else if (context->getState().isScissorTestEnabled()) - { - const Rectangle &scissor = context->getState().getScissor(); - - return scissor.x > 0 || scissor.y > 0 || - scissor.width < writeBuffer->getWidth() || - scissor.height < writeBuffer->getHeight(); - } - else - { - return false; - } -} - -bool ValidateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, - GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, - GLenum filter, bool fromAngleExtension) -{ - switch (filter) - { - case GL_NEAREST: - break; - case GL_LINEAR: - if (fromAngleExtension) - { - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - break; - default: - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - - if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0) - { - context->recordError(Error(GL_INVALID_VALUE)); - return false; - } - - if (mask == 0) - { - // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no - // buffers are copied. - return false; - } - - if (fromAngleExtension && (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)) - { - ERR("Scaling and flipping in BlitFramebufferANGLE not supported by this implementation."); - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the - // color buffer, leaving only nearest being unfiltered from above - if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - if (context->getState().getReadFramebuffer()->id() == context->getState().getDrawFramebuffer()->id()) - { - if (fromAngleExtension) - { - ERR("Blits with the same source and destination framebuffer are not supported by this " - "implementation."); - } - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - gl::Framebuffer *readFramebuffer = context->getState().getReadFramebuffer(); - gl::Framebuffer *drawFramebuffer = context->getState().getDrawFramebuffer(); - - if (!readFramebuffer || !drawFramebuffer) - { - context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION)); - return false; - } - - if (!readFramebuffer->completeness(context->getData())) - { - context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION)); - return false; - } - - if (!drawFramebuffer->completeness(context->getData())) - { - context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION)); - return false; - } - - if (drawFramebuffer->getSamples(context->getData()) != 0) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1; - - if (mask & GL_COLOR_BUFFER_BIT) - { - gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer(); - gl::FramebufferAttachment *drawColorBuffer = drawFramebuffer->getFirstColorbuffer(); - - if (readColorBuffer && drawColorBuffer) - { - GLenum readInternalFormat = readColorBuffer->getActualFormat(); - const InternalFormat &readFormatInfo = GetInternalFormatInfo(readInternalFormat); - - for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; i++) - { - if (drawFramebuffer->isEnabledColorAttachment(i)) - { - GLenum drawInternalFormat = drawFramebuffer->getColorbuffer(i)->getActualFormat(); - const InternalFormat &drawFormatInfo = GetInternalFormatInfo(drawInternalFormat); - - // The GL ES 3.0.2 spec (pg 193) states that: - // 1) If the read buffer is fixed point format, the draw buffer must be as well - // 2) If the read buffer is an unsigned integer format, the draw buffer must be as well - // 3) If the read buffer is a signed integer format, the draw buffer must be as well - if ( (readFormatInfo.componentType == GL_UNSIGNED_NORMALIZED || readFormatInfo.componentType == GL_SIGNED_NORMALIZED) && - !(drawFormatInfo.componentType == GL_UNSIGNED_NORMALIZED || drawFormatInfo.componentType == GL_SIGNED_NORMALIZED)) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - if (readFormatInfo.componentType == GL_UNSIGNED_INT && drawFormatInfo.componentType != GL_UNSIGNED_INT) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - if (readFormatInfo.componentType == GL_INT && drawFormatInfo.componentType != GL_INT) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - if (readColorBuffer->getSamples() > 0 && (readInternalFormat != drawInternalFormat || !sameBounds)) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - } - } - - if ((readFormatInfo.componentType == GL_INT || readFormatInfo.componentType == GL_UNSIGNED_INT) && filter == GL_LINEAR) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - if (fromAngleExtension) - { - const GLenum readColorbufferType = readFramebuffer->getReadColorbufferType(); - if (readColorbufferType != GL_TEXTURE_2D && readColorbufferType != GL_RENDERBUFFER) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) - { - if (drawFramebuffer->isEnabledColorAttachment(colorAttachment)) - { - FramebufferAttachment *attachment = drawFramebuffer->getColorbuffer(colorAttachment); - ASSERT(attachment); - - if (attachment->type() != GL_TEXTURE_2D && attachment->type() != GL_RENDERBUFFER) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - // Return an error if the destination formats do not match - if (attachment->getInternalFormat() != readColorBuffer->getInternalFormat()) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - } - } - - int readSamples = readFramebuffer->getSamples(context->getData()); - - if (readSamples != 0 && IsPartialBlit(context, readColorBuffer, drawColorBuffer, - srcX0, srcY0, srcX1, srcY1, - dstX0, dstY0, dstX1, dstY1)) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - } - } - } - - if (mask & GL_DEPTH_BUFFER_BIT) - { - gl::FramebufferAttachment *readDepthBuffer = readFramebuffer->getDepthbuffer(); - gl::FramebufferAttachment *drawDepthBuffer = drawFramebuffer->getDepthbuffer(); - - if (readDepthBuffer && drawDepthBuffer) - { - if (readDepthBuffer->getActualFormat() != drawDepthBuffer->getActualFormat()) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - if (readDepthBuffer->getSamples() > 0 && !sameBounds) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - if (fromAngleExtension) - { - if (IsPartialBlit(context, readDepthBuffer, drawDepthBuffer, - srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1)) - { - ERR("Only whole-buffer depth and stencil blits are supported by this implementation."); - context->recordError(Error(GL_INVALID_OPERATION)); // only whole-buffer copies are permitted - return false; - } - - if (readDepthBuffer->getSamples() != 0 || drawDepthBuffer->getSamples() != 0) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - } - } - } - - if (mask & GL_STENCIL_BUFFER_BIT) - { - gl::FramebufferAttachment *readStencilBuffer = readFramebuffer->getStencilbuffer(); - gl::FramebufferAttachment *drawStencilBuffer = drawFramebuffer->getStencilbuffer(); - - if (readStencilBuffer && drawStencilBuffer) - { - if (readStencilBuffer->getActualFormat() != drawStencilBuffer->getActualFormat()) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - if (readStencilBuffer->getSamples() > 0 && !sameBounds) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - if (fromAngleExtension) - { - if (IsPartialBlit(context, readStencilBuffer, drawStencilBuffer, - srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1)) - { - ERR("Only whole-buffer depth and stencil blits are supported by this implementation."); - context->recordError(Error(GL_INVALID_OPERATION)); // only whole-buffer copies are permitted - return false; - } - - if (readStencilBuffer->getSamples() != 0 || drawStencilBuffer->getSamples() != 0) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - } - } - } - - return true; -} - -bool ValidateGetVertexAttribParameters(Context *context, GLenum pname) -{ - switch (pname) - { - case GL_VERTEX_ATTRIB_ARRAY_ENABLED: - case GL_VERTEX_ATTRIB_ARRAY_SIZE: - case GL_VERTEX_ATTRIB_ARRAY_STRIDE: - case GL_VERTEX_ATTRIB_ARRAY_TYPE: - case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED: - case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: - case GL_CURRENT_VERTEX_ATTRIB: - return true; - - case GL_VERTEX_ATTRIB_ARRAY_DIVISOR: - // Don't verify ES3 context because GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE uses - // the same constant. - META_ASSERT(GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE); - return true; - - case GL_VERTEX_ATTRIB_ARRAY_INTEGER: - if (context->getClientVersion() < 3) - { - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - return true; - - default: - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } -} - -bool ValidateTexParamParameters(gl::Context *context, GLenum pname, GLint param) -{ - switch (pname) - { - case GL_TEXTURE_WRAP_R: - case GL_TEXTURE_SWIZZLE_R: - case GL_TEXTURE_SWIZZLE_G: - case GL_TEXTURE_SWIZZLE_B: - case GL_TEXTURE_SWIZZLE_A: - case GL_TEXTURE_BASE_LEVEL: - case GL_TEXTURE_MAX_LEVEL: - case GL_TEXTURE_COMPARE_MODE: - case GL_TEXTURE_COMPARE_FUNC: - case GL_TEXTURE_MIN_LOD: - case GL_TEXTURE_MAX_LOD: - if (context->getClientVersion() < 3) - { - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - break; - - default: break; - } - - switch (pname) - { - case GL_TEXTURE_WRAP_S: - case GL_TEXTURE_WRAP_T: - case GL_TEXTURE_WRAP_R: - switch (param) - { - case GL_REPEAT: - case GL_CLAMP_TO_EDGE: - case GL_MIRRORED_REPEAT: - return true; - default: - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - - case GL_TEXTURE_MIN_FILTER: - switch (param) - { - case GL_NEAREST: - case GL_LINEAR: - case GL_NEAREST_MIPMAP_NEAREST: - case GL_LINEAR_MIPMAP_NEAREST: - case GL_NEAREST_MIPMAP_LINEAR: - case GL_LINEAR_MIPMAP_LINEAR: - return true; - default: - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - break; - - case GL_TEXTURE_MAG_FILTER: - switch (param) - { - case GL_NEAREST: - case GL_LINEAR: - return true; - default: - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - break; - - case GL_TEXTURE_USAGE_ANGLE: - switch (param) - { - case GL_NONE: - case GL_FRAMEBUFFER_ATTACHMENT_ANGLE: - return true; - default: - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - break; - - case GL_TEXTURE_MAX_ANISOTROPY_EXT: - if (!context->getExtensions().textureFilterAnisotropic) - { - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - - // we assume the parameter passed to this validation method is truncated, not rounded - if (param < 1) - { - context->recordError(Error(GL_INVALID_VALUE)); - return false; - } - return true; - - case GL_TEXTURE_MIN_LOD: - case GL_TEXTURE_MAX_LOD: - // any value is permissible - return true; - - case GL_TEXTURE_COMPARE_MODE: - // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17 - switch (param) - { - case GL_NONE: - case GL_COMPARE_REF_TO_TEXTURE: - return true; - default: - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - break; - - case GL_TEXTURE_COMPARE_FUNC: - // Acceptable function parameters from GLES 3.0.2 spec, table 3.17 - switch (param) - { - case GL_LEQUAL: - case GL_GEQUAL: - case GL_LESS: - case GL_GREATER: - case GL_EQUAL: - case GL_NOTEQUAL: - case GL_ALWAYS: - case GL_NEVER: - return true; - default: - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - break; - - case GL_TEXTURE_SWIZZLE_R: - case GL_TEXTURE_SWIZZLE_G: - case GL_TEXTURE_SWIZZLE_B: - case GL_TEXTURE_SWIZZLE_A: - switch (param) - { - case GL_RED: - case GL_GREEN: - case GL_BLUE: - case GL_ALPHA: - case GL_ZERO: - case GL_ONE: - return true; - default: - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - break; - - case GL_TEXTURE_BASE_LEVEL: - case GL_TEXTURE_MAX_LEVEL: - if (param < 0) - { - context->recordError(Error(GL_INVALID_VALUE)); - return false; - } - return true; - - default: - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } -} - -bool ValidateSamplerObjectParameter(gl::Context *context, GLenum pname) -{ - switch (pname) - { - case GL_TEXTURE_MIN_FILTER: - case GL_TEXTURE_MAG_FILTER: - case GL_TEXTURE_WRAP_S: - case GL_TEXTURE_WRAP_T: - case GL_TEXTURE_WRAP_R: - case GL_TEXTURE_MIN_LOD: - case GL_TEXTURE_MAX_LOD: - case GL_TEXTURE_COMPARE_MODE: - case GL_TEXTURE_COMPARE_FUNC: - return true; - - default: - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } -} - -bool ValidateReadPixelsParameters(gl::Context *context, GLint x, GLint y, GLsizei width, GLsizei height, - GLenum format, GLenum type, GLsizei *bufSize, GLvoid *pixels) -{ - gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer(); - ASSERT(framebuffer); - - if (framebuffer->completeness(context->getData()) != GL_FRAMEBUFFER_COMPLETE) - { - context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION)); - return false; - } - - if (context->getState().getReadFramebuffer()->id() != 0 && - framebuffer->getSamples(context->getData()) != 0) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - if (!framebuffer->getReadColorbuffer()) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - GLenum currentInternalFormat, currentFormat, currentType; - GLuint clientVersion = context->getClientVersion(); - - context->getCurrentReadFormatType(¤tInternalFormat, ¤tFormat, ¤tType); - - bool validReadFormat = (clientVersion < 3) ? ValidES2ReadFormatType(context, format, type) : - ValidES3ReadFormatType(context, currentInternalFormat, format, type); - - if (!(currentFormat == format && currentType == type) && !validReadFormat) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - GLenum sizedInternalFormat = GetSizedInternalFormat(format, type); - const InternalFormat &sizedFormatInfo = GetInternalFormatInfo(sizedInternalFormat); - - GLsizei outputPitch = sizedFormatInfo.computeRowPitch(type, width, context->getState().getPackAlignment()); - // sized query sanity check - if (bufSize) - { - int requiredSize = outputPitch * height; - if (requiredSize > *bufSize) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - } - - return true; -} - -bool ValidateBeginQuery(gl::Context *context, GLenum target, GLuint id) -{ - if (!ValidQueryType(context, target)) - { - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - - if (id == 0) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an - // of zero, if the active query object name for is non-zero (for the - // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if - // the active query for either target is non-zero), if is the name of an - // existing query object whose type does not match , or if is the - // active query object name for any query type, the error INVALID_OPERATION is - // generated. - - // Ensure no other queries are active - // NOTE: If other queries than occlusion are supported, we will need to check - // separately that: - // a) The query ID passed is not the current active query for any target/type - // b) There are no active queries for the requested target (and in the case - // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, - // no query may be active for either if glBeginQuery targets either. - if (context->getState().isQueryActive()) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - Query *queryObject = context->getQuery(id, true, target); - - // check that name was obtained with glGenQueries - if (!queryObject) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - // check for type mismatch - if (queryObject->getType() != target) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - return true; -} - -bool ValidateEndQuery(gl::Context *context, GLenum target) -{ - if (!ValidQueryType(context, target)) - { - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - - const Query *queryObject = context->getState().getActiveQuery(target); - - if (queryObject == NULL) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - return true; -} - -static bool ValidateUniformCommonBase(gl::Context *context, GLenum targetUniformType, - GLint location, GLsizei count, LinkedUniform **uniformOut) -{ - if (count < 0) - { - context->recordError(Error(GL_INVALID_VALUE)); - return false; - } - - gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); - if (!programBinary) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - if (location == -1) - { - // Silently ignore the uniform command - return false; - } - - if (!programBinary->isValidUniformLocation(location)) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - LinkedUniform *uniform = programBinary->getUniformByLocation(location); - - // attempting to write an array to a non-array uniform is an INVALID_OPERATION - if (uniform->elementCount() == 1 && count > 1) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - *uniformOut = uniform; - return true; -} - -bool ValidateUniform(gl::Context *context, GLenum uniformType, GLint location, GLsizei count) -{ - // Check for ES3 uniform entry points - if (VariableComponentType(uniformType) == GL_UNSIGNED_INT && context->getClientVersion() < 3) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - LinkedUniform *uniform = NULL; - if (!ValidateUniformCommonBase(context, uniformType, location, count, &uniform)) - { - return false; - } - - GLenum targetBoolType = VariableBoolVectorType(uniformType); - bool samplerUniformCheck = (IsSampler(uniform->type) && uniformType == GL_INT); - if (!samplerUniformCheck && uniformType != uniform->type && targetBoolType != uniform->type) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - return true; -} - -bool ValidateUniformMatrix(gl::Context *context, GLenum matrixType, GLint location, GLsizei count, - GLboolean transpose) -{ - // Check for ES3 uniform entry points - int rows = VariableRowCount(matrixType); - int cols = VariableColumnCount(matrixType); - if (rows != cols && context->getClientVersion() < 3) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - if (transpose != GL_FALSE && context->getClientVersion() < 3) - { - context->recordError(Error(GL_INVALID_VALUE)); - return false; - } - - LinkedUniform *uniform = NULL; - if (!ValidateUniformCommonBase(context, matrixType, location, count, &uniform)) - { - return false; - } - - if (uniform->type != matrixType) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - return true; -} - -bool ValidateStateQuery(gl::Context *context, GLenum pname, GLenum *nativeType, unsigned int *numParams) -{ - if (!context->getQueryParameterInfo(pname, nativeType, numParams)) - { - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - - if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15) - { - unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0); - - if (colorAttachment >= context->getCaps().maxDrawBuffers) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - } - - switch (pname) - { - case GL_TEXTURE_BINDING_2D: - case GL_TEXTURE_BINDING_CUBE_MAP: - case GL_TEXTURE_BINDING_3D: - case GL_TEXTURE_BINDING_2D_ARRAY: - if (context->getState().getActiveSampler() >= context->getCaps().maxCombinedTextureImageUnits) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - break; - - case GL_IMPLEMENTATION_COLOR_READ_TYPE: - case GL_IMPLEMENTATION_COLOR_READ_FORMAT: - { - Framebuffer *framebuffer = context->getState().getReadFramebuffer(); - ASSERT(framebuffer); - if (framebuffer->completeness(context->getData()) != GL_FRAMEBUFFER_COMPLETE) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - FramebufferAttachment *attachment = framebuffer->getReadColorbuffer(); - if (!attachment) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - } - break; - - default: - break; - } - - // pname is valid, but there are no parameters to return - if (numParams == 0) - { - return false; - } - - return true; -} - -bool ValidateCopyTexImageParametersBase(gl::Context* context, GLenum target, GLint level, GLenum internalformat, bool isSubImage, - GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, - GLint border, GLenum *textureFormatOut) -{ - - if (!ValidTexture2DDestinationTarget(context, target)) - { - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - - if (level < 0 || xoffset < 0 || yoffset < 0 || zoffset < 0 || width < 0 || height < 0) - { - context->recordError(Error(GL_INVALID_VALUE)); - return false; - } - - if (std::numeric_limits::max() - xoffset < width || std::numeric_limits::max() - yoffset < height) - { - context->recordError(Error(GL_INVALID_VALUE)); - return false; - } - - if (border != 0) - { - context->recordError(Error(GL_INVALID_VALUE)); - return false; - } - - if (!ValidMipLevel(context, target, level)) - { - context->recordError(Error(GL_INVALID_VALUE)); - return false; - } - - gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer(); - if (framebuffer->completeness(context->getData()) != GL_FRAMEBUFFER_COMPLETE) - { - context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION)); - return false; - } - - if (context->getState().getReadFramebuffer()->id() != 0 && framebuffer->getSamples(context->getData()) != 0) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - const gl::Caps &caps = context->getCaps(); - - gl::Texture *texture = NULL; - GLenum textureInternalFormat = GL_NONE; - GLint textureLevelWidth = 0; - GLint textureLevelHeight = 0; - GLint textureLevelDepth = 0; - GLuint maxDimension = 0; - - switch (target) - { - case GL_TEXTURE_2D: - { - gl::Texture2D *texture2d = context->getTexture2D(); - if (texture2d) - { - textureInternalFormat = texture2d->getInternalFormat(level); - textureLevelWidth = texture2d->getWidth(level); - textureLevelHeight = texture2d->getHeight(level); - textureLevelDepth = 1; - texture = texture2d; - maxDimension = caps.max2DTextureSize; - } - } - break; - - case GL_TEXTURE_CUBE_MAP_POSITIVE_X: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: - { - gl::TextureCubeMap *textureCube = context->getTextureCubeMap(); - if (textureCube) - { - textureInternalFormat = textureCube->getInternalFormat(target, level); - textureLevelWidth = textureCube->getWidth(target, level); - textureLevelHeight = textureCube->getHeight(target, level); - textureLevelDepth = 1; - texture = textureCube; - maxDimension = caps.maxCubeMapTextureSize; - } - } - break; - - case GL_TEXTURE_2D_ARRAY: - { - gl::Texture2DArray *texture2dArray = context->getTexture2DArray(); - if (texture2dArray) - { - textureInternalFormat = texture2dArray->getInternalFormat(level); - textureLevelWidth = texture2dArray->getWidth(level); - textureLevelHeight = texture2dArray->getHeight(level); - textureLevelDepth = texture2dArray->getLayers(level); - texture = texture2dArray; - maxDimension = caps.max2DTextureSize; - } - } - break; - - case GL_TEXTURE_3D: - { - gl::Texture3D *texture3d = context->getTexture3D(); - if (texture3d) - { - textureInternalFormat = texture3d->getInternalFormat(level); - textureLevelWidth = texture3d->getWidth(level); - textureLevelHeight = texture3d->getHeight(level); - textureLevelDepth = texture3d->getDepth(level); - texture = texture3d; - maxDimension = caps.max3DTextureSize; - } - } - break; - - default: - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - - if (!texture) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - if (texture->isImmutable() && !isSubImage) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat); - - if (formatInfo.depthBits > 0) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - if (formatInfo.compressed) - { - if (((width % formatInfo.compressedBlockWidth) != 0 && width != textureLevelWidth) || - ((height % formatInfo.compressedBlockHeight) != 0 && height != textureLevelHeight)) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - } - - if (isSubImage) - { - if (xoffset + width > textureLevelWidth || - yoffset + height > textureLevelHeight || - zoffset >= textureLevelDepth) - { - context->recordError(Error(GL_INVALID_VALUE)); - return false; - } - } - else - { - if (IsCubemapTextureTarget(target) && width != height) - { - context->recordError(Error(GL_INVALID_VALUE)); - return false; - } - - if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions())) - { - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - - int maxLevelDimension = (maxDimension >> level); - if (static_cast(width) > maxLevelDimension || static_cast(height) > maxLevelDimension) - { - context->recordError(Error(GL_INVALID_VALUE)); - return false; - } - } - - *textureFormatOut = textureInternalFormat; - return true; -} - -static bool ValidateDrawBase(Context *context, GLenum mode, GLsizei count, GLsizei maxVertex, GLsizei primcount) -{ - switch (mode) - { - case GL_POINTS: - case GL_LINES: - case GL_LINE_LOOP: - case GL_LINE_STRIP: - case GL_TRIANGLES: - case GL_TRIANGLE_STRIP: - case GL_TRIANGLE_FAN: - break; - default: - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - - if (count < 0) - { - context->recordError(Error(GL_INVALID_VALUE)); - return false; - } - - const State &state = context->getState(); - - // Check for mapped buffers - if (state.hasMappedBuffer(GL_ARRAY_BUFFER)) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - const gl::DepthStencilState &depthStencilState = state.getDepthStencilState(); - if (depthStencilState.stencilWritemask != depthStencilState.stencilBackWritemask || - state.getStencilRef() != state.getStencilBackRef() || - depthStencilState.stencilMask != depthStencilState.stencilBackMask) - { - // Note: these separate values are not supported in WebGL, due to D3D's limitations. - // See Section 6.10 of the WebGL 1.0 spec - ERR("This ANGLE implementation does not support separate front/back stencil " - "writemasks, reference values, or stencil mask values."); - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - const gl::Framebuffer *fbo = state.getDrawFramebuffer(); - if (!fbo || fbo->completeness(context->getData()) != GL_FRAMEBUFFER_COMPLETE) - { - context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION)); - return false; - } - - if (state.getCurrentProgramId() == 0) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - gl::ProgramBinary *programBinary = state.getCurrentProgramBinary(); - if (!programBinary->validateSamplers(NULL, context->getCaps())) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - // Buffer validations - const VertexArray *vao = state.getVertexArray(); - for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++) - { - const VertexAttribute &attrib = vao->getVertexAttribute(attributeIndex); - bool attribActive = (programBinary->getSemanticIndex(attributeIndex) != -1); - if (attribActive && attrib.enabled) - { - gl::Buffer *buffer = attrib.buffer.get(); - - if (buffer) - { - GLint64 attribStride = static_cast(ComputeVertexAttributeStride(attrib)); - GLint64 maxVertexElement = 0; - - if (attrib.divisor > 0) - { - maxVertexElement = static_cast(primcount) / static_cast(attrib.divisor); - } - else - { - maxVertexElement = static_cast(maxVertex); - } - - GLint64 attribDataSize = maxVertexElement * attribStride; - - // [OpenGL ES 3.0.2] section 2.9.4 page 40: - // We can return INVALID_OPERATION if our vertex attribute does not have - // enough backing data. - if (attribDataSize > buffer->getSize()) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - } - else if (attrib.pointer == NULL) - { - // This is an application error that would normally result in a crash, - // but we catch it and return an error - context->recordError(Error(GL_INVALID_OPERATION, "An enabled vertex array has no buffer and no pointer.")); - return false; - } - } - } - - // No-op if zero count - return (count > 0); -} - -bool ValidateDrawArrays(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount) -{ - if (first < 0) - { - context->recordError(Error(GL_INVALID_VALUE)); - return false; - } - - const State &state = context->getState(); - gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback(); - if (curTransformFeedback && curTransformFeedback->isStarted() && !curTransformFeedback->isPaused() && - curTransformFeedback->getDrawMode() != mode) - { - // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode - // that does not match the current transform feedback object's draw mode (if transform feedback - // is active), (3.0.2, section 2.14, pg 86) - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - if (!ValidateDrawBase(context, mode, count, count, primcount)) - { - return false; - } - - return true; -} - -bool ValidateDrawArraysInstanced(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount) -{ - if (primcount < 0) - { - context->recordError(Error(GL_INVALID_VALUE)); - return false; - } - - if (!ValidateDrawArrays(context, mode, first, count, primcount)) - { - return false; - } - - // No-op if zero primitive count - return (primcount > 0); -} - -static bool ValidateDrawInstancedANGLE(Context *context) -{ - // Verify there is at least one active attribute with a divisor of zero - const gl::State& state = context->getState(); - - gl::ProgramBinary *programBinary = state.getCurrentProgramBinary(); - - const VertexArray *vao = state.getVertexArray(); - for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++) - { - const VertexAttribute &attrib = vao->getVertexAttribute(attributeIndex); - bool active = (programBinary->getSemanticIndex(attributeIndex) != -1); - if (active && attrib.divisor == 0) - { - return true; - } - } - - context->recordError(Error(GL_INVALID_OPERATION, "ANGLE_instanced_arrays requires that at least one active attribute" - "has a divisor of zero.")); - return false; -} - -bool ValidateDrawArraysInstancedANGLE(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount) -{ - if (!ValidateDrawInstancedANGLE(context)) - { - return false; - } - - return ValidateDrawArraysInstanced(context, mode, first, count, primcount); -} - -bool ValidateDrawElements(Context *context, GLenum mode, GLsizei count, GLenum type, - const GLvoid* indices, GLsizei primcount, rx::RangeUI *indexRangeOut) -{ - switch (type) - { - case GL_UNSIGNED_BYTE: - case GL_UNSIGNED_SHORT: - break; - case GL_UNSIGNED_INT: - if (!context->getExtensions().elementIndexUint) - { - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - break; - default: - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - - const State &state = context->getState(); - - gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback(); - if (curTransformFeedback && curTransformFeedback->isStarted() && !curTransformFeedback->isPaused()) - { - // It is an invalid operation to call DrawElements, DrawRangeElements or DrawElementsInstanced - // while transform feedback is active, (3.0.2, section 2.14, pg 86) - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - // Check for mapped buffers - if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER)) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - const gl::VertexArray *vao = state.getVertexArray(); - const gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer(); - if (!indices && !elementArrayBuffer) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - if (elementArrayBuffer) - { - const gl::Type &typeInfo = gl::GetTypeInfo(type); - - GLint64 offset = reinterpret_cast(indices); - GLint64 byteCount = static_cast(typeInfo.bytes) * static_cast(count)+offset; - - // check for integer overflows - if (static_cast(count) > (std::numeric_limits::max() / typeInfo.bytes) || - byteCount > static_cast(std::numeric_limits::max())) - { - context->recordError(Error(GL_OUT_OF_MEMORY)); - return false; - } - - // Check for reading past the end of the bound buffer object - if (byteCount > elementArrayBuffer->getSize()) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - } - else if (!indices) - { - // Catch this programming error here - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - // Use max index to validate if our vertex buffers are large enough for the pull. - // TODO: offer fast path, with disabled index validation. - // TODO: also disable index checking on back-ends that are robust to out-of-range accesses. - if (elementArrayBuffer) - { - uintptr_t offset = reinterpret_cast(indices); - if (!elementArrayBuffer->getIndexRangeCache()->findRange(type, offset, count, indexRangeOut, NULL)) - { - // FIXME(jmadill): Use buffer data caching instead of the D3D back-end - rx::BufferD3D *bufferD3D = rx::BufferD3D::makeBufferD3D(elementArrayBuffer->getImplementation()); - const uint8_t *dataPointer = NULL; - Error error = bufferD3D->getData(&dataPointer); - if (error.isError()) - { - context->recordError(error); - return false; - } - - const uint8_t *offsetPointer = dataPointer + offset; - *indexRangeOut = rx::IndexRangeCache::ComputeRange(type, offsetPointer, count); - } - } - else - { - *indexRangeOut = rx::IndexRangeCache::ComputeRange(type, indices, count); - } - - if (!ValidateDrawBase(context, mode, count, static_cast(indexRangeOut->end), primcount)) - { - return false; - } - - return true; -} - -bool ValidateDrawElementsInstanced(Context *context, - GLenum mode, GLsizei count, GLenum type, - const GLvoid *indices, GLsizei primcount, - rx::RangeUI *indexRangeOut) -{ - if (primcount < 0) - { - context->recordError(Error(GL_INVALID_VALUE)); - return false; - } - - if (!ValidateDrawElements(context, mode, count, type, indices, primcount, indexRangeOut)) - { - return false; - } - - // No-op zero primitive count - return (primcount > 0); -} - -bool ValidateDrawElementsInstancedANGLE(Context *context, GLenum mode, GLsizei count, GLenum type, - const GLvoid *indices, GLsizei primcount, rx::RangeUI *indexRangeOut) -{ - if (!ValidateDrawInstancedANGLE(context)) - { - return false; - } - - return ValidateDrawElementsInstanced(context, mode, count, type, indices, primcount, indexRangeOut); -} - -bool ValidateFramebufferTextureBase(Context *context, GLenum target, GLenum attachment, - GLuint texture, GLint level) -{ - if (!ValidFramebufferTarget(target)) - { - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - - if (!ValidateAttachmentTarget(context, attachment)) - { - return false; - } - - if (texture != 0) - { - gl::Texture *tex = context->getTexture(texture); - - if (tex == NULL) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - if (level < 0) - { - context->recordError(Error(GL_INVALID_VALUE)); - return false; - } - } - - const gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target); - GLuint framebufferHandle = context->getState().getTargetFramebuffer(target)->id(); - - if (framebufferHandle == 0 || !framebuffer) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - return true; -} - -bool ValidateFramebufferTexture2D(Context *context, GLenum target, GLenum attachment, - GLenum textarget, GLuint texture, GLint level) -{ - // Attachments are required to be bound to level 0 in ES2 - if (context->getClientVersion() < 3 && level != 0) - { - context->recordError(Error(GL_INVALID_VALUE)); - return false; - } - - if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level)) - { - return false; - } - - if (texture != 0) - { - gl::Texture *tex = context->getTexture(texture); - ASSERT(tex); - - const gl::Caps &caps = context->getCaps(); - - switch (textarget) - { - case GL_TEXTURE_2D: - { - if (level > gl::log2(caps.max2DTextureSize)) - { - context->recordError(Error(GL_INVALID_VALUE)); - return false; - } - if (tex->getTarget() != GL_TEXTURE_2D) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - gl::Texture2D *tex2d = static_cast(tex); - if (tex2d->isCompressed(level)) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - } - break; - - case GL_TEXTURE_CUBE_MAP_POSITIVE_X: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: - { - if (level > gl::log2(caps.maxCubeMapTextureSize)) - { - context->recordError(Error(GL_INVALID_VALUE)); - return false; - } - if (tex->getTarget() != GL_TEXTURE_CUBE_MAP) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - gl::TextureCubeMap *texcube = static_cast(tex); - if (texcube->isCompressed(textarget, level)) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - } - break; - - default: - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - } - - return true; -} - -bool ValidateGetUniformBase(Context *context, GLuint program, GLint location) -{ - if (program == 0) - { - context->recordError(Error(GL_INVALID_VALUE)); - return false; - } - - if (!ValidProgram(context, program)) - { - return false; - } - - gl::Program *programObject = context->getProgram(program); - - if (!programObject || !programObject->isLinked()) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - gl::ProgramBinary *programBinary = programObject->getProgramBinary(); - if (!programBinary) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - if (!programBinary->isValidUniformLocation(location)) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - return true; -} - -bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat* params) -{ - return ValidateGetUniformBase(context, program, location); -} - -bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint* params) -{ - return ValidateGetUniformBase(context, program, location); -} - -static bool ValidateSizedGetUniform(Context *context, GLuint program, GLint location, GLsizei bufSize) -{ - if (!ValidateGetUniformBase(context, program, location)) - { - return false; - } - - gl::Program *programObject = context->getProgram(program); - ASSERT(programObject); - gl::ProgramBinary *programBinary = programObject->getProgramBinary(); - - // sized queries -- ensure the provided buffer is large enough - LinkedUniform *uniform = programBinary->getUniformByLocation(location); - size_t requiredBytes = VariableExternalSize(uniform->type); - if (static_cast(bufSize) < requiredBytes) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - return true; -} - -bool ValidateGetnUniformfvEXT(Context *context, GLuint program, GLint location, GLsizei bufSize, GLfloat* params) -{ - return ValidateSizedGetUniform(context, program, location, bufSize); -} - -bool ValidateGetnUniformivEXT(Context *context, GLuint program, GLint location, GLsizei bufSize, GLint* params) -{ - return ValidateSizedGetUniform(context, program, location, bufSize); -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/validationES.h b/src/3rdparty/angle/src/libGLESv2/validationES.h deleted file mode 100644 index 1fdb633cb6..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/validationES.h +++ /dev/null @@ -1,92 +0,0 @@ -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// validationES.h: Validation functions for generic OpenGL ES entry point parameters - -#ifndef LIBGLESV2_VALIDATION_ES_H -#define LIBGLESV2_VALIDATION_ES_H - -#include "common/mathutil.h" - -#include -#include - -namespace gl -{ - -class Context; - -bool ValidCap(const Context *context, GLenum cap); -bool ValidTextureTarget(const Context *context, GLenum target); -bool ValidTexture2DDestinationTarget(const Context *context, GLenum target); -bool ValidFramebufferTarget(GLenum target); -bool ValidBufferTarget(const Context *context, GLenum target); -bool ValidBufferParameter(const Context *context, GLenum pname); -bool ValidMipLevel(const Context *context, GLenum target, GLint level); -bool ValidImageSize(const Context *context, GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth); -bool ValidCompressedImageSize(const Context *context, GLenum internalFormat, GLsizei width, GLsizei height); -bool ValidQueryType(const Context *context, GLenum queryType); -bool ValidProgram(Context *context, GLuint id); - -bool ValidateAttachmentTarget(Context *context, GLenum attachment); -bool ValidateRenderbufferStorageParameters(Context *context, GLenum target, GLsizei samples, - GLenum internalformat, GLsizei width, GLsizei height, - bool angleExtension); -bool ValidateFramebufferRenderbufferParameters(Context *context, GLenum target, GLenum attachment, - GLenum renderbuffertarget, GLuint renderbuffer); - -bool ValidateBlitFramebufferParameters(Context *context, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, - GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, - GLenum filter, bool fromAngleExtension); - -bool ValidateGetVertexAttribParameters(Context *context, GLenum pname); - -bool ValidateTexParamParameters(Context *context, GLenum pname, GLint param); - -bool ValidateSamplerObjectParameter(Context *context, GLenum pname); - -bool ValidateReadPixelsParameters(Context *context, GLint x, GLint y, GLsizei width, GLsizei height, - GLenum format, GLenum type, GLsizei *bufSize, GLvoid *pixels); - -bool ValidateBeginQuery(Context *context, GLenum target, GLuint id); -bool ValidateEndQuery(Context *context, GLenum target); - -bool ValidateUniform(Context *context, GLenum uniformType, GLint location, GLsizei count); -bool ValidateUniformMatrix(Context *context, GLenum matrixType, GLint location, GLsizei count, - GLboolean transpose); - -bool ValidateStateQuery(Context *context, GLenum pname, GLenum *nativeType, unsigned int *numParams); - -bool ValidateCopyTexImageParametersBase(Context* context, GLenum target, GLint level, GLenum internalformat, bool isSubImage, - GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, - GLint border, GLenum *textureInternalFormatOut); - -bool ValidateDrawArrays(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount); -bool ValidateDrawArraysInstanced(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount); -bool ValidateDrawArraysInstancedANGLE(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount); - -bool ValidateDrawElements(Context *context, GLenum mode, GLsizei count, GLenum type, - const GLvoid* indices, GLsizei primcount, rx::RangeUI *indexRangeOut); - -bool ValidateDrawElementsInstanced(Context *context, GLenum mode, GLsizei count, GLenum type, - const GLvoid *indices, GLsizei primcount, rx::RangeUI *indexRangeOut); -bool ValidateDrawElementsInstancedANGLE(Context *context, GLenum mode, GLsizei count, GLenum type, - const GLvoid *indices, GLsizei primcount, rx::RangeUI *indexRangeOut); - -bool ValidateFramebufferTextureBase(Context *context, GLenum target, GLenum attachment, - GLuint texture, GLint level); -bool ValidateFramebufferTexture2D(Context *context, GLenum target, GLenum attachment, - GLenum textarget, GLuint texture, GLint level); - -bool ValidateGetUniformBase(Context *context, GLuint program, GLint location); -bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat* params); -bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint* params); -bool ValidateGetnUniformfvEXT(Context *context, GLuint program, GLint location, GLsizei bufSize, GLfloat* params); -bool ValidateGetnUniformivEXT(Context *context, GLuint program, GLint location, GLsizei bufSize, GLint* params); - -} - -#endif // LIBGLESV2_VALIDATION_ES_H diff --git a/src/3rdparty/angle/src/libGLESv2/validationES2.cpp b/src/3rdparty/angle/src/libGLESv2/validationES2.cpp deleted file mode 100644 index f950454df0..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/validationES2.cpp +++ /dev/null @@ -1,980 +0,0 @@ -// -// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// validationES2.cpp: Validation functions for OpenGL ES 2.0 entry point parameters - -#include "libGLESv2/validationES2.h" -#include "libGLESv2/validationES.h" -#include "libGLESv2/Context.h" -#include "libGLESv2/Texture.h" -#include "libGLESv2/Framebuffer.h" -#include "libGLESv2/Renderbuffer.h" -#include "libGLESv2/formatutils.h" -#include "libGLESv2/main.h" -#include "libGLESv2/FramebufferAttachment.h" - -#include "common/mathutil.h" -#include "common/utilities.h" - -namespace gl -{ - -static bool ValidateSubImageParams2D(Context *context, bool compressed, GLsizei width, GLsizei height, - GLint xoffset, GLint yoffset, GLint level, GLenum format, GLenum type, - gl::Texture2D *texture) -{ - if (!texture) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - if (compressed != texture->isCompressed(level)) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - if (format != GL_NONE) - { - if (gl::GetFormatTypeInfo(format, type).internalFormat != texture->getInternalFormat(level)) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - } - - if (compressed) - { - if ((width % 4 != 0 && width != texture->getWidth(level)) || - (height % 4 != 0 && height != texture->getHeight(level))) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - } - - if (xoffset + width > texture->getWidth(level) || - yoffset + height > texture->getHeight(level)) - { - context->recordError(Error(GL_INVALID_VALUE)); - return false; - } - - return true; -} - -static bool ValidateSubImageParamsCube(Context *context, bool compressed, GLsizei width, GLsizei height, - GLint xoffset, GLint yoffset, GLenum target, GLint level, GLenum format, GLenum type, - gl::TextureCubeMap *texture) -{ - if (!texture) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - if (compressed != texture->isCompressed(target, level)) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - if (format != GL_NONE) - { - if (gl::GetFormatTypeInfo(format, type).internalFormat != texture->getInternalFormat(target, level)) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - } - - if (compressed) - { - if ((width % 4 != 0 && width != texture->getWidth(target, 0)) || - (height % 4 != 0 && height != texture->getHeight(target, 0))) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - } - - if (xoffset + width > texture->getWidth(target, level) || - yoffset + height > texture->getHeight(target, level)) - { - context->recordError(Error(GL_INVALID_VALUE)); - return false; - } - - return true; -} - -bool ValidateES2TexImageParameters(Context *context, GLenum target, GLint level, GLenum internalformat, bool isCompressed, bool isSubImage, - GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, - GLint border, GLenum format, GLenum type, const GLvoid *pixels) -{ - if (!ValidTexture2DDestinationTarget(context, target)) - { - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - - if (!ValidImageSize(context, target, level, width, height, 1)) - { - context->recordError(Error(GL_INVALID_VALUE)); - return false; - } - - if (level < 0 || xoffset < 0 || - std::numeric_limits::max() - xoffset < width || - std::numeric_limits::max() - yoffset < height) - { - context->recordError(Error(GL_INVALID_VALUE)); - return false; - } - - if (!isSubImage && !isCompressed && internalformat != format) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - const gl::Caps &caps = context->getCaps(); - - gl::Texture *texture = NULL; - bool textureCompressed = false; - GLenum textureInternalFormat = GL_NONE; - GLint textureLevelWidth = 0; - GLint textureLevelHeight = 0; - switch (target) - { - case GL_TEXTURE_2D: - { - if (static_cast(width) > (caps.max2DTextureSize >> level) || - static_cast(height) > (caps.max2DTextureSize >> level)) - { - context->recordError(Error(GL_INVALID_VALUE)); - return false; - } - - gl::Texture2D *tex2d = context->getTexture2D(); - if (tex2d) - { - textureCompressed = tex2d->isCompressed(level); - textureInternalFormat = tex2d->getInternalFormat(level); - textureLevelWidth = tex2d->getWidth(level); - textureLevelHeight = tex2d->getHeight(level); - texture = tex2d; - } - - if (isSubImage && !ValidateSubImageParams2D(context, isCompressed, width, height, xoffset, yoffset, - level, format, type, tex2d)) - { - return false; - } - - texture = tex2d; - } - break; - - case GL_TEXTURE_CUBE_MAP_POSITIVE_X: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: - { - if (!isSubImage && width != height) - { - context->recordError(Error(GL_INVALID_VALUE)); - return false; - } - - if (static_cast(width) > (caps.maxCubeMapTextureSize >> level) || - static_cast(height) > (caps.maxCubeMapTextureSize >> level)) - { - context->recordError(Error(GL_INVALID_VALUE)); - return false; - } - - gl::TextureCubeMap *texCube = context->getTextureCubeMap(); - if (texCube) - { - textureCompressed = texCube->isCompressed(target, level); - textureInternalFormat = texCube->getInternalFormat(target, level); - textureLevelWidth = texCube->getWidth(target, level); - textureLevelHeight = texCube->getHeight(target, level); - texture = texCube; - } - - if (isSubImage && !ValidateSubImageParamsCube(context, isCompressed, width, height, xoffset, yoffset, - target, level, format, type, texCube)) - { - return false; - } - } - break; - - default: - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - - if (!texture) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - if (!isSubImage && texture->isImmutable()) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - // Verify zero border - if (border != 0) - { - context->recordError(Error(GL_INVALID_VALUE)); - return false; - } - - GLenum actualInternalFormat = isSubImage ? textureInternalFormat : internalformat; - if (isCompressed) - { - if (!ValidCompressedImageSize(context, actualInternalFormat, width, height)) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - switch (actualInternalFormat) - { - case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: - case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: - if (!context->getExtensions().textureCompressionDXT1) - { - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - break; - case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: - if (!context->getExtensions().textureCompressionDXT1) - { - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - break; - case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: - if (!context->getExtensions().textureCompressionDXT5) - { - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - break; - default: - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - } - else - { - // validate by itself (used as secondary key below) - switch (type) - { - case GL_UNSIGNED_BYTE: - case GL_UNSIGNED_SHORT_5_6_5: - case GL_UNSIGNED_SHORT_4_4_4_4: - case GL_UNSIGNED_SHORT_5_5_5_1: - case GL_UNSIGNED_SHORT: - case GL_UNSIGNED_INT: - case GL_UNSIGNED_INT_24_8_OES: - case GL_HALF_FLOAT_OES: - case GL_FLOAT: - break; - default: - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - - // validate + combinations - // - invalid -> sets INVALID_ENUM - // - invalid + combination -> sets INVALID_OPERATION - switch (format) - { - case GL_ALPHA: - case GL_LUMINANCE: - case GL_LUMINANCE_ALPHA: - switch (type) - { - case GL_UNSIGNED_BYTE: - case GL_FLOAT: - case GL_HALF_FLOAT_OES: - break; - default: - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - break; - case GL_RED: - case GL_RG: - if (!context->getExtensions().textureRG) - { - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - switch (type) - { - case GL_UNSIGNED_BYTE: - case GL_FLOAT: - case GL_HALF_FLOAT_OES: - break; - default: - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - break; - case GL_RGB: - switch (type) - { - case GL_UNSIGNED_BYTE: - case GL_UNSIGNED_SHORT_5_6_5: - case GL_FLOAT: - case GL_HALF_FLOAT_OES: - break; - default: - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - break; - case GL_RGBA: - switch (type) - { - case GL_UNSIGNED_BYTE: - case GL_UNSIGNED_SHORT_4_4_4_4: - case GL_UNSIGNED_SHORT_5_5_5_1: - case GL_FLOAT: - case GL_HALF_FLOAT_OES: - break; - default: - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - break; - case GL_BGRA_EXT: - switch (type) - { - case GL_UNSIGNED_BYTE: - break; - default: - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - break; - case GL_SRGB_EXT: - case GL_SRGB_ALPHA_EXT: - if (!context->getExtensions().sRGB) - { - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - switch (type) - { - case GL_UNSIGNED_BYTE: - break; - default: - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - break; - case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: // error cases for compressed textures are handled below - case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: - case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: - case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: - break; - case GL_DEPTH_COMPONENT: - switch (type) - { - case GL_UNSIGNED_SHORT: - case GL_UNSIGNED_INT: - break; - default: - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - break; - case GL_DEPTH_STENCIL_OES: - switch (type) - { - case GL_UNSIGNED_INT_24_8_OES: - break; - default: - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - break; - default: - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - - switch (format) - { - case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: - case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: - if (context->getExtensions().textureCompressionDXT1) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - else - { - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - break; - case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: - if (context->getExtensions().textureCompressionDXT3) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - else - { - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - break; - case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: - if (context->getExtensions().textureCompressionDXT5) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - else - { - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - break; - case GL_DEPTH_COMPONENT: - case GL_DEPTH_STENCIL_OES: - if (!context->getExtensions().depthTextures) - { - context->recordError(Error(GL_INVALID_VALUE)); - return false; - } - if (target != GL_TEXTURE_2D) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - // OES_depth_texture supports loading depth data and multiple levels, - // but ANGLE_depth_texture does not - if (pixels != NULL || level != 0) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - break; - default: - break; - } - - if (type == GL_FLOAT) - { - if (!context->getExtensions().textureFloat) - { - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - } - else if (type == GL_HALF_FLOAT_OES) - { - if (!context->getExtensions().textureHalfFloat) - { - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - } - } - - return true; -} - - - -bool ValidateES2CopyTexImageParameters(Context* context, GLenum target, GLint level, GLenum internalformat, bool isSubImage, - GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, - GLint border) -{ - GLenum textureInternalFormat = GL_NONE; - - if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage, - xoffset, yoffset, 0, x, y, width, height, border, &textureInternalFormat)) - { - return false; - } - - gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer(); - GLenum colorbufferFormat = framebuffer->getReadColorbuffer()->getInternalFormat(); - GLenum textureFormat = gl::GetInternalFormatInfo(textureInternalFormat).format; - - // [OpenGL ES 2.0.24] table 3.9 - if (isSubImage) - { - switch (textureFormat) - { - case GL_ALPHA: - if (colorbufferFormat != GL_ALPHA8_EXT && - colorbufferFormat != GL_RGBA4 && - colorbufferFormat != GL_RGB5_A1 && - colorbufferFormat != GL_RGBA8_OES) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - break; - case GL_LUMINANCE: - if (colorbufferFormat != GL_R8_EXT && - colorbufferFormat != GL_RG8_EXT && - colorbufferFormat != GL_RGB565 && - colorbufferFormat != GL_RGB8_OES && - colorbufferFormat != GL_RGBA4 && - colorbufferFormat != GL_RGB5_A1 && - colorbufferFormat != GL_RGBA8_OES) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - break; - case GL_RED_EXT: - if (colorbufferFormat != GL_R8_EXT && - colorbufferFormat != GL_RG8_EXT && - colorbufferFormat != GL_RGB565 && - colorbufferFormat != GL_RGB8_OES && - colorbufferFormat != GL_RGBA4 && - colorbufferFormat != GL_RGB5_A1 && - colorbufferFormat != GL_RGBA8_OES) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - break; - case GL_RG_EXT: - if (colorbufferFormat != GL_RG8_EXT && - colorbufferFormat != GL_RGB565 && - colorbufferFormat != GL_RGB8_OES && - colorbufferFormat != GL_RGBA4 && - colorbufferFormat != GL_RGB5_A1 && - colorbufferFormat != GL_RGBA8_OES) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - break; - case GL_RGB: - if (colorbufferFormat != GL_RGB565 && - colorbufferFormat != GL_RGB8_OES && - colorbufferFormat != GL_RGBA4 && - colorbufferFormat != GL_RGB5_A1 && - colorbufferFormat != GL_RGBA8_OES) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - break; - case GL_LUMINANCE_ALPHA: - case GL_RGBA: - if (colorbufferFormat != GL_RGBA4 && - colorbufferFormat != GL_RGB5_A1 && - colorbufferFormat != GL_RGBA8_OES) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - 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: - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - case GL_DEPTH_COMPONENT: - case GL_DEPTH_STENCIL_OES: - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - default: - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - } - else - { - switch (internalformat) - { - case GL_ALPHA: - if (colorbufferFormat != GL_ALPHA8_EXT && - colorbufferFormat != GL_RGBA4 && - colorbufferFormat != GL_RGB5_A1 && - colorbufferFormat != GL_BGRA8_EXT && - colorbufferFormat != GL_RGBA8_OES) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - break; - case GL_LUMINANCE: - if (colorbufferFormat != GL_R8_EXT && - colorbufferFormat != GL_RG8_EXT && - colorbufferFormat != GL_RGB565 && - colorbufferFormat != GL_RGB8_OES && - colorbufferFormat != GL_RGBA4 && - colorbufferFormat != GL_RGB5_A1 && - colorbufferFormat != GL_BGRA8_EXT && - colorbufferFormat != GL_RGBA8_OES) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - break; - case GL_RED_EXT: - if (colorbufferFormat != GL_R8_EXT && - colorbufferFormat != GL_RG8_EXT && - colorbufferFormat != GL_RGB565 && - colorbufferFormat != GL_RGB8_OES && - colorbufferFormat != GL_RGBA4 && - colorbufferFormat != GL_RGB5_A1 && - colorbufferFormat != GL_BGRA8_EXT && - colorbufferFormat != GL_RGBA8_OES) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - break; - case GL_RG_EXT: - if (colorbufferFormat != GL_RG8_EXT && - colorbufferFormat != GL_RGB565 && - colorbufferFormat != GL_RGB8_OES && - colorbufferFormat != GL_RGBA4 && - colorbufferFormat != GL_RGB5_A1 && - colorbufferFormat != GL_BGRA8_EXT && - colorbufferFormat != GL_RGBA8_OES) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - break; - case GL_RGB: - if (colorbufferFormat != GL_RGB565 && - colorbufferFormat != GL_RGB8_OES && - colorbufferFormat != GL_RGBA4 && - colorbufferFormat != GL_RGB5_A1 && - colorbufferFormat != GL_BGRA8_EXT && - colorbufferFormat != GL_RGBA8_OES) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - break; - case GL_LUMINANCE_ALPHA: - case GL_RGBA: - if (colorbufferFormat != GL_RGBA4 && - colorbufferFormat != GL_RGB5_A1 && - colorbufferFormat != GL_BGRA8_EXT && - colorbufferFormat != GL_RGBA8_OES) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - break; - case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: - case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: - if (context->getExtensions().textureCompressionDXT1) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - else - { - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - break; - case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: - if (context->getExtensions().textureCompressionDXT3) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - else - { - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - break; - case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: - if (context->getExtensions().textureCompressionDXT5) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - else - { - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - break; - case GL_DEPTH_COMPONENT: - case GL_DEPTH_COMPONENT16: - case GL_DEPTH_COMPONENT32_OES: - case GL_DEPTH_STENCIL_OES: - case GL_DEPTH24_STENCIL8_OES: - if (context->getExtensions().depthTextures) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - else - { - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - default: - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - } - - // If width or height is zero, it is a no-op. Return false without setting an error. - return (width > 0 && height > 0); -} - -bool ValidateES2TexStorageParameters(Context *context, GLenum target, GLsizei levels, GLenum internalformat, - GLsizei width, GLsizei height) -{ - if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP) - { - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - - if (width < 1 || height < 1 || levels < 1) - { - context->recordError(Error(GL_INVALID_VALUE)); - return false; - } - - if (target == GL_TEXTURE_CUBE_MAP && width != height) - { - context->recordError(Error(GL_INVALID_VALUE)); - return false; - } - - if (levels != 1 && levels != gl::log2(std::max(width, height)) + 1) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat); - if (formatInfo.format == GL_NONE || formatInfo.type == GL_NONE) - { - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - - const gl::Caps &caps = context->getCaps(); - - switch (target) - { - case GL_TEXTURE_2D: - if (static_cast(width) > caps.max2DTextureSize || - static_cast(height) > caps.max2DTextureSize) - { - context->recordError(Error(GL_INVALID_VALUE)); - return false; - } - break; - case GL_TEXTURE_CUBE_MAP: - if (static_cast(width) > caps.maxCubeMapTextureSize || - static_cast(height) > caps.maxCubeMapTextureSize) - { - context->recordError(Error(GL_INVALID_VALUE)); - return false; - } - break; - default: - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - - if (levels != 1 && !context->getExtensions().textureNPOT) - { - if (!gl::isPow2(width) || !gl::isPow2(height)) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - } - - switch (internalformat) - { - case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: - case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: - if (!context->getExtensions().textureCompressionDXT1) - { - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - break; - case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: - if (!context->getExtensions().textureCompressionDXT3) - { - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - break; - case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: - if (!context->getExtensions().textureCompressionDXT5) - { - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - break; - case GL_RGBA32F_EXT: - case GL_RGB32F_EXT: - case GL_ALPHA32F_EXT: - case GL_LUMINANCE32F_EXT: - case GL_LUMINANCE_ALPHA32F_EXT: - if (!context->getExtensions().textureFloat) - { - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - break; - case GL_RGBA16F_EXT: - case GL_RGB16F_EXT: - case GL_ALPHA16F_EXT: - case GL_LUMINANCE16F_EXT: - case GL_LUMINANCE_ALPHA16F_EXT: - if (!context->getExtensions().textureHalfFloat) - { - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - break; - case GL_R8_EXT: - case GL_RG8_EXT: - case GL_R16F_EXT: - case GL_RG16F_EXT: - case GL_R32F_EXT: - case GL_RG32F_EXT: - if (!context->getExtensions().textureRG) - { - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - break; - case GL_DEPTH_COMPONENT16: - case GL_DEPTH_COMPONENT32_OES: - case GL_DEPTH24_STENCIL8_OES: - if (!context->getExtensions().depthTextures) - { - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - if (target != GL_TEXTURE_2D) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - // ANGLE_depth_texture only supports 1-level textures - if (levels != 1) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - break; - default: - break; - } - - gl::Texture *texture = NULL; - switch(target) - { - case GL_TEXTURE_2D: - texture = context->getTexture2D(); - break; - case GL_TEXTURE_CUBE_MAP: - texture = context->getTextureCubeMap(); - break; - default: - UNREACHABLE(); - } - - if (!texture || texture->id() == 0) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - if (texture->isImmutable()) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - return true; -} - -// check for combinations of format and type that are valid for ReadPixels -bool ValidES2ReadFormatType(Context *context, GLenum format, GLenum type) -{ - switch (format) - { - case GL_RGBA: - switch (type) - { - case GL_UNSIGNED_BYTE: - break; - default: - return false; - } - break; - case GL_BGRA_EXT: - switch (type) - { - case GL_UNSIGNED_BYTE: - case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT: - case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT: - break; - default: - return false; - } - break; - case GL_RG_EXT: - case GL_RED_EXT: - if (!context->getExtensions().textureRG) - { - return false; - } - switch (type) - { - case GL_UNSIGNED_BYTE: - break; - default: - return false; - } - break; - - default: - return false; - } - return true; -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/validationES2.h b/src/3rdparty/angle/src/libGLESv2/validationES2.h deleted file mode 100644 index 53a0b630ea..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/validationES2.h +++ /dev/null @@ -1,34 +0,0 @@ -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// validationES2.h: Validation functions for OpenGL ES 2.0 entry point parameters - -#ifndef LIBGLESV2_VALIDATION_ES2_H -#define LIBGLESV2_VALIDATION_ES2_H - -#include - -namespace gl -{ - -class Context; - -bool ValidateES2TexImageParameters(Context *context, GLenum target, GLint level, GLenum internalformat, bool isCompressed, bool isSubImage, - GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, - GLint border, GLenum format, GLenum type, const GLvoid *pixels); - -bool ValidateES2CopyTexImageParameters(Context* context, GLenum target, GLint level, GLenum internalformat, bool isSubImage, - GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, - GLint border); - -bool ValidateES2TexStorageParameters(Context *context, GLenum target, GLsizei levels, GLenum internalformat, - GLsizei width, GLsizei height); - -bool ValidES2ReadFormatType(Context *context, GLenum format, GLenum type); - -} - -#endif // LIBGLESV2_VALIDATION_ES2_H diff --git a/src/3rdparty/angle/src/libGLESv2/validationES3.cpp b/src/3rdparty/angle/src/libGLESv2/validationES3.cpp deleted file mode 100644 index 2d3a039e13..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/validationES3.cpp +++ /dev/null @@ -1,1286 +0,0 @@ -// -// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// validationES3.cpp: Validation functions for OpenGL ES 3.0 entry point parameters - -#include "libGLESv2/validationES3.h" -#include "libGLESv2/validationES.h" -#include "libGLESv2/Context.h" -#include "libGLESv2/Texture.h" -#include "libGLESv2/Framebuffer.h" -#include "libGLESv2/Renderbuffer.h" -#include "libGLESv2/formatutils.h" -#include "libGLESv2/main.h" -#include "libGLESv2/FramebufferAttachment.h" - -#include "common/mathutil.h" - -namespace gl -{ - -struct ES3FormatCombination -{ - GLenum internalFormat; - GLenum format; - GLenum type; -}; - -bool operator<(const ES3FormatCombination& a, const ES3FormatCombination& b) -{ - return memcmp(&a, &b, sizeof(ES3FormatCombination)) < 0; -} - -typedef std::set ES3FormatCombinationSet; - -static inline void InsertES3FormatCombo(ES3FormatCombinationSet *set, GLenum internalFormat, GLenum format, GLenum type) -{ - ES3FormatCombination info; - info.internalFormat = internalFormat; - info.format = format; - info.type = type; - set->insert(info); -} - -ES3FormatCombinationSet BuildES3FormatSet() -{ - ES3FormatCombinationSet set; - - // Format combinations from ES 3.0.1 spec, table 3.2 - - // | Internal format | Format | Type | - // | | | | - InsertES3FormatCombo(&set, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE ); - InsertES3FormatCombo(&set, GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_BYTE ); - InsertES3FormatCombo(&set, GL_RGBA4, GL_RGBA, GL_UNSIGNED_BYTE ); - InsertES3FormatCombo(&set, GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE ); - InsertES3FormatCombo(&set, GL_RGBA8_SNORM, GL_RGBA, GL_BYTE ); - InsertES3FormatCombo(&set, GL_RGBA4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4 ); - InsertES3FormatCombo(&set, GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV ); - InsertES3FormatCombo(&set, GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV ); - InsertES3FormatCombo(&set, GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1 ); - InsertES3FormatCombo(&set, GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT ); - InsertES3FormatCombo(&set, GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT_OES ); - InsertES3FormatCombo(&set, GL_RGBA32F, GL_RGBA, GL_FLOAT ); - InsertES3FormatCombo(&set, GL_RGBA16F, GL_RGBA, GL_FLOAT ); - InsertES3FormatCombo(&set, GL_RGBA8UI, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE ); - InsertES3FormatCombo(&set, GL_RGBA8I, GL_RGBA_INTEGER, GL_BYTE ); - InsertES3FormatCombo(&set, GL_RGBA16UI, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT ); - InsertES3FormatCombo(&set, GL_RGBA16I, GL_RGBA_INTEGER, GL_SHORT ); - InsertES3FormatCombo(&set, GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT ); - InsertES3FormatCombo(&set, GL_RGBA32I, GL_RGBA_INTEGER, GL_INT ); - InsertES3FormatCombo(&set, GL_RGB10_A2UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV ); - InsertES3FormatCombo(&set, GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE ); - InsertES3FormatCombo(&set, GL_RGB565, GL_RGB, GL_UNSIGNED_BYTE ); - InsertES3FormatCombo(&set, GL_SRGB8, GL_RGB, GL_UNSIGNED_BYTE ); - InsertES3FormatCombo(&set, GL_RGB8_SNORM, GL_RGB, GL_BYTE ); - InsertES3FormatCombo(&set, GL_RGB565, GL_RGB, GL_UNSIGNED_SHORT_5_6_5 ); - InsertES3FormatCombo(&set, GL_R11F_G11F_B10F, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV ); - InsertES3FormatCombo(&set, GL_RGB9_E5, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV ); - InsertES3FormatCombo(&set, GL_RGB16F, GL_RGB, GL_HALF_FLOAT ); - InsertES3FormatCombo(&set, GL_RGB16F, GL_RGB, GL_HALF_FLOAT_OES ); - InsertES3FormatCombo(&set, GL_R11F_G11F_B10F, GL_RGB, GL_HALF_FLOAT ); - InsertES3FormatCombo(&set, GL_R11F_G11F_B10F, GL_RGB, GL_HALF_FLOAT_OES ); - InsertES3FormatCombo(&set, GL_RGB9_E5, GL_RGB, GL_HALF_FLOAT ); - InsertES3FormatCombo(&set, GL_RGB9_E5, GL_RGB, GL_HALF_FLOAT_OES ); - InsertES3FormatCombo(&set, GL_RGB32F, GL_RGB, GL_FLOAT ); - InsertES3FormatCombo(&set, GL_RGB16F, GL_RGB, GL_FLOAT ); - InsertES3FormatCombo(&set, GL_R11F_G11F_B10F, GL_RGB, GL_FLOAT ); - InsertES3FormatCombo(&set, GL_RGB9_E5, GL_RGB, GL_FLOAT ); - InsertES3FormatCombo(&set, GL_RGB8UI, GL_RGB_INTEGER, GL_UNSIGNED_BYTE ); - InsertES3FormatCombo(&set, GL_RGB8I, GL_RGB_INTEGER, GL_BYTE ); - InsertES3FormatCombo(&set, GL_RGB16UI, GL_RGB_INTEGER, GL_UNSIGNED_SHORT ); - InsertES3FormatCombo(&set, GL_RGB16I, GL_RGB_INTEGER, GL_SHORT ); - InsertES3FormatCombo(&set, GL_RGB32UI, GL_RGB_INTEGER, GL_UNSIGNED_INT ); - InsertES3FormatCombo(&set, GL_RGB32I, GL_RGB_INTEGER, GL_INT ); - InsertES3FormatCombo(&set, GL_RG8, GL_RG, GL_UNSIGNED_BYTE ); - InsertES3FormatCombo(&set, GL_RG8_SNORM, GL_RG, GL_BYTE ); - InsertES3FormatCombo(&set, GL_RG16F, GL_RG, GL_HALF_FLOAT ); - InsertES3FormatCombo(&set, GL_RG16F, GL_RG, GL_HALF_FLOAT_OES ); - InsertES3FormatCombo(&set, GL_RG32F, GL_RG, GL_FLOAT ); - InsertES3FormatCombo(&set, GL_RG16F, GL_RG, GL_FLOAT ); - InsertES3FormatCombo(&set, GL_RG8UI, GL_RG_INTEGER, GL_UNSIGNED_BYTE ); - InsertES3FormatCombo(&set, GL_RG8I, GL_RG_INTEGER, GL_BYTE ); - InsertES3FormatCombo(&set, GL_RG16UI, GL_RG_INTEGER, GL_UNSIGNED_SHORT ); - InsertES3FormatCombo(&set, GL_RG16I, GL_RG_INTEGER, GL_SHORT ); - InsertES3FormatCombo(&set, GL_RG32UI, GL_RG_INTEGER, GL_UNSIGNED_INT ); - InsertES3FormatCombo(&set, GL_RG32I, GL_RG_INTEGER, GL_INT ); - InsertES3FormatCombo(&set, GL_R8, GL_RED, GL_UNSIGNED_BYTE ); - InsertES3FormatCombo(&set, GL_R8_SNORM, GL_RED, GL_BYTE ); - InsertES3FormatCombo(&set, GL_R16F, GL_RED, GL_HALF_FLOAT ); - InsertES3FormatCombo(&set, GL_R16F, GL_RED, GL_HALF_FLOAT_OES ); - InsertES3FormatCombo(&set, GL_R32F, GL_RED, GL_FLOAT ); - InsertES3FormatCombo(&set, GL_R16F, GL_RED, GL_FLOAT ); - InsertES3FormatCombo(&set, GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE ); - InsertES3FormatCombo(&set, GL_R8I, GL_RED_INTEGER, GL_BYTE ); - InsertES3FormatCombo(&set, GL_R16UI, GL_RED_INTEGER, GL_UNSIGNED_SHORT ); - InsertES3FormatCombo(&set, GL_R16I, GL_RED_INTEGER, GL_SHORT ); - InsertES3FormatCombo(&set, GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT ); - InsertES3FormatCombo(&set, GL_R32I, GL_RED_INTEGER, GL_INT ); - - // Unsized formats - InsertES3FormatCombo(&set, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE ); - InsertES3FormatCombo(&set, GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4 ); - InsertES3FormatCombo(&set, GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1 ); - InsertES3FormatCombo(&set, GL_RGB, GL_RGB, GL_UNSIGNED_BYTE ); - InsertES3FormatCombo(&set, GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5 ); - InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE ); - InsertES3FormatCombo(&set, GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE ); - InsertES3FormatCombo(&set, GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE ); - InsertES3FormatCombo(&set, GL_SRGB_ALPHA_EXT, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE ); - InsertES3FormatCombo(&set, GL_SRGB_EXT, GL_SRGB_EXT, GL_UNSIGNED_BYTE ); - - // Depth stencil formats - InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT ); - InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT ); - InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT ); - InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT ); - InsertES3FormatCombo(&set, GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8 ); - InsertES3FormatCombo(&set, GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV); - - // From GL_EXT_sRGB - InsertES3FormatCombo(&set, GL_SRGB8_ALPHA8_EXT, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE ); - InsertES3FormatCombo(&set, GL_SRGB8, GL_SRGB_EXT, GL_UNSIGNED_BYTE ); - - // From GL_OES_texture_float - InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_FLOAT ); - InsertES3FormatCombo(&set, GL_LUMINANCE, GL_LUMINANCE, GL_FLOAT ); - InsertES3FormatCombo(&set, GL_ALPHA, GL_ALPHA, GL_FLOAT ); - - // From GL_OES_texture_half_float - InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT ); - InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES ); - InsertES3FormatCombo(&set, GL_LUMINANCE, GL_LUMINANCE, GL_HALF_FLOAT ); - InsertES3FormatCombo(&set, GL_LUMINANCE, GL_LUMINANCE, GL_HALF_FLOAT_OES ); - InsertES3FormatCombo(&set, GL_ALPHA, GL_ALPHA, GL_HALF_FLOAT ); - InsertES3FormatCombo(&set, GL_ALPHA, GL_ALPHA, GL_HALF_FLOAT_OES ); - - // From GL_EXT_texture_format_BGRA8888 - InsertES3FormatCombo(&set, GL_BGRA_EXT, GL_BGRA_EXT, GL_UNSIGNED_BYTE ); - - // From GL_EXT_texture_storage - // | Internal format | Format | Type | - // | | | | - InsertES3FormatCombo(&set, GL_ALPHA8_EXT, GL_ALPHA, GL_UNSIGNED_BYTE ); - InsertES3FormatCombo(&set, GL_LUMINANCE8_EXT, GL_LUMINANCE, GL_UNSIGNED_BYTE ); - InsertES3FormatCombo(&set, GL_LUMINANCE8_ALPHA8_EXT, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE ); - InsertES3FormatCombo(&set, GL_ALPHA32F_EXT, GL_ALPHA, GL_FLOAT ); - InsertES3FormatCombo(&set, GL_LUMINANCE32F_EXT, GL_LUMINANCE, GL_FLOAT ); - InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA32F_EXT, GL_LUMINANCE_ALPHA, GL_FLOAT ); - InsertES3FormatCombo(&set, GL_ALPHA16F_EXT, GL_ALPHA, GL_HALF_FLOAT ); - InsertES3FormatCombo(&set, GL_ALPHA16F_EXT, GL_ALPHA, GL_HALF_FLOAT_OES ); - InsertES3FormatCombo(&set, GL_LUMINANCE16F_EXT, GL_LUMINANCE, GL_HALF_FLOAT ); - InsertES3FormatCombo(&set, GL_LUMINANCE16F_EXT, GL_LUMINANCE, GL_HALF_FLOAT_OES ); - InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA16F_EXT, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT ); - InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA16F_EXT, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES ); - - // From GL_EXT_texture_storage and GL_EXT_texture_format_BGRA8888 - InsertES3FormatCombo(&set, GL_BGRA8_EXT, GL_BGRA_EXT, GL_UNSIGNED_BYTE ); - InsertES3FormatCombo(&set, GL_BGRA4_ANGLEX, GL_BGRA_EXT, GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT); - InsertES3FormatCombo(&set, GL_BGRA4_ANGLEX, GL_BGRA_EXT, GL_UNSIGNED_BYTE ); - InsertES3FormatCombo(&set, GL_BGR5_A1_ANGLEX, GL_BGRA_EXT, GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT); - InsertES3FormatCombo(&set, GL_BGR5_A1_ANGLEX, GL_BGRA_EXT, GL_UNSIGNED_BYTE ); - - // From GL_ANGLE_depth_texture - InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT32_OES, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT_24_8_OES ); - - // Compressed formats - // From ES 3.0.1 spec, table 3.16 - // | Internal format | Format | Type | - // | | | | - InsertES3FormatCombo(&set, GL_COMPRESSED_R11_EAC, GL_COMPRESSED_R11_EAC, GL_UNSIGNED_BYTE); - InsertES3FormatCombo(&set, GL_COMPRESSED_R11_EAC, GL_COMPRESSED_R11_EAC, GL_UNSIGNED_BYTE); - InsertES3FormatCombo(&set, GL_COMPRESSED_SIGNED_R11_EAC, GL_COMPRESSED_SIGNED_R11_EAC, GL_UNSIGNED_BYTE); - InsertES3FormatCombo(&set, GL_COMPRESSED_RG11_EAC, GL_COMPRESSED_RG11_EAC, GL_UNSIGNED_BYTE); - InsertES3FormatCombo(&set, GL_COMPRESSED_SIGNED_RG11_EAC, GL_COMPRESSED_SIGNED_RG11_EAC, GL_UNSIGNED_BYTE); - InsertES3FormatCombo(&set, GL_COMPRESSED_RGB8_ETC2, GL_COMPRESSED_RGB8_ETC2, GL_UNSIGNED_BYTE); - InsertES3FormatCombo(&set, GL_COMPRESSED_SRGB8_ETC2, GL_COMPRESSED_SRGB8_ETC2, GL_UNSIGNED_BYTE); - InsertES3FormatCombo(&set, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_UNSIGNED_BYTE); - InsertES3FormatCombo(&set, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_UNSIGNED_BYTE); - InsertES3FormatCombo(&set, GL_COMPRESSED_RGBA8_ETC2_EAC, GL_COMPRESSED_RGBA8_ETC2_EAC, GL_UNSIGNED_BYTE); - InsertES3FormatCombo(&set, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, GL_UNSIGNED_BYTE); - - - // From GL_EXT_texture_compression_dxt1 - InsertES3FormatCombo(&set, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE); - InsertES3FormatCombo(&set, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE); - - // From GL_ANGLE_texture_compression_dxt3 - InsertES3FormatCombo(&set, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, GL_UNSIGNED_BYTE); - - // From GL_ANGLE_texture_compression_dxt5 - InsertES3FormatCombo(&set, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, GL_UNSIGNED_BYTE); - - return set; -} - -static bool ValidateTexImageFormatCombination(gl::Context *context, GLenum internalFormat, GLenum format, GLenum type) -{ - // Note: dEQP 2013.4 expects an INVALID_VALUE error for TexImage3D with an invalid - // internal format. (dEQP-GLES3.functional.negative_api.texture.teximage3d) - const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat); - if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions())) - { - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - - // The type and format are valid if any supported internal format has that type and format - bool formatSupported = false; - bool typeSupported = false; - - static const ES3FormatCombinationSet es3FormatSet = BuildES3FormatSet(); - for (ES3FormatCombinationSet::const_iterator i = es3FormatSet.begin(); i != es3FormatSet.end(); i++) - { - if (i->format == format || i->type == type) - { - const gl::InternalFormat &info = gl::GetInternalFormatInfo(i->internalFormat); - bool supported = info.textureSupport(context->getClientVersion(), context->getExtensions()); - if (supported && i->type == type) - { - typeSupported = true; - } - if (supported && i->format == format) - { - formatSupported = true; - } - - // Early-out if both type and format are supported now - if (typeSupported && formatSupported) - { - break; - } - } - } - - if (!typeSupported || !formatSupported) - { - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - - // Check if this is a valid format combination to load texture data - ES3FormatCombination searchFormat; - searchFormat.internalFormat = internalFormat; - searchFormat.format = format; - searchFormat.type = type; - - if (es3FormatSet.find(searchFormat) == es3FormatSet.end()) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - return true; -} - -bool ValidateES3TexImageParameters(Context *context, GLenum target, GLint level, GLenum internalformat, bool isCompressed, bool isSubImage, - GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, - GLint border, GLenum format, GLenum type, const GLvoid *pixels) -{ - if (!ValidTexture2DDestinationTarget(context, target)) - { - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - - // Validate image size - if (!ValidImageSize(context, target, level, width, height, depth)) - { - context->recordError(Error(GL_INVALID_VALUE)); - return false; - } - - // Verify zero border - if (border != 0) - { - context->recordError(Error(GL_INVALID_VALUE)); - return false; - } - - if (xoffset < 0 || yoffset < 0 || zoffset < 0 || - std::numeric_limits::max() - xoffset < width || - std::numeric_limits::max() - yoffset < height || - std::numeric_limits::max() - zoffset < depth) - { - context->recordError(Error(GL_INVALID_VALUE)); - return false; - } - - const gl::Caps &caps = context->getCaps(); - - gl::Texture *texture = NULL; - bool textureCompressed = false; - GLenum textureInternalFormat = GL_NONE; - GLint textureLevelWidth = 0; - GLint textureLevelHeight = 0; - GLint textureLevelDepth = 0; - switch (target) - { - case GL_TEXTURE_2D: - { - if (static_cast(width) > (caps.max2DTextureSize >> level) || - static_cast(height) > (caps.max2DTextureSize >> level)) - { - context->recordError(Error(GL_INVALID_VALUE)); - return false; - } - - gl::Texture2D *texture2d = context->getTexture2D(); - if (texture2d) - { - textureCompressed = texture2d->isCompressed(level); - textureInternalFormat = texture2d->getInternalFormat(level); - textureLevelWidth = texture2d->getWidth(level); - textureLevelHeight = texture2d->getHeight(level); - textureLevelDepth = 1; - texture = texture2d; - } - } - break; - - case GL_TEXTURE_CUBE_MAP_POSITIVE_X: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: - { - if (!isSubImage && width != height) - { - context->recordError(Error(GL_INVALID_VALUE)); - return false; - } - - if (static_cast(width) > (caps.maxCubeMapTextureSize >> level)) - { - context->recordError(Error(GL_INVALID_VALUE)); - return false; - } - - gl::TextureCubeMap *textureCube = context->getTextureCubeMap(); - if (textureCube) - { - textureCompressed = textureCube->isCompressed(target, level); - textureInternalFormat = textureCube->getInternalFormat(target, level); - textureLevelWidth = textureCube->getWidth(target, level); - textureLevelHeight = textureCube->getHeight(target, level); - textureLevelDepth = 1; - texture = textureCube; - } - } - break; - - case GL_TEXTURE_3D: - { - if (static_cast(width) > (caps.max3DTextureSize >> level) || - static_cast(height) > (caps.max3DTextureSize >> level) || - static_cast(depth) > (caps.max3DTextureSize >> level)) - { - context->recordError(Error(GL_INVALID_VALUE)); - return false; - } - - gl::Texture3D *texture3d = context->getTexture3D(); - if (texture3d) - { - textureCompressed = texture3d->isCompressed(level); - textureInternalFormat = texture3d->getInternalFormat(level); - textureLevelWidth = texture3d->getWidth(level); - textureLevelHeight = texture3d->getHeight(level); - textureLevelDepth = texture3d->getDepth(level); - texture = texture3d; - } - } - break; - - case GL_TEXTURE_2D_ARRAY: - { - if (static_cast(width) > (caps.max2DTextureSize >> level) || - static_cast(height) > (caps.max2DTextureSize >> level) || - static_cast(depth) > (caps.maxArrayTextureLayers >> level)) - { - context->recordError(Error(GL_INVALID_VALUE)); - return false; - } - - gl::Texture2DArray *texture2darray = context->getTexture2DArray(); - if (texture2darray) - { - textureCompressed = texture2darray->isCompressed(level); - textureInternalFormat = texture2darray->getInternalFormat(level); - textureLevelWidth = texture2darray->getWidth(level); - textureLevelHeight = texture2darray->getHeight(level); - textureLevelDepth = texture2darray->getLayers(level); - texture = texture2darray; - } - } - break; - - default: - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - - if (!texture) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - if (texture->isImmutable() && !isSubImage) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - // Validate texture formats - GLenum actualInternalFormat = isSubImage ? textureInternalFormat : internalformat; - const gl::InternalFormat &actualFormatInfo = gl::GetInternalFormatInfo(actualInternalFormat); - if (isCompressed) - { - if (!ValidCompressedImageSize(context, actualInternalFormat, width, height)) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - if (!actualFormatInfo.compressed) - { - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - - if (target == GL_TEXTURE_3D) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - } - else - { - if (!ValidateTexImageFormatCombination(context, actualInternalFormat, format, type)) - { - return false; - } - - if (target == GL_TEXTURE_3D && (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL)) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - } - - // Validate sub image parameters - if (isSubImage) - { - if (isCompressed != textureCompressed) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - if (isCompressed) - { - if ((width % 4 != 0 && width != textureLevelWidth) || - (height % 4 != 0 && height != textureLevelHeight)) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - } - - if (width == 0 || height == 0 || depth == 0) - { - return false; - } - - if (xoffset < 0 || yoffset < 0 || zoffset < 0) - { - context->recordError(Error(GL_INVALID_VALUE)); - return false; - } - - if (std::numeric_limits::max() - xoffset < width || - std::numeric_limits::max() - yoffset < height || - std::numeric_limits::max() - zoffset < depth) - { - context->recordError(Error(GL_INVALID_VALUE)); - return false; - } - - if (xoffset + width > textureLevelWidth || - yoffset + height > textureLevelHeight || - zoffset + depth > textureLevelDepth) - { - context->recordError(Error(GL_INVALID_VALUE)); - return false; - } - } - - // Check for pixel unpack buffer related API errors - gl::Buffer *pixelUnpackBuffer = context->getState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER); - if (pixelUnpackBuffer != NULL) - { - // ...the data would be unpacked from the buffer object such that the memory reads required - // would exceed the data store size. - size_t widthSize = static_cast(width); - size_t heightSize = static_cast(height); - size_t depthSize = static_cast(depth); - GLenum sizedFormat = GetSizedInternalFormat(actualInternalFormat, type); - - size_t pixelBytes = static_cast(gl::GetInternalFormatInfo(sizedFormat).pixelBytes); - - if (!rx::IsUnsignedMultiplicationSafe(widthSize, heightSize) || - !rx::IsUnsignedMultiplicationSafe(widthSize * heightSize, depthSize) || - !rx::IsUnsignedMultiplicationSafe(widthSize * heightSize * depthSize, pixelBytes)) - { - // Overflow past the end of the buffer - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedFormat); - size_t copyBytes = formatInfo.computeBlockSize(type, width, height); - size_t offset = reinterpret_cast(pixels); - - if (!rx::IsUnsignedAdditionSafe(offset, copyBytes) || - ((offset + copyBytes) > static_cast(pixelUnpackBuffer->getSize()))) - { - // Overflow past the end of the buffer - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - // ...data is not evenly divisible into the number of bytes needed to store in memory a datum - // indicated by type. - if (!isCompressed) - { - size_t dataBytesPerPixel = static_cast(gl::GetTypeInfo(type).bytes); - - if ((offset % dataBytesPerPixel) != 0) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - } - - // ...the buffer object's data store is currently mapped. - if (pixelUnpackBuffer->isMapped()) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - } - - return true; -} - -struct EffectiveInternalFormatInfo -{ - GLenum mEffectiveFormat; - GLenum mDestFormat; - GLuint mMinRedBits; - GLuint mMaxRedBits; - GLuint mMinGreenBits; - GLuint mMaxGreenBits; - GLuint mMinBlueBits; - GLuint mMaxBlueBits; - GLuint mMinAlphaBits; - GLuint mMaxAlphaBits; - - EffectiveInternalFormatInfo(GLenum effectiveFormat, GLenum destFormat, GLuint minRedBits, GLuint maxRedBits, - GLuint minGreenBits, GLuint maxGreenBits, GLuint minBlueBits, GLuint maxBlueBits, - GLuint minAlphaBits, GLuint maxAlphaBits) - : mEffectiveFormat(effectiveFormat), mDestFormat(destFormat), mMinRedBits(minRedBits), - mMaxRedBits(maxRedBits), mMinGreenBits(minGreenBits), mMaxGreenBits(maxGreenBits), - mMinBlueBits(minBlueBits), mMaxBlueBits(maxBlueBits), mMinAlphaBits(minAlphaBits), - mMaxAlphaBits(maxAlphaBits) {}; -}; - -typedef std::vector EffectiveInternalFormatList; - -static EffectiveInternalFormatList BuildSizedEffectiveInternalFormatList() -{ - EffectiveInternalFormatList list; - - // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141: Effective internal format coresponding to destination internal format and - // linear source buffer component sizes. - // | Source channel min/max sizes | - // Effective Internal Format | N/A | R | G | B | A | - list.push_back(EffectiveInternalFormatInfo(GL_ALPHA8_EXT, GL_NONE, 0, 0, 0, 0, 0, 0, 1, 8)); - list.push_back(EffectiveInternalFormatInfo(GL_R8, GL_NONE, 1, 8, 0, 0, 0, 0, 0, 0)); - list.push_back(EffectiveInternalFormatInfo(GL_RG8, GL_NONE, 1, 8, 1, 8, 0, 0, 0, 0)); - list.push_back(EffectiveInternalFormatInfo(GL_RGB565, GL_NONE, 1, 5, 1, 6, 1, 5, 0, 0)); - list.push_back(EffectiveInternalFormatInfo(GL_RGB8, GL_NONE, 6, 8, 7, 8, 6, 8, 0, 0)); - list.push_back(EffectiveInternalFormatInfo(GL_RGBA4, GL_NONE, 1, 4, 1, 4, 1, 4, 1, 4)); - list.push_back(EffectiveInternalFormatInfo(GL_RGB5_A1, GL_NONE, 5, 5, 5, 5, 5, 5, 1, 1)); - list.push_back(EffectiveInternalFormatInfo(GL_RGBA8, GL_NONE, 5, 8, 5, 8, 5, 8, 2, 8)); - list.push_back(EffectiveInternalFormatInfo(GL_RGB10_A2, GL_NONE, 9, 10, 9, 10, 9, 10, 2, 2)); - - return list; -} - -static EffectiveInternalFormatList BuildUnsizedEffectiveInternalFormatList() -{ - EffectiveInternalFormatList list; - - // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141: Effective internal format coresponding to destination internal format and - // linear source buffer component sizes. - // | Source channel min/max sizes | - // Effective Internal Format | Dest Format | R | G | B | A | - list.push_back(EffectiveInternalFormatInfo(GL_ALPHA8_EXT, GL_ALPHA, 0, UINT_MAX, 0, UINT_MAX, 0, UINT_MAX, 1, 8)); - list.push_back(EffectiveInternalFormatInfo(GL_LUMINANCE8_EXT, GL_LUMINANCE, 1, 8, 0, UINT_MAX, 0, UINT_MAX, 0, UINT_MAX)); - list.push_back(EffectiveInternalFormatInfo(GL_LUMINANCE8_ALPHA8_EXT, GL_LUMINANCE_ALPHA, 1, 8, 0, UINT_MAX, 0, UINT_MAX, 1, 8)); - list.push_back(EffectiveInternalFormatInfo(GL_RGB565, GL_RGB, 1, 5, 1, 6, 1, 5, 0, UINT_MAX)); - list.push_back(EffectiveInternalFormatInfo(GL_RGB8, GL_RGB, 6, 8, 7, 8, 6, 8, 0, UINT_MAX)); - list.push_back(EffectiveInternalFormatInfo(GL_RGBA4, GL_RGBA, 1, 4, 1, 4, 1, 4, 1, 4)); - list.push_back(EffectiveInternalFormatInfo(GL_RGB5_A1, GL_RGBA, 5, 5, 5, 5, 5, 5, 1, 1)); - list.push_back(EffectiveInternalFormatInfo(GL_RGBA8, GL_RGBA, 5, 8, 5, 8, 5, 8, 5, 8)); - - return list; -} - -static bool GetEffectiveInternalFormat(const InternalFormat &srcFormat, const InternalFormat &destFormat, - GLenum *outEffectiveFormat) -{ - const EffectiveInternalFormatList *list = NULL; - GLenum targetFormat = GL_NONE; - - if (destFormat.pixelBytes > 0) - { - static const EffectiveInternalFormatList sizedList = BuildSizedEffectiveInternalFormatList(); - list = &sizedList; - } - else - { - static const EffectiveInternalFormatList unsizedList = BuildUnsizedEffectiveInternalFormatList(); - list = &unsizedList; - targetFormat = destFormat.format; - } - - for (size_t curFormat = 0; curFormat < list->size(); ++curFormat) - { - const EffectiveInternalFormatInfo& formatInfo = list->at(curFormat); - if ((formatInfo.mDestFormat == targetFormat) && - (formatInfo.mMinRedBits <= srcFormat.redBits && formatInfo.mMaxRedBits >= srcFormat.redBits) && - (formatInfo.mMinGreenBits <= srcFormat.greenBits && formatInfo.mMaxGreenBits >= srcFormat.greenBits) && - (formatInfo.mMinBlueBits <= srcFormat.blueBits && formatInfo.mMaxBlueBits >= srcFormat.blueBits) && - (formatInfo.mMinAlphaBits <= srcFormat.alphaBits && formatInfo.mMaxAlphaBits >= srcFormat.alphaBits)) - { - *outEffectiveFormat = formatInfo.mEffectiveFormat; - return true; - } - } - - return false; -} - -struct CopyConversion -{ - GLenum mTextureFormat; - GLenum mFramebufferFormat; - - CopyConversion(GLenum textureFormat, GLenum framebufferFormat) - : mTextureFormat(textureFormat), mFramebufferFormat(framebufferFormat) { } - - bool operator<(const CopyConversion& other) const - { - return memcmp(this, &other, sizeof(CopyConversion)) < 0; - } -}; - -typedef std::set CopyConversionSet; - -static CopyConversionSet BuildValidES3CopyTexImageCombinations() -{ - CopyConversionSet set; - - // From ES 3.0.1 spec, table 3.15 - set.insert(CopyConversion(GL_ALPHA, GL_RGBA)); - set.insert(CopyConversion(GL_LUMINANCE, GL_RED)); - set.insert(CopyConversion(GL_LUMINANCE, GL_RG)); - set.insert(CopyConversion(GL_LUMINANCE, GL_RGB)); - set.insert(CopyConversion(GL_LUMINANCE, GL_RGBA)); - set.insert(CopyConversion(GL_LUMINANCE_ALPHA, GL_RGBA)); - set.insert(CopyConversion(GL_RED, GL_RED)); - set.insert(CopyConversion(GL_RED, GL_RG)); - set.insert(CopyConversion(GL_RED, GL_RGB)); - set.insert(CopyConversion(GL_RED, GL_RGBA)); - set.insert(CopyConversion(GL_RG, GL_RG)); - set.insert(CopyConversion(GL_RG, GL_RGB)); - set.insert(CopyConversion(GL_RG, GL_RGBA)); - set.insert(CopyConversion(GL_RGB, GL_RGB)); - set.insert(CopyConversion(GL_RGB, GL_RGBA)); - set.insert(CopyConversion(GL_RGBA, GL_RGBA)); - - // Necessary for ANGLE back-buffers - set.insert(CopyConversion(GL_ALPHA, GL_BGRA_EXT)); - set.insert(CopyConversion(GL_LUMINANCE, GL_BGRA_EXT)); - set.insert(CopyConversion(GL_LUMINANCE_ALPHA, GL_BGRA_EXT)); - set.insert(CopyConversion(GL_RED, GL_BGRA_EXT)); - set.insert(CopyConversion(GL_RG, GL_BGRA_EXT)); - set.insert(CopyConversion(GL_RGB, GL_BGRA_EXT)); - set.insert(CopyConversion(GL_RGBA, GL_BGRA_EXT)); - - set.insert(CopyConversion(GL_RED_INTEGER, GL_RED_INTEGER)); - set.insert(CopyConversion(GL_RED_INTEGER, GL_RG_INTEGER)); - set.insert(CopyConversion(GL_RED_INTEGER, GL_RGB_INTEGER)); - set.insert(CopyConversion(GL_RED_INTEGER, GL_RGBA_INTEGER)); - set.insert(CopyConversion(GL_RG_INTEGER, GL_RG_INTEGER)); - set.insert(CopyConversion(GL_RG_INTEGER, GL_RGB_INTEGER)); - set.insert(CopyConversion(GL_RG_INTEGER, GL_RGBA_INTEGER)); - set.insert(CopyConversion(GL_RGB_INTEGER, GL_RGB_INTEGER)); - set.insert(CopyConversion(GL_RGB_INTEGER, GL_RGBA_INTEGER)); - set.insert(CopyConversion(GL_RGBA_INTEGER, GL_RGBA_INTEGER)); - - return set; -} - -static bool IsValidES3CopyTexImageCombination(GLenum textureInternalFormat, GLenum frameBufferInternalFormat, GLuint readBufferHandle) -{ - const InternalFormat &textureInternalFormatInfo = GetInternalFormatInfo(textureInternalFormat); - const InternalFormat &framebufferInternalFormatInfo = GetInternalFormatInfo(frameBufferInternalFormat); - - static const CopyConversionSet conversionSet = BuildValidES3CopyTexImageCombinations(); - if (conversionSet.find(CopyConversion(textureInternalFormatInfo.format, framebufferInternalFormatInfo.format)) != conversionSet.end()) - { - // Section 3.8.5 of the GLES 3.0.3 spec states that source and destination formats - // must both be signed, unsigned, or fixed point and both source and destinations - // must be either both SRGB or both not SRGB. EXT_color_buffer_float adds allowed - // conversion between fixed and floating point. - - if ((textureInternalFormatInfo.colorEncoding == GL_SRGB) != (framebufferInternalFormatInfo.colorEncoding == GL_SRGB)) - { - return false; - } - - if (((textureInternalFormatInfo.componentType == GL_INT) != (framebufferInternalFormatInfo.componentType == GL_INT )) || - ((textureInternalFormatInfo.componentType == GL_UNSIGNED_INT) != (framebufferInternalFormatInfo.componentType == GL_UNSIGNED_INT))) - { - return false; - } - - if ((textureInternalFormatInfo.componentType == GL_UNSIGNED_NORMALIZED || - textureInternalFormatInfo.componentType == GL_SIGNED_NORMALIZED || - textureInternalFormatInfo.componentType == GL_FLOAT) && - !(framebufferInternalFormatInfo.componentType == GL_UNSIGNED_NORMALIZED || - framebufferInternalFormatInfo.componentType == GL_SIGNED_NORMALIZED || - framebufferInternalFormatInfo.componentType == GL_FLOAT)) - { - return false; - } - - // GLES specification 3.0.3, sec 3.8.5, pg 139-140: - // The effective internal format of the source buffer is determined with the following rules applied in order: - // * If the source buffer is a texture or renderbuffer that was created with a sized internal format then the - // effective internal format is the source buffer's sized internal format. - // * If the source buffer is a texture that was created with an unsized base internal format, then the - // effective internal format is the source image array's effective internal format, as specified by table - // 3.12, which is determined from the and that were used when the source image array was - // specified by TexImage*. - // * Otherwise the effective internal format is determined by the row in table 3.17 or 3.18 where - // Destination Internal Format matches internalformat and where the [source channel sizes] are consistent - // with the values of the source buffer's [channel sizes]. Table 3.17 is used if the - // FRAMEBUFFER_ATTACHMENT_ENCODING is LINEAR and table 3.18 is used if the FRAMEBUFFER_ATTACHMENT_ENCODING - // is SRGB. - const InternalFormat *sourceEffectiveFormat = NULL; - if (readBufferHandle != 0) - { - // Not the default framebuffer, therefore the read buffer must be a user-created texture or renderbuffer - if (framebufferInternalFormatInfo.pixelBytes > 0) - { - sourceEffectiveFormat = &framebufferInternalFormatInfo; - } - else - { - // Renderbuffers cannot be created with an unsized internal format, so this must be an unsized-format - // texture. We can use the same table we use when creating textures to get its effective sized format. - const FormatType &typeInfo = GetFormatTypeInfo(framebufferInternalFormatInfo.format, framebufferInternalFormatInfo.type); - sourceEffectiveFormat = &GetInternalFormatInfo(typeInfo.internalFormat); - } - } - else - { - // The effective internal format must be derived from the source framebuffer's channel sizes. - // This is done in GetEffectiveInternalFormat for linear buffers (table 3.17) - if (framebufferInternalFormatInfo.colorEncoding == GL_LINEAR) - { - GLenum effectiveFormat; - if (GetEffectiveInternalFormat(framebufferInternalFormatInfo, textureInternalFormatInfo, &effectiveFormat)) - { - sourceEffectiveFormat = &GetInternalFormatInfo(effectiveFormat); - } - else - { - return false; - } - } - else if (framebufferInternalFormatInfo.colorEncoding == GL_SRGB) - { - // SRGB buffers can only be copied to sized format destinations according to table 3.18 - if ((textureInternalFormatInfo.pixelBytes > 0) && - (framebufferInternalFormatInfo.redBits >= 1 && framebufferInternalFormatInfo.redBits <= 8) && - (framebufferInternalFormatInfo.greenBits >= 1 && framebufferInternalFormatInfo.greenBits <= 8) && - (framebufferInternalFormatInfo.blueBits >= 1 && framebufferInternalFormatInfo.blueBits <= 8) && - (framebufferInternalFormatInfo.alphaBits >= 1 && framebufferInternalFormatInfo.alphaBits <= 8)) - { - sourceEffectiveFormat = &GetInternalFormatInfo(GL_SRGB8_ALPHA8); - } - else - { - return false; - } - } - else - { - UNREACHABLE(); - return false; - } - } - - if (textureInternalFormatInfo.pixelBytes > 0) - { - // Section 3.8.5 of the GLES 3.0.3 spec, pg 139, requires that, if the destination format is sized, - // component sizes of the source and destination formats must exactly match - if (textureInternalFormatInfo.redBits != sourceEffectiveFormat->redBits || - textureInternalFormatInfo.greenBits != sourceEffectiveFormat->greenBits || - textureInternalFormatInfo.blueBits != sourceEffectiveFormat->blueBits || - textureInternalFormatInfo.alphaBits != sourceEffectiveFormat->alphaBits) - { - return false; - } - } - - - return true; // A conversion function exists, and no rule in the specification has precluded conversion - // between these formats. - } - - return false; -} - -bool ValidateES3CopyTexImageParameters(Context *context, GLenum target, GLint level, GLenum internalformat, - bool isSubImage, GLint xoffset, GLint yoffset, GLint zoffset, - GLint x, GLint y, GLsizei width, GLsizei height, GLint border) -{ - GLenum textureInternalFormat; - if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage, - xoffset, yoffset, zoffset, x, y, width, height, - border, &textureInternalFormat)) - { - return false; - } - - gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer(); - - if (framebuffer->completeness(context->getData()) != GL_FRAMEBUFFER_COMPLETE) - { - context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION)); - return false; - } - - if (context->getState().getReadFramebuffer()->id() != 0 && - framebuffer->getSamples(context->getData()) != 0) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - gl::FramebufferAttachment *source = framebuffer->getReadColorbuffer(); - GLenum colorbufferInternalFormat = source->getInternalFormat(); - - if (isSubImage) - { - if (!IsValidES3CopyTexImageCombination(textureInternalFormat, colorbufferInternalFormat, - context->getState().getReadFramebuffer()->id())) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - } - else - { - if (!gl::IsValidES3CopyTexImageCombination(internalformat, colorbufferInternalFormat, - context->getState().getReadFramebuffer()->id())) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - } - - // If width or height is zero, it is a no-op. Return false without setting an error. - return (width > 0 && height > 0); -} - -bool ValidateES3TexStorageParameters(Context *context, GLenum target, GLsizei levels, GLenum internalformat, - GLsizei width, GLsizei height, GLsizei depth) -{ - if (width < 1 || height < 1 || depth < 1 || levels < 1) - { - context->recordError(Error(GL_INVALID_VALUE)); - return false; - } - - if (levels > gl::log2(std::max(std::max(width, height), depth)) + 1) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - const gl::Caps &caps = context->getCaps(); - - gl::Texture *texture = NULL; - switch (target) - { - case GL_TEXTURE_2D: - { - texture = context->getTexture2D(); - - if (static_cast(width) > caps.max2DTextureSize || - static_cast(height) > caps.max2DTextureSize) - { - context->recordError(Error(GL_INVALID_VALUE)); - return false; - } - } - break; - - case GL_TEXTURE_CUBE_MAP: - { - texture = context->getTextureCubeMap(); - - if (width != height) - { - context->recordError(Error(GL_INVALID_VALUE)); - return false; - } - - if (static_cast(width) > caps.maxCubeMapTextureSize) - { - context->recordError(Error(GL_INVALID_VALUE)); - return false; - } - } - break; - - case GL_TEXTURE_3D: - { - texture = context->getTexture3D(); - - if (static_cast(width) > caps.max3DTextureSize || - static_cast(height) > caps.max3DTextureSize || - static_cast(depth) > caps.max3DTextureSize) - { - context->recordError(Error(GL_INVALID_VALUE)); - return false; - } - } - break; - - case GL_TEXTURE_2D_ARRAY: - { - texture = context->getTexture2DArray(); - - if (static_cast(width) > caps.max2DTextureSize || - static_cast(height) > caps.max2DTextureSize || - static_cast(depth) > caps.maxArrayTextureLayers) - { - context->recordError(Error(GL_INVALID_VALUE)); - return false; - } - } - break; - - default: - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - - if (!texture || texture->id() == 0) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - if (texture->isImmutable()) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat); - if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions())) - { - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - - if (formatInfo.pixelBytes == 0) - { - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - - return true; -} - -bool ValidateFramebufferTextureLayer(Context *context, GLenum target, GLenum attachment, - GLuint texture, GLint level, GLint layer) -{ - if (context->getClientVersion() < 3) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - if (layer < 0) - { - context->recordError(Error(GL_INVALID_VALUE)); - return false; - } - - if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level)) - { - return false; - } - - const gl::Caps &caps = context->getCaps(); - if (texture != 0) - { - gl::Texture *tex = context->getTexture(texture); - ASSERT(tex); - - switch (tex->getTarget()) - { - case GL_TEXTURE_2D_ARRAY: - { - if (level > gl::log2(caps.max2DTextureSize)) - { - context->recordError(Error(GL_INVALID_VALUE)); - return false; - } - - if (static_cast(layer) >= caps.maxArrayTextureLayers) - { - context->recordError(Error(GL_INVALID_VALUE)); - return false; - } - - gl::Texture2DArray *texArray = static_cast(tex); - if (texArray->isCompressed(level)) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - } - break; - - case GL_TEXTURE_3D: - { - if (level > gl::log2(caps.max3DTextureSize)) - { - context->recordError(Error(GL_INVALID_VALUE)); - return false; - } - - if (static_cast(layer) >= caps.max3DTextureSize) - { - context->recordError(Error(GL_INVALID_VALUE)); - return false; - } - - gl::Texture3D *tex3d = static_cast(tex); - if (tex3d->isCompressed(level)) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - } - break; - - default: - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - } - - return true; -} - -bool ValidES3ReadFormatType(Context *context, GLenum internalFormat, GLenum format, GLenum type) -{ - const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat); - - switch (format) - { - case GL_RGBA: - switch (type) - { - case GL_UNSIGNED_BYTE: - break; - case GL_UNSIGNED_INT_2_10_10_10_REV: - if (internalFormat != GL_RGB10_A2) - { - return false; - } - break; - case GL_FLOAT: - if (internalFormatInfo.componentType != GL_FLOAT) - { - return false; - } - break; - default: - return false; - } - break; - case GL_RGBA_INTEGER: - switch (type) - { - case GL_INT: - if (internalFormatInfo.componentType != GL_INT) - { - return false; - } - break; - case GL_UNSIGNED_INT: - if (internalFormatInfo.componentType != GL_UNSIGNED_INT) - { - return false; - } - break; - default: - return false; - } - break; - case GL_BGRA_EXT: - switch (type) - { - case GL_UNSIGNED_BYTE: - case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT: - case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT: - break; - default: - return false; - } - break; - case GL_RG_EXT: - case GL_RED_EXT: - if (!context->getExtensions().textureRG) - { - return false; - } - switch (type) - { - case GL_UNSIGNED_BYTE: - break; - default: - return false; - } - break; - default: - return false; - } - return true; -} - -bool ValidateInvalidateFramebufferParameters(Context *context, GLenum target, GLsizei numAttachments, - const GLenum* attachments) -{ - bool defaultFramebuffer = false; - - switch (target) - { - case GL_DRAW_FRAMEBUFFER: - case GL_FRAMEBUFFER: - defaultFramebuffer = context->getState().getDrawFramebuffer()->id() == 0; - break; - case GL_READ_FRAMEBUFFER: - defaultFramebuffer = context->getState().getReadFramebuffer()->id() == 0; - break; - default: - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - - for (int i = 0; i < numAttachments; ++i) - { - if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT15) - { - if (defaultFramebuffer) - { - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - - if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - } - else - { - switch (attachments[i]) - { - case GL_DEPTH_ATTACHMENT: - case GL_STENCIL_ATTACHMENT: - case GL_DEPTH_STENCIL_ATTACHMENT: - if (defaultFramebuffer) - { - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - break; - case GL_COLOR: - case GL_DEPTH: - case GL_STENCIL: - if (!defaultFramebuffer) - { - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - break; - default: - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - } - } - - return true; -} - -bool ValidateClearBuffer(Context *context) -{ - if (context->getClientVersion() < 3) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - const gl::Framebuffer *fbo = context->getState().getDrawFramebuffer(); - if (!fbo || fbo->completeness(context->getData()) != GL_FRAMEBUFFER_COMPLETE) - { - context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION)); - return false; - } - - return true; -} - -bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint* params) -{ - if (context->getClientVersion() < 3) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - return ValidateGetUniformBase(context, program, location); -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/validationES3.h b/src/3rdparty/angle/src/libGLESv2/validationES3.h deleted file mode 100644 index cafacca601..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/validationES3.h +++ /dev/null @@ -1,44 +0,0 @@ -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// validationES3.h: Validation functions for OpenGL ES 3.0 entry point parameters - -#ifndef LIBGLESV2_VALIDATION_ES3_H -#define LIBGLESV2_VALIDATION_ES3_H - -#include - -namespace gl -{ - -class Context; - -bool ValidateES3TexImageParameters(Context *context, GLenum target, GLint level, GLenum internalformat, bool isCompressed, bool isSubImage, - GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, - GLint border, GLenum format, GLenum type, const GLvoid *pixels); - -bool ValidateES3CopyTexImageParameters(Context *context, GLenum target, GLint level, GLenum internalformat, - bool isSubImage, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, - GLsizei width, GLsizei height, GLint border); - -bool ValidateES3TexStorageParameters(Context *context, GLenum target, GLsizei levels, GLenum internalformat, - GLsizei width, GLsizei height, GLsizei depth); - -bool ValidateFramebufferTextureLayer(Context *context, GLenum target, GLenum attachment, - GLuint texture, GLint level, GLint layer); - -bool ValidES3ReadFormatType(Context *context, GLenum internalFormat, GLenum format, GLenum type); - -bool ValidateInvalidateFramebufferParameters(Context *context, GLenum target, GLsizei numAttachments, - const GLenum* attachments); - -bool ValidateClearBuffer(Context *context); - -bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint* params); - -} - -#endif // LIBGLESV2_VALIDATION_ES3_H diff --git a/src/3rdparty/angle/src/third_party/compiler/ArrayBoundsClamper.h b/src/3rdparty/angle/src/third_party/compiler/ArrayBoundsClamper.h index 30bb7e3b94..27917e6eec 100644 --- a/src/3rdparty/angle/src/third_party/compiler/ArrayBoundsClamper.h +++ b/src/3rdparty/angle/src/third_party/compiler/ArrayBoundsClamper.h @@ -23,8 +23,8 @@ * 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_ +#ifndef THIRD_PARTY_COMPILER_ARRAYBOUNDSCLAMPER_H_ +#define THIRD_PARTY_COMPILER_ARRAYBOUNDSCLAMPER_H_ #include "compiler/translator/InfoSink.h" #include "compiler/translator/IntermNode.h" @@ -57,4 +57,4 @@ private: bool mArrayBoundsClampDefinitionNeeded; }; -#endif // THIRD_PARTY_COMPILER_ARRAY_BOUNDS_CLAMPER_H_ +#endif // THIRD_PARTY_COMPILER_ARRAYBOUNDSCLAMPER_H_ diff --git a/src/3rdparty/angle/src/third_party/murmurhash/MurmurHash3.cpp b/src/3rdparty/angle/src/third_party/murmurhash/MurmurHash3.cpp index dd86292649..a599c26502 100644 --- a/src/3rdparty/angle/src/third_party/murmurhash/MurmurHash3.cpp +++ b/src/3rdparty/angle/src/third_party/murmurhash/MurmurHash3.cpp @@ -29,6 +29,8 @@ #else // defined(_MSC_VER) +// Ignore GCC force inline warnings +#pragma GCC diagnostic ignored "-Wattributes" #define FORCE_INLINE __attribute__((always_inline)) inline uint32_t rotl32 ( uint32_t x, int8_t r ) diff --git a/src/3rdparty/angle/src/third_party/murmurhash/MurmurHash3.h b/src/3rdparty/angle/src/third_party/murmurhash/MurmurHash3.h index adb52004e2..bb02cd508f 100644 --- a/src/3rdparty/angle/src/third_party/murmurhash/MurmurHash3.h +++ b/src/3rdparty/angle/src/third_party/murmurhash/MurmurHash3.h @@ -20,4 +20,4 @@ void MurmurHash3_x64_128 ( const void * key, int len, uint32_t seed, void * out //----------------------------------------------------------------------------- -#endif // _MURMURHASH3_H_ \ No newline at end of file +#endif // _MURMURHASH3_H_ diff --git a/src/3rdparty/angle/src/third_party/systeminfo/SystemInfo.h b/src/3rdparty/angle/src/third_party/systeminfo/SystemInfo.h index 65005ee9c6..226085fbd3 100644 --- a/src/3rdparty/angle/src/third_party/systeminfo/SystemInfo.h +++ b/src/3rdparty/angle/src/third_party/systeminfo/SystemInfo.h @@ -23,8 +23,8 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef SystemInfo_h -#define SystemInfo_h +#ifndef THIRD_PARTY_SYSTEMINFO_SYSTEMINFO_H_ +#define THIRD_PARTY_SYSTEMINFO_SYSTEMINFO_H_ namespace rx { @@ -32,4 +32,4 @@ bool isWindowsVistaOrGreater(); } // namespace rx -#endif // SystemInfo_h +#endif // THIRD_PARTY_SYSTEMINFO_SYSTEMINFO_H_ diff --git a/src/3rdparty/angle/src/third_party/trace_event/trace_event.h b/src/3rdparty/angle/src/third_party/trace_event/trace_event.h new file mode 100644 index 0000000000..af59dcfcc3 --- /dev/null +++ b/src/3rdparty/angle/src/third_party/trace_event/trace_event.h @@ -0,0 +1,795 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Trace events are for tracking application performance and resource usage. +// Macros are provided to track: +// Begin and end of function calls +// Counters +// +// Events are issued against categories. Whereas LOG's +// categories are statically defined, TRACE categories are created +// implicitly with a string. For example: +// TRACE_EVENT_INSTANT0("MY_SUBSYSTEM", "SomeImportantEvent") +// +// Events can be INSTANT, or can be pairs of BEGIN and END in the same scope: +// TRACE_EVENT_BEGIN0("MY_SUBSYSTEM", "SomethingCostly") +// doSomethingCostly() +// TRACE_EVENT_END0("MY_SUBSYSTEM", "SomethingCostly") +// Note: our tools can't always determine the correct BEGIN/END pairs unless +// these are used in the same scope. Use ASYNC_BEGIN/ASYNC_END macros if you need them +// to be in separate scopes. +// +// A common use case is to trace entire function scopes. This +// issues a trace BEGIN and END automatically: +// void doSomethingCostly() { +// TRACE_EVENT0("MY_SUBSYSTEM", "doSomethingCostly"); +// ... +// } +// +// Additional parameters can be associated with an event: +// void doSomethingCostly2(int howMuch) { +// TRACE_EVENT1("MY_SUBSYSTEM", "doSomethingCostly", +// "howMuch", howMuch); +// ... +// } +// +// The trace system will automatically add to this information the +// current process id, thread id, and a timestamp in microseconds. +// +// To trace an asynchronous procedure such as an IPC send/receive, use ASYNC_BEGIN and +// ASYNC_END: +// [single threaded sender code] +// static int send_count = 0; +// ++send_count; +// TRACE_EVENT_ASYNC_BEGIN0("ipc", "message", send_count); +// Send(new MyMessage(send_count)); +// [receive code] +// void OnMyMessage(send_count) { +// TRACE_EVENT_ASYNC_END0("ipc", "message", send_count); +// } +// The third parameter is a unique ID to match ASYNC_BEGIN/ASYNC_END pairs. +// ASYNC_BEGIN and ASYNC_END can occur on any thread of any traced process. Pointers can +// be used for the ID parameter, and they will be mangled internally so that +// the same pointer on two different processes will not match. For example: +// class MyTracedClass { +// public: +// MyTracedClass() { +// TRACE_EVENT_ASYNC_BEGIN0("category", "MyTracedClass", this); +// } +// ~MyTracedClass() { +// TRACE_EVENT_ASYNC_END0("category", "MyTracedClass", this); +// } +// } +// +// Trace event also supports counters, which is a way to track a quantity +// as it varies over time. Counters are created with the following macro: +// TRACE_COUNTER1("MY_SUBSYSTEM", "myCounter", g_myCounterValue); +// +// Counters are process-specific. The macro itself can be issued from any +// thread, however. +// +// Sometimes, you want to track two counters at once. You can do this with two +// counter macros: +// TRACE_COUNTER1("MY_SUBSYSTEM", "myCounter0", g_myCounterValue[0]); +// TRACE_COUNTER1("MY_SUBSYSTEM", "myCounter1", g_myCounterValue[1]); +// Or you can do it with a combined macro: +// TRACE_COUNTER2("MY_SUBSYSTEM", "myCounter", +// "bytesPinned", g_myCounterValue[0], +// "bytesAllocated", g_myCounterValue[1]); +// This indicates to the tracing UI that these counters should be displayed +// in a single graph, as a summed area chart. +// +// Since counters are in a global namespace, you may want to disembiguate with a +// unique ID, by using the TRACE_COUNTER_ID* variations. +// +// By default, trace collection is compiled in, but turned off at runtime. +// Collecting trace data is the responsibility of the embedding +// application. In Chrome's case, navigating to about:tracing will turn on +// tracing and display data collected across all active processes. +// +// +// Memory scoping note: +// Tracing copies the pointers, not the string content, of the strings passed +// in for category, name, and arg_names. Thus, the following code will +// cause problems: +// char* str = strdup("impprtantName"); +// TRACE_EVENT_INSTANT0("SUBSYSTEM", str); // BAD! +// free(str); // Trace system now has dangling pointer +// +// To avoid this issue with the |name| and |arg_name| parameters, use the +// TRACE_EVENT_COPY_XXX overloads of the macros at additional runtime overhead. +// Notes: The category must always be in a long-lived char* (i.e. static const). +// The |arg_values|, when used, are always deep copied with the _COPY +// macros. +// +// When are string argument values copied: +// const char* arg_values are only referenced by default: +// TRACE_EVENT1("category", "name", +// "arg1", "literal string is only referenced"); +// Use TRACE_STR_COPY to force copying of a const char*: +// TRACE_EVENT1("category", "name", +// "arg1", TRACE_STR_COPY("string will be copied")); +// std::string arg_values are always copied: +// TRACE_EVENT1("category", "name", +// "arg1", std::string("string will be copied")); +// +// +// Thread Safety: +// A thread safe singleton and mutex are used for thread safety. Category +// enabled flags are used to limit the performance impact when the system +// is not enabled. +// +// TRACE_EVENT macros first cache a pointer to a category. The categories are +// statically allocated and safe at all times, even after exit. Fetching a +// category is protected by the TraceLog::lock_. Multiple threads initializing +// the static variable is safe, as they will be serialized by the lock and +// multiple calls will return the same pointer to the category. +// +// Then the category_enabled flag is checked. This is a unsigned char, and +// not intended to be multithread safe. It optimizes access to addTraceEvent +// which is threadsafe internally via TraceLog::lock_. The enabled flag may +// cause some threads to incorrectly call or skip calling addTraceEvent near +// the time of the system being enabled or disabled. This is acceptable as +// we tolerate some data loss while the system is being enabled/disabled and +// because addTraceEvent is threadsafe internally and checks the enabled state +// again under lock. +// +// Without the use of these static category pointers and enabled flags all +// trace points would carry a significant performance cost of aquiring a lock +// and resolving the category. + +#ifndef COMMON_TRACE_EVENT_H_ +#define COMMON_TRACE_EVENT_H_ + +#include + +#include "common/event_tracer.h" + +// By default, const char* argument values are assumed to have long-lived scope +// and will not be copied. Use this macro to force a const char* to be copied. +#define TRACE_STR_COPY(str) \ + WebCore::TraceEvent::TraceStringWithCopy(str) + +// Records a pair of begin and end events called "name" for the current +// scope, with 0, 1 or 2 associated arguments. If the category is not +// enabled, then this does nothing. +// - category and name strings must have application lifetime (statics or +// literals). They may not include " chars. +#define TRACE_EVENT0(category, name) \ + INTERNAL_TRACE_EVENT_ADD_SCOPED(category, name) +#define TRACE_EVENT1(category, name, arg1_name, arg1_val) \ + INTERNAL_TRACE_EVENT_ADD_SCOPED(category, name, arg1_name, arg1_val) +#define TRACE_EVENT2(category, name, arg1_name, arg1_val, arg2_name, arg2_val) \ + INTERNAL_TRACE_EVENT_ADD_SCOPED(category, name, arg1_name, arg1_val, \ + arg2_name, arg2_val) + +// Records a single event called "name" immediately, with 0, 1 or 2 +// associated arguments. If the category is not enabled, then this +// does nothing. +// - category and name strings must have application lifetime (statics or +// literals). They may not include " chars. +#define TRACE_EVENT_INSTANT0(category, name) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \ + category, name, TRACE_EVENT_FLAG_NONE) +#define TRACE_EVENT_INSTANT1(category, name, arg1_name, arg1_val) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \ + category, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val) +#define TRACE_EVENT_INSTANT2(category, name, arg1_name, arg1_val, \ + arg2_name, arg2_val) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \ + category, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, \ + arg2_name, arg2_val) +#define TRACE_EVENT_COPY_INSTANT0(category, name) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \ + category, name, TRACE_EVENT_FLAG_COPY) +#define TRACE_EVENT_COPY_INSTANT1(category, name, arg1_name, arg1_val) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \ + category, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val) +#define TRACE_EVENT_COPY_INSTANT2(category, name, arg1_name, arg1_val, \ + arg2_name, arg2_val) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \ + category, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val, \ + arg2_name, arg2_val) + +// Records a single BEGIN event called "name" immediately, with 0, 1 or 2 +// associated arguments. If the category is not enabled, then this +// does nothing. +// - category and name strings must have application lifetime (statics or +// literals). They may not include " chars. +#define TRACE_EVENT_BEGIN0(category, name) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \ + category, name, TRACE_EVENT_FLAG_NONE) +#define TRACE_EVENT_BEGIN1(category, name, arg1_name, arg1_val) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \ + category, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val) +#define TRACE_EVENT_BEGIN2(category, name, arg1_name, arg1_val, \ + arg2_name, arg2_val) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \ + category, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, \ + arg2_name, arg2_val) +#define TRACE_EVENT_COPY_BEGIN0(category, name) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \ + category, name, TRACE_EVENT_FLAG_COPY) +#define TRACE_EVENT_COPY_BEGIN1(category, name, arg1_name, arg1_val) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \ + category, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val) +#define TRACE_EVENT_COPY_BEGIN2(category, name, arg1_name, arg1_val, \ + arg2_name, arg2_val) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \ + category, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val, \ + arg2_name, arg2_val) + +// Records a single END event for "name" immediately. If the category +// is not enabled, then this does nothing. +// - category and name strings must have application lifetime (statics or +// literals). They may not include " chars. +#define TRACE_EVENT_END0(category, name) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \ + category, name, TRACE_EVENT_FLAG_NONE) +#define TRACE_EVENT_END1(category, name, arg1_name, arg1_val) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \ + category, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val) +#define TRACE_EVENT_END2(category, name, arg1_name, arg1_val, \ + arg2_name, arg2_val) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \ + category, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, \ + arg2_name, arg2_val) +#define TRACE_EVENT_COPY_END0(category, name) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \ + category, name, TRACE_EVENT_FLAG_COPY) +#define TRACE_EVENT_COPY_END1(category, name, arg1_name, arg1_val) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \ + category, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val) +#define TRACE_EVENT_COPY_END2(category, name, arg1_name, arg1_val, \ + arg2_name, arg2_val) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \ + category, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val, \ + arg2_name, arg2_val) + +// Records the value of a counter called "name" immediately. Value +// must be representable as a 32 bit integer. +// - category and name strings must have application lifetime (statics or +// literals). They may not include " chars. +#define TRACE_COUNTER1(category, name, value) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, \ + category, name, TRACE_EVENT_FLAG_NONE, \ + "value", static_cast(value)) +#define TRACE_COPY_COUNTER1(category, name, value) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, \ + category, name, TRACE_EVENT_FLAG_COPY, \ + "value", static_cast(value)) + +// Records the values of a multi-parted counter called "name" immediately. +// The UI will treat value1 and value2 as parts of a whole, displaying their +// values as a stacked-bar chart. +// - category and name strings must have application lifetime (statics or +// literals). They may not include " chars. +#define TRACE_COUNTER2(category, name, value1_name, value1_val, \ + value2_name, value2_val) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, \ + category, name, TRACE_EVENT_FLAG_NONE, \ + value1_name, static_cast(value1_val), \ + value2_name, static_cast(value2_val)) +#define TRACE_COPY_COUNTER2(category, name, value1_name, value1_val, \ + value2_name, value2_val) \ + INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, \ + category, name, TRACE_EVENT_FLAG_COPY, \ + value1_name, static_cast(value1_val), \ + value2_name, static_cast(value2_val)) + +// Records the value of a counter called "name" immediately. Value +// must be representable as a 32 bit integer. +// - category and name strings must have application lifetime (statics or +// literals). They may not include " chars. +// - |id| is used to disambiguate counters with the same name. It must either +// be a pointer or an integer value up to 64 bits. If it's a pointer, the bits +// will be xored with a hash of the process ID so that the same pointer on +// two different processes will not collide. +#define TRACE_COUNTER_ID1(category, name, id, value) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_COUNTER, \ + category, name, id, TRACE_EVENT_FLAG_NONE, \ + "value", static_cast(value)) +#define TRACE_COPY_COUNTER_ID1(category, name, id, value) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_COUNTER, \ + category, name, id, TRACE_EVENT_FLAG_COPY, \ + "value", static_cast(value)) + +// Records the values of a multi-parted counter called "name" immediately. +// The UI will treat value1 and value2 as parts of a whole, displaying their +// values as a stacked-bar chart. +// - category and name strings must have application lifetime (statics or +// literals). They may not include " chars. +// - |id| is used to disambiguate counters with the same name. It must either +// be a pointer or an integer value up to 64 bits. If it's a pointer, the bits +// will be xored with a hash of the process ID so that the same pointer on +// two different processes will not collide. +#define TRACE_COUNTER_ID2(category, name, id, value1_name, value1_val, \ + value2_name, value2_val) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_COUNTER, \ + category, name, id, TRACE_EVENT_FLAG_NONE, \ + value1_name, static_cast(value1_val), \ + value2_name, static_cast(value2_val)) +#define TRACE_COPY_COUNTER_ID2(category, name, id, value1_name, value1_val, \ + value2_name, value2_val) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_COUNTER, \ + category, name, id, TRACE_EVENT_FLAG_COPY, \ + value1_name, static_cast(value1_val), \ + value2_name, static_cast(value2_val)) + +// Records a single ASYNC_BEGIN event called "name" immediately, with 0, 1 or 2 +// associated arguments. If the category is not enabled, then this +// does nothing. +// - category and name strings must have application lifetime (statics or +// literals). They may not include " chars. +// - |id| is used to match the ASYNC_BEGIN event with the ASYNC_END event. ASYNC +// events are considered to match if their category, name and id values all +// match. |id| must either be a pointer or an integer value up to 64 bits. If +// it's a pointer, the bits will be xored with a hash of the process ID so +// that the same pointer on two different processes will not collide. +// An asynchronous operation can consist of multiple phases. The first phase is +// defined by the ASYNC_BEGIN calls. Additional phases can be defined using the +// ASYNC_STEP_BEGIN macros. When the operation completes, call ASYNC_END. +// An async operation can span threads and processes, but all events in that +// operation must use the same |name| and |id|. Each event can have its own +// args. +#define TRACE_EVENT_ASYNC_BEGIN0(category, name, id) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \ + category, name, id, TRACE_EVENT_FLAG_NONE) +#define TRACE_EVENT_ASYNC_BEGIN1(category, name, id, arg1_name, arg1_val) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \ + category, name, id, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val) +#define TRACE_EVENT_ASYNC_BEGIN2(category, name, id, arg1_name, arg1_val, \ + arg2_name, arg2_val) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \ + category, name, id, TRACE_EVENT_FLAG_NONE, \ + arg1_name, arg1_val, arg2_name, arg2_val) +#define TRACE_EVENT_COPY_ASYNC_BEGIN0(category, name, id) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \ + category, name, id, TRACE_EVENT_FLAG_COPY) +#define TRACE_EVENT_COPY_ASYNC_BEGIN1(category, name, id, arg1_name, arg1_val) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \ + category, name, id, TRACE_EVENT_FLAG_COPY, \ + arg1_name, arg1_val) +#define TRACE_EVENT_COPY_ASYNC_BEGIN2(category, name, id, arg1_name, arg1_val, \ + arg2_name, arg2_val) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \ + category, name, id, TRACE_EVENT_FLAG_COPY, \ + arg1_name, arg1_val, arg2_name, arg2_val) + +// Records a single ASYNC_STEP event for |step| immediately. If the category +// is not enabled, then this does nothing. The |name| and |id| must match the +// ASYNC_BEGIN event above. The |step| param identifies this step within the +// async event. This should be called at the beginning of the next phase of an +// asynchronous operation. +#define TRACE_EVENT_ASYNC_STEP0(category, name, id, step) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_STEP, \ + category, name, id, TRACE_EVENT_FLAG_NONE, "step", step) +#define TRACE_EVENT_ASYNC_STEP1(category, name, id, step, \ + arg1_name, arg1_val) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_STEP, \ + category, name, id, TRACE_EVENT_FLAG_NONE, "step", step, \ + arg1_name, arg1_val) +#define TRACE_EVENT_COPY_ASYNC_STEP0(category, name, id, step) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_STEP, \ + category, name, id, TRACE_EVENT_FLAG_COPY, "step", step) +#define TRACE_EVENT_COPY_ASYNC_STEP1(category, name, id, step, \ + arg1_name, arg1_val) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_STEP, \ + category, name, id, TRACE_EVENT_FLAG_COPY, "step", step, \ + arg1_name, arg1_val) + +// Records a single ASYNC_END event for "name" immediately. If the category +// is not enabled, then this does nothing. +#define TRACE_EVENT_ASYNC_END0(category, name, id) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \ + category, name, id, TRACE_EVENT_FLAG_NONE) +#define TRACE_EVENT_ASYNC_END1(category, name, id, arg1_name, arg1_val) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \ + category, name, id, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val) +#define TRACE_EVENT_ASYNC_END2(category, name, id, arg1_name, arg1_val, \ + arg2_name, arg2_val) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \ + category, name, id, TRACE_EVENT_FLAG_NONE, \ + arg1_name, arg1_val, arg2_name, arg2_val) +#define TRACE_EVENT_COPY_ASYNC_END0(category, name, id) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \ + category, name, id, TRACE_EVENT_FLAG_COPY) +#define TRACE_EVENT_COPY_ASYNC_END1(category, name, id, arg1_name, arg1_val) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \ + category, name, id, TRACE_EVENT_FLAG_COPY, \ + arg1_name, arg1_val) +#define TRACE_EVENT_COPY_ASYNC_END2(category, name, id, arg1_name, arg1_val, \ + arg2_name, arg2_val) \ + INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \ + category, name, id, TRACE_EVENT_FLAG_COPY, \ + arg1_name, arg1_val, arg2_name, arg2_val) + +// Creates a scope of a sampling state with the given category and name (both must +// be constant strings). These states are intended for a sampling profiler. +// Implementation note: we store category and name together because we don't +// want the inconsistency/expense of storing two pointers. +// |thread_bucket| is [0..2] and is used to statically isolate samples in one +// thread from others. +// +// { // The sampling state is set within this scope. +// TRACE_EVENT_SAMPLING_STATE_SCOPE_FOR_BUCKET(0, "category", "name"); +// ...; +// } +#define TRACE_EVENT_SCOPED_SAMPLING_STATE_FOR_BUCKET(bucket_number, category, name) \ + TraceEvent::SamplingStateScope traceEventSamplingScope(category "\0" name); + +// Returns a current sampling state of the given bucket. +// The format of the returned string is "category\0name". +#define TRACE_EVENT_GET_SAMPLING_STATE_FOR_BUCKET(bucket_number) \ + TraceEvent::SamplingStateScope::current() + +// Sets a current sampling state of the given bucket. +// |category| and |name| have to be constant strings. +#define TRACE_EVENT_SET_SAMPLING_STATE_FOR_BUCKET(bucket_number, category, name) \ + TraceEvent::SamplingStateScope::set(category "\0" name) + +// Sets a current sampling state of the given bucket. +// |categoryAndName| doesn't need to be a constant string. +// The format of the string is "category\0name". +#define TRACE_EVENT_SET_NONCONST_SAMPLING_STATE_FOR_BUCKET(bucket_number, categoryAndName) \ + TraceEvent::SamplingStateScope::set(categoryAndName) + +// Syntactic sugars for the sampling tracing in the main thread. +#define TRACE_EVENT_SCOPED_SAMPLING_STATE(category, name) \ + TRACE_EVENT_SCOPED_SAMPLING_STATE_FOR_BUCKET(0, category, name) +#define TRACE_EVENT_GET_SAMPLING_STATE() \ + TRACE_EVENT_GET_SAMPLING_STATE_FOR_BUCKET(0) +#define TRACE_EVENT_SET_SAMPLING_STATE(category, name) \ + TRACE_EVENT_SET_SAMPLING_STATE_FOR_BUCKET(0, category, name) +#define TRACE_EVENT_SET_NONCONST_SAMPLING_STATE(categoryAndName) \ + TRACE_EVENT_SET_NONCONST_SAMPLING_STATE_FOR_BUCKET(0, categoryAndName) + +//////////////////////////////////////////////////////////////////////////////// +// Implementation specific tracing API definitions. + +// Get a pointer to the enabled state of the given trace category. Only +// long-lived literal strings should be given as the category name. The returned +// pointer can be held permanently in a local static for example. If the +// unsigned char is non-zero, tracing is enabled. If tracing is enabled, +// TRACE_EVENT_API_ADD_TRACE_EVENT can be called. It's OK if tracing is disabled +// between the load of the tracing state and the call to +// TRACE_EVENT_API_ADD_TRACE_EVENT, because this flag only provides an early out +// for best performance when tracing is disabled. +// const unsigned char* +// TRACE_EVENT_API_GET_CATEGORY_ENABLED(const char* category_name) +#define TRACE_EVENT_API_GET_CATEGORY_ENABLED \ + gl::TraceGetTraceCategoryEnabledFlag + +// Add a trace event to the platform tracing system. +// void TRACE_EVENT_API_ADD_TRACE_EVENT( +// char phase, +// const unsigned char* category_enabled, +// const char* name, +// unsigned long long id, +// int num_args, +// const char** arg_names, +// const unsigned char* arg_types, +// const unsigned long long* arg_values, +// unsigned char flags) +#define TRACE_EVENT_API_ADD_TRACE_EVENT \ + gl::TraceAddTraceEvent + +//////////////////////////////////////////////////////////////////////////////// + +// Implementation detail: trace event macros create temporary variables +// to keep instrumentation overhead low. These macros give each temporary +// variable a unique name based on the line number to prevent name collissions. +#define INTERNAL_TRACE_EVENT_UID3(a, b) \ + trace_event_unique_##a##b +#define INTERNAL_TRACE_EVENT_UID2(a, b) \ + INTERNAL_TRACE_EVENT_UID3(a, b) +#define INTERNALTRACEEVENTUID(name_prefix) \ + INTERNAL_TRACE_EVENT_UID2(name_prefix, __LINE__) + +// Implementation detail: internal macro to create static category. +#define INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category) \ + static const unsigned char* INTERNALTRACEEVENTUID(catstatic) = 0; \ + if (!INTERNALTRACEEVENTUID(catstatic)) \ + INTERNALTRACEEVENTUID(catstatic) = \ + TRACE_EVENT_API_GET_CATEGORY_ENABLED(category); + +// Implementation detail: internal macro to create static category and add +// event if the category is enabled. +#define INTERNAL_TRACE_EVENT_ADD(phase, category, name, flags, ...) \ + do { \ + INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category); \ + if (*INTERNALTRACEEVENTUID(catstatic)) { \ + gl::TraceEvent::addTraceEvent( \ + phase, INTERNALTRACEEVENTUID(catstatic), name, \ + gl::TraceEvent::noEventId, flags, ##__VA_ARGS__); \ + } \ + } while (0) + +// Implementation detail: internal macro to create static category and add begin +// event if the category is enabled. Also adds the end event when the scope +// ends. +#define INTERNAL_TRACE_EVENT_ADD_SCOPED(category, name, ...) \ + INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category); \ + gl::TraceEvent::TraceEndOnScopeClose \ + INTERNALTRACEEVENTUID(profileScope); \ + if (*INTERNALTRACEEVENTUID(catstatic)) { \ + gl::TraceEvent::addTraceEvent( \ + TRACE_EVENT_PHASE_BEGIN, \ + INTERNALTRACEEVENTUID(catstatic), \ + name, gl::TraceEvent::noEventId, \ + TRACE_EVENT_FLAG_NONE, ##__VA_ARGS__); \ + INTERNALTRACEEVENTUID(profileScope).initialize( \ + INTERNALTRACEEVENTUID(catstatic), name); \ + } + +// Implementation detail: internal macro to create static category and add +// event if the category is enabled. +#define INTERNAL_TRACE_EVENT_ADD_WITH_ID(phase, category, name, id, flags, \ + ...) \ + do { \ + INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category); \ + if (*INTERNALTRACEEVENTUID(catstatic)) { \ + unsigned char traceEventFlags = flags | TRACE_EVENT_FLAG_HAS_ID; \ + gl::TraceEvent::TraceID traceEventTraceID( \ + id, &traceEventFlags); \ + gl::TraceEvent::addTraceEvent( \ + phase, INTERNALTRACEEVENTUID(catstatic), \ + name, traceEventTraceID.data(), traceEventFlags, \ + ##__VA_ARGS__); \ + } \ + } while (0) + +// Notes regarding the following definitions: +// New values can be added and propagated to third party libraries, but existing +// definitions must never be changed, because third party libraries may use old +// definitions. + +// Phase indicates the nature of an event entry. E.g. part of a begin/end pair. +#define TRACE_EVENT_PHASE_BEGIN ('B') +#define TRACE_EVENT_PHASE_END ('E') +#define TRACE_EVENT_PHASE_INSTANT ('I') +#define TRACE_EVENT_PHASE_ASYNC_BEGIN ('S') +#define TRACE_EVENT_PHASE_ASYNC_STEP ('T') +#define TRACE_EVENT_PHASE_ASYNC_END ('F') +#define TRACE_EVENT_PHASE_METADATA ('M') +#define TRACE_EVENT_PHASE_COUNTER ('C') +#define TRACE_EVENT_PHASE_SAMPLE ('P') + +// Flags for changing the behavior of TRACE_EVENT_API_ADD_TRACE_EVENT. +#define TRACE_EVENT_FLAG_NONE (static_cast(0)) +#define TRACE_EVENT_FLAG_COPY (static_cast(1 << 0)) +#define TRACE_EVENT_FLAG_HAS_ID (static_cast(1 << 1)) +#define TRACE_EVENT_FLAG_MANGLE_ID (static_cast(1 << 2)) + +// Type values for identifying types in the TraceValue union. +#define TRACE_VALUE_TYPE_BOOL (static_cast(1)) +#define TRACE_VALUE_TYPE_UINT (static_cast(2)) +#define TRACE_VALUE_TYPE_INT (static_cast(3)) +#define TRACE_VALUE_TYPE_DOUBLE (static_cast(4)) +#define TRACE_VALUE_TYPE_POINTER (static_cast(5)) +#define TRACE_VALUE_TYPE_STRING (static_cast(6)) +#define TRACE_VALUE_TYPE_COPY_STRING (static_cast(7)) + + +namespace gl { + +namespace TraceEvent { + +// Specify these values when the corresponding argument of addTraceEvent is not +// used. +const int zeroNumArgs = 0; +const unsigned long long noEventId = 0; + +// TraceID encapsulates an ID that can either be an integer or pointer. Pointers +// are mangled with the Process ID so that they are unlikely to collide when the +// same pointer is used on different processes. +class TraceID { +public: + explicit TraceID(const void* id, unsigned char* flags) : + m_data(static_cast(reinterpret_cast(id))) + { + *flags |= TRACE_EVENT_FLAG_MANGLE_ID; + } + explicit TraceID(unsigned long long id, unsigned char* flags) : m_data(id) { (void)flags; } + explicit TraceID(unsigned long id, unsigned char* flags) : m_data(id) { (void)flags; } + explicit TraceID(unsigned int id, unsigned char* flags) : m_data(id) { (void)flags; } + explicit TraceID(unsigned short id, unsigned char* flags) : m_data(id) { (void)flags; } + explicit TraceID(unsigned char id, unsigned char* flags) : m_data(id) { (void)flags; } + explicit TraceID(long long id, unsigned char* flags) : + m_data(static_cast(id)) { (void)flags; } + explicit TraceID(long id, unsigned char* flags) : + m_data(static_cast(id)) { (void)flags; } + explicit TraceID(int id, unsigned char* flags) : + m_data(static_cast(id)) { (void)flags; } + explicit TraceID(short id, unsigned char* flags) : + m_data(static_cast(id)) { (void)flags; } + explicit TraceID(signed char id, unsigned char* flags) : + m_data(static_cast(id)) { (void)flags; } + + unsigned long long data() const { return m_data; } + +private: + unsigned long long m_data; +}; + +// Simple union to store various types as unsigned long long. +union TraceValueUnion { + bool m_bool; + unsigned long long m_uint; + long long m_int; + double m_double; + const void* m_pointer; + const char* m_string; +}; + +// Simple container for const char* that should be copied instead of retained. +class TraceStringWithCopy { +public: + explicit TraceStringWithCopy(const char* str) : m_str(str) { } + operator const char* () const { return m_str; } +private: + const char* m_str; +}; + +// Define setTraceValue for each allowed type. It stores the type and +// value in the return arguments. This allows this API to avoid declaring any +// structures so that it is portable to third_party libraries. +#define INTERNAL_DECLARE_SET_TRACE_VALUE(actual_type, \ + union_member, \ + value_type_id) \ + static inline void setTraceValue(actual_type arg, \ + unsigned char* type, \ + unsigned long long* value) { \ + TraceValueUnion typeValue; \ + typeValue.union_member = arg; \ + *type = value_type_id; \ + *value = typeValue.m_uint; \ + } +// Simpler form for int types that can be safely casted. +#define INTERNAL_DECLARE_SET_TRACE_VALUE_INT(actual_type, \ + value_type_id) \ + static inline void setTraceValue(actual_type arg, \ + unsigned char* type, \ + unsigned long long* value) { \ + *type = value_type_id; \ + *value = static_cast(arg); \ + } + +INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned long long, TRACE_VALUE_TYPE_UINT) +INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned int, TRACE_VALUE_TYPE_UINT) +INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned short, TRACE_VALUE_TYPE_UINT) +INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned char, TRACE_VALUE_TYPE_UINT) +INTERNAL_DECLARE_SET_TRACE_VALUE_INT(long long, TRACE_VALUE_TYPE_INT) +INTERNAL_DECLARE_SET_TRACE_VALUE_INT(int, TRACE_VALUE_TYPE_INT) +INTERNAL_DECLARE_SET_TRACE_VALUE_INT(short, TRACE_VALUE_TYPE_INT) +INTERNAL_DECLARE_SET_TRACE_VALUE_INT(signed char, TRACE_VALUE_TYPE_INT) +INTERNAL_DECLARE_SET_TRACE_VALUE(bool, m_bool, TRACE_VALUE_TYPE_BOOL) +INTERNAL_DECLARE_SET_TRACE_VALUE(double, m_double, TRACE_VALUE_TYPE_DOUBLE) +INTERNAL_DECLARE_SET_TRACE_VALUE(const void*, m_pointer, + TRACE_VALUE_TYPE_POINTER) +INTERNAL_DECLARE_SET_TRACE_VALUE(const char*, m_string, + TRACE_VALUE_TYPE_STRING) +INTERNAL_DECLARE_SET_TRACE_VALUE(const TraceStringWithCopy&, m_string, + TRACE_VALUE_TYPE_COPY_STRING) + +#undef INTERNAL_DECLARE_SET_TRACE_VALUE +#undef INTERNAL_DECLARE_SET_TRACE_VALUE_INT + +static inline void setTraceValue(const std::string& arg, + unsigned char* type, + unsigned long long* value) { + TraceValueUnion typeValue; + typeValue.m_string = arg.data(); + *type = TRACE_VALUE_TYPE_COPY_STRING; + *value = typeValue.m_uint; +} + +// These addTraceEvent template functions are defined here instead of in the +// macro, because the arg values could be temporary string objects. In order to +// store pointers to the internal c_str and pass through to the tracing API, the +// arg values must live throughout these procedures. + +static inline void addTraceEvent(char phase, + const unsigned char* categoryEnabled, + const char* name, + unsigned long long id, + unsigned char flags) { + TRACE_EVENT_API_ADD_TRACE_EVENT( + phase, categoryEnabled, name, id, + zeroNumArgs, 0, 0, 0, + flags); +} + +template +static inline void addTraceEvent(char phase, + const unsigned char* categoryEnabled, + const char* name, + unsigned long long id, + unsigned char flags, + const char* arg1Name, + const ARG1_TYPE& arg1Val) { + const int numArgs = 1; + unsigned char argTypes[1]; + unsigned long long argValues[1]; + setTraceValue(arg1Val, &argTypes[0], &argValues[0]); + TRACE_EVENT_API_ADD_TRACE_EVENT( + phase, categoryEnabled, name, id, + numArgs, &arg1Name, argTypes, argValues, + flags); +} + +template +static inline void addTraceEvent(char phase, + const unsigned char* categoryEnabled, + const char* name, + unsigned long long id, + unsigned char flags, + const char* arg1Name, + const ARG1_TYPE& arg1Val, + const char* arg2Name, + const ARG2_TYPE& arg2Val) { + const int numArgs = 2; + const char* argNames[2] = { arg1Name, arg2Name }; + unsigned char argTypes[2]; + unsigned long long argValues[2]; + setTraceValue(arg1Val, &argTypes[0], &argValues[0]); + setTraceValue(arg2Val, &argTypes[1], &argValues[1]); + return TRACE_EVENT_API_ADD_TRACE_EVENT( + phase, categoryEnabled, name, id, + numArgs, argNames, argTypes, argValues, + flags); +} + +// Used by TRACE_EVENTx macro. Do not use directly. +class TraceEndOnScopeClose { +public: + // Note: members of m_data intentionally left uninitialized. See initialize. + TraceEndOnScopeClose() : m_pdata(0) { } + ~TraceEndOnScopeClose() + { + if (m_pdata) + addEventIfEnabled(); + } + + void initialize(const unsigned char* categoryEnabled, + const char* name) + { + m_data.categoryEnabled = categoryEnabled; + m_data.name = name; + m_pdata = &m_data; + } + +private: + // Add the end event if the category is still enabled. + void addEventIfEnabled() + { + // Only called when m_pdata is non-null. + if (*m_pdata->categoryEnabled) { + TRACE_EVENT_API_ADD_TRACE_EVENT( + TRACE_EVENT_PHASE_END, + m_pdata->categoryEnabled, + m_pdata->name, noEventId, + zeroNumArgs, 0, 0, 0, + TRACE_EVENT_FLAG_NONE); + } + } + + // This Data struct workaround is to avoid initializing all the members + // in Data during construction of this object, since this object is always + // constructed, even when tracing is disabled. If the members of Data were + // members of this class instead, compiler warnings occur about potential + // uninitialized accesses. + struct Data { + const unsigned char* categoryEnabled; + const char* name; + }; + Data* m_pdata; + Data m_data; +}; + +} // namespace TraceEvent + +} // namespace gl + +#endif diff --git a/src/angle/patches/0000-General-fixes-for-ANGLE-2.1.patch b/src/angle/patches/0000-General-fixes-for-ANGLE-2.1.patch deleted file mode 100644 index ad3187ec7c..0000000000 --- a/src/angle/patches/0000-General-fixes-for-ANGLE-2.1.patch +++ /dev/null @@ -1,477 +0,0 @@ -From bd27c33a4a7c48bd14b9b6c18c8cdce1c3aae155 Mon Sep 17 00:00:00 2001 -From: Andrew Knight -Date: Fri, 14 Nov 2014 10:53:40 +0200 -Subject: [PATCH] General fixes for ANGLE 2.1 - -- Fix commit.h include (use hard-coded version) -- Fix export mismatch in libEGL.cpp and libGLESv2.cpp -- Normalize all precompiled shader names and includes -- Remove third-party event tracing; it was hardly used in ANGLE - and not enabled in Qt builds anyway. - -Change-Id: I22254aed62e89a26756ca0784bae95909189c0f9 ---- - src/3rdparty/angle/src/commit.h | 6 +- - src/3rdparty/angle/src/common/version.h | 2 +- - .../src/common/winrt/CoreWindowNativeWindow.cpp | 2 +- - src/3rdparty/angle/src/libEGL/libEGL.cpp | 3 + - src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp | 4 ++ - src/3rdparty/angle/src/libGLESv2/libGLESv2.def | 3 - - .../src/libGLESv2/renderer/d3d/HLSLCompiler.cpp | 3 - - .../src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp | 66 +++++++++++----------- - .../src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp | 12 ++-- - .../renderer/d3d/d3d11/PixelTransfer11.cpp | 10 ++-- - .../libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp | 4 +- - .../renderer/d3d/d3d11/shaders/Clear11.hlsl | 4 ++ - .../src/libGLESv2/renderer/d3d/d3d9/Blit9.cpp | 20 +++---- - .../src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp | 12 ---- - .../libGLESv2/renderer/d3d/d3d9/shaders/Blit.ps | 6 +- - .../libGLESv2/renderer/d3d/d3d9/shaders/Blit.vs | 4 +- - 16 files changed, 76 insertions(+), 85 deletions(-) - -diff --git a/src/3rdparty/angle/src/commit.h b/src/3rdparty/angle/src/commit.h -index 4c89a65..08fc893 100644 ---- a/src/3rdparty/angle/src/commit.h -+++ b/src/3rdparty/angle/src/commit.h -@@ -7,8 +7,6 @@ - // This is a default commit hash header, when git is not available. - // - --#define ANGLE_COMMIT_HASH "unknown hash" -+#define ANGLE_COMMIT_HASH "30d6c255d238" - #define ANGLE_COMMIT_HASH_SIZE 12 --#define ANGLE_COMMIT_DATE "unknown date" -- --#define ANGLE_DISABLE_PROGRAM_BINARY_LOAD -+#define ANGLE_COMMIT_DATE "2014-11-13 17:37:03 +0000" -diff --git a/src/3rdparty/angle/src/common/version.h b/src/3rdparty/angle/src/common/version.h -index d9148d1..f01e024 100644 ---- a/src/3rdparty/angle/src/common/version.h -+++ b/src/3rdparty/angle/src/common/version.h -@@ -1,4 +1,4 @@ --#include "id/commit.h" -+#include "../commit.h" - - #define ANGLE_MAJOR_VERSION 2 - #define ANGLE_MINOR_VERSION 1 -diff --git a/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.cpp b/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.cpp -index 0de16f4..0e63fa5 100644 ---- a/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.cpp -+++ b/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.cpp -@@ -184,4 +184,4 @@ long ConvertDipsToPixels(float dips) - static const float dipsPerInch = 96.0f; - return lround((dips * GetLogicalDpi() / dipsPerInch)); - } --} -\ No newline at end of file -+} -diff --git a/src/3rdparty/angle/src/libEGL/libEGL.cpp b/src/3rdparty/angle/src/libEGL/libEGL.cpp -index 851b723..6110698 100644 ---- a/src/3rdparty/angle/src/libEGL/libEGL.cpp -+++ b/src/3rdparty/angle/src/libEGL/libEGL.cpp -@@ -6,6 +6,9 @@ - - // libEGL.cpp: Implements the exported EGL functions. - -+#undef EGLAPI -+#define EGLAPI -+ - #include - - #include "common/debug.h" -diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp b/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp -index 2306168..587950a 100644 ---- a/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp -+++ b/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp -@@ -6,6 +6,10 @@ - - // libGLESv2.cpp: Implements the exported OpenGL ES 2.0 functions. - -+#undef GL_APICALL -+#define GL_APICALL -+#define GL_GLEXT_PROTOTYPES -+ - #include "common/version.h" - #include "common/utilities.h" - -diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2.def b/src/3rdparty/angle/src/libGLESv2/libGLESv2.def -index 88dceb3..33557eb 100644 ---- a/src/3rdparty/angle/src/libGLESv2/libGLESv2.def -+++ b/src/3rdparty/angle/src/libGLESv2/libGLESv2.def -@@ -294,6 +294,3 @@ EXPORTS - glBindTexImage @158 NONAME - glCreateRenderer @177 NONAME - glDestroyRenderer @178 NONAME -- -- ; Setting up TRACE macro callbacks -- SetTraceFunctionPointers @284 -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp -index 5c44fe0..bfeaf51 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp -@@ -11,8 +11,6 @@ - #include "common/features.h" - #include "common/utilities.h" - --#include "third_party/trace_event/trace_event.h" -- - // Definitions local to the translation unit - namespace - { -@@ -120,7 +118,6 @@ HLSLCompiler::~HLSLCompiler() - - bool HLSLCompiler::initialize() - { -- TRACE_EVENT0("gpu", "initializeCompiler"); - #if !defined(ANGLE_ENABLE_WINDOWS_STORE) - #if defined(ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES) - // Find a D3DCompiler module that had already been loaded based on a predefined list of versions. -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp -index 8ed1650..91e7552 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp -@@ -13,39 +13,39 @@ - #include "libGLESv2/main.h" - #include "libGLESv2/formatutils.h" - --#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthrough2d11vs.h" --#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughdepth2d11ps.h" --#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2d11ps.h" --#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dui11ps.h" --#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2di11ps.h" --#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2d11ps.h" --#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2dui11ps.h" --#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2di11ps.h" --#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg2d11ps.h" --#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg2dui11ps.h" --#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg2di11ps.h" --#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr2d11ps.h" --#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr2dui11ps.h" --#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr2di11ps.h" --#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughlum2d11ps.h" --#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha2d11ps.h" -- --#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthrough3d11vs.h" --#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthrough3d11gs.h" --#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3d11ps.h" --#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3dui11ps.h" --#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3di11ps.h" --#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3d11ps.h" --#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3dui11ps.h" --#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3di11ps.h" --#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg3d11ps.h" --#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg3dui11ps.h" --#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg3di11ps.h" --#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr3d11ps.h" --#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr3dui11ps.h" --#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr3di11ps.h" --#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughlum3d11ps.h" --#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha3d11ps.h" -+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthrough2dvs.h" -+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughdepth2dps.h" -+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dps.h" -+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2duips.h" -+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dips.h" -+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2dps.h" -+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2duips.h" -+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2dips.h" -+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg2dps.h" -+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg2duips.h" -+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg2dips.h" -+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr2dps.h" -+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr2duips.h" -+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr2dips.h" -+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughlum2dps.h" -+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha2dps.h" -+ -+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthrough3dvs.h" -+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthrough3dgs.h" -+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3dps.h" -+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3duips.h" -+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3dips.h" -+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3dps.h" -+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3duips.h" -+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3dips.h" -+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg3dps.h" -+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg3duips.h" -+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg3dips.h" -+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr3dps.h" -+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr3duips.h" -+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr3dips.h" -+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughlum3dps.h" -+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha3dps.h" - - #include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzlef2dps.h" - #include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzlei2dps.h" -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp -index 12905d0..4630762 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp -@@ -15,14 +15,14 @@ - #include "libGLESv2/FramebufferAttachment.h" - - // Precompiled shaders --#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearfloat11vs.h" --#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps.h" -+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearfloatvs.h" -+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearfloatps.h" - --#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearuint11vs.h" --#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearuint11ps.h" -+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearuintvs.h" -+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearuintps.h" - --#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearsint11vs.h" --#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearsint11ps.h" -+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearsintvs.h" -+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearsintps.h" - - namespace rx - { -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.cpp -index 1bc2bd8..a4072d8 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.cpp -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.cpp -@@ -22,11 +22,11 @@ - #include "libGLESv2/Context.h" - - // Precompiled shaders --#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_vs.h" --#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_gs.h" --#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4f.h" --#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4i.h" --#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4ui.h" -+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/buffertotexturevs.h" -+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/buffertotexturegs.h" -+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/buffertotexture_4fps.h" -+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/buffertotexture_4ips.h" -+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/buffertotexture_4uips.h" - - namespace rx - { -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp -index 3fcacf6..834b7bd 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp -@@ -12,8 +12,8 @@ - #include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" - - // Precompiled shaders --#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthrough2d11vs.h" --#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2d11ps.h" -+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthrough2dvs.h" -+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dps.h" - - #include "common/features.h" - #include "common/NativeWindow.h" -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Clear11.hlsl b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Clear11.hlsl -index 6deef2b..b4cf380 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Clear11.hlsl -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Clear11.hlsl -@@ -13,10 +13,12 @@ struct PS_OutputFloat - float4 color1 : SV_TARGET1; - float4 color2 : SV_TARGET2; - float4 color3 : SV_TARGET3; -+#if SM4 - float4 color4 : SV_TARGET4; - float4 color5 : SV_TARGET5; - float4 color6 : SV_TARGET6; - float4 color7 : SV_TARGET7; -+#endif - }; - - PS_OutputFloat PS_ClearFloat(in float4 inPosition : SV_POSITION, in float4 inColor : COLOR) -@@ -26,10 +28,12 @@ PS_OutputFloat PS_ClearFloat(in float4 inPosition : SV_POSITION, in float4 inCol - outColor.color1 = inColor; - outColor.color2 = inColor; - outColor.color3 = inColor; -+#if SM4 - outColor.color4 = inColor; - outColor.color5 = inColor; - outColor.color6 = inColor; - outColor.color7 = inColor; -+#endif - return outColor; - } - -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.cpp -index d4fcd17..2ca7a9c 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.cpp -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.cpp -@@ -27,20 +27,20 @@ namespace - - const BYTE* const g_shaderCode[] = - { -- g_vs20_standardvs, -- g_vs20_flipyvs, -- g_ps20_passthroughps, -- g_ps20_luminanceps, -- g_ps20_componentmaskps -+ g_vs20_VS_standard, -+ g_vs20_VS_flipy, -+ g_ps20_PS_passthrough, -+ g_ps20_PS_luminance, -+ g_ps20_PS_componentmask - }; - - 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) -+ sizeof(g_vs20_VS_standard), -+ sizeof(g_vs20_VS_flipy), -+ sizeof(g_ps20_PS_passthrough), -+ sizeof(g_ps20_PS_luminance), -+ sizeof(g_ps20_PS_componentmask) - }; - } - -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp -index 3bac4ba..82963ec 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp -@@ -42,8 +42,6 @@ - #include "common/features.h" - #include "common/utilities.h" - --#include "third_party/trace_event/trace_event.h" -- - #include - - // Can also be enabled by defining FORCE_REF_RAST in the project's predefined macros -@@ -185,7 +183,6 @@ EGLint Renderer9::initialize() - return EGL_NOT_INITIALIZED; - } - -- TRACE_EVENT0("gpu", "GetModuleHandle_d3d9"); - mD3d9Module = GetModuleHandle(TEXT("d3d9.dll")); - - if (mD3d9Module == NULL) -@@ -202,14 +199,12 @@ EGLint Renderer9::initialize() - // desktop. Direct3D9Ex is available in Windows Vista and later if suitable drivers are available. - if (ANGLE_D3D9EX == ANGLE_ENABLED && Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &mD3d9Ex))) - { -- TRACE_EVENT0("gpu", "D3d9Ex_QueryInterface"); - ASSERT(mD3d9Ex); - mD3d9Ex->QueryInterface(__uuidof(IDirect3D9), reinterpret_cast(&mD3d9)); - ASSERT(mD3d9); - } - else - { -- TRACE_EVENT0("gpu", "Direct3DCreate9"); - mD3d9 = Direct3DCreate9(D3D_SDK_VERSION); - } - -@@ -228,7 +223,6 @@ EGLint Renderer9::initialize() - - // Give up on getting device caps after about one second. - { -- TRACE_EVENT0("gpu", "GetDeviceCaps"); - for (int i = 0; i < 10; ++i) - { - result = mD3d9->GetDeviceCaps(mAdapter, mDeviceType, &mDeviceCaps); -@@ -263,7 +257,6 @@ EGLint Renderer9::initialize() - } - - { -- TRACE_EVENT0("gpu", "GetAdapterIdentifier"); - mD3d9->GetAdapterIdentifier(mAdapter, 0, &mAdapterIdentifier); - } - -@@ -300,7 +293,6 @@ EGLint Renderer9::initialize() - static const TCHAR className[] = TEXT("STATIC"); - - { -- TRACE_EVENT0("gpu", "CreateWindowEx"); - mDeviceWindow = CreateWindowEx(WS_EX_NOACTIVATE, className, windowName, WS_DISABLED | WS_POPUP, 0, 0, 1, 1, HWND_MESSAGE, NULL, GetModuleHandle(NULL), NULL); - } - -@@ -308,7 +300,6 @@ EGLint Renderer9::initialize() - DWORD behaviorFlags = D3DCREATE_FPU_PRESERVE | D3DCREATE_NOWINDOWCHANGES; - - { -- TRACE_EVENT0("gpu", "D3d9_CreateDevice"); - result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE, &presentParameters, &mDevice); - } - if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DEVICELOST) -@@ -318,7 +309,6 @@ EGLint Renderer9::initialize() - - if (FAILED(result)) - { -- TRACE_EVENT0("gpu", "D3d9_CreateDevice2"); - result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_SOFTWARE_VERTEXPROCESSING, &presentParameters, &mDevice); - - if (FAILED(result)) -@@ -330,13 +320,11 @@ EGLint Renderer9::initialize() - - if (mD3d9Ex) - { -- TRACE_EVENT0("gpu", "mDevice_QueryInterface"); - result = mDevice->QueryInterface(__uuidof(IDirect3DDevice9Ex), (void**)&mDeviceEx); - ASSERT(SUCCEEDED(result)); - } - - { -- TRACE_EVENT0("gpu", "ShaderCache initialize"); - mVertexShaderCache.initialize(mDevice); - mPixelShaderCache.initialize(mDevice); - } -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/shaders/Blit.ps b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/shaders/Blit.ps -index dc357d0..eb43eb3 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/shaders/Blit.ps -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/shaders/Blit.ps -@@ -11,7 +11,7 @@ uniform float4 add : c1; - - // Passthrough Pixel Shader - // Outputs texture 0 sampled at texcoord 0. --float4 passthroughps(float4 texcoord : TEXCOORD0) : COLOR -+float4 PS_passthrough(float4 texcoord : TEXCOORD0) : COLOR - { - return tex2D(tex, texcoord.xy); - }; -@@ -19,7 +19,7 @@ float4 passthroughps(float4 texcoord : TEXCOORD0) : COLOR - // Luminance Conversion Pixel Shader - // Performs a mad operation using the LA data from the texture with mult.xw and add.xw. - // Returns data in the form of llla --float4 luminanceps(float4 texcoord : TEXCOORD0) : COLOR -+float4 PS_luminance(float4 texcoord : TEXCOORD0) : COLOR - { - return (tex2D(tex, texcoord.xy).xw * mult.xw + add.xw).xxxy; - }; -@@ -27,7 +27,7 @@ float4 luminanceps(float4 texcoord : TEXCOORD0) : COLOR - // RGB/A Component Mask Pixel Shader - // Performs a mad operation using the texture's RGBA data with mult.xyzw and add.xyzw. - // Returns data in the form of rgba --float4 componentmaskps(float4 texcoord : TEXCOORD0) : COLOR -+float4 PS_componentmask(float4 texcoord : TEXCOORD0) : COLOR - { - return tex2D(tex, texcoord.xy) * mult + add; - }; -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/shaders/Blit.vs b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/shaders/Blit.vs -index 3a36980..3bd611b 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/shaders/Blit.vs -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/shaders/Blit.vs -@@ -17,7 +17,7 @@ uniform float4 halfPixelSize : c0; - // 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 VS_standard(in float4 position : POSITION) - { - VS_OUTPUT Out; - -@@ -32,7 +32,7 @@ VS_OUTPUT standardvs(in float4 position : 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 VS_flipy(in float4 position : POSITION) - { - VS_OUTPUT Out; - --- -1.9.4.msysgit.1 - diff --git a/src/angle/patches/0001-ANGLE-Improve-Windows-Phone-Support.patch b/src/angle/patches/0001-ANGLE-Improve-Windows-Phone-Support.patch new file mode 100644 index 0000000000..1361b8b656 --- /dev/null +++ b/src/angle/patches/0001-ANGLE-Improve-Windows-Phone-Support.patch @@ -0,0 +1,439 @@ +From ed09eff731b5d286e0bf6a5958b937a50ecc2362 Mon Sep 17 00:00:00 2001 +From: Andrew Knight +Date: Tue, 7 Apr 2015 13:24:59 +0300 +Subject: [PATCH 1/5] ANGLE: Improve Windows Phone Support + +This contains compile fixes for Windows Phone as well as improved +orientation handling. + +Change-Id: Ia312b5318b977838a2953f1f530487cbf24974bc +--- + src/3rdparty/angle/src/common/platform.h | 2 ++ + .../renderer/d3d/d3d11/DebugAnnotator11.cpp | 2 +- + .../src/libANGLE/renderer/d3d/d3d11/NativeWindow.h | 4 +++ + .../src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp | 8 +++-- + .../libANGLE/renderer/d3d/d3d11/SwapChain11.cpp | 40 ++++++++++++++++++++++ + .../d3d/d3d11/winrt/CoreWindowNativeWindow.cpp | 31 +++++++++++++++-- + .../d3d/d3d11/winrt/CoreWindowNativeWindow.h | 34 +++++++++++++++++- + .../d3d/d3d11/winrt/InspectableNativeWindow.cpp | 12 +++++++ + .../d3d/d3d11/winrt/InspectableNativeWindow.h | 14 +++++++- + src/3rdparty/angle/src/libANGLE/validationEGL.cpp | 4 ++- + 10 files changed, 142 insertions(+), 9 deletions(-) + +diff --git a/src/3rdparty/angle/src/common/platform.h b/src/3rdparty/angle/src/common/platform.h +index 56db297..4e3851c 100644 +--- a/src/3rdparty/angle/src/common/platform.h ++++ b/src/3rdparty/angle/src/common/platform.h +@@ -68,7 +68,9 @@ + # if defined(ANGLE_ENABLE_WINDOWS_STORE) + # include + # if defined(_DEBUG) ++# if WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP + # include ++# endif + # include + # endif + # endif +diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp +index bc7cdcc..fcca904 100644 +--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp ++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp +@@ -60,7 +60,7 @@ bool DebugAnnotator11::getStatus() + { + // ID3DUserDefinedAnnotation::GetStatus doesn't work with the Graphics Diagnostics tools in Visual Studio 2013. + +-#if defined(_DEBUG) && defined(ANGLE_ENABLE_WINDOWS_STORE) ++#if defined(_DEBUG) && defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP) + // In the Windows Store, we can use IDXGraphicsAnalysis. The call to GetDebugInterface1 only succeeds if the app is under capture. + // This should only be called in DEBUG mode. + // If an app links against DXGIGetDebugInterface1 in release mode then it will fail Windows Store ingestion checks. +diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow.h +index ce50c32..81b9ea7 100644 +--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow.h ++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow.h +@@ -49,11 +49,15 @@ namespace rx + class NativeWindow + { + public: ++ enum RotationFlags { RotateNone = 0, RotateLeft = 1, RotateRight = 2 }; + explicit NativeWindow(EGLNativeWindowType window); + + bool initialize(); + bool getClientRect(LPRECT rect); + bool isIconic(); ++#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) ++ RotationFlags rotationFlags() const; ++#endif + static bool isValidNativeWindow(EGLNativeWindowType window); + + HRESULT createSwapChain(ID3D11Device* device, DXGIFactory* factory, +diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp +index eba40a4..dbed23f 100644 +--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp ++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp +@@ -230,7 +230,11 @@ Renderer11::Renderer11(egl::Display *display) + } + } + ++#if defined(ANGLE_ENABLE_WINDOWS_STORE) ++ if (requestedMajorVersion == EGL_DONT_CARE || requestedMajorVersion >= 9) ++#else + if (requestedMajorVersion == 9 && requestedMinorVersion == 3) ++#endif + { + mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_3); + } +@@ -587,10 +591,10 @@ egl::ConfigSet Renderer11::generateConfigs() const + config.bindToTextureRGB = (colorBufferFormatInfo.format == GL_RGB); + config.bindToTextureRGBA = (colorBufferFormatInfo.format == GL_RGBA || colorBufferFormatInfo.format == GL_BGRA_EXT); + config.colorBufferType = EGL_RGB_BUFFER; +- config.configCaveat = EGL_NONE; + config.configID = static_cast(configs.size() + 1); + // Can only support a conformant ES2 with feature level greater than 10.0. + config.conformant = (mFeatureLevel >= D3D_FEATURE_LEVEL_10_0) ? (EGL_OPENGL_ES2_BIT | EGL_OPENGL_ES3_BIT_KHR) : EGL_NONE; ++ config.configCaveat = config.conformant == EGL_NONE ? EGL_NON_CONFORMANT_CONFIG : EGL_NONE; + config.depthSize = depthStencilBufferFormatInfo.depthBits; + config.level = 0; + config.matchNativePixmap = EGL_NONE; +@@ -2290,7 +2294,7 @@ bool Renderer11::getShareHandleSupport() const + // chrome needs BGRA. Once chrome fixes this, we should always support them. + // PIX doesn't seem to support using share handles, so disable them. + // Also disable share handles on Feature Level 9_3, since it doesn't support share handles on RGBA8 textures/swapchains. +- return getRendererExtensions().textureFormatBGRA8888 && !gl::DebugAnnotationsActive() && !(mFeatureLevel <= D3D_FEATURE_LEVEL_9_3); ++ return getRendererExtensions().textureFormatBGRA8888 && !gl::DebugAnnotationsActive();// && !(mFeatureLevel <= D3D_FEATURE_LEVEL_9_3); Qt: we don't care about the 9_3 limitation + } + + bool Renderer11::getPostSubBufferSupport() const +diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp +index 2558528..bcb2505 100644 +--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp ++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp +@@ -154,8 +154,14 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei + const bool useSharedResource = !mNativeWindow.getNativeWindow() && mRenderer->getShareHandleSupport(); + + D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0}; ++#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) ++ const int textureLength = std::max(backbufferWidth, backbufferHeight); ++ offscreenTextureDesc.Width = textureLength; ++ offscreenTextureDesc.Height = textureLength; ++#else + offscreenTextureDesc.Width = backbufferWidth; + offscreenTextureDesc.Height = backbufferHeight; ++#endif + offscreenTextureDesc.Format = backbufferFormatInfo.texFormat; + offscreenTextureDesc.MipLevels = 1; + offscreenTextureDesc.ArraySize = 1; +@@ -235,8 +241,14 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei + if (mDepthBufferFormat != GL_NONE) + { + D3D11_TEXTURE2D_DESC depthStencilTextureDesc; ++#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) ++ const int textureLength = std::max(backbufferWidth, backbufferHeight); ++ depthStencilTextureDesc.Width = textureLength; ++ depthStencilTextureDesc.Height = textureLength; ++#else + depthStencilTextureDesc.Width = backbufferWidth; + depthStencilTextureDesc.Height = backbufferHeight; ++#endif + depthStencilTextureDesc.Format = depthBufferFormatInfo.texFormat; + depthStencilTextureDesc.MipLevels = 1; + depthStencilTextureDesc.ArraySize = 1; +@@ -337,6 +349,7 @@ EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight) + return EGL_SUCCESS; + } + ++#if !defined(ANGLE_ENABLE_WINDOWS_STORE) || (WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP) + // Can only call resize if we have already created our swap buffer and resources + ASSERT(mSwapChain && mBackBufferTexture && mBackBufferRTView); + +@@ -379,6 +392,12 @@ EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight) + } + + return resetOffscreenTexture(backbufferWidth, backbufferHeight); ++#else ++ // Do nothing on Windows Phone apart from updating the internal buffer/width height ++ mWidth = backbufferWidth; ++ mHeight = backbufferHeight; ++ return EGL_SUCCESS; ++#endif + } + + EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swapInterval) +@@ -539,6 +558,21 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) + float x2 = ((x + width) / float(mWidth)) * 2.0f - 1.0f; + float y2 = ((y + height) / float(mHeight)) * 2.0f - 1.0f; + ++#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) ++ const float dim = std::max(mWidth, mHeight); ++ float u1 = x / dim; ++ float v1 = y / dim; ++ float u2 = (x + width) / dim; ++ float v2 = (y + height) / dim; ++ ++ const NativeWindow::RotationFlags flags = mNativeWindow.rotationFlags(); ++ const bool rotateL = flags == NativeWindow::RotateLeft; ++ const bool rotateR = flags == NativeWindow::RotateRight; ++ d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, rotateL ? u2 : u1, rotateR ? v2 : v1); ++ d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, rotateR ? u2 : u1, rotateL ? v1 : v2); ++ d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, rotateR ? u1 : u2, rotateL ? v2 : v1); ++ d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, rotateL ? u1 : u2, rotateR ? v1 : v2); ++#else + float u1 = x / float(mWidth); + float v1 = y / float(mHeight); + float u2 = (x + width) / float(mWidth); +@@ -548,6 +582,7 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) + d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, u1, v2); + d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, u2, v1); + d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, u2, v2); ++#endif + + deviceContext->Unmap(mQuadVB, 0); + +@@ -577,8 +612,13 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) + D3D11_VIEWPORT viewport; + viewport.TopLeftX = 0; + viewport.TopLeftY = 0; ++#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) ++ viewport.Width = (rotateL || rotateR) ? mHeight : mWidth; ++ viewport.Height = (rotateL || rotateR) ? mWidth : mHeight; ++#else + viewport.Width = mWidth; + viewport.Height = mHeight; ++#endif + viewport.MinDepth = 0.0f; + viewport.MaxDepth = 1.0f; + deviceContext->RSSetViewports(1, &viewport); +diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp +index 8cfaa84..350526c 100644 +--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp ++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp +@@ -8,8 +8,6 @@ + + #include "libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h" + +-#include +- + using namespace ABI::Windows::Foundation::Collections; + + namespace rx +@@ -21,6 +19,7 @@ CoreWindowNativeWindow::~CoreWindowNativeWindow() + + bool CoreWindowNativeWindow::initialize(EGLNativeWindowType window, IPropertySet *propertySet) + { ++ mOrientationChangedEventToken.value = 0; + ComPtr props = propertySet; + ComPtr win = window; + SIZE swapChainSize = {}; +@@ -68,6 +67,16 @@ bool CoreWindowNativeWindow::initialize(EGLNativeWindowType window, IPropertySet + + if (SUCCEEDED(result)) + { ++ ComPtr displayInformation; ++ result = GetActivationFactory(HStringReference(RuntimeClass_Windows_Graphics_Display_DisplayInformation).Get(), &displayInformation); ++ if (SUCCEEDED(result)) ++ { ++ result = displayInformation->GetForCurrentView(&mDisplayInformation); ++ } ++ } ++ ++ if (SUCCEEDED(result)) ++ { + mNewClientRect = mClientRect; + mClientRectChanged = false; + return registerForSizeChangeEvents(); +@@ -85,6 +94,15 @@ bool CoreWindowNativeWindow::registerForSizeChangeEvents() + result = mCoreWindow->add_SizeChanged(sizeChangedHandler.Get(), &mSizeChangedEventToken); + } + ++#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) ++ ComPtr orientationChangedHandler; ++ result = sizeChangedHandler.As(&orientationChangedHandler); ++ if (SUCCEEDED(result)) ++ { ++ result = mDisplayInformation->add_OrientationChanged(orientationChangedHandler.Get(), &mOrientationChangedEventToken); ++ } ++#endif ++ + if (SUCCEEDED(result)) + { + return true; +@@ -99,7 +117,14 @@ void CoreWindowNativeWindow::unregisterForSizeChangeEvents() + { + (void)mCoreWindow->remove_SizeChanged(mSizeChangedEventToken); + } ++#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) ++ if (mDisplayInformation) ++ { ++ (void)mDisplayInformation->remove_OrientationChanged(mOrientationChangedEventToken); ++ } ++#endif + mSizeChangedEventToken.value = 0; ++ mOrientationChangedEventToken.value = 0; + } + + HRESULT CoreWindowNativeWindow::createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain) +@@ -128,7 +153,7 @@ HRESULT CoreWindowNativeWindow::createSwapChain(ID3D11Device *device, DXGIFactor + if (SUCCEEDED(result)) + { + +-#if (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) ++#if 0 //(WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) // Qt: allow Windows Phone to resize, but don't modify the backing texture in the swap chain. + // Test if swapchain supports resize. On Windows Phone devices, this will return DXGI_ERROR_UNSUPPORTED. On + // other devices DXGI_ERROR_INVALID_CALL should be returned because the combination of flags passed + // (DXGI_SWAP_CHAIN_FLAG_NONPREROTATED | DXGI_SWAP_CHAIN_FLAG_GDI_COMPATIBLE) are invalid flag combinations. +diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h +index c230c84..59df9d5 100644 +--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h ++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h +@@ -12,8 +12,10 @@ + #include "libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h" + + #include ++#include + + typedef ABI::Windows::Foundation::__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CWindowSizeChangedEventArgs_t IWindowSizeChangedEventHandler; ++typedef ABI::Windows::Foundation::__FITypedEventHandler_2_Windows__CGraphics__CDisplay__CDisplayInformation_IInspectable_t IDisplayOrientationEventHandler; + + namespace rx + { +@@ -32,11 +34,13 @@ class CoreWindowNativeWindow : public InspectableNativeWindow, public std::enabl + private: + ComPtr mCoreWindow; + ComPtr> mPropertyMap; ++ ComPtr mDisplayInformation; ++ EventRegistrationToken mOrientationChangedEventToken; + }; + + [uuid(7F924F66-EBAE-40E5-A10B-B8F35E245190)] + class CoreWindowSizeChangedHandler : +- public Microsoft::WRL::RuntimeClass, IWindowSizeChangedEventHandler> ++ public Microsoft::WRL::RuntimeClass, IWindowSizeChangedEventHandler, IDisplayOrientationEventHandler> + { + public: + CoreWindowSizeChangedHandler() { } +@@ -68,6 +72,34 @@ class CoreWindowSizeChangedHandler : + return S_OK; + } + ++ IFACEMETHOD(Invoke)(ABI::Windows::Graphics::Display::IDisplayInformation *displayInformation, IInspectable *) ++ { ++#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) ++ NativeWindow::RotationFlags flags = NativeWindow::RotateNone; ++ ABI::Windows::Graphics::Display::DisplayOrientations orientation; ++ if (SUCCEEDED(displayInformation->get_CurrentOrientation(&orientation))) ++ { ++ switch (orientation) ++ { ++ case ABI::Windows::Graphics::Display::DisplayOrientations_Landscape: ++ flags = NativeWindow::RotateLeft; ++ break; ++ case ABI::Windows::Graphics::Display::DisplayOrientations_LandscapeFlipped: ++ flags = NativeWindow::RotateRight; ++ break; ++ default: ++ break; ++ } ++ } ++ std::shared_ptr host = mHost.lock(); ++ if (host) ++ { ++ host->setRotationFlags(flags); ++ } ++#endif ++ return S_OK; ++ } ++ + private: + std::weak_ptr mHost; + }; +diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.cpp +index 7ac53c7..2bf48c5 100644 +--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.cpp ++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.cpp +@@ -69,6 +69,18 @@ bool NativeWindow::getClientRect(RECT *rect) + return false; + } + ++#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) ++NativeWindow::RotationFlags NativeWindow::rotationFlags() const ++{ ++ if (mImpl) ++ { ++ return mImpl->rotationFlags(); ++ } ++ ++ return NativeWindow::RotateNone; ++} ++#endif ++ + bool NativeWindow::isIconic() + { + return false; +diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h +index e89c900..575bdf8 100644 +--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h ++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h +@@ -34,7 +34,8 @@ class InspectableNativeWindow + mRequiresSwapChainScaling(false), + mClientRectChanged(false), + mClientRect({0,0,0,0}), +- mNewClientRect({0,0,0,0}) ++ mNewClientRect({0,0,0,0}), ++ mRotationFlags(NativeWindow::RotateNone) + { + mSizeChangedEventToken.value = 0; + } +@@ -72,12 +73,23 @@ class InspectableNativeWindow + } + } + ++ NativeWindow::RotationFlags rotationFlags() const ++ { ++ return mRotationFlags; ++ } ++ ++ void setRotationFlags(NativeWindow::RotationFlags flags) ++ { ++ mRotationFlags = flags; ++ } ++ + protected: + bool mSupportsSwapChainResize; + bool mRequiresSwapChainScaling; + RECT mClientRect; + RECT mNewClientRect; + bool mClientRectChanged; ++ NativeWindow::RotationFlags mRotationFlags; + + EventRegistrationToken mSizeChangedEventToken; + }; +diff --git a/src/3rdparty/angle/src/libANGLE/validationEGL.cpp b/src/3rdparty/angle/src/libANGLE/validationEGL.cpp +index 4e3b44b..12ee6a2 100644 +--- a/src/3rdparty/angle/src/libANGLE/validationEGL.cpp ++++ b/src/3rdparty/angle/src/libANGLE/validationEGL.cpp +@@ -160,7 +160,7 @@ Error ValidateCreateContext(Display *display, Config *configuration, gl::Context + return Error(EGL_BAD_CONFIG); + } + +- if (clientMajorVersion == 3 && !(configuration->conformant & EGL_OPENGL_ES3_BIT_KHR)) ++ if (clientMajorVersion == 3 && !(configuration->conformant & EGL_OPENGL_ES3_BIT_KHR) && !(configuration->configCaveat & EGL_NON_CONFORMANT_CONFIG)) + { + return Error(EGL_BAD_CONFIG); + } +@@ -488,11 +488,13 @@ Error ValidateCreatePbufferFromClientBuffer(Display *display, EGLenum buftype, E + return Error(EGL_BAD_ATTRIBUTE); + } + ++#if !defined(ANGLE_ENABLE_WINDOWS_STORE) // On Windows Store, we know the originating texture came from D3D11, so bypass this check + const Caps &caps = display->getCaps(); + if (textureFormat != EGL_NO_TEXTURE && !caps.textureNPOT && (!gl::isPow2(width) || !gl::isPow2(height))) + { + return Error(EGL_BAD_MATCH); + } ++#endif + } + + return Error(EGL_SUCCESS); +-- +2.1.4 + diff --git a/src/angle/patches/0002-ANGLE-Fix-compilation-with-MinGW.patch b/src/angle/patches/0002-ANGLE-Fix-compilation-with-MinGW.patch new file mode 100644 index 0000000000..e28bc797e3 --- /dev/null +++ b/src/angle/patches/0002-ANGLE-Fix-compilation-with-MinGW.patch @@ -0,0 +1,927 @@ +From 6f98a957829fd37106fb1f1c9f43a5bad626cdfc Mon Sep 17 00:00:00 2001 +From: Andrew Knight +Date: Wed, 25 Mar 2015 20:21:33 +0200 +Subject: [PATCH 2/5] ANGLE: Fix compilation with MinGW + +This adds definition guards for Direct3D 11 and DirectX SDK layers, which +are only available in very recent versions (4.9.2 rev 4) of MinGW builds. +It additionally adds a few missing includes needed for compilation. + +Change-Id: I254c208209c0071fae5efb6727f2b3cfd5542da6 +--- + src/3rdparty/angle/src/common/mathutil.h | 4 + + src/3rdparty/angle/src/common/platform.h | 10 +- + src/3rdparty/angle/src/libANGLE/angletypes.h | 1 + + .../src/libANGLE/renderer/d3d/HLSLCompiler.cpp | 9 ++ + .../src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp | 6 + + .../src/libANGLE/renderer/d3d/d3d11/Clear11.cpp | 4 + + .../renderer/d3d/d3d11/DebugAnnotator11.cpp | 10 ++ + .../libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h | 2 + + .../src/libANGLE/renderer/d3d/d3d11/Query11.cpp | 7 + + .../src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp | 83 +++++++++-- + .../src/libANGLE/renderer/d3d/d3d11/Renderer11.h | 3 +- + .../renderer/d3d/d3d11/renderer11_utils.cpp | 152 +++++++++++++++++++++ + .../src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp | 4 +- + 13 files changed, 283 insertions(+), 12 deletions(-) + +diff --git a/src/3rdparty/angle/src/common/mathutil.h b/src/3rdparty/angle/src/common/mathutil.h +index e096b1a..1015bd2 100644 +--- a/src/3rdparty/angle/src/common/mathutil.h ++++ b/src/3rdparty/angle/src/common/mathutil.h +@@ -119,6 +119,9 @@ inline bool supportsSSE2() + return supports; + } + ++#if defined(__GNUC__) ++ supports = __builtin_cpu_supports("sse2"); ++#else + int info[4]; + __cpuid(info, 0); + +@@ -128,6 +131,7 @@ inline bool supportsSSE2() + + supports = (info[3] >> 26) & 1; + } ++#endif + + checked = true; + +diff --git a/src/3rdparty/angle/src/common/platform.h b/src/3rdparty/angle/src/common/platform.h +index 4e3851c..be4cb94 100644 +--- a/src/3rdparty/angle/src/common/platform.h ++++ b/src/3rdparty/angle/src/common/platform.h +@@ -59,9 +59,17 @@ + # if defined(ANGLE_ENABLE_D3D11) + # include + # include +-# include + # include ++# if defined(__MINGW32__) && !defined(__d3d11sdklayers_h__) ++# define ANGLE_MINGW32_COMPAT ++# endif ++# if defined(_MSC_VER) && _MSC_VER >= 1800 ++# define ANGLE_ENABLE_D3D11_1 ++# endif ++# if defined(ANGLE_ENABLE_D3D11_1) ++# include + # include ++# endif + # include + # endif + +diff --git a/src/3rdparty/angle/src/libANGLE/angletypes.h b/src/3rdparty/angle/src/libANGLE/angletypes.h +index a5f471d..e4e08b5 100644 +--- a/src/3rdparty/angle/src/libANGLE/angletypes.h ++++ b/src/3rdparty/angle/src/libANGLE/angletypes.h +@@ -13,6 +13,7 @@ + #include "libANGLE/RefCountObject.h" + + #include ++#include + + namespace gl + { +diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp +index d709dca..9c72d6f 100644 +--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp ++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp +@@ -22,6 +22,15 @@ namespace + + #define CREATE_COMPILER_FLAG_INFO(flag) { flag, #flag } + ++#if defined(ANGLE_MINGW32_COMPAT) ++#ifndef D3DCOMPILE_RESERVED16 ++#define D3DCOMPILE_RESERVED16 0x10000 ++#endif ++#ifndef D3DCOMPILE_RESERVED17 ++#define D3DCOMPILE_RESERVED17 0x20000 ++#endif ++#endif ++ + struct CompilerFlagInfo + { + UINT mFlag; +diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp +index 3b36c64..d56b0ea 100644 +--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp ++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp +@@ -12,6 +12,12 @@ + #include "libANGLE/renderer/d3d/d3d11/Renderer11.h" + #include "libANGLE/renderer/d3d/d3d11/formatutils11.h" + ++#if defined(ANGLE_MINGW32_COMPAT) ++typedef enum D3D11_MAP_FLAG { ++ D3D11_MAP_FLAG_DO_NOT_WAIT = 0x100000 ++} D3D11_MAP_FLAG; ++#endif ++ + namespace rx + { + +diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp +index ae373f5..057c3be 100644 +--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp ++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp +@@ -133,12 +133,14 @@ Clear11::Clear11(Renderer11 *renderer) + mIntClearShader = CreateClearShader(device, DXGI_FORMAT_R32G32B32A32_SINT, g_VS_ClearSint, g_PS_ClearSint ); + } + ++#if defined(ANGLE_ENABLE_D3D11_1) + if (renderer->getDeviceContext1IfSupported()) + { + D3D11_FEATURE_DATA_D3D11_OPTIONS d3d11Options; + device->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS, &d3d11Options, sizeof(D3D11_FEATURE_DATA_D3D11_OPTIONS)); + mSupportsClearView = (d3d11Options.ClearView != FALSE); + } ++#endif + } + + Clear11::~Clear11() +@@ -321,6 +323,7 @@ gl::Error Clear11::clearFramebuffer(const ClearParameters &clearParams, const gl + + if (needScissoredClear) + { ++#if defined(ANGLE_ENABLE_D3D11_1) + // We shouldn't reach here if deviceContext1 is unavailable. + ASSERT(deviceContext1); + +@@ -331,6 +334,7 @@ gl::Error Clear11::clearFramebuffer(const ClearParameters &clearParams, const gl + rect.bottom = clearParams.scissor.y + clearParams.scissor.height; + + deviceContext1->ClearView(framebufferRTV, clearValues, &rect, 1); ++#endif + } + else + { +diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp +index fcca904..f1fe2bb 100644 +--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp ++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp +@@ -27,7 +27,9 @@ DebugAnnotator11::~DebugAnnotator11() + { + if (mInitialized) + { ++#if defined(ANGLE_ENABLE_D3D11_1) + SafeRelease(mUserDefinedAnnotation); ++#endif + + #if !defined(ANGLE_ENABLE_WINDOWS_STORE) + FreeLibrary(mD3d11Module); +@@ -39,21 +41,27 @@ void DebugAnnotator11::beginEvent(const std::wstring &eventName) + { + initializeDevice(); + ++#if defined(ANGLE_ENABLE_D3D11_1) + mUserDefinedAnnotation->BeginEvent(eventName.c_str()); ++#endif + } + + void DebugAnnotator11::endEvent() + { + initializeDevice(); + ++#if defined(ANGLE_ENABLE_D3D11_1) + mUserDefinedAnnotation->EndEvent(); ++#endif + } + + void DebugAnnotator11::setMarker(const std::wstring &markerName) + { + initializeDevice(); + ++#if defined(ANGLE_ENABLE_D3D11_1) + mUserDefinedAnnotation->SetMarker(markerName.c_str()); ++#endif + } + + bool DebugAnnotator11::getStatus() +@@ -96,8 +104,10 @@ void DebugAnnotator11::initializeDevice() + hr = D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_NULL, nullptr, 0, nullptr, 0, D3D11_SDK_VERSION, &device, nullptr, &context); + ASSERT(SUCCEEDED(hr)); + ++#if defined(ANGLE_ENABLE_D3D11_1) + mUserDefinedAnnotation = d3d11::DynamicCastComObject(context); + ASSERT(mUserDefinedAnnotation != nullptr); ++#endif + + SafeRelease(device); + SafeRelease(context); +diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h +index 0638364..3df62b0 100644 +--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h ++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h +@@ -11,6 +11,8 @@ + + #include "common/debug.h" + ++struct ID3DUserDefinedAnnotation; ++ + namespace rx + { + +diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Query11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Query11.cpp +index e010190..4979ff5 100644 +--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Query11.cpp ++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Query11.cpp +@@ -13,6 +13,13 @@ + + #include + ++#if defined(ANGLE_MINGW32_COMPAT) ++typedef struct D3D11_QUERY_DATA_SO_STATISTICS { ++ UINT64 NumPrimitivesWritten; ++ UINT64 PrimitivesStorageNeeded; ++} D3D11_QUERY_DATA_SO_STATISTICS; ++#endif ++ + namespace rx + { + +diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp +index dbed23f..5291a3a 100644 +--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp ++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp +@@ -62,6 +62,67 @@ + #define ANGLE_SUPPRESS_D3D11_HAZARD_WARNINGS 1 + #endif + ++#ifndef __d3d11sdklayers_h__ ++#define D3D11_MESSAGE_CATEGORY UINT ++#define D3D11_MESSAGE_SEVERITY UINT ++#define D3D11_MESSAGE_ID UINT ++struct D3D11_MESSAGE; ++typedef struct D3D11_INFO_QUEUE_FILTER_DESC ++{ ++ UINT NumCategories; ++ D3D11_MESSAGE_CATEGORY *pCategoryList; ++ UINT NumSeverities; ++ D3D11_MESSAGE_SEVERITY *pSeverityList; ++ UINT NumIDs; ++ D3D11_MESSAGE_ID *pIDList; ++} D3D11_INFO_QUEUE_FILTER_DESC; ++typedef struct D3D11_INFO_QUEUE_FILTER ++{ ++ D3D11_INFO_QUEUE_FILTER_DESC AllowList; ++ D3D11_INFO_QUEUE_FILTER_DESC DenyList; ++} D3D11_INFO_QUEUE_FILTER; ++static const IID IID_ID3D11InfoQueue = { 0x6543dbb6, 0x1b48, 0x42f5, 0xab, 0x82, 0xe9, 0x7e, 0xc7, 0x43, 0x26, 0xf6 }; ++MIDL_INTERFACE("6543dbb6-1b48-42f5-ab82-e97ec74326f6") ID3D11InfoQueue : public IUnknown ++{ ++public: ++ virtual HRESULT __stdcall SetMessageCountLimit(UINT64) = 0; ++ virtual void __stdcall ClearStoredMessages() = 0; ++ virtual HRESULT __stdcall GetMessage(UINT64, D3D11_MESSAGE *, SIZE_T *) = 0; ++ virtual UINT64 __stdcall GetNumMessagesAllowedByStorageFilter() = 0; ++ virtual UINT64 __stdcall GetNumMessagesDeniedByStorageFilter() = 0; ++ virtual UINT64 __stdcall GetNumStoredMessages() = 0; ++ virtual UINT64 __stdcall GetNumStoredMessagesAllowedByRetrievalFilter() = 0; ++ virtual UINT64 __stdcall GetNumMessagesDiscardedByMessageCountLimit() = 0; ++ virtual UINT64 __stdcall GetMessageCountLimit() = 0; ++ virtual HRESULT __stdcall AddStorageFilterEntries(D3D11_INFO_QUEUE_FILTER *) = 0; ++ virtual HRESULT __stdcall GetStorageFilter(D3D11_INFO_QUEUE_FILTER *, SIZE_T *) = 0; ++ virtual void __stdcall ClearStorageFilter() = 0; ++ virtual HRESULT __stdcall PushEmptyStorageFilter() = 0; ++ virtual HRESULT __stdcall PushCopyOfStorageFilter() = 0; ++ virtual HRESULT __stdcall PushStorageFilter(D3D11_INFO_QUEUE_FILTER *) = 0; ++ virtual void __stdcall PopStorageFilter() = 0; ++ virtual UINT __stdcall GetStorageFilterStackSize() = 0; ++ virtual HRESULT __stdcall AddRetrievalFilterEntries(D3D11_INFO_QUEUE_FILTER *) = 0; ++ virtual HRESULT __stdcall GetRetrievalFilter(D3D11_INFO_QUEUE_FILTER *, SIZE_T *) = 0; ++ virtual void __stdcall ClearRetrievalFilter() = 0; ++ virtual HRESULT __stdcall PushEmptyRetrievalFilter() = 0; ++ virtual HRESULT __stdcall PushCopyOfRetrievalFilter() = 0; ++ virtual HRESULT __stdcall PushRetrievalFilter(D3D11_INFO_QUEUE_FILTER *) = 0; ++ virtual void __stdcall PopRetrievalFilter() = 0; ++ virtual UINT __stdcall GetRetrievalFilterStackSize() = 0; ++ virtual HRESULT __stdcall AddMessage(D3D11_MESSAGE_CATEGORY, D3D11_MESSAGE_SEVERITY, D3D11_MESSAGE_ID, LPCSTR) = 0; ++ virtual HRESULT __stdcall AddApplicationMessage(D3D11_MESSAGE_SEVERITY, LPCSTR) = 0; ++ virtual HRESULT __stdcall SetBreakOnCategory(D3D11_MESSAGE_CATEGORY, BOOL) = 0; ++ virtual HRESULT __stdcall SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY, BOOL) = 0; ++ virtual HRESULT __stdcall SetBreakOnID(D3D11_MESSAGE_ID, BOOL) = 0; ++ virtual BOOL __stdcall GetBreakOnCategory(D3D11_MESSAGE_CATEGORY) = 0; ++ virtual BOOL __stdcall GetBreakOnSeverity(D3D11_MESSAGE_SEVERITY) = 0; ++ virtual BOOL __stdcall GetBreakOnID(D3D11_MESSAGE_ID) = 0; ++ virtual void __stdcall SetMuteDebugOutput(BOOL) = 0; ++ virtual BOOL __stdcall GetMuteDebugOutput() = 0; ++}; ++#endif ++ + namespace rx + { + +@@ -164,8 +225,7 @@ void CalculateConstantBufferParams(GLintptr offset, GLsizeiptr size, UINT *outFi + + Renderer11::Renderer11(egl::Display *display) + : RendererD3D(display), +- mStateCache(this), +- mDebug(nullptr) ++ mStateCache(this) + { + // Initialize global annotator + gl::InitializeDebugAnnotations(&mAnnotator); +@@ -398,7 +458,9 @@ egl::Error Renderer11::initialize() + // Cast the DeviceContext to a DeviceContext1. + // This could fail on Windows 7 without the Platform Update. + // Don't error in this case- just don't use mDeviceContext1. ++#if defined(ANGLE_ENABLE_D3D11_1) + mDeviceContext1 = d3d11::DynamicCastComObject(mDeviceContext); ++#endif + + IDXGIDevice *dxgiDevice = NULL; + result = mDevice->QueryInterface(__uuidof(IDXGIDevice), (void**)&dxgiDevice); +@@ -421,6 +483,7 @@ egl::Error Renderer11::initialize() + + SafeRelease(dxgiDevice); + ++#if defined(ANGLE_ENABLE_D3D11_1) + IDXGIAdapter2 *dxgiAdapter2 = d3d11::DynamicCastComObject(mDxgiAdapter); + + // On D3D_FEATURE_LEVEL_9_*, IDXGIAdapter::GetDesc returns "Software Adapter" for the description string. +@@ -447,6 +510,7 @@ egl::Error Renderer11::initialize() + } + + SafeRelease(dxgiAdapter2); ++#endif + + memset(mDescription, 0, sizeof(mDescription)); + wcstombs(mDescription, mAdapterDescription.Description, sizeof(mDescription) - 1); +@@ -463,7 +527,7 @@ egl::Error Renderer11::initialize() + // 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); ++ result = mDevice->QueryInterface(IID_ID3D11InfoQueue, (void **)&infoQueue); + + if (SUCCEEDED(result)) + { +@@ -481,10 +545,6 @@ egl::Error Renderer11::initialize() + } + #endif + +-#if !defined(NDEBUG) +- mDebug = d3d11::DynamicCastComObject(mDevice); +-#endif +- + initializeDevice(); + + return egl::Error(EGL_SUCCESS); +@@ -525,12 +585,14 @@ void Renderer11::initializeDevice() + + const gl::Caps &rendererCaps = getRendererCaps(); + ++#if defined(ANGLE_ENABLE_D3D11_1) + if (getDeviceContext1IfSupported()) + { + D3D11_FEATURE_DATA_D3D11_OPTIONS d3d11Options; + mDevice->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS, &d3d11Options, sizeof(D3D11_FEATURE_DATA_D3D11_OPTIONS)); + mSupportsConstantBufferOffsets = (d3d11Options.ConstantBufferOffsetting != FALSE); + } ++#endif + + mForceSetVertexSamplerStates.resize(rendererCaps.maxVertexTextureImageUnits); + mCurVertexSamplerStates.resize(rendererCaps.maxVertexTextureImageUnits); +@@ -853,6 +915,7 @@ gl::Error Renderer11::setUniformBuffers(const gl::Data &data, + mCurrentConstantBufferVSOffset[uniformBufferIndex] != uniformBufferOffset || + mCurrentConstantBufferVSSize[uniformBufferIndex] != uniformBufferSize) + { ++#if defined(ANGLE_ENABLE_D3D11_1) + if (mSupportsConstantBufferOffsets && uniformBufferSize != 0) + { + UINT firstConstant = 0, numConstants = 0; +@@ -861,6 +924,7 @@ gl::Error Renderer11::setUniformBuffers(const gl::Data &data, + 1, &constantBuffer, &firstConstant, &numConstants); + } + else ++#endif + { + ASSERT(uniformBufferOffset == 0); + mDeviceContext->VSSetConstantBuffers(getReservedVertexUniformBuffers() + uniformBufferIndex, +@@ -901,6 +965,7 @@ gl::Error Renderer11::setUniformBuffers(const gl::Data &data, + mCurrentConstantBufferPSOffset[uniformBufferIndex] != uniformBufferOffset || + mCurrentConstantBufferPSSize[uniformBufferIndex] != uniformBufferSize) + { ++#if defined(ANGLE_ENABLE_D3D11_1) + if (mSupportsConstantBufferOffsets && uniformBufferSize != 0) + { + UINT firstConstant = 0, numConstants = 0; +@@ -909,6 +974,7 @@ gl::Error Renderer11::setUniformBuffers(const gl::Data &data, + 1, &constantBuffer, &firstConstant, &numConstants); + } + else ++#endif + { + ASSERT(uniformBufferOffset == 0); + mDeviceContext->PSSetConstantBuffers(getReservedFragmentUniformBuffers() + uniformBufferIndex, +@@ -2194,7 +2260,9 @@ void Renderer11::release() + SafeRelease(mDxgiFactory); + SafeRelease(mDxgiAdapter); + ++#if defined(ANGLE_ENABLE_D3D11_1) + SafeRelease(mDeviceContext1); ++#endif + + if (mDeviceContext) + { +@@ -2204,7 +2272,6 @@ void Renderer11::release() + } + + SafeRelease(mDevice); +- SafeRelease(mDebug); + + if (mD3d11Module) + { +diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.h +index d1fec55..cc7d6c2 100644 +--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.h ++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.h +@@ -20,6 +20,8 @@ + #include "libANGLE/renderer/d3d/d3d11/InputLayoutCache.h" + #include "libANGLE/renderer/d3d/d3d11/RenderStateCache.h" + ++struct ID3D11DeviceContext1; ++ + namespace gl + { + class FramebufferAttachment; +@@ -390,7 +392,6 @@ class Renderer11 : public RendererD3D + DXGI_ADAPTER_DESC mAdapterDescription; + char mDescription[128]; + DXGIFactory *mDxgiFactory; +- ID3D11Debug *mDebug; + + DebugAnnotator11 mAnnotator; + }; +diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp +index 70b2b79..63085f4 100644 +--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp ++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp +@@ -20,6 +20,88 @@ + + #include + ++#ifndef D3D_FL9_1_DEFAULT_MAX_ANISOTROPY ++# define D3D_FL9_1_DEFAULT_MAX_ANISOTROPY 2 ++#endif ++#ifndef D3D_FL9_1_SIMULTANEOUS_RENDER_TARGET_COUNT ++# define D3D_FL9_1_SIMULTANEOUS_RENDER_TARGET_COUNT 1 ++#endif ++#ifndef D3D_FL9_3_SIMULTANEOUS_RENDER_TARGET_COUNT ++# define D3D_FL9_3_SIMULTANEOUS_RENDER_TARGET_COUNT 4 ++#endif ++#ifndef D3D_FL9_1_IA_PRIMITIVE_MAX_COUNT ++# define D3D_FL9_1_IA_PRIMITIVE_MAX_COUNT 65535 ++#endif ++#ifndef D3D_FL9_2_IA_PRIMITIVE_MAX_COUNT ++# define D3D_FL9_2_IA_PRIMITIVE_MAX_COUNT 1048575 ++#endif ++#ifndef D3D_FL9_1_REQ_TEXTURECUBE_DIMENSION ++# define D3D_FL9_1_REQ_TEXTURECUBE_DIMENSION 512 ++#endif ++#ifndef D3D_FL9_3_REQ_TEXTURECUBE_DIMENSION ++# define D3D_FL9_3_REQ_TEXTURECUBE_DIMENSION 4096 ++#endif ++#ifndef D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION ++# define D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION 2048 ++#endif ++#ifndef D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION ++# define D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION 256 ++#endif ++#ifndef D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION ++# define D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION 4096 ++#endif ++#ifndef D3D11_REQ_TEXTURECUBE_DIMENSION ++# define D3D11_REQ_TEXTURECUBE_DIMENSION 16384 ++#endif ++#ifndef D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION ++# define D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION 2048 ++#endif ++#ifndef D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION ++# define D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION 2048 ++#endif ++#ifndef D3D11_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP ++# define D3D11_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP 32 ++#endif ++#ifndef D3D11_REQ_DRAW_VERTEX_COUNT_2_TO_EXP ++# define D3D11_REQ_DRAW_VERTEX_COUNT_2_TO_EXP 32 ++#endif ++#ifndef D3D10_1_STANDARD_VERTEX_ELEMENT_COUNT ++# define D3D10_1_STANDARD_VERTEX_ELEMENT_COUNT 32 ++#endif ++#ifndef D3D11_STANDARD_VERTEX_ELEMENT_COUNT ++# define D3D11_STANDARD_VERTEX_ELEMENT_COUNT 32 ++#endif ++#ifndef D3D10_1_SO_BUFFER_SLOT_COUNT ++# define D3D10_1_SO_BUFFER_SLOT_COUNT 4 ++#endif ++#ifndef D3D11_SO_BUFFER_SLOT_COUNT ++# define D3D11_SO_BUFFER_SLOT_COUNT 4 ++#endif ++#ifndef D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT ++# define D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT 14 ++#endif ++#ifndef D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT ++# define D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT 16 ++#endif ++#ifndef D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE ++# define D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE -8 ++#endif ++#ifndef D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE ++# define D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE 7 ++#endif ++#ifndef D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT ++# define D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT 4096 ++#endif ++#ifndef D3D11_PS_INPUT_REGISTER_COUNT ++# define D3D11_PS_INPUT_REGISTER_COUNT 32 ++#endif ++#ifndef D3D10_1_VS_OUTPUT_REGISTER_COUNT ++# define D3D10_1_VS_OUTPUT_REGISTER_COUNT 32 ++#endif ++#if defined(ANGLE_MINGW32_COMPAT) ++static const IID WKPDID_D3DDebugObjectName = { 0x429b8c22, 0x9188, 0x4b0c, 0x87, 0x42, 0xac, 0xb0, 0xbf, 0x85, 0xc2, 0x00 }; ++#endif ++ + namespace rx + { + +@@ -232,7 +314,9 @@ GLint GetMaximumClientVersion(D3D_FEATURE_LEVEL featureLevel) + { + switch (featureLevel) + { ++#if defined(ANGLE_ENABLE_D3D11_1) + case D3D_FEATURE_LEVEL_11_1: ++#endif + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return 3; +@@ -298,7 +382,9 @@ static bool GetNPOTTextureSupport(D3D_FEATURE_LEVEL featureLevel) + { + switch (featureLevel) + { ++#if defined(ANGLE_ENABLE_D3D11_1) + case D3D_FEATURE_LEVEL_11_1: ++#endif + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return true; +@@ -316,7 +402,9 @@ static float GetMaximumAnisotropy(D3D_FEATURE_LEVEL featureLevel) + { + switch (featureLevel) + { ++#if defined(ANGLE_ENABLE_D3D11_1) + case D3D_FEATURE_LEVEL_11_1: ++#endif + case D3D_FEATURE_LEVEL_11_0: return D3D11_MAX_MAXANISOTROPY; + + case D3D_FEATURE_LEVEL_10_1: +@@ -336,7 +424,9 @@ static bool GetOcclusionQuerySupport(D3D_FEATURE_LEVEL featureLevel) + { + switch (featureLevel) + { ++#if defined(ANGLE_ENABLE_D3D11_1) + case D3D_FEATURE_LEVEL_11_1: ++#endif + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return true; +@@ -356,7 +446,9 @@ static bool GetEventQuerySupport(D3D_FEATURE_LEVEL featureLevel) + + switch (featureLevel) + { ++#if defined(ANGLE_ENABLE_D3D11_1) + case D3D_FEATURE_LEVEL_11_1: ++#endif + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: +@@ -374,7 +466,9 @@ static bool GetInstancingSupport(D3D_FEATURE_LEVEL featureLevel) + + switch (featureLevel) + { ++#if defined(ANGLE_ENABLE_D3D11_1) + case D3D_FEATURE_LEVEL_11_1: ++#endif + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return true; +@@ -397,7 +491,9 @@ static bool GetFramebufferMultisampleSupport(D3D_FEATURE_LEVEL featureLevel) + { + switch (featureLevel) + { ++#if defined(ANGLE_ENABLE_D3D11_1) + case D3D_FEATURE_LEVEL_11_1: ++#endif + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return true; +@@ -414,7 +510,9 @@ static bool GetFramebufferBlitSupport(D3D_FEATURE_LEVEL featureLevel) + { + switch (featureLevel) + { ++#if defined(ANGLE_ENABLE_D3D11_1) + case D3D_FEATURE_LEVEL_11_1: ++#endif + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return true; +@@ -437,7 +535,9 @@ static bool GetDerivativeInstructionSupport(D3D_FEATURE_LEVEL featureLevel) + + switch (featureLevel) + { ++#if defined(ANGLE_ENABLE_D3D11_1) + case D3D_FEATURE_LEVEL_11_1: ++#endif + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: +@@ -453,7 +553,9 @@ static bool GetShaderTextureLODSupport(D3D_FEATURE_LEVEL featureLevel) + { + switch (featureLevel) + { ++#if defined(ANGLE_ENABLE_D3D11_1) + case D3D_FEATURE_LEVEL_11_1: ++#endif + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return true; +@@ -472,7 +574,9 @@ static size_t GetMaximumSimultaneousRenderTargets(D3D_FEATURE_LEVEL featureLevel + + switch (featureLevel) + { ++#if defined(ANGLE_ENABLE_D3D11_1) + case D3D_FEATURE_LEVEL_11_1: ++#endif + case D3D_FEATURE_LEVEL_11_0: return D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; + + case D3D_FEATURE_LEVEL_10_1: +@@ -490,7 +594,9 @@ static size_t GetMaximum2DTextureSize(D3D_FEATURE_LEVEL featureLevel) + { + switch (featureLevel) + { ++#if defined(ANGLE_ENABLE_D3D11_1) + case D3D_FEATURE_LEVEL_11_1: ++#endif + case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; + + case D3D_FEATURE_LEVEL_10_1: +@@ -508,7 +614,9 @@ static size_t GetMaximumCubeMapTextureSize(D3D_FEATURE_LEVEL featureLevel) + { + switch (featureLevel) + { ++#if defined(ANGLE_ENABLE_D3D11_1) + case D3D_FEATURE_LEVEL_11_1: ++#endif + case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURECUBE_DIMENSION; + + case D3D_FEATURE_LEVEL_10_1: +@@ -526,7 +634,9 @@ static size_t GetMaximum2DTextureArraySize(D3D_FEATURE_LEVEL featureLevel) + { + switch (featureLevel) + { ++#if defined(ANGLE_ENABLE_D3D11_1) + case D3D_FEATURE_LEVEL_11_1: ++#endif + case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION; + + case D3D_FEATURE_LEVEL_10_1: +@@ -544,7 +654,9 @@ static size_t GetMaximum3DTextureSize(D3D_FEATURE_LEVEL featureLevel) + { + switch (featureLevel) + { ++#if defined(ANGLE_ENABLE_D3D11_1) + case D3D_FEATURE_LEVEL_11_1: ++#endif + case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION; + + case D3D_FEATURE_LEVEL_10_1: +@@ -562,7 +674,9 @@ static size_t GetMaximumViewportSize(D3D_FEATURE_LEVEL featureLevel) + { + switch (featureLevel) + { ++#if defined(ANGLE_ENABLE_D3D11_1) + case D3D_FEATURE_LEVEL_11_1: ++#endif + case D3D_FEATURE_LEVEL_11_0: return D3D11_VIEWPORT_BOUNDS_MAX; + + case D3D_FEATURE_LEVEL_10_1: +@@ -586,7 +700,9 @@ static size_t GetMaximumDrawIndexedIndexCount(D3D_FEATURE_LEVEL featureLevel) + + switch (featureLevel) + { ++#if defined(ANGLE_ENABLE_D3D11_1) + case D3D_FEATURE_LEVEL_11_1: ++#endif + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return std::numeric_limits::max(); +@@ -608,7 +724,9 @@ static size_t GetMaximumDrawVertexCount(D3D_FEATURE_LEVEL featureLevel) + + switch (featureLevel) + { ++#if defined(ANGLE_ENABLE_D3D11_1) + case D3D_FEATURE_LEVEL_11_1: ++#endif + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return std::numeric_limits::max(); +@@ -625,7 +743,9 @@ static size_t GetMaximumVertexInputSlots(D3D_FEATURE_LEVEL featureLevel) + { + switch (featureLevel) + { ++#if defined(ANGLE_ENABLE_D3D11_1) + case D3D_FEATURE_LEVEL_11_1: ++#endif + case D3D_FEATURE_LEVEL_11_0: return D3D11_STANDARD_VERTEX_ELEMENT_COUNT; + + case D3D_FEATURE_LEVEL_10_1: return D3D10_1_STANDARD_VERTEX_ELEMENT_COUNT; +@@ -645,7 +765,9 @@ static size_t GetMaximumVertexUniformVectors(D3D_FEATURE_LEVEL featureLevel) + // TODO(geofflang): Remove hard-coded limit once the gl-uniform-arrays test can pass + switch (featureLevel) + { ++#if defined(ANGLE_ENABLE_D3D11_1) + case D3D_FEATURE_LEVEL_11_1: ++#endif + case D3D_FEATURE_LEVEL_11_0: return 1024; // D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT; + + case D3D_FEATURE_LEVEL_10_1: +@@ -670,7 +792,9 @@ static size_t GetMaximumVertexUniformBlocks(D3D_FEATURE_LEVEL featureLevel) + { + switch (featureLevel) + { ++#if defined(ANGLE_ENABLE_D3D11_1) + case D3D_FEATURE_LEVEL_11_1: ++#endif + case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - GetReservedVertexUniformBuffers(); + + case D3D_FEATURE_LEVEL_10_1: +@@ -698,7 +822,9 @@ static size_t GetReservedVertexOutputVectors(D3D_FEATURE_LEVEL featureLevel) + // We must reserve one output vector for dx_Position. + // We also reserve one for gl_Position, which we unconditionally output on Feature Levels 10_0+, + // even if it's unused in the shader (e.g. for transform feedback). TODO: This could be improved. ++#if defined(ANGLE_ENABLE_D3D11_1) + case D3D_FEATURE_LEVEL_11_1: ++#endif + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return 2; +@@ -720,7 +846,9 @@ static size_t GetMaximumVertexOutputVectors(D3D_FEATURE_LEVEL featureLevel) + + switch (featureLevel) + { ++#if defined(ANGLE_ENABLE_D3D11_1) + case D3D_FEATURE_LEVEL_11_1: ++#endif + case D3D_FEATURE_LEVEL_11_0: return D3D11_VS_OUTPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(featureLevel); + + case D3D_FEATURE_LEVEL_10_1: return D3D10_1_VS_OUTPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(featureLevel); +@@ -739,7 +867,9 @@ static size_t GetMaximumVertexTextureUnits(D3D_FEATURE_LEVEL featureLevel) + { + switch (featureLevel) + { ++#if defined(ANGLE_ENABLE_D3D11_1) + case D3D_FEATURE_LEVEL_11_1: ++#endif + case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT; + + case D3D_FEATURE_LEVEL_10_1: +@@ -761,7 +891,9 @@ static size_t GetMaximumPixelUniformVectors(D3D_FEATURE_LEVEL featureLevel) + // TODO(geofflang): Remove hard-coded limit once the gl-uniform-arrays test can pass + switch (featureLevel) + { ++#if defined(ANGLE_ENABLE_D3D11_1) + case D3D_FEATURE_LEVEL_11_1: ++#endif + case D3D_FEATURE_LEVEL_11_0: return 1024; // D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT; + + case D3D_FEATURE_LEVEL_10_1: +@@ -786,7 +918,9 @@ static size_t GetMaximumPixelUniformBlocks(D3D_FEATURE_LEVEL featureLevel) + { + switch (featureLevel) + { ++#if defined(ANGLE_ENABLE_D3D11_1) + case D3D_FEATURE_LEVEL_11_1: ++#endif + case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - GetReservedPixelUniformBuffers(); + + case D3D_FEATURE_LEVEL_10_1: +@@ -805,7 +939,9 @@ static size_t GetMaximumPixelInputVectors(D3D_FEATURE_LEVEL featureLevel) + { + switch (featureLevel) + { ++#if defined(ANGLE_ENABLE_D3D11_1) + case D3D_FEATURE_LEVEL_11_1: ++#endif + case D3D_FEATURE_LEVEL_11_0: return D3D11_PS_INPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(featureLevel); + + case D3D_FEATURE_LEVEL_10_1: +@@ -824,7 +960,9 @@ static size_t GetMaximumPixelTextureUnits(D3D_FEATURE_LEVEL featureLevel) + { + switch (featureLevel) + { ++#if defined(ANGLE_ENABLE_D3D11_1) + case D3D_FEATURE_LEVEL_11_1: ++#endif + case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT; + + case D3D_FEATURE_LEVEL_10_1: +@@ -843,7 +981,9 @@ static int GetMinimumTexelOffset(D3D_FEATURE_LEVEL featureLevel) + { + switch (featureLevel) + { ++#if defined(ANGLE_ENABLE_D3D11_1) + case D3D_FEATURE_LEVEL_11_1: ++#endif + case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE; + + case D3D_FEATURE_LEVEL_10_1: +@@ -862,7 +1002,9 @@ static int GetMaximumTexelOffset(D3D_FEATURE_LEVEL featureLevel) + { + switch (featureLevel) + { ++#if defined(ANGLE_ENABLE_D3D11_1) + case D3D_FEATURE_LEVEL_11_1: ++#endif + case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE; + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE; +@@ -885,7 +1027,9 @@ static size_t GetMaximumConstantBufferSize(D3D_FEATURE_LEVEL featureLevel) + + switch (featureLevel) + { ++#if defined(ANGLE_ENABLE_D3D11_1) + case D3D_FEATURE_LEVEL_11_1: ++#endif + case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * bytesPerComponent; + + case D3D_FEATURE_LEVEL_10_1: +@@ -904,7 +1048,9 @@ static size_t GetMaximumStreamOutputBuffers(D3D_FEATURE_LEVEL featureLevel) + { + switch (featureLevel) + { ++#if defined(ANGLE_ENABLE_D3D11_1) + case D3D_FEATURE_LEVEL_11_1: ++#endif + case D3D_FEATURE_LEVEL_11_0: return D3D11_SO_BUFFER_SLOT_COUNT; + + case D3D_FEATURE_LEVEL_10_1: return D3D10_1_SO_BUFFER_SLOT_COUNT; +@@ -922,7 +1068,9 @@ static size_t GetMaximumStreamOutputInterleavedComponents(D3D_FEATURE_LEVEL feat + { + switch (featureLevel) + { ++#if defined(ANGLE_ENABLE_D3D11_1) + case D3D_FEATURE_LEVEL_11_1: ++#endif + case D3D_FEATURE_LEVEL_11_0: + + case D3D_FEATURE_LEVEL_10_1: +@@ -940,7 +1088,9 @@ static size_t GetMaximumStreamOutputSeparateComponents(D3D_FEATURE_LEVEL feature + { + switch (featureLevel) + { ++#if defined(ANGLE_ENABLE_D3D11_1) + case D3D_FEATURE_LEVEL_11_1: ++#endif + case D3D_FEATURE_LEVEL_11_0: return GetMaximumStreamOutputInterleavedComponents(featureLevel) / + GetMaximumStreamOutputBuffers(featureLevel); + +@@ -1054,6 +1204,7 @@ void GenerateCaps(ID3D11Device *device, ID3D11DeviceContext *deviceContext, gl:: + + // Setting a large alignment forces uniform buffers to bind with zero offset + caps->uniformBufferOffsetAlignment = static_cast(std::numeric_limits::max()); ++#if defined(ANGLE_ENABLE_D3D11_1) + ID3D11DeviceContext1 *deviceContext1 = d3d11::DynamicCastComObject(deviceContext); + + if (deviceContext1) +@@ -1070,6 +1221,7 @@ void GenerateCaps(ID3D11Device *device, ID3D11DeviceContext *deviceContext, gl:: + + SafeRelease(deviceContext1); + } ++#endif + + caps->maxCombinedUniformBlocks = caps->maxVertexUniformBlocks + caps->maxFragmentUniformBlocks; + caps->maxCombinedVertexUniformComponents = (static_cast(caps->maxVertexUniformBlocks) * static_cast(caps->maxUniformBlockSize / 4)) + +diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp +index c59808d..bf1c367 100644 +--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp ++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp +@@ -206,7 +206,7 @@ egl::Error Renderer9::initialize() + { + TRACE_EVENT0("gpu", "D3d9Ex_QueryInterface"); + ASSERT(mD3d9Ex); +- mD3d9Ex->QueryInterface(__uuidof(IDirect3D9), reinterpret_cast(&mD3d9)); ++ mD3d9Ex->QueryInterface(IID_IDirect3D9, reinterpret_cast(&mD3d9)); + ASSERT(mD3d9); + } + else +@@ -314,7 +314,7 @@ egl::Error Renderer9::initialize() + if (mD3d9Ex) + { + TRACE_EVENT0("gpu", "mDevice_QueryInterface"); +- result = mDevice->QueryInterface(__uuidof(IDirect3DDevice9Ex), (void**)&mDeviceEx); ++ result = mDevice->QueryInterface(IID_IDirect3DDevice9Ex, (void**)&mDeviceEx); + ASSERT(SUCCEEDED(result)); + } + +-- +2.1.4 + diff --git a/src/angle/patches/0003-ANGLE-Fix-compilation-on-MSVC2010-2012.patch b/src/angle/patches/0003-ANGLE-Fix-compilation-on-MSVC2010-2012.patch new file mode 100644 index 0000000000..62300e1e9b --- /dev/null +++ b/src/angle/patches/0003-ANGLE-Fix-compilation-on-MSVC2010-2012.patch @@ -0,0 +1,363 @@ +From 11304df7f66d0d8bc5dfdc960b86b5cac0f18313 Mon Sep 17 00:00:00 2001 +From: Andrew Knight +Date: Wed, 8 Apr 2015 17:09:47 +0300 +Subject: [PATCH 3/5] ANGLE: Fix compilation on MSVC2010/2012 + +Allow the D3D11 renderer to build with the June 2010 DirectX SDK. +This mainly addresses C++11 language incompatibilities, such as replacing +range-based for loops with iterators. + +Change-Id: I2343acedab16845d6a0d4a53cf3145f583efc4a7 +--- + src/3rdparty/angle/src/common/angleutils.h | 2 ++ + src/3rdparty/angle/src/common/platform.h | 9 +++++++ + .../angle/src/compiler/translator/OutputHLSL.cpp | 31 +++++++++++++--------- + src/3rdparty/angle/src/libANGLE/Context.cpp | 4 +-- + src/3rdparty/angle/src/libANGLE/Error.h | 1 + + src/3rdparty/angle/src/libANGLE/Framebuffer.cpp | 23 ++++++++-------- + src/3rdparty/angle/src/libANGLE/State.cpp | 3 ++- + src/3rdparty/angle/src/libANGLE/Texture.cpp | 2 +- + .../angle/src/libANGLE/renderer/d3d/DisplayD3D.cpp | 6 +++-- + .../src/libANGLE/renderer/d3d/RendererD3D.cpp | 4 +-- + .../libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp | 3 ++- + 11 files changed, 55 insertions(+), 33 deletions(-) + +diff --git a/src/3rdparty/angle/src/common/angleutils.h b/src/3rdparty/angle/src/common/angleutils.h +index f3d2019..4cf84a3 100644 +--- a/src/3rdparty/angle/src/common/angleutils.h ++++ b/src/3rdparty/angle/src/common/angleutils.h +@@ -25,12 +25,14 @@ namespace angle + + class NonCopyable + { ++#if !defined(_MSC_VER) || (_MSC_VER >= 1800) + public: + NonCopyable() = default; + ~NonCopyable() = default; + protected: + NonCopyable(const NonCopyable&) = delete; + void operator=(const NonCopyable&) = delete; ++#endif + }; + + } +diff --git a/src/3rdparty/angle/src/common/platform.h b/src/3rdparty/angle/src/common/platform.h +index be4cb94..3a2aa91 100644 +--- a/src/3rdparty/angle/src/common/platform.h ++++ b/src/3rdparty/angle/src/common/platform.h +@@ -53,7 +53,9 @@ + + # if defined(ANGLE_ENABLE_D3D9) + # include ++# if !defined(ANGLE_TRANSLATOR_IMPLEMENTATION) + # include ++# endif + # endif + + # if defined(ANGLE_ENABLE_D3D11) +@@ -70,7 +72,9 @@ + # include + # include + # endif ++# if !defined(ANGLE_TRANSLATOR_IMPLEMENTATION) + # include ++# endif + # endif + + # if defined(ANGLE_ENABLE_WINDOWS_STORE) +@@ -83,6 +87,11 @@ + # endif + # endif + ++# if defined(_MSC_VER) && (_MSC_VER <= 1600) ++# define final ++# define override ++# endif ++ + # undef near + # undef far + #endif +diff --git a/src/3rdparty/angle/src/compiler/translator/OutputHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/OutputHLSL.cpp +index c3240f5..94225b8 100644 +--- a/src/3rdparty/angle/src/compiler/translator/OutputHLSL.cpp ++++ b/src/3rdparty/angle/src/compiler/translator/OutputHLSL.cpp +@@ -158,13 +158,13 @@ OutputHLSL::~OutputHLSL() + SafeDelete(mUnfoldShortCircuit); + SafeDelete(mStructureHLSL); + SafeDelete(mUniformHLSL); +- for (auto &eqFunction : mStructEqualityFunctions) ++ for (auto it = mStructEqualityFunctions.begin(); it != mStructEqualityFunctions.end(); ++it) + { +- SafeDelete(eqFunction); ++ SafeDelete(*it); + } +- for (auto &eqFunction : mArrayEqualityFunctions) ++ for (auto it = mArrayEqualityFunctions.begin(); it != mArrayEqualityFunctions.end(); ++it) + { +- SafeDelete(eqFunction); ++ SafeDelete(*it); + } + } + +@@ -340,17 +340,17 @@ void OutputHLSL::header(const BuiltInFunctionEmulator *builtInFunctionEmulator) + if (!mEqualityFunctions.empty()) + { + out << "\n// Equality functions\n\n"; +- for (const auto &eqFunction : mEqualityFunctions) ++ for (auto it = mEqualityFunctions.cbegin(); it != mEqualityFunctions.cend(); ++it) + { +- out << eqFunction->functionDefinition << "\n"; ++ out << (*it)->functionDefinition << "\n"; + } + } + if (!mArrayAssignmentFunctions.empty()) + { + out << "\n// Assignment functions\n\n"; +- for (const auto &assignmentFunction : mArrayAssignmentFunctions) ++ for (auto it = mArrayAssignmentFunctions.cbegin(); it != mArrayAssignmentFunctions.cend(); ++it) + { +- out << assignmentFunction.functionDefinition << "\n"; ++ out << it->functionDefinition << "\n"; + } + } + +@@ -1858,8 +1858,9 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) + + if (!variable->getAsSymbolNode() || variable->getAsSymbolNode()->getSymbol() != "") // Variable declaration + { +- for (const auto &seqElement : *sequence) ++ for (auto it = sequence->cbegin(); it != sequence->cend(); ++it) + { ++ const auto &seqElement = *it; + if (isSingleStatement(seqElement)) + { + mUnfoldShortCircuit->traverse(seqElement); +@@ -2941,8 +2942,9 @@ void OutputHLSL::writeDeferredGlobalInitializers(TInfoSinkBase &out) + << "void initializeDeferredGlobals()\n" + << "{\n"; + +- for (const auto &deferredGlobal : mDeferredGlobalInitializers) ++ for (auto it = mDeferredGlobalInitializers.cbegin(); it != mDeferredGlobalInitializers.cend(); ++it) + { ++ const auto &deferredGlobal = *it; + TIntermSymbol *symbol = deferredGlobal.first; + TIntermTyped *expression = deferredGlobal.second; + ASSERT(symbol); +@@ -2967,8 +2969,9 @@ TString OutputHLSL::addStructEqualityFunction(const TStructure &structure) + { + const TFieldList &fields = structure.fields(); + +- for (const auto &eqFunction : mStructEqualityFunctions) ++ for (auto it = mStructEqualityFunctions.cbegin(); it != mStructEqualityFunctions.cend(); ++it) + { ++ auto *eqFunction = *it; + if (eqFunction->structure == &structure) + { + return eqFunction->functionName; +@@ -3021,8 +3024,9 @@ TString OutputHLSL::addStructEqualityFunction(const TStructure &structure) + + TString OutputHLSL::addArrayEqualityFunction(const TType& type) + { +- for (const auto &eqFunction : mArrayEqualityFunctions) ++ for (auto it = mArrayEqualityFunctions.cbegin(); it != mArrayEqualityFunctions.cend(); ++it) + { ++ const auto &eqFunction = *it; + if (eqFunction->type == type) + { + return eqFunction->functionName; +@@ -3072,8 +3076,9 @@ TString OutputHLSL::addArrayEqualityFunction(const TType& type) + + TString OutputHLSL::addArrayAssignmentFunction(const TType& type) + { +- for (const auto &assignFunction : mArrayAssignmentFunctions) ++ for (auto it = mArrayAssignmentFunctions.cbegin(); it != mArrayAssignmentFunctions.cend(); ++it) + { ++ const auto &assignFunction = *it; + if (assignFunction.type == type) + { + return assignFunction.functionName; +diff --git a/src/3rdparty/angle/src/libANGLE/Context.cpp b/src/3rdparty/angle/src/libANGLE/Context.cpp +index 5ea039f..1da5fda 100644 +--- a/src/3rdparty/angle/src/libANGLE/Context.cpp ++++ b/src/3rdparty/angle/src/libANGLE/Context.cpp +@@ -158,9 +158,9 @@ Context::~Context() + deleteTransformFeedback(mTransformFeedbackMap.begin()->first); + } + +- for (auto &zeroTexture : mZeroTextures) ++ for (auto it = mZeroTextures.begin(); it != mZeroTextures.end(); ++it) + { +- zeroTexture.second.set(NULL); ++ it->second.set(NULL); + } + mZeroTextures.clear(); + +diff --git a/src/3rdparty/angle/src/libANGLE/Error.h b/src/3rdparty/angle/src/libANGLE/Error.h +index 5812943..896b777 100644 +--- a/src/3rdparty/angle/src/libANGLE/Error.h ++++ b/src/3rdparty/angle/src/libANGLE/Error.h +@@ -10,6 +10,7 @@ + #define LIBANGLE_ERROR_H_ + + #include "angle_gl.h" ++#include "common/platform.h" + #include + + #include +diff --git a/src/3rdparty/angle/src/libANGLE/Framebuffer.cpp b/src/3rdparty/angle/src/libANGLE/Framebuffer.cpp +index 5fa7513..b1dd4a1 100644 +--- a/src/3rdparty/angle/src/libANGLE/Framebuffer.cpp ++++ b/src/3rdparty/angle/src/libANGLE/Framebuffer.cpp +@@ -48,9 +48,9 @@ Framebuffer::Data::Data(const Caps &caps) + + Framebuffer::Data::~Data() + { +- for (auto &colorAttachment : mColorAttachments) ++ for (auto it = mColorAttachments.begin(); it != mColorAttachments.end(); ++it) + { +- SafeDelete(colorAttachment); ++ SafeDelete(*it); + } + SafeDelete(mDepthAttachment); + SafeDelete(mStencilAttachment); +@@ -66,11 +66,11 @@ FramebufferAttachment *Framebuffer::Data::getReadAttachment() const + + FramebufferAttachment *Framebuffer::Data::getFirstColorAttachment() const + { +- for (FramebufferAttachment *colorAttachment : mColorAttachments) ++ for (auto it = mColorAttachments.cbegin(); it != mColorAttachments.cend(); ++it) + { +- if (colorAttachment != nullptr) ++ if (*it != nullptr) + { +- return colorAttachment; ++ return *it; + } + } + +@@ -115,9 +115,9 @@ void Framebuffer::detachRenderbuffer(GLuint renderbufferId) + + void Framebuffer::detachResourceById(GLenum resourceType, GLuint resourceId) + { +- for (auto &colorAttachment : mData.mColorAttachments) ++ for (auto it = mData.mColorAttachments.begin(); it != mData.mColorAttachments.end(); ++it) + { +- DeleteMatchingAttachment(colorAttachment, resourceType, resourceId); ++ DeleteMatchingAttachment(*it, resourceType, resourceId); + } + + DeleteMatchingAttachment(mData.mDepthAttachment, resourceType, resourceId); +@@ -278,8 +278,9 @@ GLenum Framebuffer::checkStatus(const gl::Data &data) const + int samples = -1; + bool missingAttachment = true; + +- for (const FramebufferAttachment *colorAttachment : mData.mColorAttachments) ++ for (auto it = mData.mColorAttachments.cbegin(); it != mData.mColorAttachments.cend(); ++it) + { ++ const auto &colorAttachment = *it; + if (colorAttachment != nullptr) + { + if (colorAttachment->getWidth() == 0 || colorAttachment->getHeight() == 0) +@@ -533,11 +534,11 @@ int Framebuffer::getSamples(const gl::Data &data) const + { + // for a complete framebuffer, all attachments must have the same sample count + // in this case return the first nonzero sample size +- for (const FramebufferAttachment *colorAttachment : mData.mColorAttachments) ++ for (auto it = mData.mColorAttachments.cbegin(); it != mData.mColorAttachments.cend(); ++it) + { +- if (colorAttachment != nullptr) ++ if (*it != nullptr) + { +- return colorAttachment->getSamples(); ++ return (*it)->getSamples(); + } + } + } +diff --git a/src/3rdparty/angle/src/libANGLE/State.cpp b/src/3rdparty/angle/src/libANGLE/State.cpp +index 15274c6..4c044d2 100644 +--- a/src/3rdparty/angle/src/libANGLE/State.cpp ++++ b/src/3rdparty/angle/src/libANGLE/State.cpp +@@ -633,8 +633,9 @@ void State::detachTexture(const TextureMap &zeroTextures, GLuint texture) + + void State::initializeZeroTextures(const TextureMap &zeroTextures) + { +- for (const auto &zeroTexture : zeroTextures) ++ for (auto it = zeroTextures.cbegin(); it != zeroTextures.cend(); ++it) + { ++ const auto &zeroTexture = *it; + auto &samplerTextureArray = mSamplerTextures[zeroTexture.first]; + + for (size_t textureUnit = 0; textureUnit < samplerTextureArray.size(); ++textureUnit) +diff --git a/src/3rdparty/angle/src/libANGLE/Texture.cpp b/src/3rdparty/angle/src/libANGLE/Texture.cpp +index 2d68bec..cd4584f 100644 +--- a/src/3rdparty/angle/src/libANGLE/Texture.cpp ++++ b/src/3rdparty/angle/src/libANGLE/Texture.cpp +@@ -316,7 +316,7 @@ void Texture::setImageDescChain(size_t levels, Extents baseSize, GLenum sizedInt + } + + Texture::ImageDesc::ImageDesc() +- : ImageDesc(Extents(0, 0, 0), GL_NONE) ++ : size(0, 0, 0), internalFormat(GL_NONE) + { + } + +diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/DisplayD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/DisplayD3D.cpp +index db5f445..add5d62 100644 +--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/DisplayD3D.cpp ++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/DisplayD3D.cpp +@@ -276,8 +276,9 @@ bool DisplayD3D::testDeviceLost() + egl::Error DisplayD3D::restoreLostDevice() + { + // Release surface resources to make the Reset() succeed +- for (auto &surface : mSurfaceSet) ++ for (auto it = mSurfaceSet.cbegin(); it != mSurfaceSet.cend(); ++it) + { ++ const auto &surface = *it; + if (surface->getBoundTexture()) + { + surface->releaseTexImage(EGL_BACK_BUFFER); +@@ -292,8 +293,9 @@ egl::Error DisplayD3D::restoreLostDevice() + } + + // Restore any surfaces that may have been lost +- for (const auto &surface : mSurfaceSet) ++ for (auto it = mSurfaceSet.cbegin(); it != mSurfaceSet.cend(); ++it) + { ++ const auto &surface = *it; + SurfaceD3D *surfaceD3D = GetImplAs(surface); + + egl::Error error = surfaceD3D->resetSwapChain(); +diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/RendererD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/RendererD3D.cpp +index ff9600e..2ce0ce5 100644 +--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/RendererD3D.cpp ++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/RendererD3D.cpp +@@ -47,9 +47,9 @@ RendererD3D::~RendererD3D() + void RendererD3D::cleanup() + { + mScratchMemoryBuffer.resize(0); +- for (auto &incompleteTexture : mIncompleteTextures) ++ for (auto it = mIncompleteTextures.begin(); it != mIncompleteTextures.end(); ++it) + { +- incompleteTexture.second.set(NULL); ++ it->second.set(NULL); + } + mIncompleteTextures.clear(); + } +diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp +index ab2a902..da01f32 100644 +--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp ++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp +@@ -64,8 +64,9 @@ static gl::Error InvalidateAttachmentSwizzles(const gl::FramebufferAttachment *a + + gl::Error Framebuffer11::invalidateSwizzles() const + { +- for (gl::FramebufferAttachment *colorAttachment : mData.mColorAttachments) ++ for (auto it = mData.mColorAttachments.cbegin(); it != mData.mColorAttachments.cend(); ++it) + { ++ gl::FramebufferAttachment *colorAttachment = *it; + gl::Error error = InvalidateAttachmentSwizzles(colorAttachment); + if (error.isError()) + { +-- +2.1.4 + diff --git a/src/angle/patches/0004-ANGLE-Dynamically-load-D3D-compiler-from-a-list.patch b/src/angle/patches/0004-ANGLE-Dynamically-load-D3D-compiler-from-a-list.patch new file mode 100644 index 0000000000..ff93920317 --- /dev/null +++ b/src/angle/patches/0004-ANGLE-Dynamically-load-D3D-compiler-from-a-list.patch @@ -0,0 +1,61 @@ +From bbb62a69dd2b49d7cc4214937077c22b6997ffac Mon Sep 17 00:00:00 2001 +From: Andrew Knight +Date: Fri, 27 Mar 2015 17:27:38 +0200 +Subject: [PATCH 4/5] ANGLE: Dynamically load D3D compiler from a list + +If the default compiler cannot be found, load it from a list of DLL names, +including a non-versioned proxy DLL provided by Qt. On Desktop Windows, +the default compiler can also be specified by an environment variable, +QT_D3DCOMPILER_DLL. + +Change-Id: I0d7a8a8a36cc571836f8fa59ea14513b9b19c19b +--- + .../src/libANGLE/renderer/d3d/HLSLCompiler.cpp | 25 ++++++++++++++++++++++ + 1 file changed, 25 insertions(+) + +diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp +index 9c72d6f..8961a36 100644 +--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp ++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp +@@ -12,6 +12,10 @@ + + #include "third_party/trace_event/trace_event.h" + ++#ifndef QT_D3DCOMPILER_DLL ++#define QT_D3DCOMPILER_DLL D3DCOMPILER_DLL ++#endif ++ + // Definitions local to the translation unit + namespace + { +@@ -143,6 +147,27 @@ bool HLSLCompiler::initialize() + } + #endif // ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES + ++ // Load the compiler DLL specified by the environment, or default to QT_D3DCOMPILER_DLL ++ const wchar_t *defaultCompiler = _wgetenv(L"QT_D3DCOMPILER_DLL"); ++ if (!defaultCompiler) ++ defaultCompiler = QT_D3DCOMPILER_DLL; ++ ++ const wchar_t *compilerDlls[] = { ++ defaultCompiler, ++ L"d3dcompiler_47.dll", ++ L"d3dcompiler_46.dll", ++ L"d3dcompiler_43.dll", ++ 0 ++ }; ++ ++ // Load the first available known compiler DLL ++ for (int i = 0; compilerDlls[i]; ++i) ++ { ++ mD3DCompilerModule = LoadLibrary(compilerDlls[i]); ++ if (mD3DCompilerModule) ++ break; ++ } ++ + if (!mD3DCompilerModule) + { + // Load the version of the D3DCompiler DLL associated with the Direct3D version ANGLE was built with. +-- +2.1.4 + diff --git a/src/angle/patches/0004-Make-it-possible-to-link-ANGLE-statically-for-single.patch b/src/angle/patches/0004-Make-it-possible-to-link-ANGLE-statically-for-single.patch deleted file mode 100644 index 45a3f17cca..0000000000 --- a/src/angle/patches/0004-Make-it-possible-to-link-ANGLE-statically-for-single.patch +++ /dev/null @@ -1,109 +0,0 @@ -From 3a39939b5eba9f788789961c4800ba62618f758c Mon Sep 17 00:00:00 2001 -From: Friedemann Kleint -Date: Tue, 11 Nov 2014 10:26:32 +0200 -Subject: [PATCH 04/16] Make it possible to link ANGLE statically for - single-thread use. - -Fix exports and provide static instances of thread-local -data depending on QT_OPENGL_ES_2_ANGLE_STATIC. - -Change-Id: Ifab25a820adf5953bb3b09036de53dbf7f1a7fd5 ---- - src/3rdparty/angle/include/KHR/khrplatform.h | 2 +- - src/3rdparty/angle/src/libEGL/main.cpp | 10 ++++++++++ - src/3rdparty/angle/src/libGLESv2/main.cpp | 10 ++++++++-- - 3 files changed, 19 insertions(+), 3 deletions(-) - -diff --git a/src/3rdparty/angle/include/KHR/khrplatform.h b/src/3rdparty/angle/include/KHR/khrplatform.h -index c9e6f17..1ac2d3f 100644 ---- a/src/3rdparty/angle/include/KHR/khrplatform.h -+++ b/src/3rdparty/angle/include/KHR/khrplatform.h -@@ -97,7 +97,7 @@ - *------------------------------------------------------------------------- - * This precedes the return type of the function in the function prototype. - */ --#if defined(_WIN32) && !defined(__SCITECH_SNAP__) -+#if defined(_WIN32) && !defined(__SCITECH_SNAP__) && !defined(QT_OPENGL_ES_2_ANGLE_STATIC) - # define KHRONOS_APICALL __declspec(dllimport) - #elif defined (__SYMBIAN32__) - # define KHRONOS_APICALL IMPORT_C -diff --git a/src/3rdparty/angle/src/libEGL/main.cpp b/src/3rdparty/angle/src/libEGL/main.cpp -index d1489f2..e88cad7 100644 ---- a/src/3rdparty/angle/src/libEGL/main.cpp -+++ b/src/3rdparty/angle/src/libEGL/main.cpp -@@ -49,6 +49,8 @@ void DeallocateCurrent() - - } - -+#ifndef QT_OPENGL_ES_2_ANGLE_STATIC -+ - extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved) - { - switch (reason) -@@ -108,16 +110,24 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved - return TRUE; - } - -+#endif // !QT_OPENGL_ES_2_ANGLE_STATIC -+ - namespace egl - { - - Current *GetCurrentData() - { -+#ifndef QT_OPENGL_ES_2_ANGLE_STATIC - Current *current = reinterpret_cast(GetTLSValue(currentTLS)); - - // ANGLE issue 488: when the dll is loaded after thread initialization, - // thread local storage (current) might not exist yet. - return (current ? current : AllocateCurrent()); -+#else -+ // No precautions for thread safety taken as ANGLE is used single-threaded in Qt. -+ static Current current = { EGL_SUCCESS, EGL_OPENGL_ES_API, EGL_NO_DISPLAY, EGL_NO_SURFACE, EGL_NO_SURFACE }; -+ return ¤t; -+#endif - } - - void recordError(const Error &error) -diff --git a/src/3rdparty/angle/src/libGLESv2/main.cpp b/src/3rdparty/angle/src/libGLESv2/main.cpp -index 3ac00d5..00f63ae 100644 ---- a/src/3rdparty/angle/src/libGLESv2/main.cpp -+++ b/src/3rdparty/angle/src/libGLESv2/main.cpp -@@ -74,7 +74,7 @@ void DeallocateCurrent() - - } - --#ifdef ANGLE_PLATFORM_WINDOWS -+#if defined(ANGLE_PLATFORM_WINDOWS) && !defined(QT_OPENGL_ES_2_ANGLE_STATIC) - extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved) - { - switch (reason) -@@ -117,18 +117,24 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved - - return TRUE; - } --#endif -+#endif // ANGLE_PLATFORM_WINDOWS && !QT_OPENGL_ES_2_ANGLE_STATIC - - namespace gl - { - - Current *GetCurrentData() - { -+#ifndef QT_OPENGL_ES_2_ANGLE_STATIC - Current *current = reinterpret_cast(GetTLSValue(currentTLS)); - - // ANGLE issue 488: when the dll is loaded after thread initialization, - // thread local storage (current) might not exist yet. - return (current ? current : AllocateCurrent()); -+#else -+ // No precautions for thread safety taken as ANGLE is used single-threaded in Qt. -+ static Current current = { 0, 0 }; -+ return ¤t; -+#endif - } - - void makeCurrent(Context *context, egl::Display *display, egl::Surface *surface) --- -1.9.4.msysgit.1 - diff --git a/src/angle/patches/0005-ANGLE-Add-support-for-querying-platform-device.patch b/src/angle/patches/0005-ANGLE-Add-support-for-querying-platform-device.patch new file mode 100644 index 0000000000..8a5bffebe4 --- /dev/null +++ b/src/angle/patches/0005-ANGLE-Add-support-for-querying-platform-device.patch @@ -0,0 +1,84 @@ +From f6bfeecf2c7d14e9fd2b637e6ce9555489e3a256 Mon Sep 17 00:00:00 2001 +From: Andrew Knight +Date: Fri, 27 Mar 2015 17:58:41 +0200 +Subject: [PATCH 5/5] ANGLE: Add support for querying platform device + +The EGL_EXT_device_base extension allows for querying the platform +device of the graphics hardware via eglQueryDisplayAttribEXT(). +As that extension is not supported by ANGLE, this patch adds similar +functionality to the existing eglQuerySurfacePointerANGLE API. When +EGL_DEVICE_EXT is passed as the queried attribute, the underlying +D3D/DXGI device pointer is passed back to the caller via the value +argument. + +The D3D device is needed for video support in QtMultimedia as well as +the IDXGIDevice3::Trim() calls required by the Windows Store. + +Change-Id: Ibdf228d81d6604e56db9dd8597d7cd2983ebc428 +--- + src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp | 7 +++++-- + src/3rdparty/angle/src/libANGLE/renderer/d3d/SwapChainD3D.h | 1 + + src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp | 5 +++++ + src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h | 2 ++ + 4 files changed, 13 insertions(+), 2 deletions(-) + +diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp +index a3c457d..4fde295 100644 +--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp ++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp +@@ -385,8 +385,11 @@ EGLint SurfaceD3D::isPostSubBufferSupported() const + + egl::Error SurfaceD3D::querySurfacePointerANGLE(EGLint attribute, void **value) + { +- ASSERT(attribute == EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE); +- *value = mSwapChain->getShareHandle(); ++ ASSERT(attribute == EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE || attribute == EGL_DEVICE_EXT); ++ if (attribute == EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE) ++ *value = mSwapChain->getShareHandle(); ++ else if (attribute == EGL_DEVICE_EXT) ++ *value = mSwapChain->getDevice(); + return egl::Error(EGL_SUCCESS); + } + +diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/SwapChainD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SwapChainD3D.h +index 3bde92e..da36e52 100644 +--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/SwapChainD3D.h ++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SwapChainD3D.h +@@ -41,6 +41,7 @@ class SwapChainD3D : angle::NonCopyable + 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 void *getDevice() { return NULL; } + + virtual RenderTargetD3D *getColorRenderTarget() = 0; + virtual RenderTargetD3D *getDepthStencilRenderTarget() = 0; +diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp +index bcb2505..298f3cc 100644 +--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp ++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp +@@ -703,4 +703,9 @@ void SwapChain11::recreate() + // possibly should use this method instead of reset + } + ++void *rx::SwapChain11::getDevice() ++{ ++ return mRenderer->getDevice(); ++} ++ + } +diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h +index 4ea6778..48c808a 100644 +--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h ++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h +@@ -43,6 +43,8 @@ class SwapChain11 : public SwapChainD3D + EGLint getWidth() const { return mWidth; } + EGLint getHeight() const { return mHeight; } + ++ virtual void *getDevice(); ++ + static SwapChain11 *makeSwapChain11(SwapChainD3D *swapChain); + + private: +-- +2.1.4 + diff --git a/src/angle/patches/0008-ANGLE-Dynamically-load-D3D-compiler-from-a-list-or-t.patch b/src/angle/patches/0008-ANGLE-Dynamically-load-D3D-compiler-from-a-list-or-t.patch deleted file mode 100644 index 801db67682..0000000000 --- a/src/angle/patches/0008-ANGLE-Dynamically-load-D3D-compiler-from-a-list-or-t.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 4a5960465d1632ab089320fcbba4af294d58fd9a Mon Sep 17 00:00:00 2001 -From: Andrew Knight -Date: Fri, 7 Nov 2014 14:05:36 +0200 -Subject: [PATCH 08/16] ANGLE: Dynamically load D3D compiler from a list or the - environment - -If the default compiler cannot be found, load it from a list of DLL names, -including a non-versioned proxy DLL provided by Qt. On Desktop Windows, -the default compiler can also be specified by an environment variable, -QT_D3DCOMPILER_DLL. - -Change-Id: I0d7a8a8a36cc571836f8fa59ea14513b9b19c19b ---- - .../src/libGLESv2/renderer/d3d/HLSLCompiler.cpp | 27 ++++++++++++++++++++++ - 1 file changed, 27 insertions(+) - -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp -index bfeaf51..9d003b4 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp -@@ -11,6 +11,10 @@ - #include "common/features.h" - #include "common/utilities.h" - -+#ifndef QT_D3DCOMPILER_DLL -+#define QT_D3DCOMPILER_DLL D3DCOMPILER_DLL -+#endif -+ - // Definitions local to the translation unit - namespace - { -@@ -132,6 +136,29 @@ bool HLSLCompiler::initialize() - } - #endif // ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES - -+ // Load the compiler DLL specified by the environment, or default to QT_D3DCOMPILER_DLL -+ const wchar_t *defaultCompiler = _wgetenv(L"QT_D3DCOMPILER_DLL"); -+ if (!defaultCompiler) -+ defaultCompiler = QT_D3DCOMPILER_DLL; -+ -+ const wchar_t *compilerDlls[] = { -+ defaultCompiler, -+ L"d3dcompiler_47.dll", -+ L"d3dcompiler_46.dll", -+ L"d3dcompiler_45.dll", -+ L"d3dcompiler_44.dll", -+ L"d3dcompiler_43.dll", -+ 0 -+ }; -+ -+ // Load the first available known compiler DLL -+ for (int i = 0; compilerDlls[i]; ++i) -+ { -+ mD3DCompilerModule = LoadLibrary(compilerDlls[i]); -+ if (mD3DCompilerModule) -+ break; -+ } -+ - if (!mD3DCompilerModule) - { - // Load the version of the D3DCompiler DLL associated with the Direct3D version ANGLE was built with. --- -1.9.4.msysgit.1 - diff --git a/src/angle/patches/0009-ANGLE-Support-WinRT.patch b/src/angle/patches/0009-ANGLE-Support-WinRT.patch deleted file mode 100644 index a38fb4ea13..0000000000 --- a/src/angle/patches/0009-ANGLE-Support-WinRT.patch +++ /dev/null @@ -1,837 +0,0 @@ -From 4d150ba3814f824f1cadaedbdb83d0ac79d0e1a2 Mon Sep 17 00:00:00 2001 -From: Andrew Knight -Date: Fri, 14 Nov 2014 09:28:11 +0200 -Subject: [PATCH 09/16] ANGLE: Support WinRT - -Tweak ANGLE's existing support for WinRT to allow for changing the -window size on Windows Phone. - -Change-Id: Ia312b5318b977838a2953f1f530487cbf24974bc ---- - src/3rdparty/angle/include/EGL/eglplatform.h | 5 +- - src/3rdparty/angle/src/common/NativeWindow.h | 7 +- - src/3rdparty/angle/src/common/platform.h | 4 +- - .../angle/src/common/win32/NativeWindow.cpp | 2 +- - .../src/common/winrt/CoreWindowNativeWindow.cpp | 87 +++++++++++++--------- - .../src/common/winrt/CoreWindowNativeWindow.h | 48 ++---------- - .../src/common/winrt/InspectableNativeWindow.cpp | 8 +- - .../src/common/winrt/InspectableNativeWindow.h | 7 +- - .../common/winrt/SwapChainPanelNativeWindow.cpp | 2 +- - .../src/common/winrt/SwapChainPanelNativeWindow.h | 2 +- - src/3rdparty/angle/src/libEGL/Display.h | 1 + - src/3rdparty/angle/src/libEGL/Surface.cpp | 45 ++++++++--- - src/3rdparty/angle/src/libEGL/Surface.h | 4 + - src/3rdparty/angle/src/libEGL/libEGL.cpp | 20 +++++ - .../src/libGLESv2/renderer/d3d/d3d11/Renderer11.h | 2 +- - .../libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp | 74 +++++++++++------- - .../src/libGLESv2/renderer/d3d/d3d11/SwapChain11.h | 2 + - 17 files changed, 189 insertions(+), 131 deletions(-) - -diff --git a/src/3rdparty/angle/include/EGL/eglplatform.h b/src/3rdparty/angle/include/EGL/eglplatform.h -index 3793e57..2eb3674 100644 ---- a/src/3rdparty/angle/include/EGL/eglplatform.h -+++ b/src/3rdparty/angle/include/EGL/eglplatform.h -@@ -73,13 +73,14 @@ - #endif - #include - --typedef HDC EGLNativeDisplayType; - typedef HBITMAP EGLNativePixmapType; - --#if defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_PC_APP /* Windows Store */ -+#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PC_APP || WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) /* Windows Store */ - #include -+typedef IInspectable* EGLNativeDisplayType; - typedef IInspectable* EGLNativeWindowType; - #else -+typedef HDC EGLNativeDisplayType; - typedef HWND EGLNativeWindowType; - #endif - -diff --git a/src/3rdparty/angle/src/common/NativeWindow.h b/src/3rdparty/angle/src/common/NativeWindow.h -index dc5fc8f..9e93aea 100644 ---- a/src/3rdparty/angle/src/common/NativeWindow.h -+++ b/src/3rdparty/angle/src/common/NativeWindow.h -@@ -44,10 +44,11 @@ typedef IDXGIFactory DXGIFactory; - - namespace rx - { -+ - class NativeWindow - { -- public: -- explicit NativeWindow(EGLNativeWindowType window); -+public: -+ explicit NativeWindow(EGLNativeWindowType window, EGLNativeDisplayType display); - - bool initialize(); - bool getClientRect(LPRECT rect); -@@ -58,9 +59,11 @@ class NativeWindow - DXGISwapChain** swapChain); - - inline EGLNativeWindowType getNativeWindow() const { return mWindow; } -+ inline EGLNativeDisplayType getNativeDisplay() const { return mDisplay; } - - private: - EGLNativeWindowType mWindow; -+ EGLNativeDisplayType mDisplay; - - #if defined(ANGLE_ENABLE_WINDOWS_STORE) - std::shared_ptr mImpl; -diff --git a/src/3rdparty/angle/src/common/platform.h b/src/3rdparty/angle/src/common/platform.h -index cd12dba..0065ec7 100644 ---- a/src/3rdparty/angle/src/common/platform.h -+++ b/src/3rdparty/angle/src/common/platform.h -@@ -34,7 +34,7 @@ - #endif - - #ifdef ANGLE_PLATFORM_WINDOWS --# if defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_PC_APP -+# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PC_APP || WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) - # define ANGLE_ENABLE_WINDOWS_STORE 1 - # endif - # ifndef STRICT -@@ -67,7 +67,9 @@ - # if defined(ANGLE_ENABLE_WINDOWS_STORE) - # include - # if defined(_DEBUG) -+# if (WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP) - # include -+# endif - # include - # endif - # endif -diff --git a/src/3rdparty/angle/src/common/win32/NativeWindow.cpp b/src/3rdparty/angle/src/common/win32/NativeWindow.cpp -index aa2bfa4..2440747 100644 ---- a/src/3rdparty/angle/src/common/win32/NativeWindow.cpp -+++ b/src/3rdparty/angle/src/common/win32/NativeWindow.cpp -@@ -16,7 +16,7 @@ bool IsValidEGLNativeWindowType(EGLNativeWindowType window) - return (IsWindow(window) == TRUE); - } - --NativeWindow::NativeWindow(EGLNativeWindowType window) : mWindow(window) -+NativeWindow::NativeWindow(EGLNativeWindowType window, EGLNativeDisplayType display) : mWindow(window), mDisplay(display) - { - } - -diff --git a/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.cpp b/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.cpp -index 0e63fa5..9b65c15 100644 ---- a/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.cpp -+++ b/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.cpp -@@ -6,21 +6,25 @@ - - // CoreWindowNativeWindow.cpp: NativeWindow for managing ICoreWindow native window types. - --#include -+#include - #include "common/winrt/CoreWindowNativeWindow.h" - using namespace ABI::Windows::Foundation::Collections; - - namespace rx - { -+ -+typedef ITypedEventHandler SizeChangedHandler; -+ - CoreWindowNativeWindow::~CoreWindowNativeWindow() - { - unregisterForSizeChangeEvents(); - } - --bool CoreWindowNativeWindow::initialize(EGLNativeWindowType window, IPropertySet *propertySet) -+bool CoreWindowNativeWindow::initialize(EGLNativeWindowType window, EGLNativeDisplayType display, IPropertySet *propertySet) - { - ComPtr props = propertySet; - ComPtr win = window; -+ ComPtr displayInformation = display; - SIZE swapChainSize = {}; - bool swapChainSizeSpecified = false; - HRESULT result = S_OK; -@@ -47,6 +51,29 @@ bool CoreWindowNativeWindow::initialize(EGLNativeWindowType window, IPropertySet - - if (SUCCEEDED(result)) - { -+ result = displayInformation.As(&mDisplayInformation); -+ } -+ -+ if (SUCCEEDED(result)) -+ { -+#if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP -+ ComPtr displayInformation2; -+ result = mDisplayInformation.As(&displayInformation2); -+ ASSERT(SUCCEEDED(result)); -+ -+ result = displayInformation2->get_RawPixelsPerViewPixel(&mScaleFactor); -+ ASSERT(SUCCEEDED(result)); -+#else -+ ABI::Windows::Graphics::Display::ResolutionScale resolutionScale; -+ result = mDisplayInformation->get_ResolutionScale(&resolutionScale); -+ ASSERT(SUCCEEDED(result)); -+ -+ mScaleFactor = DOUBLE(resolutionScale) / 100.0; -+#endif -+ } -+ -+ if (SUCCEEDED(result)) -+ { - // If a swapchain size is specfied, then the automatic resize - // behaviors implemented by the host should be disabled. The swapchain - // will be still be scaled when being rendered to fit the bounds -@@ -60,7 +87,14 @@ bool CoreWindowNativeWindow::initialize(EGLNativeWindowType window, IPropertySet - } - else - { -- result = GetCoreWindowSizeInPixels(mCoreWindow, &mClientRect); -+ ABI::Windows::Foundation::Rect rect; -+ HRESULT result = mCoreWindow->get_Bounds(&rect); -+ if (SUCCEEDED(result)) -+ { -+ LONG width = std::floor(rect.Width * mScaleFactor + 0.5); -+ LONG height = std::floor(rect.Height * mScaleFactor + 0.5); -+ mClientRect = { 0, 0, width, height }; -+ } - } - } - -@@ -76,12 +110,8 @@ bool CoreWindowNativeWindow::initialize(EGLNativeWindowType window, IPropertySet - - bool CoreWindowNativeWindow::registerForSizeChangeEvents() - { -- ComPtr sizeChangedHandler; -- HRESULT result = Microsoft::WRL::MakeAndInitialize(sizeChangedHandler.ReleaseAndGetAddressOf(), this->shared_from_this()); -- if (SUCCEEDED(result)) -- { -- result = mCoreWindow->add_SizeChanged(sizeChangedHandler.Get(), &mSizeChangedEventToken); -- } -+ HRESULT result = mCoreWindow->add_SizeChanged(Callback(this, &CoreWindowNativeWindow::onSizeChanged).Get(), -+ &mSizeChangedEventToken); - - if (SUCCEEDED(result)) - { -@@ -126,7 +156,7 @@ HRESULT CoreWindowNativeWindow::createSwapChain(ID3D11Device *device, DXGIFactor - if (SUCCEEDED(result)) - { - --#if (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) -+#if (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) // This block is disabled for Qt applications, as the resize events are expected - // Test if swapchain supports resize. On Windows Phone devices, this will return DXGI_ERROR_UNSUPPORTED. On - // other devices DXGI_ERROR_INVALID_CALL should be returned because the combination of flags passed - // (DXGI_SWAP_CHAIN_FLAG_NONPREROTATED | DXGI_SWAP_CHAIN_FLAG_GDI_COMPATIBLE) are invalid flag combinations. -@@ -152,36 +182,19 @@ HRESULT CoreWindowNativeWindow::createSwapChain(ID3D11Device *device, DXGIFactor - return result; - } - --HRESULT GetCoreWindowSizeInPixels(const ComPtr& coreWindow, RECT *windowSize) -+// Basically, this shouldn't be used on Phone -+HRESULT CoreWindowNativeWindow::onSizeChanged(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IWindowSizeChangedEventArgs *e) - { -- ABI::Windows::Foundation::Rect bounds; -- HRESULT result = coreWindow->get_Bounds(&bounds); -- if (SUCCEEDED(result)) -+ ABI::Windows::Foundation::Size size; -+ if (SUCCEEDED(e->get_Size(&size))) - { -- *windowSize = { 0, 0, ConvertDipsToPixels(bounds.Width), ConvertDipsToPixels(bounds.Height) }; -+ SIZE windowSizeInPixels = { -+ std::floor(size.Width * mScaleFactor + 0.5), -+ std::floor(size.Height * mScaleFactor + 0.5) -+ }; -+ setNewClientSize(windowSizeInPixels); - } - -- return result; --} -- --static float GetLogicalDpi() --{ -- ComPtr displayProperties; -- float dpi = 96.0f; -- -- if (SUCCEEDED(GetActivationFactory(HStringReference(RuntimeClass_Windows_Graphics_Display_DisplayProperties).Get(), displayProperties.GetAddressOf()))) -- { -- if (SUCCEEDED(displayProperties->get_LogicalDpi(&dpi))) -- { -- return dpi; -- } -- } -- return dpi; --} -- --long ConvertDipsToPixels(float dips) --{ -- static const float dipsPerInch = 96.0f; -- return lround((dips * GetLogicalDpi() / dipsPerInch)); -+ return S_OK; - } - } -diff --git a/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.h b/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.h -index 0c6222d..1c55124 100644 ---- a/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.h -+++ b/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.h -@@ -11,67 +11,29 @@ - - #include "common/winrt/InspectableNativeWindow.h" - #include -- --typedef ABI::Windows::Foundation::__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CWindowSizeChangedEventArgs_t IWindowSizeChangedEventHandler; -+#include - - namespace rx - { --long ConvertDipsToPixels(float dips); - - class CoreWindowNativeWindow : public InspectableNativeWindow, public std::enable_shared_from_this - { - public: - ~CoreWindowNativeWindow(); - -- bool initialize(EGLNativeWindowType window, IPropertySet *propertySet); -+ bool initialize(EGLNativeWindowType window, EGLNativeDisplayType display, IPropertySet *propertySet); - bool registerForSizeChangeEvents(); - void unregisterForSizeChangeEvents(); - HRESULT createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain); - - private: -+ HRESULT onSizeChanged(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IWindowSizeChangedEventArgs *); -+ - ComPtr mCoreWindow; -+ ComPtr mDisplayInformation; - ComPtr> mPropertyMap; - }; - --[uuid(7F924F66-EBAE-40E5-A10B-B8F35E245190)] --class CoreWindowSizeChangedHandler : -- public Microsoft::WRL::RuntimeClass, IWindowSizeChangedEventHandler> --{ -- public: -- CoreWindowSizeChangedHandler() { } -- HRESULT RuntimeClassInitialize(std::shared_ptr host) -- { -- if (!host) -- { -- return E_INVALIDARG; -- } -- -- mHost = host; -- return S_OK; -- } -- -- // IWindowSizeChangedEventHandler -- IFACEMETHOD(Invoke)(ABI::Windows::UI::Core::ICoreWindow *sender, ABI::Windows::UI::Core::IWindowSizeChangedEventArgs *sizeChangedEventArgs) -- { -- std::shared_ptr host = mHost.lock(); -- if (host) -- { -- ABI::Windows::Foundation::Size windowSize; -- if (SUCCEEDED(sizeChangedEventArgs->get_Size(&windowSize))) -- { -- SIZE windowSizeInPixels = { ConvertDipsToPixels(windowSize.Width), ConvertDipsToPixels(windowSize.Height) }; -- host->setNewClientSize(windowSizeInPixels); -- } -- } -- -- return S_OK; -- } -- -- private: -- std::weak_ptr mHost; --}; -- --HRESULT GetCoreWindowSizeInPixels(const ComPtr& coreWindow, RECT *windowSize); - } - - #endif // COMMON_WINRT_COREWINDOWNATIVEWINDOW_H_ -diff --git a/src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.cpp b/src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.cpp -index c062a48..0589f6d 100644 ---- a/src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.cpp -+++ b/src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.cpp -@@ -11,9 +11,9 @@ - - namespace rx - { --NativeWindow::NativeWindow(EGLNativeWindowType window) -+NativeWindow::NativeWindow(EGLNativeWindowType window, EGLNativeDisplayType display) -+ : mWindow(window), mDisplay(display) - { -- mWindow = window; - } - - bool NativeWindow::initialize() -@@ -40,7 +40,7 @@ bool NativeWindow::initialize() - mImpl = std::make_shared(); - if (mImpl) - { -- return mImpl->initialize(mWindow, propertySet.Get()); -+ return mImpl->initialize(mWindow, mDisplay, propertySet.Get()); - } - } - else if (IsSwapChainPanel(mWindow, &swapChainPanel)) -@@ -48,7 +48,7 @@ bool NativeWindow::initialize() - mImpl = std::make_shared(); - if (mImpl) - { -- return mImpl->initialize(mWindow, propertySet.Get()); -+ return mImpl->initialize(mWindow, mDisplay, propertySet.Get()); - } - } - else -diff --git a/src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.h b/src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.h -index c625348..402941a 100644 ---- a/src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.h -+++ b/src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.h -@@ -32,13 +32,14 @@ class InspectableNativeWindow - mRequiresSwapChainScaling(false), - mClientRectChanged(false), - mClientRect({0,0,0,0}), -- mNewClientRect({0,0,0,0}) -+ mNewClientRect({0,0,0,0}), -+ mScaleFactor(1.0) - { - mSizeChangedEventToken.value = 0; - } - virtual ~InspectableNativeWindow(){} - -- virtual bool initialize(EGLNativeWindowType window, IPropertySet *propertySet) = 0; -+ virtual bool initialize(EGLNativeWindowType window, EGLNativeDisplayType display, IPropertySet *propertySet) = 0; - virtual HRESULT createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain) = 0; - virtual bool registerForSizeChangeEvents() = 0; - virtual void unregisterForSizeChangeEvents() = 0; -@@ -49,6 +50,7 @@ class InspectableNativeWindow - if (mClientRectChanged && mSupportsSwapChainResize) - { - mClientRect = mNewClientRect; -+ mClientRectChanged = false; - } - - *rect = mClientRect; -@@ -76,6 +78,7 @@ protected: - RECT mClientRect; - RECT mNewClientRect; - bool mClientRectChanged; -+ DOUBLE mScaleFactor; - - EventRegistrationToken mSizeChangedEventToken; - }; -diff --git a/src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.cpp b/src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.cpp -index 4e4fb6d..268dfbd 100644 ---- a/src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.cpp -+++ b/src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.cpp -@@ -18,7 +18,7 @@ SwapChainPanelNativeWindow::~SwapChainPanelNativeWindow() - unregisterForSizeChangeEvents(); - } - --bool SwapChainPanelNativeWindow::initialize(EGLNativeWindowType window, IPropertySet *propertySet) -+bool SwapChainPanelNativeWindow::initialize(EGLNativeWindowType window, EGLNativeDisplayType display, IPropertySet *propertySet) - { - ComPtr props = propertySet; - ComPtr win = window; -diff --git a/src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.h b/src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.h -index e88f554..5bbf274 100644 ---- a/src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.h -+++ b/src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.h -@@ -18,7 +18,7 @@ class SwapChainPanelNativeWindow : public InspectableNativeWindow, public std::e - public: - ~SwapChainPanelNativeWindow(); - -- bool initialize(EGLNativeWindowType window, IPropertySet *propertySet); -+ bool initialize(EGLNativeWindowType window, EGLNativeDisplayType display, IPropertySet *propertySet); - bool registerForSizeChangeEvents(); - void unregisterForSizeChangeEvents(); - HRESULT createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain); -diff --git a/src/3rdparty/angle/src/libEGL/Display.h b/src/3rdparty/angle/src/libEGL/Display.h -index 378323a..b3ffcc8 100644 ---- a/src/3rdparty/angle/src/libEGL/Display.h -+++ b/src/3rdparty/angle/src/libEGL/Display.h -@@ -67,6 +67,7 @@ class Display - - const char *getExtensionString() const; - const char *getVendorString() const; -+ EGLNativeDisplayType getDisplayId() const { return mDisplayId; } - - private: - DISALLOW_COPY_AND_ASSIGN(Display); -diff --git a/src/3rdparty/angle/src/libEGL/Surface.cpp b/src/3rdparty/angle/src/libEGL/Surface.cpp -index 3414656..b664a85 100644 ---- a/src/3rdparty/angle/src/libEGL/Surface.cpp -+++ b/src/3rdparty/angle/src/libEGL/Surface.cpp -@@ -31,7 +31,7 @@ namespace egl - { - - Surface::Surface(Display *display, const Config *config, EGLNativeWindowType window, EGLint fixedSize, EGLint width, EGLint height, EGLint postSubBufferSupported) -- : mDisplay(display), mConfig(config), mNativeWindow(window), mPostSubBufferSupported(postSubBufferSupported) -+ : mDisplay(display), mConfig(config), mNativeWindow(window, display->getDisplayId()), mPostSubBufferSupported(postSubBufferSupported) - { - //TODO(jmadill): MANGLE refactor. (note, can't call makeRendererD3D because of dll export issues) - mRenderer = static_cast(mDisplay->getRenderer()); -@@ -47,6 +47,8 @@ Surface::Surface(Display *display, const Config *config, EGLNativeWindowType win - mSwapInterval = -1; - mWidth = width; - mHeight = height; -+ mFixedWidth = mWidth; -+ mFixedHeight = mHeight; - setSwapInterval(1); - mFixedSize = fixedSize; - -@@ -54,7 +56,7 @@ Surface::Surface(Display *display, const Config *config, EGLNativeWindowType win - } - - Surface::Surface(Display *display, const Config *config, HANDLE shareHandle, EGLint width, EGLint height, EGLenum textureFormat, EGLenum textureType) -- : mDisplay(display), mNativeWindow(NULL), mConfig(config), mShareHandle(shareHandle), mWidth(width), mHeight(height), mPostSubBufferSupported(EGL_FALSE) -+ : mDisplay(display), mNativeWindow(NULL, NULL), mConfig(config), mShareHandle(shareHandle), mWidth(width), mHeight(height), mPostSubBufferSupported(EGL_FALSE) - { - //TODO(jmadill): MANGLE refactor. (note, can't call makeRendererD3D because of dll export issues) - mRenderer = static_cast(mDisplay->getRenderer()); -@@ -71,6 +73,8 @@ Surface::Surface(Display *display, const Config *config, HANDLE shareHandle, EGL - setSwapInterval(1); - // This constructor is for offscreen surfaces, which are always fixed-size. - mFixedSize = EGL_TRUE; -+ mFixedWidth = mWidth; -+ mFixedHeight = mHeight; - } - - Surface::~Surface() -@@ -157,10 +161,13 @@ Error Surface::resetSwapChain() - - Error Surface::resizeSwapChain(int backbufferWidth, int backbufferHeight) - { -- ASSERT(backbufferWidth >= 0 && backbufferHeight >= 0); - ASSERT(mSwapChain); - -- EGLint status = mSwapChain->resize(std::max(1, backbufferWidth), std::max(1, backbufferHeight)); -+#if !defined(ANGLE_ENABLE_WINDOWS_STORE) -+ backbufferWidth = std::max(1, backbufferWidth); -+ backbufferHeight = std::max(1, backbufferHeight); -+#endif -+ EGLint status = mSwapChain->resize(backbufferWidth, backbufferHeight); - - if (status == EGL_CONTEXT_LOST) - { -@@ -209,14 +216,14 @@ Error Surface::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) - return Error(EGL_SUCCESS); - } - -- if (x + width > mWidth) -+ if (x + width > abs(mWidth)) - { -- width = mWidth - x; -+ width = abs(mWidth) - x; - } - -- if (y + height > mHeight) -+ if (y + height > abs(mHeight)) - { -- height = mHeight - y; -+ height = abs(mHeight) - y; - } - - if (width == 0 || height == 0) -@@ -224,6 +231,9 @@ Error Surface::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) - return Error(EGL_SUCCESS); - } - -+ ASSERT(width > 0); -+ ASSERT(height > 0); -+ - EGLint status = mSwapChain->swapRect(x, y, width, height); - - if (status == EGL_CONTEXT_LOST) -@@ -352,6 +362,13 @@ bool Surface::checkForOutOfDateSwapChain() - sizeDirty = clientWidth != getWidth() || clientHeight != getHeight(); - } - -+ if (mFixedSize && (mWidth != mFixedWidth || mHeight != mFixedHeight)) -+ { -+ clientWidth = mFixedWidth; -+ clientHeight = mFixedHeight; -+ sizeDirty = true; -+ } -+ - bool wasDirty = (mSwapIntervalDirty || sizeDirty); - - if (mSwapIntervalDirty) -@@ -378,7 +395,7 @@ bool Surface::checkForOutOfDateSwapChain() - - Error Surface::swap() - { -- return swapRect(0, 0, mWidth, mHeight); -+ return swapRect(0, 0, abs(mWidth), abs(mHeight)); - } - - Error Surface::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) -@@ -471,6 +488,16 @@ EGLint Surface::isFixedSize() const - return mFixedSize; - } - -+void Surface::setFixedWidth(EGLint width) -+{ -+ mFixedWidth = width; -+} -+ -+void Surface::setFixedHeight(EGLint height) -+{ -+ mFixedHeight = height; -+} -+ - 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 662fe21..46382d0 100644 ---- a/src/3rdparty/angle/src/libEGL/Surface.h -+++ b/src/3rdparty/angle/src/libEGL/Surface.h -@@ -70,6 +70,8 @@ class Surface - virtual gl::Texture2D *getBoundTexture() const; - - EGLint isFixedSize() const; -+ void setFixedWidth(EGLint width); -+ void setFixedHeight(EGLint height); - - private: - DISALLOW_COPY_AND_ASSIGN(Surface); -@@ -91,6 +93,8 @@ class Surface - const egl::Config *mConfig; // EGL config surface was created with - EGLint mHeight; // Height of surface - EGLint mWidth; // Width of surface -+ EGLint mFixedHeight; // Pending height of the surface -+ EGLint mFixedWidth; // Pending width of the surface - // EGLint horizontalResolution; // Horizontal dot pitch - // EGLint verticalResolution; // Vertical dot pitch - // EGLBoolean largestPBuffer; // If true, create largest pbuffer possible -diff --git a/src/3rdparty/angle/src/libEGL/libEGL.cpp b/src/3rdparty/angle/src/libEGL/libEGL.cpp -index 6110698..dc20d85 100644 ---- a/src/3rdparty/angle/src/libEGL/libEGL.cpp -+++ b/src/3rdparty/angle/src/libEGL/libEGL.cpp -@@ -706,6 +706,26 @@ EGLBoolean __stdcall eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint - return EGL_FALSE; - } - -+ switch (attribute) -+ { -+ case EGL_WIDTH: -+ if (!eglSurface->isFixedSize() || !value) { -+ recordError(egl::Error(EGL_BAD_PARAMETER)); -+ return EGL_FALSE; -+ } -+ eglSurface->setFixedWidth(value); -+ return EGL_TRUE; -+ case EGL_HEIGHT: -+ if (!eglSurface->isFixedSize() || !value) { -+ recordError(egl::Error(EGL_BAD_PARAMETER)); -+ return EGL_FALSE; -+ } -+ eglSurface->setFixedHeight(value); -+ return EGL_TRUE; -+ default: -+ break; -+ } -+ - UNIMPLEMENTED(); // FIXME - - recordError(egl::Error(EGL_SUCCESS)); -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h -index 1655f1d..c789cae 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h -@@ -231,7 +231,7 @@ class Renderer11 : public RendererD3D - - HMODULE mD3d11Module; - HMODULE mDxgiModule; -- HDC mDc; -+ EGLNativeDisplayType mDc; - std::vector mAvailableFeatureLevels; - D3D_DRIVER_TYPE mDriverType; - -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp -index 834b7bd..52c8a81 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp -@@ -42,6 +42,8 @@ SwapChain11::SwapChain11(Renderer11 *renderer, NativeWindow nativeWindow, HANDLE - mPassThroughPS = NULL; - mWidth = -1; - mHeight = -1; -+ mRotateL = false; -+ mRotateR = false; - mSwapInterval = 0; - mAppCreatedShareHandle = mShareHandle != NULL; - mPassThroughResourcesInit = false; -@@ -92,10 +94,11 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei - ASSERT(device != NULL); - - // D3D11 does not allow zero size textures -- ASSERT(backbufferWidth >= 1); -- ASSERT(backbufferHeight >= 1); -+ ASSERT(backbufferWidth != 0); -+ ASSERT(backbufferHeight != 0); - - // Preserve the render target content -+#if !defined(ANGLE_ENABLE_WINDOWS_STORE) - ID3D11Texture2D *previousOffscreenTexture = mOffscreenTexture; - if (previousOffscreenTexture) - { -@@ -103,6 +106,7 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei - } - const int previousWidth = mWidth; - const int previousHeight = mHeight; -+#endif - - releaseOffscreenTexture(); - -@@ -136,8 +140,8 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei - D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0}; - mOffscreenTexture->GetDesc(&offscreenTextureDesc); - -- if (offscreenTextureDesc.Width != (UINT)backbufferWidth || -- offscreenTextureDesc.Height != (UINT)backbufferHeight || -+ if (offscreenTextureDesc.Width != UINT(abs(backbufferWidth)) || -+ offscreenTextureDesc.Height != UINT(abs(backbufferHeight)) || - offscreenTextureDesc.Format != backbufferFormatInfo.texFormat || - offscreenTextureDesc.MipLevels != 1 || - offscreenTextureDesc.ArraySize != 1) -@@ -152,8 +156,8 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei - const bool useSharedResource = !mNativeWindow.getNativeWindow() && mRenderer->getShareHandleSupport(); - - D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0}; -- offscreenTextureDesc.Width = backbufferWidth; -- offscreenTextureDesc.Height = backbufferHeight; -+ offscreenTextureDesc.Width = abs(backbufferWidth); -+ offscreenTextureDesc.Height = abs(backbufferHeight); - offscreenTextureDesc.Format = backbufferFormatInfo.texFormat; - offscreenTextureDesc.MipLevels = 1; - offscreenTextureDesc.ArraySize = 1; -@@ -233,8 +237,8 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei - if (mDepthBufferFormat != GL_NONE) - { - D3D11_TEXTURE2D_DESC depthStencilTextureDesc; -- depthStencilTextureDesc.Width = backbufferWidth; -- depthStencilTextureDesc.Height = backbufferHeight; -+ depthStencilTextureDesc.Width = abs(backbufferWidth); -+ depthStencilTextureDesc.Height = abs(backbufferHeight); - depthStencilTextureDesc.Format = depthBufferFormatInfo.texFormat; - depthStencilTextureDesc.MipLevels = 1; - depthStencilTextureDesc.ArraySize = 1; -@@ -286,6 +290,7 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei - mWidth = backbufferWidth; - mHeight = backbufferHeight; - -+#if !defined(ANGLE_ENABLE_WINDOWS_STORE) - if (previousOffscreenTexture != NULL) - { - D3D11_BOX sourceBox = {0}; -@@ -307,6 +312,7 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei - swapRect(0, 0, mWidth, mHeight); - } - } -+#endif - - return EGL_SUCCESS; - } -@@ -320,8 +326,16 @@ EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight) - return EGL_BAD_ACCESS; - } - -+ // Windows Phone works around the rotation limitation by using negative values for the swap chain size -+#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) -+ mRotateL = backbufferWidth < 0; // Landscape/InvertedLandscape -+ mRotateR = backbufferHeight < 0; // InvertedPortrait/InvertedLandscape -+ backbufferWidth = abs(backbufferWidth); -+ backbufferHeight = abs(backbufferHeight); -+#endif -+ - // EGL allows creating a surface with 0x0 dimension, however, DXGI does not like 0x0 swapchains -- if (backbufferWidth < 1 || backbufferHeight < 1) -+ if (backbufferWidth == 0 || backbufferHeight == 0) - { - return EGL_SUCCESS; - } -@@ -329,6 +343,7 @@ EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight) - // Can only call resize if we have already created our swap buffer and resources - ASSERT(mSwapChain && mBackBufferTexture && mBackBufferRTView); - -+#if !defined(ANGLE_ENABLE_WINDOWS_STORE) || (WINAPI_FAMILY == WINAPI_FAMILY_PC_APP) // The swap chain is not directly resized on Windows Phone - SafeRelease(mBackBufferTexture); - SafeRelease(mBackBufferRTView); - -@@ -366,6 +381,7 @@ EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight) - { - d3d11::SetDebugName(mBackBufferRTView, "Back buffer render target"); - } -+#endif - - return resetOffscreenTexture(backbufferWidth, backbufferHeight); - } -@@ -512,16 +528,6 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) - 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; -@@ -533,10 +539,23 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) - 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); -+ const bool rotateL = mRotateL; -+ const bool rotateR = mRotateR; -+ -+ // 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); -+ -+ d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, rotateL ? u2 : u1, rotateR ? v2 : v1); -+ d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, rotateR ? u2 : u1, rotateL ? v1 : v2); -+ d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, rotateR ? u1 : u2, rotateL ? v2 : v1); -+ d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, rotateL ? u1 : u2, rotateR ? v1 : v2); - - deviceContext->Unmap(mQuadVB, 0); - -@@ -564,10 +583,11 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) - - // Set the viewport - D3D11_VIEWPORT viewport; -- viewport.TopLeftX = 0; -- viewport.TopLeftY = 0; -- viewport.Width = mWidth; -- viewport.Height = mHeight; -+ viewport.TopLeftX = 0.0f; -+ viewport.TopLeftY = 0.0f; -+ const bool invertViewport = (mRotateL || mRotateR) && !(mRotateL && mRotateR); -+ viewport.Width = FLOAT(invertViewport ? mHeight : mWidth); -+ viewport.Height = FLOAT(invertViewport ? mWidth : mHeight); - viewport.MinDepth = 0.0f; - viewport.MaxDepth = 1.0f; - deviceContext->RSSetViewports(1, &viewport); -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.h -index 22401d8..77509ed 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.h -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.h -@@ -52,6 +52,8 @@ class SwapChain11 : public SwapChain - Renderer11 *mRenderer; - EGLint mHeight; - EGLint mWidth; -+ bool mRotateL; -+ bool mRotateR; - bool mAppCreatedShareHandle; - unsigned int mSwapInterval; - bool mPassThroughResourcesInit; --- -1.9.4.msysgit.1 - diff --git a/src/angle/patches/0010-ANGLE-Enable-D3D11-for-feature-level-9-cards.patch b/src/angle/patches/0010-ANGLE-Enable-D3D11-for-feature-level-9-cards.patch deleted file mode 100644 index dd2768cf3e..0000000000 --- a/src/angle/patches/0010-ANGLE-Enable-D3D11-for-feature-level-9-cards.patch +++ /dev/null @@ -1,637 +0,0 @@ -From 829bf86c57357d3c8ec598b92fcfdb1849e84075 Mon Sep 17 00:00:00 2001 -From: Andrew Knight -Date: Tue, 11 Nov 2014 17:11:54 +0200 -Subject: [PATCH 10/16] ANGLE: Enable D3D11 for feature level 9 cards - -Enable use of ANGLE on lower-end hardware, such as Surface RT and -Windows Phone 8. - -Change-Id: Ice536802e4eedc1d264abd0dd65960638fce59e4 ---- - src/3rdparty/angle/src/libGLESv2/angletypes.cpp | 6 +- - .../src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp | 69 ++++--- - .../src/libGLESv2/renderer/d3d/d3d11/Buffer11.cpp | 4 +- - .../src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp | 7 +- - .../renderer/d3d/d3d11/PixelTransfer11.cpp | 9 +- - .../libGLESv2/renderer/d3d/d3d11/Renderer11.cpp | 226 +++++++++++++-------- - .../src/libGLESv2/renderer/d3d/d3d11/Renderer11.h | 1 + - .../renderer/d3d/d3d11/TextureStorage11.cpp | 4 +- - .../libGLESv2/renderer/d3d/d3d11/formatutils11.cpp | 4 +- - .../renderer/d3d/d3d11/renderer11_utils.cpp | 2 +- - 10 files changed, 208 insertions(+), 124 deletions(-) - -diff --git a/src/3rdparty/angle/src/libGLESv2/angletypes.cpp b/src/3rdparty/angle/src/libGLESv2/angletypes.cpp -index 6fd02e0..5a0cfc5 100644 ---- a/src/3rdparty/angle/src/libGLESv2/angletypes.cpp -+++ b/src/3rdparty/angle/src/libGLESv2/angletypes.cpp -@@ -12,6 +12,8 @@ - #include "libGLESv2/State.h" - #include "libGLESv2/VertexArray.h" - -+#include -+ - namespace gl - { - -@@ -24,8 +26,8 @@ SamplerState::SamplerState() - maxAnisotropy(1.0f), - baseLevel(0), - maxLevel(1000), -- minLod(-1000.0f), -- maxLod(1000.0f), -+ minLod(-FLT_MAX), -+ maxLod(FLT_MAX), - compareMode(GL_NONE), - compareFunc(GL_LEQUAL), - swizzleRed(GL_RED), -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp -index 91e7552..06aea9b 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp -@@ -209,7 +209,7 @@ Blit11::Blit11(Renderer11 *renderer) - pointSamplerDesc.BorderColor[2] = 0.0f; - pointSamplerDesc.BorderColor[3] = 0.0f; - pointSamplerDesc.MinLOD = 0.0f; -- pointSamplerDesc.MaxLOD = 0.0f; -+ pointSamplerDesc.MaxLOD = mRenderer->isLevel9() ? D3D11_FLOAT32_MAX : 0.0f; - - result = device->CreateSamplerState(&pointSamplerDesc, &mPointSampler); - ASSERT(SUCCEEDED(result)); -@@ -228,7 +228,7 @@ Blit11::Blit11(Renderer11 *renderer) - linearSamplerDesc.BorderColor[2] = 0.0f; - linearSamplerDesc.BorderColor[3] = 0.0f; - linearSamplerDesc.MinLOD = 0.0f; -- linearSamplerDesc.MaxLOD = 0.0f; -+ linearSamplerDesc.MaxLOD = mRenderer->isLevel9() ? D3D11_FLOAT32_MAX : 0.0f; - - result = device->CreateSamplerState(&linearSamplerDesc, &mLinearSampler); - ASSERT(SUCCEEDED(result)); -@@ -290,28 +290,31 @@ Blit11::Blit11(Renderer11 *renderer) - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mQuad2DVS, "Blit11 2D vertex shader"); - -- result = device->CreatePixelShader(g_PS_PassthroughDepth2D, ArraySize(g_PS_PassthroughDepth2D), NULL, &mDepthPS); -- ASSERT(SUCCEEDED(result)); -- d3d11::SetDebugName(mDepthPS, "Blit11 2D depth pixel shader"); -- -- D3D11_INPUT_ELEMENT_DESC quad3DLayout[] = -+ if (!renderer->isLevel9()) - { -- { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, -- { "LAYER", 0, DXGI_FORMAT_R32_UINT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0 }, -- { "TEXCOORD", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, -- }; -- -- result = device->CreateInputLayout(quad3DLayout, ArraySize(quad3DLayout), g_VS_Passthrough3D, ArraySize(g_VS_Passthrough3D), &mQuad3DIL); -- ASSERT(SUCCEEDED(result)); -- d3d11::SetDebugName(mQuad3DIL, "Blit11 3D input layout"); -- -- result = device->CreateVertexShader(g_VS_Passthrough3D, ArraySize(g_VS_Passthrough3D), NULL, &mQuad3DVS); -- ASSERT(SUCCEEDED(result)); -- d3d11::SetDebugName(mQuad3DVS, "Blit11 3D vertex shader"); -+ result = device->CreatePixelShader(g_PS_PassthroughDepth2D, ArraySize(g_PS_PassthroughDepth2D), NULL, &mDepthPS); -+ ASSERT(SUCCEEDED(result)); -+ d3d11::SetDebugName(mDepthPS, "Blit11 2D depth pixel shader"); - -- result = device->CreateGeometryShader(g_GS_Passthrough3D, ArraySize(g_GS_Passthrough3D), NULL, &mQuad3DGS); -- ASSERT(SUCCEEDED(result)); -- d3d11::SetDebugName(mQuad3DGS, "Renderer11 copy 3D texture geometry shader"); -+ D3D11_INPUT_ELEMENT_DESC quad3DLayout[] = -+ { -+ { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, -+ { "LAYER", 0, DXGI_FORMAT_R32_UINT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0 }, -+ { "TEXCOORD", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, -+ }; -+ -+ result = device->CreateInputLayout(quad3DLayout, ArraySize(quad3DLayout), g_VS_Passthrough3D, ArraySize(g_VS_Passthrough3D), &mQuad3DIL); -+ ASSERT(SUCCEEDED(result)); -+ d3d11::SetDebugName(mQuad3DIL, "Blit11 3D input layout"); -+ -+ result = device->CreateVertexShader(g_VS_Passthrough3D, ArraySize(g_VS_Passthrough3D), NULL, &mQuad3DVS); -+ ASSERT(SUCCEEDED(result)); -+ d3d11::SetDebugName(mQuad3DVS, "Blit11 3D vertex shader"); -+ -+ result = device->CreateGeometryShader(g_GS_Passthrough3D, ArraySize(g_GS_Passthrough3D), NULL, &mQuad3DGS); -+ ASSERT(SUCCEEDED(result)); -+ d3d11::SetDebugName(mQuad3DGS, "Renderer11 copy 3D texture geometry shader"); -+ } - - buildShaderMap(); - -@@ -970,22 +973,27 @@ void Blit11::buildShaderMap() - ID3D11Device *device = mRenderer->getDevice(); - - add2DBlitShaderToMap(GL_RGBA, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA2D, "Blit11 2D RGBA pixel shader" )); -- add2DBlitShaderToMap(GL_RGBA_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA2DUI, "Blit11 2D RGBA UI pixel shader" )); -- add2DBlitShaderToMap(GL_RGBA_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughRGBA2DI, "Blit11 2D RGBA I pixel shader" )); - add2DBlitShaderToMap(GL_BGRA_EXT, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA2D, "Blit11 2D BGRA pixel shader" )); - add2DBlitShaderToMap(GL_RGB, false, d3d11::CompilePS(device, g_PS_PassthroughRGB2D, "Blit11 2D RGB pixel shader" )); -- add2DBlitShaderToMap(GL_RGB_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughRGB2DUI, "Blit11 2D RGB UI pixel shader" )); -- add2DBlitShaderToMap(GL_RGB_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughRGB2DI, "Blit11 2D RGB I pixel shader" )); - add2DBlitShaderToMap(GL_RG, false, d3d11::CompilePS(device, g_PS_PassthroughRG2D, "Blit11 2D RG pixel shader" )); -- add2DBlitShaderToMap(GL_RG_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughRG2DUI, "Blit11 2D RG UI pixel shader" )); -- add2DBlitShaderToMap(GL_RG_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughRG2DI, "Blit11 2D RG I pixel shader" )); - add2DBlitShaderToMap(GL_RED, false, d3d11::CompilePS(device, g_PS_PassthroughR2D, "Blit11 2D R pixel shader" )); -- add2DBlitShaderToMap(GL_RED_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughR2DUI, "Blit11 2D R UI pixel shader" )); -- add2DBlitShaderToMap(GL_RED_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughR2DI, "Blit11 2D R I pixel shader" )); - add2DBlitShaderToMap(GL_ALPHA, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA2D, "Blit11 2D alpha pixel shader" )); - add2DBlitShaderToMap(GL_LUMINANCE, false, d3d11::CompilePS(device, g_PS_PassthroughLum2D, "Blit11 2D lum pixel shader" )); - add2DBlitShaderToMap(GL_LUMINANCE_ALPHA, false, d3d11::CompilePS(device, g_PS_PassthroughLumAlpha2D, "Blit11 2D luminance alpha pixel shader")); - -+ addSwizzleShaderToMap(GL_FLOAT, D3D_SRV_DIMENSION_TEXTURE2D, d3d11::CompilePS(device, g_PS_SwizzleF2D, "Blit11 2D F swizzle pixel shader" )); -+ -+ if (mRenderer->isLevel9()) -+ return; -+ -+ add2DBlitShaderToMap(GL_RGBA_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA2DUI, "Blit11 2D RGBA UI pixel shader" )); -+ add2DBlitShaderToMap(GL_RGBA_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughRGBA2DI, "Blit11 2D RGBA I pixel shader" )); -+ add2DBlitShaderToMap(GL_RGB_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughRGB2DUI, "Blit11 2D RGB UI pixel shader" )); -+ add2DBlitShaderToMap(GL_RGB_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughRGB2DI, "Blit11 2D RGB I pixel shader" )); -+ add2DBlitShaderToMap(GL_RG_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughRG2DUI, "Blit11 2D RG UI pixel shader" )); -+ add2DBlitShaderToMap(GL_RG_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughRG2DI, "Blit11 2D RG I pixel shader" )); -+ add2DBlitShaderToMap(GL_RED_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughR2DUI, "Blit11 2D R UI pixel shader" )); -+ add2DBlitShaderToMap(GL_RED_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughR2DI, "Blit11 2D R I pixel shader" )); - add3DBlitShaderToMap(GL_RGBA, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA3D, "Blit11 3D RGBA pixel shader" )); - add3DBlitShaderToMap(GL_RGBA_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA3DUI, "Blit11 3D UI RGBA pixel shader" )); - add3DBlitShaderToMap(GL_RGBA_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughRGBA3DI, "Blit11 3D I RGBA pixel shader" )); -@@ -1003,7 +1011,6 @@ void Blit11::buildShaderMap() - add3DBlitShaderToMap(GL_LUMINANCE, false, d3d11::CompilePS(device, g_PS_PassthroughLum3D, "Blit11 3D luminance pixel shader" )); - add3DBlitShaderToMap(GL_LUMINANCE_ALPHA, false, d3d11::CompilePS(device, g_PS_PassthroughLumAlpha3D, "Blit11 3D luminance alpha pixel shader")); - -- addSwizzleShaderToMap(GL_FLOAT, D3D_SRV_DIMENSION_TEXTURE2D, d3d11::CompilePS(device, g_PS_SwizzleF2D, "Blit11 2D F swizzle pixel shader" )); - addSwizzleShaderToMap(GL_UNSIGNED_INT, D3D_SRV_DIMENSION_TEXTURE2D, d3d11::CompilePS(device, g_PS_SwizzleUI2D, "Blit11 2D UI swizzle pixel shader")); - addSwizzleShaderToMap(GL_INT, D3D_SRV_DIMENSION_TEXTURE2D, d3d11::CompilePS(device, g_PS_SwizzleI2D, "Blit11 2D I swizzle pixel shader" )); - -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.cpp -index 2d5fa3c..5aab379 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.cpp -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.cpp -@@ -753,7 +753,9 @@ void Buffer11::NativeBuffer11::fillBufferDesc(D3D11_BUFFER_DESC* bufferDesc, Ren - - case BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK: - bufferDesc->Usage = D3D11_USAGE_DEFAULT; -- bufferDesc->BindFlags = D3D11_BIND_VERTEX_BUFFER | D3D11_BIND_STREAM_OUTPUT; -+ bufferDesc->BindFlags = D3D11_BIND_VERTEX_BUFFER; -+ if (!renderer->isLevel9()) -+ bufferDesc->BindFlags |= D3D11_BIND_STREAM_OUTPUT; - bufferDesc->CPUAccessFlags = 0; - break; - -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp -index 4630762..7185a05 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp -@@ -104,7 +104,7 @@ Clear11::Clear11(Renderer11 *renderer) - rsDesc.DepthBias = 0; - rsDesc.DepthBiasClamp = 0.0f; - rsDesc.SlopeScaledDepthBias = 0.0f; -- rsDesc.DepthClipEnable = FALSE; -+ rsDesc.DepthClipEnable = renderer->isLevel9(); - rsDesc.ScissorEnable = FALSE; - rsDesc.MultisampleEnable = FALSE; - rsDesc.AntialiasedLineEnable = FALSE; -@@ -114,6 +114,11 @@ Clear11::Clear11(Renderer11 *renderer) - d3d11::SetDebugName(mRasterizerState, "Clear11 masked clear rasterizer state"); - - mFloatClearShader = CreateClearShader(device, DXGI_FORMAT_R32G32B32A32_FLOAT, g_VS_ClearFloat, g_PS_ClearFloat); -+ if (mRenderer->isLevel9()) { -+ memset(&mUintClearShader, 0, sizeof(ClearShader)); -+ memset(&mIntClearShader, 0, sizeof(ClearShader)); -+ return; -+ } - mUintClearShader = CreateClearShader(device, DXGI_FORMAT_R32G32B32A32_UINT, g_VS_ClearUint, g_PS_ClearUint ); - mIntClearShader = CreateClearShader(device, DXGI_FORMAT_R32G32B32A32_SINT, g_VS_ClearSint, g_PS_ClearSint ); - } -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.cpp -index a4072d8..6a3d347 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.cpp -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.cpp -@@ -133,10 +133,13 @@ gl::Error PixelTransfer11::loadResources() - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal buffer to texture vertex shader."); - } - -- mBufferToTextureGS = d3d11::CompileGS(device, g_GS_BufferToTexture, "BufferToTexture GS"); -- if (!mBufferToTextureGS) -+ if (!mRenderer->isLevel9()) - { -- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal buffer to texture geometry shader."); -+ mBufferToTextureGS = d3d11::CompileGS(device, g_GS_BufferToTexture, "BufferToTexture GS"); -+ if (!mBufferToTextureGS) -+ { -+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal buffer to texture geometry shader."); -+ } - } - - gl::Error error = buildShaderMap(); -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp -index ffc6cc9..f6ba930 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp -@@ -153,6 +153,24 @@ Renderer11::Renderer11(egl::Display *display, EGLNativeDisplayType hDc, const eg - } - } - -+#if !defined(ANGLE_ENABLE_D3D9) -+ if (requestedMajorVersion == EGL_DONT_CARE || requestedMajorVersion >= 9) -+ { -+ if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 3) -+ { -+ mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_3); -+ } -+ if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 2) -+ { -+ mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_2); -+ } -+ if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 1) -+ { -+ mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_1); -+ } -+ } -+#endif -+ - mDriverType = (attributes.get(EGL_PLATFORM_ANGLE_USE_WARP_ANGLE, EGL_FALSE) == EGL_TRUE) ? D3D_DRIVER_TYPE_WARP - : D3D_DRIVER_TYPE_HARDWARE; - } -@@ -1170,6 +1188,83 @@ gl::Error Renderer11::drawElements(GLenum mode, GLsizei count, GLenum type, cons - return gl::Error(GL_NO_ERROR); - } - } -+template -+static void fillLineLoopIndices(GLenum type, GLsizei count, const GLvoid *indices, T *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(); -+ } -+} -+ -+template -+static void fillTriangleFanIndices(GLenum type, unsigned int numTris, const GLvoid *indices, T *data) -+{ -+ switch (type) -+ { -+ case GL_NONE: // Non-indexed draw -+ for (unsigned int i = 0; i < numTris; i++) -+ { -+ data[i*3 + 0] = 0; -+ data[i*3 + 1] = i + 1; -+ data[i*3 + 2] = i + 2; -+ } -+ break; -+ case GL_UNSIGNED_BYTE: -+ for (unsigned int i = 0; i < numTris; i++) -+ { -+ data[i*3 + 0] = static_cast(indices)[0]; -+ data[i*3 + 1] = static_cast(indices)[i + 1]; -+ data[i*3 + 2] = static_cast(indices)[i + 2]; -+ } -+ break; -+ case GL_UNSIGNED_SHORT: -+ for (unsigned int i = 0; i < numTris; i++) -+ { -+ data[i*3 + 0] = static_cast(indices)[0]; -+ data[i*3 + 1] = static_cast(indices)[i + 1]; -+ data[i*3 + 2] = static_cast(indices)[i + 2]; -+ } -+ break; -+ case GL_UNSIGNED_INT: -+ for (unsigned int i = 0; i < numTris; i++) -+ { -+ data[i*3 + 0] = static_cast(indices)[0]; -+ data[i*3 + 1] = static_cast(indices)[i + 1]; -+ data[i*3 + 2] = static_cast(indices)[i + 2]; -+ } -+ break; -+ default: UNREACHABLE(); -+ } -+} - - gl::Error Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer) - { -@@ -1189,10 +1284,13 @@ gl::Error Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *ind - indices = bufferData + offset; - } - -+ // TODO: some level 9 hardware supports 32-bit indices; test and store support instead -+ const int indexType = isLevel9() ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT; -+ - if (!mLineLoopIB) - { - mLineLoopIB = new StreamingIndexBufferInterface(this); -- gl::Error error = mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT); -+ gl::Error error = mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, indexType); - if (error.isError()) - { - SafeDelete(mLineLoopIB); -@@ -1203,7 +1301,8 @@ gl::Error Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *ind - // Checked by Renderer11::applyPrimitiveType - ASSERT(count >= 0); - -- if (static_cast(count) + 1 > (std::numeric_limits::max() / sizeof(unsigned int))) -+ int indexTypeSize = indexType == GL_UNSIGNED_SHORT ? sizeof(unsigned short) : sizeof(unsigned int); -+ if (static_cast(count) + 1 > (std::numeric_limits::max() / indexTypeSize)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create a 32-bit looping index buffer for GL_LINE_LOOP, too many indices required."); - } -@@ -1223,42 +1322,12 @@ gl::Error Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *ind - return error; - } - -- unsigned int *data = reinterpret_cast(mappedMemory); -+ if (indexType == GL_UNSIGNED_SHORT) -+ fillLineLoopIndices(type, count, indices, reinterpret_cast(mappedMemory)); -+ else -+ fillLineLoopIndices(type, count, indices, reinterpret_cast(mappedMemory)); - unsigned int indexBufferOffset = offset; - -- switch (type) -- { -- case GL_NONE: // Non-indexed draw -- for (int i = 0; i < count; i++) -- { -- data[i] = i; -- } -- data[count] = 0; -- break; -- case GL_UNSIGNED_BYTE: -- for (int i = 0; i < count; i++) -- { -- data[i] = static_cast(indices)[i]; -- } -- data[count] = static_cast(indices)[0]; -- break; -- case GL_UNSIGNED_SHORT: -- for (int i = 0; i < count; i++) -- { -- data[i] = static_cast(indices)[i]; -- } -- data[count] = static_cast(indices)[0]; -- break; -- case GL_UNSIGNED_INT: -- for (int i = 0; i < count; i++) -- { -- data[i] = static_cast(indices)[i]; -- } -- data[count] = static_cast(indices)[0]; -- break; -- default: UNREACHABLE(); -- } -- - error = mLineLoopIB->unmapBuffer(); - if (error.isError()) - { -@@ -1300,10 +1369,12 @@ gl::Error Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid * - indices = bufferData + offset; - } - -+ const int indexType = isLevel9() ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT; -+ - if (!mTriangleFanIB) - { - mTriangleFanIB = new StreamingIndexBufferInterface(this); -- gl::Error error = mTriangleFanIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT); -+ gl::Error error = mTriangleFanIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, indexType); - if (error.isError()) - { - SafeDelete(mTriangleFanIB); -@@ -1316,13 +1387,14 @@ gl::Error Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid * - - const unsigned int numTris = count - 2; - -- if (numTris > (std::numeric_limits::max() / (sizeof(unsigned int) * 3))) -+ int indexTypeSize = indexType == GL_UNSIGNED_SHORT ? sizeof(unsigned short) : sizeof(unsigned int); -+ if (numTris > (std::numeric_limits::max() / (indexTypeSize * 3))) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create a scratch index buffer for GL_TRIANGLE_FAN, too many indices required."); - } - -- const unsigned int spaceNeeded = (numTris * 3) * sizeof(unsigned int); -- gl::Error error = mTriangleFanIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT); -+ const unsigned int spaceNeeded = (numTris * 3) * indexTypeSize; -+ gl::Error error = mTriangleFanIB->reserveBufferSpace(spaceNeeded, indexType); - if (error.isError()) - { - return error; -@@ -1336,45 +1408,12 @@ gl::Error Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid * - return error; - } - -- unsigned int *data = reinterpret_cast(mappedMemory); -- unsigned int indexBufferOffset = offset; -+ if (indexType == GL_UNSIGNED_SHORT) -+ fillTriangleFanIndices(type, numTris, indices, reinterpret_cast(mappedMemory)); -+ else -+ fillTriangleFanIndices(type, numTris, indices, reinterpret_cast(mappedMemory)); - -- switch (type) -- { -- case GL_NONE: // Non-indexed draw -- for (unsigned int i = 0; i < numTris; i++) -- { -- data[i*3 + 0] = 0; -- data[i*3 + 1] = i + 1; -- data[i*3 + 2] = i + 2; -- } -- break; -- case GL_UNSIGNED_BYTE: -- for (unsigned int i = 0; i < numTris; i++) -- { -- data[i*3 + 0] = static_cast(indices)[0]; -- data[i*3 + 1] = static_cast(indices)[i + 1]; -- data[i*3 + 2] = static_cast(indices)[i + 2]; -- } -- break; -- case GL_UNSIGNED_SHORT: -- for (unsigned int i = 0; i < numTris; i++) -- { -- data[i*3 + 0] = static_cast(indices)[0]; -- data[i*3 + 1] = static_cast(indices)[i + 1]; -- data[i*3 + 2] = static_cast(indices)[i + 2]; -- } -- break; -- case GL_UNSIGNED_INT: -- for (unsigned int i = 0; i < numTris; i++) -- { -- data[i*3 + 0] = static_cast(indices)[0]; -- data[i*3 + 1] = static_cast(indices)[i + 1]; -- data[i*3 + 2] = static_cast(indices)[i + 2]; -- } -- break; -- default: UNREACHABLE(); -- } -+ unsigned int indexBufferOffset = offset; - - error = mTriangleFanIB->unmapBuffer(); - if (error.isError()) -@@ -1634,7 +1673,7 @@ gl::Error Renderer11::applyUniforms(const ProgramImpl &program, const std::vecto - } - - // needed for the point sprite geometry shader -- if (mCurrentGeometryConstantBuffer != mDriverConstantBufferPS) -+ if (mFeatureLevel >= D3D_FEATURE_LEVEL_10_0 && mCurrentGeometryConstantBuffer != mDriverConstantBufferPS) - { - mDeviceContext->GSSetConstantBuffers(0, 1, &mDriverConstantBufferPS); - mCurrentGeometryConstantBuffer = mDriverConstantBufferPS; -@@ -1938,7 +1977,10 @@ int Renderer11::getMajorShaderModel() const - { - case D3D_FEATURE_LEVEL_11_0: return D3D11_SHADER_MAJOR_VERSION; // 5 - case D3D_FEATURE_LEVEL_10_1: return D3D10_1_SHADER_MAJOR_VERSION; // 4 -- case D3D_FEATURE_LEVEL_10_0: return D3D10_SHADER_MAJOR_VERSION; // 4 -+ case D3D_FEATURE_LEVEL_10_0: -+ case D3D_FEATURE_LEVEL_9_3: -+ case D3D_FEATURE_LEVEL_9_2: -+ case D3D_FEATURE_LEVEL_9_1: return D3D10_SHADER_MAJOR_VERSION; // 4 - default: UNREACHABLE(); return 0; - } - } -@@ -1949,7 +1991,10 @@ int Renderer11::getMinorShaderModel() const - { - case D3D_FEATURE_LEVEL_11_0: return D3D11_SHADER_MINOR_VERSION; // 0 - case D3D_FEATURE_LEVEL_10_1: return D3D10_1_SHADER_MINOR_VERSION; // 1 -- case D3D_FEATURE_LEVEL_10_0: return D3D10_SHADER_MINOR_VERSION; // 0 -+ case D3D_FEATURE_LEVEL_10_0: -+ case D3D_FEATURE_LEVEL_9_3: -+ case D3D_FEATURE_LEVEL_9_2: -+ case D3D_FEATURE_LEVEL_9_1: return D3D10_SHADER_MINOR_VERSION; // 0 - default: UNREACHABLE(); return 0; - } - } -@@ -2455,6 +2500,7 @@ gl::Error Renderer11::compileToExecutable(gl::InfoLog &infoLog, const std::strin - - unsigned int profileMajorVersion = 0; - unsigned int profileMinorVersion = 0; -+ const char *profileSuffix = NULL; - switch (mFeatureLevel) - { - case D3D_FEATURE_LEVEL_11_0: -@@ -2469,12 +2515,30 @@ gl::Error Renderer11::compileToExecutable(gl::InfoLog &infoLog, const std::strin - profileMajorVersion = 4; - profileMinorVersion = 0; - break; -+ case D3D_FEATURE_LEVEL_9_3: -+ profileMajorVersion = 4; -+ profileMinorVersion = 0; -+ profileSuffix = "_level_9_3"; -+ break; -+ case D3D_FEATURE_LEVEL_9_2: -+ profileMajorVersion = 4; -+ profileMinorVersion = 0; -+ profileSuffix = "_level_9_2"; -+ break; -+ case D3D_FEATURE_LEVEL_9_1: -+ profileMajorVersion = 4; -+ profileMinorVersion = 0; -+ profileSuffix = "_level_9_1"; -+ break; -+ break; - default: - UNREACHABLE(); - return gl::Error(GL_INVALID_OPERATION); - } - - std::string profile = FormatString("%s_%u_%u", profileType, profileMajorVersion, profileMinorVersion); -+ if (profileSuffix) -+ profile += profileSuffix; - - UINT flags = D3DCOMPILE_OPTIMIZATION_LEVEL2; - -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h -index c789cae..d44bd2f 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h -@@ -188,6 +188,7 @@ class Renderer11 : public RendererD3D - ID3D11Device *getDevice() { return mDevice; } - ID3D11DeviceContext *getDeviceContext() { return mDeviceContext; }; - DXGIFactory *getDxgiFactory() { return mDxgiFactory; }; -+ bool isLevel9() { return mFeatureLevel <= D3D_FEATURE_LEVEL_9_3; } - - Blit11 *getBlitter() { return mBlit; } - -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.cpp -index 4287918..74af27e 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.cpp -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.cpp -@@ -744,7 +744,7 @@ gl::Error TextureStorage11_2D::getResource(ID3D11Resource **outResource) - D3D11_TEXTURE2D_DESC desc; - desc.Width = mTextureWidth; // Compressed texture size constraints? - desc.Height = mTextureHeight; -- desc.MipLevels = mMipLevels; -+ desc.MipLevels = mRenderer->isLevel9() ? 1 : mMipLevels; - desc.ArraySize = 1; - desc.Format = mTextureFormat; - desc.SampleDesc.Count = 1; -@@ -863,7 +863,7 @@ gl::Error TextureStorage11_2D::createSRV(int baseLevel, int mipLevels, DXGI_FORM - srvDesc.Format = format; - srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MostDetailedMip = mTopLevel + baseLevel; -- srvDesc.Texture2D.MipLevels = mipLevels; -+ srvDesc.Texture2D.MipLevels = mRenderer->isLevel9() ? -1 : mipLevels; - - ID3D11Device *device = mRenderer->getDevice(); - HRESULT result = device->CreateShaderResourceView(texture, &srvDesc, outSRV); -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.cpp -index 1ea916d..90a879e 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.cpp -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.cpp -@@ -557,7 +557,7 @@ D3D11LoadFunctionMap BuildD3D11LoadFunctionMap() - InsertLoadFunction(&map, GL_ALPHA, GL_HALF_FLOAT_OES, LoadA16FToRGBA16F ); - - // From GL_EXT_texture_storage -- InsertLoadFunction(&map, GL_ALPHA8_EXT, GL_UNSIGNED_BYTE, LoadToNative ); -+ InsertLoadFunction(&map, GL_ALPHA8_EXT, GL_UNSIGNED_BYTE, LoadA8ToRGBA8 ); - InsertLoadFunction(&map, GL_LUMINANCE8_EXT, GL_UNSIGNED_BYTE, LoadL8ToRGBA8 ); - InsertLoadFunction(&map, GL_LUMINANCE8_ALPHA8_EXT, GL_UNSIGNED_BYTE, LoadLA8ToRGBA8 ); - InsertLoadFunction(&map, GL_ALPHA32F_EXT, GL_FLOAT, LoadA32FToRGBA32F ); -@@ -795,7 +795,7 @@ static D3D11ES3FormatMap BuildD3D11FormatMap() - - // From GL_EXT_texture_storage - // | GL internal format | D3D11 texture format | D3D11 SRV format | D3D11 RTV format | D3D11 DSV format | -- InsertD3D11FormatInfo(&map, GL_ALPHA8_EXT, DXGI_FORMAT_A8_UNORM, DXGI_FORMAT_A8_UNORM, DXGI_FORMAT_A8_UNORM, DXGI_FORMAT_UNKNOWN ); -+ InsertD3D11FormatInfo(&map, GL_ALPHA8_EXT, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN ); - InsertD3D11FormatInfo(&map, GL_LUMINANCE8_EXT, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN ); - InsertD3D11FormatInfo(&map, GL_ALPHA32F_EXT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_UNKNOWN ); - InsertD3D11FormatInfo(&map, GL_LUMINANCE32F_EXT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_UNKNOWN ); -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp -index 9ffc32e..cbfe557 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp -@@ -284,7 +284,7 @@ static bool GetNPOTTextureSupport(D3D_FEATURE_LEVEL featureLevel) - // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876.aspx - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: -- case D3D_FEATURE_LEVEL_9_1: return false; -+ case D3D_FEATURE_LEVEL_9_1: return true; // Provided that mipmaps & wrap modes are not used - - default: UNREACHABLE(); return false; - } --- -1.9.4.msysgit.1 - diff --git a/src/angle/patches/0012-ANGLE-fix-semantic-index-lookup.patch b/src/angle/patches/0012-ANGLE-fix-semantic-index-lookup.patch deleted file mode 100644 index afc9f256a1..0000000000 --- a/src/angle/patches/0012-ANGLE-fix-semantic-index-lookup.patch +++ /dev/null @@ -1,48 +0,0 @@ -From bbfd3cfcf6e1195d86368b61ce39504ce6acda50 Mon Sep 17 00:00:00 2001 -From: Andrew Knight -Date: Wed, 12 Nov 2014 17:09:23 +0200 -Subject: [PATCH 12/16] ANGLE: fix semantic index lookup - -The sorted semantic index table was returning a direct mapping to the -new indices, instead of the old indices. This caused a mismatch in the -GL type lookup for the translated attribute. - -Change-Id: I75d05ed707f56c45210e3dcbc277f894e3dc5a48 ---- - src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp | 2 +- - .../angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.cpp | 4 ++-- - 2 files changed, 3 insertions(+), 3 deletions(-) - -diff --git a/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp b/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp -index 0619023..6d64b38 100644 ---- a/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp -+++ b/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp -@@ -1216,7 +1216,7 @@ void ProgramBinary::sortAttributesByLayout(rx::TranslatedAttribute attributes[MA - for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) - { - int oldIndex = mAttributesByLayout[i]; -- sortedSemanticIndices[i] = mSemanticIndex[oldIndex]; -+ sortedSemanticIndices[i] = oldIndex; - attributes[i] = oldTranslatedAttributes[oldIndex]; - } - } -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.cpp -index e41f238..ff90a6a 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.cpp -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.cpp -@@ -113,10 +113,10 @@ gl::Error InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl - // Record the type of the associated vertex shader vector in our key - // This will prevent mismatched vertex shaders from using the same input layout - GLint attributeSize; -- programBinary->getActiveAttribute(ilKey.elementCount, 0, NULL, &attributeSize, &ilKey.elements[ilKey.elementCount].glslElementType, NULL); -+ programBinary->getActiveAttribute(sortedSemanticIndices[i], 0, NULL, &attributeSize, &ilKey.elements[ilKey.elementCount].glslElementType, NULL); - - ilKey.elements[ilKey.elementCount].desc.SemanticName = semanticName; -- ilKey.elements[ilKey.elementCount].desc.SemanticIndex = sortedSemanticIndices[i]; -+ ilKey.elements[ilKey.elementCount].desc.SemanticIndex = i; - ilKey.elements[ilKey.elementCount].desc.Format = vertexFormatInfo.nativeFormat; - ilKey.elements[ilKey.elementCount].desc.InputSlot = i; - ilKey.elements[ilKey.elementCount].desc.AlignedByteOffset = 0; --- -1.9.4.msysgit.1 - diff --git a/src/angle/patches/0013-ANGLE-Add-support-for-querying-platform-device.patch b/src/angle/patches/0013-ANGLE-Add-support-for-querying-platform-device.patch deleted file mode 100644 index b43dcc368b..0000000000 --- a/src/angle/patches/0013-ANGLE-Add-support-for-querying-platform-device.patch +++ /dev/null @@ -1,100 +0,0 @@ -From 5ef9348de2624c21be1c9fddd265fec5a0851d25 Mon Sep 17 00:00:00 2001 -From: Andrew Knight -Date: Thu, 13 Nov 2014 15:34:26 +0200 -Subject: [PATCH 13/16] ANGLE: Add support for querying platform device - -The EGL_EXT_device_base extension allows for querying the platform -device of the graphics hardware via eglQueryDisplayAttribEXT(). -As that extension is not supported by ANGLE, this patch adds similar -functionality to the existing eglQuerySurfacePointerANGLE API. When -EGL_DEVICE_EXT is passed as the queried attribute, the underlying -D3D/DXGI device pointer is passed back to the caller via the value -argument. - -The D3D device is needed for video support in QtMultimedia as well as -the IDXGIDevice3::Trim() calls required by the Windows Store. - -Change-Id: Ibdf228d81d6604e56db9dd8597d7cd2983ebc428 ---- - src/3rdparty/angle/src/libEGL/libEGL.cpp | 50 +++++++++++++++++++++++++------- - 1 file changed, 39 insertions(+), 11 deletions(-) - -diff --git a/src/3rdparty/angle/src/libEGL/libEGL.cpp b/src/3rdparty/angle/src/libEGL/libEGL.cpp -index dc20d85..68399d6 100644 ---- a/src/3rdparty/angle/src/libEGL/libEGL.cpp -+++ b/src/3rdparty/angle/src/libEGL/libEGL.cpp -@@ -17,6 +17,9 @@ - #include "libGLESv2/Texture.h" - #include "libGLESv2/main.h" - #include "libGLESv2/renderer/SwapChain.h" -+#if defined(ANGLE_ENABLE_D3D11) -+# include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" -+#endif - - #include "libEGL/main.h" - #include "libEGL/Display.h" -@@ -582,25 +585,50 @@ EGLBoolean __stdcall eglQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surf - egl::Display *display = static_cast(dpy); - egl::Surface *eglSurface = (egl::Surface*)surface; - -- if (!validateSurface(display, eglSurface)) -- { -- return EGL_FALSE; -- } -- -- if (surface == EGL_NO_SURFACE) -- { -- recordError(egl::Error(EGL_BAD_SURFACE)); -- return EGL_FALSE; -- } -- - switch (attribute) - { - case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE: - { -+ if (!validateSurface(display, eglSurface)) -+ { -+ return EGL_FALSE; -+ } -+ -+ if (surface == EGL_NO_SURFACE) -+ { -+ recordError(egl::Error(EGL_BAD_SURFACE)); -+ return EGL_FALSE; -+ } -+ - rx::SwapChain *swapchain = eglSurface->getSwapChain(); - *value = (void*) (swapchain ? swapchain->getShareHandle() : NULL); - } - break; -+#if defined(ANGLE_ENABLE_D3D11) -+ case EGL_DEVICE_EXT: -+ { -+ if (!validateDisplay(display)) -+ { -+ return EGL_FALSE; -+ } -+ -+ rx::Renderer *renderer = display->getRenderer(); -+ if (!renderer) -+ { -+ *value = NULL; -+ break; -+ } -+ -+ if (renderer->getMajorShaderModel() < 4) -+ { -+ recordError(egl::Error(EGL_BAD_CONTEXT)); -+ return EGL_FALSE; -+ } -+ -+ *value = static_cast(renderer)->getDevice(); -+ } -+ break; -+#endif - default: - recordError(egl::Error(EGL_BAD_ATTRIBUTE)); - return EGL_FALSE; --- -1.9.4.msysgit.1 - diff --git a/src/angle/patches/0014-Let-ANGLE-use-multithreaded-devices-if-necessary.patch b/src/angle/patches/0014-Let-ANGLE-use-multithreaded-devices-if-necessary.patch deleted file mode 100644 index 9ceb34d964..0000000000 --- a/src/angle/patches/0014-Let-ANGLE-use-multithreaded-devices-if-necessary.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 5b3bc73210ed1847d9bd7a94f06cc0d5de8e0b89 Mon Sep 17 00:00:00 2001 -From: Michael Bruning -Date: Thu, 13 Nov 2014 15:40:10 +0200 -Subject: [PATCH 14/16] Let ANGLE use multithreaded devices if necessary. - -This is needed to prevent lock-ups in application that use ANGLE from -multiple threads, as e.g. QtWebEngine based applications do. - -The environment variable QT_D3DCREATE_MULTITHREADED is used to -communicate this from the QtWebEngine module. - -Change-Id: Ibd5a5c75eb68af567d420d9a35efb3490c93b27c ---- - src/3rdparty/angle/src/common/platform.h | 1 + - .../angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp | 10 ++++++++++ - .../angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp | 4 ++++ - 3 files changed, 15 insertions(+) - -diff --git a/src/3rdparty/angle/src/common/platform.h b/src/3rdparty/angle/src/common/platform.h -index 0065ec7..8b2190d 100644 ---- a/src/3rdparty/angle/src/common/platform.h -+++ b/src/3rdparty/angle/src/common/platform.h -@@ -57,6 +57,7 @@ - - # if defined(ANGLE_ENABLE_D3D11) - # include -+# include - # include - # include - # include -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp -index f6ba930..46b9984 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp -@@ -258,6 +258,16 @@ EGLint Renderer11::initialize() - } - - #if !defined(ANGLE_ENABLE_WINDOWS_STORE) -+ static wchar_t *qt_d3dcreate_multihreaded_var = _wgetenv(L"QT_D3DCREATE_MULTITHREADED"); -+ if (qt_d3dcreate_multihreaded_var && wcsstr(qt_d3dcreate_multihreaded_var, L"1")) -+ { -+ ID3D10Multithread *multithread; -+ result = mDevice->QueryInterface(IID_PPV_ARGS(&multithread)); -+ ASSERT(SUCCEEDED(result)); -+ result = multithread->SetMultithreadProtected(true); -+ ASSERT(SUCCEEDED(result)); -+ multithread->Release(); -+ } - #if !ANGLE_SKIP_DXGI_1_2_CHECK - // In order to create a swap chain for an HWND owned by another process, DXGI 1.2 is required. - // The easiest way to check is to query for a IDXGIDevice2. -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp -index 82963ec..4c552b2 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp -@@ -299,6 +299,10 @@ EGLint Renderer9::initialize() - D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters(); - DWORD behaviorFlags = D3DCREATE_FPU_PRESERVE | D3DCREATE_NOWINDOWCHANGES; - -+ static wchar_t *qt_d3dcreate_multihreaded_var = _wgetenv(L"QT_D3DCREATE_MULTITHREADED"); -+ if (qt_d3dcreate_multihreaded_var && wcsstr(qt_d3dcreate_multihreaded_var, L"1")) -+ behaviorFlags |= D3DCREATE_MULTITHREADED; -+ - { - result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE, &presentParameters, &mDevice); - } --- -1.9.4.msysgit.1 - diff --git a/src/angle/patches/0015-ANGLE-Fix-angle-d3d11-on-MSVC2010.patch b/src/angle/patches/0015-ANGLE-Fix-angle-d3d11-on-MSVC2010.patch deleted file mode 100644 index f78474f11a..0000000000 --- a/src/angle/patches/0015-ANGLE-Fix-angle-d3d11-on-MSVC2010.patch +++ /dev/null @@ -1,536 +0,0 @@ -From d9a9219ea2181dd4c1939d05747a21b67f16a906 Mon Sep 17 00:00:00 2001 -From: Andrew Knight -Date: Thu, 13 Nov 2014 16:33:53 +0200 -Subject: [PATCH 15/16] ANGLE: Fix -angle-d3d11 on MSVC2010 - -Allow the D3D11 renderer to build with the June 2010 DirectX SDK. - -Change-Id: I2343acedab16845d6a0d4a53cf3145f583efc4a7 ---- - src/3rdparty/angle/src/common/platform.h | 8 +- - src/3rdparty/angle/src/libGLESv2/Context.cpp | 8 +- - src/3rdparty/angle/src/libGLESv2/Data.h | 2 +- - src/3rdparty/angle/src/libGLESv2/State.cpp | 6 +- - .../src/libGLESv2/renderer/d3d/RendererD3D.cpp | 4 +- - .../libGLESv2/renderer/d3d/d3d11/Renderer11.cpp | 4 +- - .../renderer/d3d/d3d11/renderer11_utils.cpp | 137 +++++++++++++++++++++ - 7 files changed, 156 insertions(+), 13 deletions(-) - -diff --git a/src/3rdparty/angle/src/common/platform.h b/src/3rdparty/angle/src/common/platform.h -index 8b2190d..972eee2 100644 ---- a/src/3rdparty/angle/src/common/platform.h -+++ b/src/3rdparty/angle/src/common/platform.h -@@ -52,17 +52,23 @@ - - # if defined(ANGLE_ENABLE_D3D9) - # include -+# if !defined(COMPILER_IMPLEMENTATION) - # include -+# endif - # endif - - # if defined(ANGLE_ENABLE_D3D11) - # include - # include - # include --# include - # include -+# if defined(_MSC_VER) && (_MSC_VER >= 1700) -+# include - # include -+# endif -+# if !defined(COMPILER_IMPLEMENTATION) - # include -+# endif - # endif - - # if defined(ANGLE_ENABLE_WINDOWS_STORE) -diff --git a/src/3rdparty/angle/src/libGLESv2/Context.cpp b/src/3rdparty/angle/src/libGLESv2/Context.cpp -index fe9b1a2..b87689c 100644 ---- a/src/3rdparty/angle/src/libGLESv2/Context.cpp -+++ b/src/3rdparty/angle/src/libGLESv2/Context.cpp -@@ -168,9 +168,9 @@ Context::~Context() - } - mIncompleteTextures.clear(); - -- for (auto &zeroTexture : mZeroTextures) -+ for (TextureMap::iterator i = mZeroTextures.begin(); i != mZeroTextures.end(); i++) - { -- zeroTexture.second.set(NULL); -+ i->second.set(NULL); - } - mZeroTextures.clear(); - -@@ -354,7 +354,7 @@ void Context::deleteFenceSync(GLsync fenceSync) - - void Context::deleteVertexArray(GLuint vertexArray) - { -- auto vertexArrayObject = mVertexArrayMap.find(vertexArray); -+ VertexArrayMap::iterator vertexArrayObject = mVertexArrayMap.find(vertexArray); - - if (vertexArrayObject != mVertexArrayMap.end()) - { -@@ -460,7 +460,7 @@ FenceSync *Context::getFenceSync(GLsync handle) const - - VertexArray *Context::getVertexArray(GLuint handle) const - { -- auto vertexArray = mVertexArrayMap.find(handle); -+ VertexArrayMap::const_iterator vertexArray = mVertexArrayMap.find(handle); - - if (vertexArray == mVertexArrayMap.end()) - { -diff --git a/src/3rdparty/angle/src/libGLESv2/Data.h b/src/3rdparty/angle/src/libGLESv2/Data.h -index cff872a..9234403 100644 ---- a/src/3rdparty/angle/src/libGLESv2/Data.h -+++ b/src/3rdparty/angle/src/libGLESv2/Data.h -@@ -14,7 +14,7 @@ - namespace gl - { - --struct Data final -+struct Data - { - public: - Data(GLint clientVersion, const State &state, const Caps &caps, -diff --git a/src/3rdparty/angle/src/libGLESv2/State.cpp b/src/3rdparty/angle/src/libGLESv2/State.cpp -index e7acda2..b5b62f5 100644 ---- a/src/3rdparty/angle/src/libGLESv2/State.cpp -+++ b/src/3rdparty/angle/src/libGLESv2/State.cpp -@@ -665,13 +665,13 @@ void State::detachTexture(const TextureMap &zeroTextures, GLuint texture) - - void State::initializeZeroTextures(const TextureMap &zeroTextures) - { -- for (const auto &zeroTexture : zeroTextures) -+ for (TextureMap::const_iterator i = zeroTextures.begin(); i != zeroTextures.end(); i++) - { -- auto &samplerTextureArray = mSamplerTextures[zeroTexture.first]; -+ TextureBindingVector &samplerTextureArray = mSamplerTextures[i->first]; - - for (size_t textureUnit = 0; textureUnit < samplerTextureArray.size(); ++textureUnit) - { -- samplerTextureArray[textureUnit].set(zeroTexture.second.get()); -+ samplerTextureArray[textureUnit].set(i->second.get()); - } - } - } -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RendererD3D.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RendererD3D.cpp -index 6f58243..97da6da 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RendererD3D.cpp -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RendererD3D.cpp -@@ -27,9 +27,9 @@ RendererD3D::RendererD3D(egl::Display *display) - - RendererD3D::~RendererD3D() - { -- for (auto &incompleteTexture : mIncompleteTextures) -+ for (gl::TextureMap::iterator i = mIncompleteTextures.begin(); i != mIncompleteTextures.end(); ++i) - { -- incompleteTexture.second.set(NULL); -+ i->second.set(NULL); - } - mIncompleteTextures.clear(); - } -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp -index 46b9984..a28fd78 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp -@@ -873,7 +873,7 @@ bool Renderer11::applyPrimitiveType(GLenum mode, GLsizei count) - - void Renderer11::unsetSRVsWithResource(gl::SamplerType samplerType, const ID3D11Resource *resource) - { -- auto ¤tSRVs = (samplerType == gl::SAMPLER_VERTEX ? mCurVertexSRVs : mCurPixelSRVs); -+ std::vector ¤tSRVs = (samplerType == gl::SAMPLER_VERTEX ? mCurVertexSRVs : mCurPixelSRVs); - - for (size_t resourceIndex = 0; resourceIndex < currentSRVs.size(); ++resourceIndex) - { -@@ -3398,7 +3398,7 @@ Workarounds Renderer11::generateWorkarounds() const - - void Renderer11::setShaderResource(gl::SamplerType shaderType, UINT resourceSlot, ID3D11ShaderResourceView *srv) - { -- auto ¤tSRVs = (shaderType == gl::SAMPLER_VERTEX ? mCurVertexSRVs : mCurPixelSRVs); -+ std::vector ¤tSRVs = (shaderType == gl::SAMPLER_VERTEX ? mCurVertexSRVs : mCurPixelSRVs); - - ASSERT(static_cast(resourceSlot) < currentSRVs.size()); - -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp -index cbfe557..5831c57 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp -@@ -18,6 +18,85 @@ - - #include - -+#ifndef D3D_FL9_1_DEFAULT_MAX_ANISOTROPY -+# define D3D_FL9_1_DEFAULT_MAX_ANISOTROPY 2 -+#endif -+#ifndef D3D_FL9_1_SIMULTANEOUS_RENDER_TARGET_COUNT -+# define D3D_FL9_1_SIMULTANEOUS_RENDER_TARGET_COUNT 1 -+#endif -+#ifndef D3D_FL9_3_SIMULTANEOUS_RENDER_TARGET_COUNT -+# define D3D_FL9_3_SIMULTANEOUS_RENDER_TARGET_COUNT 4 -+#endif -+#ifndef D3D_FL9_1_IA_PRIMITIVE_MAX_COUNT -+# define D3D_FL9_1_IA_PRIMITIVE_MAX_COUNT 65535 -+#endif -+#ifndef D3D_FL9_2_IA_PRIMITIVE_MAX_COUNT -+# define D3D_FL9_2_IA_PRIMITIVE_MAX_COUNT 1048575 -+#endif -+#ifndef D3D_FL9_1_REQ_TEXTURECUBE_DIMENSION -+# define D3D_FL9_1_REQ_TEXTURECUBE_DIMENSION 512 -+#endif -+#ifndef D3D_FL9_3_REQ_TEXTURECUBE_DIMENSION -+# define D3D_FL9_3_REQ_TEXTURECUBE_DIMENSION 4096 -+#endif -+#ifndef D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION -+# define D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION 2048 -+#endif -+#ifndef D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION -+# define D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION 256 -+#endif -+#ifndef D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION -+# define D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION 4096 -+#endif -+#ifndef D3D11_REQ_TEXTURECUBE_DIMENSION -+# define D3D11_REQ_TEXTURECUBE_DIMENSION 16384 -+#endif -+#ifndef D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION -+# define D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION 2048 -+#endif -+#ifndef D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION -+# define D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION 2048 -+#endif -+#ifndef D3D11_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP -+# define D3D11_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP 32 -+#endif -+#ifndef D3D11_REQ_DRAW_VERTEX_COUNT_2_TO_EXP -+# define D3D11_REQ_DRAW_VERTEX_COUNT_2_TO_EXP 32 -+#endif -+#ifndef D3D10_1_STANDARD_VERTEX_ELEMENT_COUNT -+# define D3D10_1_STANDARD_VERTEX_ELEMENT_COUNT 32 -+#endif -+#ifndef D3D11_STANDARD_VERTEX_ELEMENT_COUNT -+# define D3D11_STANDARD_VERTEX_ELEMENT_COUNT 32 -+#endif -+#ifndef D3D10_1_SO_BUFFER_SLOT_COUNT -+# define D3D10_1_SO_BUFFER_SLOT_COUNT 4 -+#endif -+#ifndef D3D11_SO_BUFFER_SLOT_COUNT -+# define D3D11_SO_BUFFER_SLOT_COUNT 4 -+#endif -+#ifndef D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT -+# define D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT 14 -+#endif -+#ifndef D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT -+# define D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT 16 -+#endif -+#ifndef D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE -+# define D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE -8 -+#endif -+#ifndef D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE -+# define D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE 7 -+#endif -+#ifndef D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT -+# define D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT 4096 -+#endif -+#ifndef D3D11_PS_INPUT_REGISTER_COUNT -+# define D3D11_PS_INPUT_REGISTER_COUNT 32 -+#endif -+#ifndef D3D10_1_VS_OUTPUT_REGISTER_COUNT -+# define D3D10_1_VS_OUTPUT_REGISTER_COUNT 32 -+#endif -+ - namespace rx - { - -@@ -276,7 +355,9 @@ static bool GetNPOTTextureSupport(D3D_FEATURE_LEVEL featureLevel) - { - switch (featureLevel) - { -+#if !defined(_MSC_VER) || (_MSC_VER >= 1800) - case D3D_FEATURE_LEVEL_11_1: -+#endif - case D3D_FEATURE_LEVEL_11_0: - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: return true; -@@ -294,7 +375,9 @@ static float GetMaximumAnisotropy(D3D_FEATURE_LEVEL featureLevel) - { - switch (featureLevel) - { -+#if !defined(_MSC_VER) || (_MSC_VER >= 1800) - case D3D_FEATURE_LEVEL_11_1: -+#endif - case D3D_FEATURE_LEVEL_11_0: return D3D11_MAX_MAXANISOTROPY; - - case D3D_FEATURE_LEVEL_10_1: -@@ -314,7 +397,9 @@ static bool GetOcclusionQuerySupport(D3D_FEATURE_LEVEL featureLevel) - { - switch (featureLevel) - { -+#if !defined(_MSC_VER) || (_MSC_VER >= 1800) - case D3D_FEATURE_LEVEL_11_1: -+#endif - case D3D_FEATURE_LEVEL_11_0: - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: return true; -@@ -334,7 +419,9 @@ static bool GetEventQuerySupport(D3D_FEATURE_LEVEL featureLevel) - - switch (featureLevel) - { -+#if !defined(_MSC_VER) || (_MSC_VER >= 1800) - case D3D_FEATURE_LEVEL_11_1: -+#endif - case D3D_FEATURE_LEVEL_11_0: - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: -@@ -352,7 +439,9 @@ static bool GetInstancingSupport(D3D_FEATURE_LEVEL featureLevel) - - switch (featureLevel) - { -+#if !defined(_MSC_VER) || (_MSC_VER >= 1800) - case D3D_FEATURE_LEVEL_11_1: -+#endif - case D3D_FEATURE_LEVEL_11_0: - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: -@@ -375,7 +464,9 @@ static bool GetDerivativeInstructionSupport(D3D_FEATURE_LEVEL featureLevel) - - switch (featureLevel) - { -+#if !defined(_MSC_VER) || (_MSC_VER >= 1800) - case D3D_FEATURE_LEVEL_11_1: -+#endif - case D3D_FEATURE_LEVEL_11_0: - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: -@@ -393,7 +484,9 @@ static size_t GetMaximumSimultaneousRenderTargets(D3D_FEATURE_LEVEL featureLevel - - switch (featureLevel) - { -+#if !defined(_MSC_VER) || (_MSC_VER >= 1800) - case D3D_FEATURE_LEVEL_11_1: -+#endif - case D3D_FEATURE_LEVEL_11_0: return D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; - - case D3D_FEATURE_LEVEL_10_1: -@@ -411,7 +504,9 @@ static size_t GetMaximum2DTextureSize(D3D_FEATURE_LEVEL featureLevel) - { - switch (featureLevel) - { -+#if !defined(_MSC_VER) || (_MSC_VER >= 1800) - case D3D_FEATURE_LEVEL_11_1: -+#endif - case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; - - case D3D_FEATURE_LEVEL_10_1: -@@ -429,7 +524,9 @@ static size_t GetMaximumCubeMapTextureSize(D3D_FEATURE_LEVEL featureLevel) - { - switch (featureLevel) - { -+#if !defined(_MSC_VER) || (_MSC_VER >= 1800) - case D3D_FEATURE_LEVEL_11_1: -+#endif - case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURECUBE_DIMENSION; - - case D3D_FEATURE_LEVEL_10_1: -@@ -447,7 +544,9 @@ static size_t GetMaximum2DTextureArraySize(D3D_FEATURE_LEVEL featureLevel) - { - switch (featureLevel) - { -+#if !defined(_MSC_VER) || (_MSC_VER >= 1800) - case D3D_FEATURE_LEVEL_11_1: -+#endif - case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION; - - case D3D_FEATURE_LEVEL_10_1: -@@ -465,7 +564,9 @@ static size_t GetMaximum3DTextureSize(D3D_FEATURE_LEVEL featureLevel) - { - switch (featureLevel) - { -+#if !defined(_MSC_VER) || (_MSC_VER >= 1800) - case D3D_FEATURE_LEVEL_11_1: -+#endif - case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION; - - case D3D_FEATURE_LEVEL_10_1: -@@ -483,7 +584,9 @@ static size_t GetMaximumViewportSize(D3D_FEATURE_LEVEL featureLevel) - { - switch (featureLevel) - { -+#if !defined(_MSC_VER) || (_MSC_VER >= 1800) - case D3D_FEATURE_LEVEL_11_1: -+#endif - case D3D_FEATURE_LEVEL_11_0: return D3D11_VIEWPORT_BOUNDS_MAX; - - case D3D_FEATURE_LEVEL_10_1: -@@ -507,7 +610,9 @@ static size_t GetMaximumDrawIndexedIndexCount(D3D_FEATURE_LEVEL featureLevel) - - switch (featureLevel) - { -+#if !defined(_MSC_VER) || (_MSC_VER >= 1800) - case D3D_FEATURE_LEVEL_11_1: -+#endif - case D3D_FEATURE_LEVEL_11_0: - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: return std::numeric_limits::max(); -@@ -529,7 +634,9 @@ static size_t GetMaximumDrawVertexCount(D3D_FEATURE_LEVEL featureLevel) - - switch (featureLevel) - { -+#if !defined(_MSC_VER) || (_MSC_VER >= 1800) - case D3D_FEATURE_LEVEL_11_1: -+#endif - case D3D_FEATURE_LEVEL_11_0: - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: return std::numeric_limits::max(); -@@ -546,7 +653,9 @@ static size_t GetMaximumVertexInputSlots(D3D_FEATURE_LEVEL featureLevel) - { - switch (featureLevel) - { -+#if !defined(_MSC_VER) || (_MSC_VER >= 1800) - case D3D_FEATURE_LEVEL_11_1: -+#endif - case D3D_FEATURE_LEVEL_11_0: return D3D11_STANDARD_VERTEX_ELEMENT_COUNT; - - case D3D_FEATURE_LEVEL_10_1: return D3D10_1_STANDARD_VERTEX_ELEMENT_COUNT; -@@ -566,7 +675,9 @@ static size_t GetMaximumVertexUniformVectors(D3D_FEATURE_LEVEL featureLevel) - // TODO(geofflang): Remove hard-coded limit once the gl-uniform-arrays test can pass - switch (featureLevel) - { -+#if !defined(_MSC_VER) || (_MSC_VER >= 1800) - case D3D_FEATURE_LEVEL_11_1: -+#endif - case D3D_FEATURE_LEVEL_11_0: return 1024; // D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT; - - case D3D_FEATURE_LEVEL_10_1: -@@ -591,7 +702,9 @@ static size_t GetMaximumVertexUniformBlocks(D3D_FEATURE_LEVEL featureLevel) - { - switch (featureLevel) - { -+#if !defined(_MSC_VER) || (_MSC_VER >= 1800) - case D3D_FEATURE_LEVEL_11_1: -+#endif - case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - GetReservedVertexUniformBuffers(); - - case D3D_FEATURE_LEVEL_10_1: -@@ -618,7 +731,9 @@ static size_t GetMaximumVertexOutputVectors(D3D_FEATURE_LEVEL featureLevel) - - switch (featureLevel) - { -+#if !defined(_MSC_VER) || (_MSC_VER >= 1800) - case D3D_FEATURE_LEVEL_11_1: -+#endif - case D3D_FEATURE_LEVEL_11_0: return D3D11_VS_OUTPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(); - - case D3D_FEATURE_LEVEL_10_1: return D3D10_1_VS_OUTPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(); -@@ -637,7 +752,9 @@ static size_t GetMaximumVertexTextureUnits(D3D_FEATURE_LEVEL featureLevel) - { - switch (featureLevel) - { -+#if !defined(_MSC_VER) || (_MSC_VER >= 1800) - case D3D_FEATURE_LEVEL_11_1: -+#endif - case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT; - - case D3D_FEATURE_LEVEL_10_1: -@@ -659,7 +776,9 @@ static size_t GetMaximumPixelUniformVectors(D3D_FEATURE_LEVEL featureLevel) - // TODO(geofflang): Remove hard-coded limit once the gl-uniform-arrays test can pass - switch (featureLevel) - { -+#if !defined(_MSC_VER) || (_MSC_VER >= 1800) - case D3D_FEATURE_LEVEL_11_1: -+#endif - case D3D_FEATURE_LEVEL_11_0: return 1024; // D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT; - - case D3D_FEATURE_LEVEL_10_1: -@@ -684,7 +803,9 @@ static size_t GetMaximumPixelUniformBlocks(D3D_FEATURE_LEVEL featureLevel) - { - switch (featureLevel) - { -+#if !defined(_MSC_VER) || (_MSC_VER >= 1800) - case D3D_FEATURE_LEVEL_11_1: -+#endif - case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - GetReservedPixelUniformBuffers(); - - case D3D_FEATURE_LEVEL_10_1: -@@ -703,7 +824,9 @@ static size_t GetMaximumPixelInputVectors(D3D_FEATURE_LEVEL featureLevel) - { - switch (featureLevel) - { -+#if !defined(_MSC_VER) || (_MSC_VER >= 1800) - case D3D_FEATURE_LEVEL_11_1: -+#endif - case D3D_FEATURE_LEVEL_11_0: return D3D11_PS_INPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(); - - case D3D_FEATURE_LEVEL_10_1: -@@ -722,7 +845,9 @@ static size_t GetMaximumPixelTextureUnits(D3D_FEATURE_LEVEL featureLevel) - { - switch (featureLevel) - { -+#if !defined(_MSC_VER) || (_MSC_VER >= 1800) - case D3D_FEATURE_LEVEL_11_1: -+#endif - case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT; - - case D3D_FEATURE_LEVEL_10_1: -@@ -741,7 +866,9 @@ static int GetMinimumTexelOffset(D3D_FEATURE_LEVEL featureLevel) - { - switch (featureLevel) - { -+#if !defined(_MSC_VER) || (_MSC_VER >= 1800) - case D3D_FEATURE_LEVEL_11_1: -+#endif - case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE; - - case D3D_FEATURE_LEVEL_10_1: -@@ -760,7 +887,9 @@ static int GetMaximumTexelOffset(D3D_FEATURE_LEVEL featureLevel) - { - switch (featureLevel) - { -+#if !defined(_MSC_VER) || (_MSC_VER >= 1800) - case D3D_FEATURE_LEVEL_11_1: -+#endif - case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE; - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: return D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE; -@@ -783,7 +912,9 @@ static size_t GetMaximumConstantBufferSize(D3D_FEATURE_LEVEL featureLevel) - - switch (featureLevel) - { -+#if !defined(_MSC_VER) || (_MSC_VER >= 1800) - case D3D_FEATURE_LEVEL_11_1: -+#endif - case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * bytesPerComponent; - - case D3D_FEATURE_LEVEL_10_1: -@@ -802,7 +933,9 @@ static size_t GetMaximumStreamOutputBuffers(D3D_FEATURE_LEVEL featureLevel) - { - switch (featureLevel) - { -+#if !defined(_MSC_VER) || (_MSC_VER >= 1800) - case D3D_FEATURE_LEVEL_11_1: -+#endif - case D3D_FEATURE_LEVEL_11_0: return D3D11_SO_BUFFER_SLOT_COUNT; - - case D3D_FEATURE_LEVEL_10_1: return D3D10_1_SO_BUFFER_SLOT_COUNT; -@@ -820,7 +953,9 @@ static size_t GetMaximumStreamOutputInterleavedComponents(D3D_FEATURE_LEVEL feat - { - switch (featureLevel) - { -+#if !defined(_MSC_VER) || (_MSC_VER >= 1800) - case D3D_FEATURE_LEVEL_11_1: -+#endif - case D3D_FEATURE_LEVEL_11_0: - - case D3D_FEATURE_LEVEL_10_1: -@@ -838,7 +973,9 @@ static size_t GetMaximumStreamOutputSeparateComponents(D3D_FEATURE_LEVEL feature - { - switch (featureLevel) - { -+#if !defined(_MSC_VER) || (_MSC_VER >= 1800) - case D3D_FEATURE_LEVEL_11_1: -+#endif - case D3D_FEATURE_LEVEL_11_0: return GetMaximumStreamOutputInterleavedComponents(featureLevel) / - GetMaximumStreamOutputBuffers(featureLevel); - --- -1.9.4.msysgit.1 - diff --git a/src/angle/patches/0016-ANGLE-Fix-compilation-with-MinGW-D3D11.patch b/src/angle/patches/0016-ANGLE-Fix-compilation-with-MinGW-D3D11.patch deleted file mode 100644 index e3df95d8bf..0000000000 --- a/src/angle/patches/0016-ANGLE-Fix-compilation-with-MinGW-D3D11.patch +++ /dev/null @@ -1,169 +0,0 @@ -From 43c8ceb17ccd6d5ae13a07c6d01b45eb40983917 Mon Sep 17 00:00:00 2001 -From: Andrew Knight -Date: Tue, 11 Nov 2014 14:36:43 +0200 -Subject: [PATCH 16/16] ANGLE: Fix compilation with MinGW + D3D11 - -Provide workarounds for things GCC doesn't like, and define a few -missing definitions not found in the MinGW headers. - -Change-Id: I254c208209c0071fae5efb6727f2b3cfd5542da6 ---- - src/3rdparty/angle/src/common/platform.h | 73 ++++++++++++++++++++++ - .../src/libGLESv2/renderer/d3d/HLSLCompiler.cpp | 6 ++ - .../libGLESv2/renderer/d3d/d3d11/Renderer11.cpp | 2 +- - .../renderer/d3d/d3d11/renderer11_utils.cpp | 2 +- - .../src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp | 4 +- - 5 files changed, 83 insertions(+), 4 deletions(-) - -diff --git a/src/3rdparty/angle/src/common/platform.h b/src/3rdparty/angle/src/common/platform.h -index 972eee2..0001e71 100644 ---- a/src/3rdparty/angle/src/common/platform.h -+++ b/src/3rdparty/angle/src/common/platform.h -@@ -81,6 +81,79 @@ - # endif - # endif - -+# if defined(__MINGW32__) // Missing defines on MinGW -+typedef enum D3D11_MAP_FLAG -+{ -+ D3D11_MAP_FLAG_DO_NOT_WAIT = 0x100000L -+} D3D11_MAP_FLAG; -+typedef struct D3D11_QUERY_DATA_SO_STATISTICS -+{ -+ UINT64 NumPrimitivesWritten; -+ UINT64 PrimitivesStorageNeeded; -+} D3D11_QUERY_DATA_SO_STATISTICS; -+typedef HRESULT (WINAPI *PFN_D3D11_CREATE_DEVICE)( -+ IDXGIAdapter *, D3D_DRIVER_TYPE, HMODULE, UINT, CONST D3D_FEATURE_LEVEL *, -+ UINT FeatureLevels, UINT, ID3D11Device **, D3D_FEATURE_LEVEL *, ID3D11DeviceContext **); -+#define D3D11_MESSAGE_CATEGORY UINT -+#define D3D11_MESSAGE_SEVERITY UINT -+#define D3D11_MESSAGE_ID UINT -+struct D3D11_MESSAGE; -+typedef struct D3D11_INFO_QUEUE_FILTER_DESC -+{ -+ UINT NumCategories; -+ D3D11_MESSAGE_CATEGORY *pCategoryList; -+ UINT NumSeverities; -+ D3D11_MESSAGE_SEVERITY *pSeverityList; -+ UINT NumIDs; -+ D3D11_MESSAGE_ID *pIDList; -+} D3D11_INFO_QUEUE_FILTER_DESC; -+typedef struct D3D11_INFO_QUEUE_FILTER -+{ -+ D3D11_INFO_QUEUE_FILTER_DESC AllowList; -+ D3D11_INFO_QUEUE_FILTER_DESC DenyList; -+} D3D11_INFO_QUEUE_FILTER; -+static const IID IID_ID3D11InfoQueue = { 0x6543dbb6, 0x1b48, 0x42f5, 0xab, 0x82, 0xe9, 0x7e, 0xc7, 0x43, 0x26, 0xf6 }; -+MIDL_INTERFACE("6543dbb6-1b48-42f5-ab82-e97ec74326f6") ID3D11InfoQueue : public IUnknown -+{ -+public: -+ virtual HRESULT __stdcall SetMessageCountLimit(UINT64) = 0; -+ virtual void __stdcall ClearStoredMessages() = 0; -+ virtual HRESULT __stdcall GetMessage(UINT64, D3D11_MESSAGE *, SIZE_T *) = 0; -+ virtual UINT64 __stdcall GetNumMessagesAllowedByStorageFilter() = 0; -+ virtual UINT64 __stdcall GetNumMessagesDeniedByStorageFilter() = 0; -+ virtual UINT64 __stdcall GetNumStoredMessages() = 0; -+ virtual UINT64 __stdcall GetNumStoredMessagesAllowedByRetrievalFilter() = 0; -+ virtual UINT64 __stdcall GetNumMessagesDiscardedByMessageCountLimit() = 0; -+ virtual UINT64 __stdcall GetMessageCountLimit() = 0; -+ virtual HRESULT __stdcall AddStorageFilterEntries(D3D11_INFO_QUEUE_FILTER *) = 0; -+ virtual HRESULT __stdcall GetStorageFilter(D3D11_INFO_QUEUE_FILTER *, SIZE_T *) = 0; -+ virtual void __stdcall ClearStorageFilter() = 0; -+ virtual HRESULT __stdcall PushEmptyStorageFilter() = 0; -+ virtual HRESULT __stdcall PushCopyOfStorageFilter() = 0; -+ virtual HRESULT __stdcall PushStorageFilter(D3D11_INFO_QUEUE_FILTER *) = 0; -+ virtual void __stdcall PopStorageFilter() = 0; -+ virtual UINT __stdcall GetStorageFilterStackSize() = 0; -+ virtual HRESULT __stdcall AddRetrievalFilterEntries(D3D11_INFO_QUEUE_FILTER *) = 0; -+ virtual HRESULT __stdcall GetRetrievalFilter(D3D11_INFO_QUEUE_FILTER *, SIZE_T *) = 0; -+ virtual void __stdcall ClearRetrievalFilter() = 0; -+ virtual HRESULT __stdcall PushEmptyRetrievalFilter() = 0; -+ virtual HRESULT __stdcall PushCopyOfRetrievalFilter() = 0; -+ virtual HRESULT __stdcall PushRetrievalFilter(D3D11_INFO_QUEUE_FILTER *) = 0; -+ virtual void __stdcall PopRetrievalFilter() = 0; -+ virtual UINT __stdcall GetRetrievalFilterStackSize() = 0; -+ virtual HRESULT __stdcall AddMessage(D3D11_MESSAGE_CATEGORY, D3D11_MESSAGE_SEVERITY, D3D11_MESSAGE_ID, LPCSTR) = 0; -+ virtual HRESULT __stdcall AddApplicationMessage(D3D11_MESSAGE_SEVERITY, LPCSTR) = 0; -+ virtual HRESULT __stdcall SetBreakOnCategory(D3D11_MESSAGE_CATEGORY, BOOL) = 0; -+ virtual HRESULT __stdcall SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY, BOOL) = 0; -+ virtual HRESULT __stdcall SetBreakOnID(D3D11_MESSAGE_ID, BOOL) = 0; -+ virtual BOOL __stdcall GetBreakOnCategory(D3D11_MESSAGE_CATEGORY) = 0; -+ virtual BOOL __stdcall GetBreakOnSeverity(D3D11_MESSAGE_SEVERITY) = 0; -+ virtual BOOL __stdcall GetBreakOnID(D3D11_MESSAGE_ID) = 0; -+ virtual void __stdcall SetMuteDebugOutput(BOOL) = 0; -+ virtual BOOL __stdcall GetMuteDebugOutput() = 0; -+}; -+#endif // __MINGW32__ -+ - # undef near - # undef far - #endif -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp -index 9d003b4..776d92b 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp -@@ -14,6 +14,12 @@ - #ifndef QT_D3DCOMPILER_DLL - #define QT_D3DCOMPILER_DLL D3DCOMPILER_DLL - #endif -+#ifndef D3DCOMPILE_RESERVED16 -+#define D3DCOMPILE_RESERVED16 (1 << 16) -+#endif -+#ifndef D3DCOMPILE_RESERVED17 -+#define D3DCOMPILE_RESERVED17 (1 << 17) -+#endif - - // Definitions local to the translation unit - namespace -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp -index a28fd78..e6d7f30 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp -@@ -333,7 +333,7 @@ EGLint Renderer11::initialize() - // 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); -+ result = mDevice->QueryInterface(IID_ID3D11InfoQueue, (void **)&infoQueue); - - if (SUCCEEDED(result)) - { -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp -index 5831c57..121aa3b 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp -@@ -1196,7 +1196,7 @@ void SetPositionLayerTexCoord3DVertex(PositionLayerTexCoord3DVertex* vertex, flo - - HRESULT SetDebugName(ID3D11DeviceChild *resource, const char *name) - { --#if defined(_DEBUG) -+#if defined(_DEBUG) && !defined(__MINGW32__) - return resource->SetPrivateData(WKPDID_D3DDebugObjectName, strlen(name), name); - #else - return S_OK; -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp -index 4c552b2..601cd24 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp -@@ -200,7 +200,7 @@ EGLint Renderer9::initialize() - if (ANGLE_D3D9EX == ANGLE_ENABLED && Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &mD3d9Ex))) - { - ASSERT(mD3d9Ex); -- mD3d9Ex->QueryInterface(__uuidof(IDirect3D9), reinterpret_cast(&mD3d9)); -+ mD3d9Ex->QueryInterface(IID_IDirect3D9, reinterpret_cast(&mD3d9)); - ASSERT(mD3d9); - } - else -@@ -324,7 +324,7 @@ EGLint Renderer9::initialize() - - if (mD3d9Ex) - { -- result = mDevice->QueryInterface(__uuidof(IDirect3DDevice9Ex), (void**)&mDeviceEx); -+ result = mDevice->QueryInterface(IID_IDirect3DDevice9Ex, (void**)&mDeviceEx); - ASSERT(SUCCEEDED(result)); - } - --- -1.9.4.msysgit.1 - diff --git a/src/angle/patches/0017-ANGLE-Fix-compilation-with-D3D9.patch b/src/angle/patches/0017-ANGLE-Fix-compilation-with-D3D9.patch deleted file mode 100644 index 4ada6d41d2..0000000000 --- a/src/angle/patches/0017-ANGLE-Fix-compilation-with-D3D9.patch +++ /dev/null @@ -1,62 +0,0 @@ -From d7839cc052de126cc3b457fe41963fd9c7e91846 Mon Sep 17 00:00:00 2001 -From: Kai Koehne -Date: Mon, 17 Nov 2014 15:10:10 +0100 -Subject: [PATCH] ANGLE: Fix compilation with D3D9 - -Fixes a regression introduced in c6df5fe3ed0f2a722 that -broke compilation with d3d9 (namely, -target xp). - -Task-number: QTBUG-42714 -Change-Id: I1a5e9682d5463bfa082a5d0c062399a131a7cf52 ---- - src/3rdparty/angle/src/common/NativeWindow.h | 7 ++++++- - src/3rdparty/angle/src/common/platform.h | 1 + - src/3rdparty/angle/src/common/win32/NativeWindow.cpp | 2 +- - 3 files changed, 8 insertions(+), 2 deletions(-) - -diff --git a/src/3rdparty/angle/src/common/NativeWindow.h b/src/3rdparty/angle/src/common/NativeWindow.h -index 9e93aea..c4a0e42 100644 ---- a/src/3rdparty/angle/src/common/NativeWindow.h -+++ b/src/3rdparty/angle/src/common/NativeWindow.h -@@ -54,7 +54,12 @@ public: - bool getClientRect(LPRECT rect); - bool isIconic(); - -- HRESULT createSwapChain(ID3D11Device* device, DXGIFactory* factory, -+# if defined(ANGLE_ENABLE_D3D11) -+ typedef ID3D11Device Device; -+#else -+ typedef IDirect3DDevice9 Device; -+#endif -+ HRESULT createSwapChain(Device* device, DXGIFactory* factory, - DXGI_FORMAT format, UINT width, UINT height, - DXGISwapChain** swapChain); - -diff --git a/src/3rdparty/angle/src/common/platform.h b/src/3rdparty/angle/src/common/platform.h -index 0001e71..5bf97f9 100644 ---- a/src/3rdparty/angle/src/common/platform.h -+++ b/src/3rdparty/angle/src/common/platform.h -@@ -52,6 +52,7 @@ - - # if defined(ANGLE_ENABLE_D3D9) - # include -+# include - # if !defined(COMPILER_IMPLEMENTATION) - # include - # endif -diff --git a/src/3rdparty/angle/src/common/win32/NativeWindow.cpp b/src/3rdparty/angle/src/common/win32/NativeWindow.cpp -index 2440747..46082a2 100644 ---- a/src/3rdparty/angle/src/common/win32/NativeWindow.cpp -+++ b/src/3rdparty/angle/src/common/win32/NativeWindow.cpp -@@ -35,7 +35,7 @@ bool NativeWindow::isIconic() - return IsIconic(mWindow) == TRUE; - } - --HRESULT NativeWindow::createSwapChain(ID3D11Device* device, DXGIFactory* factory, -+HRESULT NativeWindow::createSwapChain(NativeWindow::Device* device, DXGIFactory* factory, - DXGI_FORMAT format, unsigned int width, unsigned int height, - DXGISwapChain** swapChain) - { --- -1.9.4.msysgit.0 - diff --git a/src/angle/patches/0018-ANGLE-Fix-releasing-textures-after-we-kill-D3D11.patch b/src/angle/patches/0018-ANGLE-Fix-releasing-textures-after-we-kill-D3D11.patch deleted file mode 100644 index 97847ad684..0000000000 --- a/src/angle/patches/0018-ANGLE-Fix-releasing-textures-after-we-kill-D3D11.patch +++ /dev/null @@ -1,106 +0,0 @@ -From 014d3fcf6011109491b0489da9c1abb1fdc6dbdc Mon Sep 17 00:00:00 2001 -From: Kai Koehne -Date: Mon, 24 Nov 2014 10:52:03 +0100 -Subject: [PATCH] ANGLE: Fix releasing textures after we kill D3D11 - -Cherry-pick upstream commit cc4cd2925b9a4f1142a86df131345a861c9d7cd9 -to fix crashes on exit. - -Task-number: QTBUG-42772 -Change-Id: Ib74be17f2b5fdd58f9e0568e1da74ba19e943019 ---- - src/3rdparty/angle/src/libGLESv2/Context.cpp | 6 ------ - src/3rdparty/angle/src/libGLESv2/Context.h | 1 - - src/3rdparty/angle/src/libGLESv2/renderer/d3d/RendererD3D.cpp | 5 +++++ - src/3rdparty/angle/src/libGLESv2/renderer/d3d/RendererD3D.h | 2 ++ - src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp | 2 ++ - src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp | 2 ++ - 6 files changed, 11 insertions(+), 7 deletions(-) - -diff --git a/src/3rdparty/angle/src/libGLESv2/Context.cpp b/src/3rdparty/angle/src/libGLESv2/Context.cpp -index b87689c..3772da6 100644 ---- a/src/3rdparty/angle/src/libGLESv2/Context.cpp -+++ b/src/3rdparty/angle/src/libGLESv2/Context.cpp -@@ -162,12 +162,6 @@ Context::~Context() - deleteTransformFeedback(mTransformFeedbackMap.begin()->first); - } - -- for (TextureMap::iterator i = mIncompleteTextures.begin(); i != mIncompleteTextures.end(); i++) -- { -- i->second.set(NULL); -- } -- mIncompleteTextures.clear(); -- - for (TextureMap::iterator i = mZeroTextures.begin(); i != mZeroTextures.end(); i++) - { - i->second.set(NULL); -diff --git a/src/3rdparty/angle/src/libGLESv2/Context.h b/src/3rdparty/angle/src/libGLESv2/Context.h -index 1e890de..0699592 100644 ---- a/src/3rdparty/angle/src/libGLESv2/Context.h -+++ b/src/3rdparty/angle/src/libGLESv2/Context.h -@@ -247,7 +247,6 @@ class Context - int mClientVersion; - - TextureMap mZeroTextures; -- TextureMap mIncompleteTextures; - - typedef std::unordered_map FramebufferMap; - FramebufferMap mFramebufferMap; -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RendererD3D.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RendererD3D.cpp -index 97da6da..5cddd8a 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RendererD3D.cpp -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RendererD3D.cpp -@@ -27,6 +27,11 @@ RendererD3D::RendererD3D(egl::Display *display) - - RendererD3D::~RendererD3D() - { -+ cleanup(); -+} -+ -+void RendererD3D::cleanup() -+{ - for (gl::TextureMap::iterator i = mIncompleteTextures.begin(); i != mIncompleteTextures.end(); ++i) - { - i->second.set(NULL); -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RendererD3D.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RendererD3D.h -index 9919207..a2f7787 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RendererD3D.h -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RendererD3D.h -@@ -160,6 +160,8 @@ class RendererD3D : public Renderer - const gl::Rectangle *scissor, bool blitRenderTarget, - bool blitDepth, bool blitStencil, GLenum filter) = 0; - -+ void cleanup(); -+ - egl::Display *mDisplay; - - private: -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp -index e6d7f30..777308e 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp -@@ -1870,6 +1870,8 @@ bool Renderer11::testDeviceResettable() - - void Renderer11::release() - { -+ RendererD3D::cleanup(); -+ - releaseShaderCompiler(); - releaseDeviceResources(); - -diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp -index 601cd24..18e6e2d 100644 ---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp -+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp -@@ -151,6 +151,8 @@ Renderer9::~Renderer9() - - void Renderer9::release() - { -+ RendererD3D::cleanup(); -+ - releaseShaderCompiler(); - releaseDeviceResources(); - --- -1.9.4.msysgit.0 - diff --git a/src/angle/patches/0019-ANGLE-Fix-handling-of-shader-source-with-fixed-lengt.patch b/src/angle/patches/0019-ANGLE-Fix-handling-of-shader-source-with-fixed-lengt.patch deleted file mode 100644 index 5fa244c1b5..0000000000 --- a/src/angle/patches/0019-ANGLE-Fix-handling-of-shader-source-with-fixed-lengt.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 5e277b05a16e7be24d36c600f158f8119ee583d8 Mon Sep 17 00:00:00 2001 -From: Andrew Knight -Date: Mon, 1 Dec 2014 11:58:08 +0200 -Subject: [PATCH] ANGLE: Fix handling of shader source with fixed length - -This is a cherry-pick of upstream f60fab6d154f4c9bf599e92976cd8cee7f8633e0 -(See https://chromium-review.googlesource.com/231612) - -Task-number: QTBUG-42882 -Change-Id: I7b4bdc4b68a1b93ff514f09ce35dbf4e9360af9b ---- - src/3rdparty/angle/src/libGLESv2/Shader.cpp | 9 ++++++++- - 1 file changed, 8 insertions(+), 1 deletion(-) - -diff --git a/src/3rdparty/angle/src/libGLESv2/Shader.cpp b/src/3rdparty/angle/src/libGLESv2/Shader.cpp -index 1cc17a0..5bca746 100644 ---- a/src/3rdparty/angle/src/libGLESv2/Shader.cpp -+++ b/src/3rdparty/angle/src/libGLESv2/Shader.cpp -@@ -51,7 +51,14 @@ void Shader::setSource(GLsizei count, const char *const *string, const GLint *le - - for (int i = 0; i < count; i++) - { -- stream << string[i]; -+ if (length == nullptr || length[i] < 0) -+ { -+ stream.write(string[i], std::strlen(string[i])); -+ } -+ else -+ { -+ stream.write(string[i], length[i]); -+ } - } - - mSource = stream.str(); --- -1.9.4.msysgit.1 - diff --git a/src/angle/patches/0020-ANGLE-Do-not-use-std-strlen.patch b/src/angle/patches/0020-ANGLE-Do-not-use-std-strlen.patch deleted file mode 100644 index 324244f6eb..0000000000 --- a/src/angle/patches/0020-ANGLE-Do-not-use-std-strlen.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 071b8936386b0b44475c91511d85479e5c633bc5 Mon Sep 17 00:00:00 2001 -From: Kai Koehne -Date: Thu, 11 Dec 2014 13:54:23 +0100 -Subject: [PATCH] ANGLE: Do not use std::strlen - -This is a cherry-pick from upstream change - -e7cfb3dd2029c1bfe5c175ad994c03cac221ad4d - -Change-Id: Iefe01545319f9ad268c0c6bf8e8b2181e09d8a84 ---- - src/3rdparty/angle/src/libGLESv2/Shader.cpp | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/3rdparty/angle/src/libGLESv2/Shader.cpp b/src/3rdparty/angle/src/libGLESv2/Shader.cpp -index 5bca746..024ef8f 100644 ---- a/src/3rdparty/angle/src/libGLESv2/Shader.cpp -+++ b/src/3rdparty/angle/src/libGLESv2/Shader.cpp -@@ -53,7 +53,7 @@ void Shader::setSource(GLsizei count, const char *const *string, const GLint *le - { - if (length == nullptr || length[i] < 0) - { -- stream.write(string[i], std::strlen(string[i])); -+ stream.write(string[i], strlen(string[i])); - } - else - { --- -1.9.4.msysgit.0 - diff --git a/src/angle/patches/0020-ANGLE-Fix-compilation-with-MSVC2013-Update4.patch b/src/angle/patches/0020-ANGLE-Fix-compilation-with-MSVC2013-Update4.patch deleted file mode 100644 index 49b229d905..0000000000 --- a/src/angle/patches/0020-ANGLE-Fix-compilation-with-MSVC2013-Update4.patch +++ /dev/null @@ -1,43 +0,0 @@ -From a48dfb3f1ecb57a59084c0e87155506586b73188 Mon Sep 17 00:00:00 2001 -From: Maurice Kalinowski -Date: Thu, 11 Dec 2014 13:11:55 +0100 -Subject: [PATCH] [ANGLE] Fix compilation with MSVC2013 Update4 - -Update4 provides a native Sleep implementation. Hence the wrapper -needs to be disabled. - -Change-Id: I162da45934b02c262ac09b557c66c3363c276e54 ---- - src/3rdparty/angle/src/common/utilities.cpp | 2 +- - src/3rdparty/angle/src/common/utilities.h | 2 +- - 2 files changed, 2 insertions(+), 2 deletions(-) - -diff --git a/src/3rdparty/angle/src/common/utilities.cpp b/src/3rdparty/angle/src/common/utilities.cpp -index 9d797a6..924573e 100644 ---- a/src/3rdparty/angle/src/common/utilities.cpp -+++ b/src/3rdparty/angle/src/common/utilities.cpp -@@ -486,7 +486,7 @@ void writeFile(const char* path, const void* content, size_t size) - } - #endif // !ANGLE_ENABLE_WINDOWS_STORE - --#if defined(ANGLE_ENABLE_WINDOWS_STORE) -+#if defined(ANGLE_ENABLE_WINDOWS_STORE) && _MSC_FULL_VER < 180031101 - - void Sleep(unsigned long dwMilliseconds) - { -diff --git a/src/3rdparty/angle/src/common/utilities.h b/src/3rdparty/angle/src/common/utilities.h -index 2cf6bed..7583d3e 100644 ---- a/src/3rdparty/angle/src/common/utilities.h -+++ b/src/3rdparty/angle/src/common/utilities.h -@@ -51,7 +51,7 @@ std::string getTempPath(); - void writeFile(const char* path, const void* data, size_t size); - #endif - --#if defined(ANGLE_ENABLE_WINDOWS_STORE) -+#if defined(ANGLE_ENABLE_WINDOWS_STORE) && _MSC_FULL_VER < 180031101 - void Sleep(_In_ unsigned long dwMilliseconds); - #endif - --- -1.9.4.msysgit.2 - diff --git a/src/angle/src/common/common.pri b/src/angle/src/common/common.pri index 7d3f46d65f..63b80347d1 100644 --- a/src/angle/src/common/common.pri +++ b/src/angle/src/common/common.pri @@ -46,20 +46,4 @@ win32-msvc2012|win32-msvc2013|winrt { } } -static: DEFINES *= QT_OPENGL_ES_2_ANGLE_STATIC - -HEADERS += \ - $$ANGLE_DIR/src/common/angleutils.h \ - $$ANGLE_DIR/src/common/debug.h \ - $$ANGLE_DIR/src/common/mathutil.h \ - $$ANGLE_DIR/src/common/platform.h \ - $$ANGLE_DIR/src/common/RefCountObject.h \ - $$ANGLE_DIR/src/common/tls.h \ - $$ANGLE_DIR/src/common/version.h - -SOURCES += \ - $$ANGLE_DIR/src/common/angleutils.cpp \ - $$ANGLE_DIR/src/common/debug.cpp \ - $$ANGLE_DIR/src/common/RefCountObject.cpp \ - $$ANGLE_DIR/src/common/tls.cpp - +static: DEFINES *= LIBGLESV2_EXPORT_H_ ANGLE_EXPORT= diff --git a/src/angle/src/compiler/preprocessor/preprocessor.pro b/src/angle/src/compiler/preprocessor/preprocessor.pro index 420cb90b36..8c5b1555dc 100644 --- a/src/angle/src/compiler/preprocessor/preprocessor.pro +++ b/src/angle/src/compiler/preprocessor/preprocessor.pro @@ -48,7 +48,7 @@ flex.dependency_type = TYPE_C flex.variable_out = GENERATED_SOURCES QMAKE_EXTRA_COMPILERS += flex -bison.commands = $$addGnuPath(bison) --no-lines --skeleton=yacc.c --output=${QMAKE_FILE_BASE}.cpp ${QMAKE_FILE_NAME} +bison.commands = $$addGnuPath(win_bison) --no-lines --skeleton=yacc.c --output=${QMAKE_FILE_BASE}.cpp ${QMAKE_FILE_NAME} bison.output = ${QMAKE_FILE_BASE}.cpp bison.input = BISON_SOURCES bison.dependency_type = TYPE_C diff --git a/src/angle/src/compiler/translator.pro b/src/angle/src/compiler/translator.pro index 6f0128d6de..e9d16ca5af 100644 --- a/src/angle/src/compiler/translator.pro +++ b/src/angle/src/compiler/translator.pro @@ -1,14 +1,11 @@ CONFIG += static include(../config.pri) -# Mingw 4.7 chokes on implicit move semantics, so disable C++11 here -mingw: CONFIG -= c++11 - INCLUDEPATH += \ $$ANGLE_DIR/src \ $$ANGLE_DIR/include -DEFINES += _SECURE_SCL=0 _LIB COMPILER_IMPLEMENTATION +DEFINES += _SECURE_SCL=0 _LIB ANGLE_TRANSLATOR_IMPLEMENTATION ANGLE_TRANSLATOR_STATIC ANGLE_ENABLE_HLSL FLEX_SOURCES = $$ANGLE_DIR/src/compiler/translator/glslang.l BISON_SOURCES = $$ANGLE_DIR/src/compiler/translator/glslang.y @@ -23,26 +20,31 @@ HEADERS += \ $$ANGLE_DIR/src/common/platform.h \ $$ANGLE_DIR/src/common/tls.h \ $$ANGLE_DIR/src/common/utilities.h \ + $$ANGLE_DIR/src/compiler/translator/blocklayout.h \ + $$ANGLE_DIR/src/compiler/translator/blocklayoutHLSL.h \ $$ANGLE_DIR/src/compiler/translator/BaseTypes.h \ $$ANGLE_DIR/src/compiler/translator/BuiltInFunctionEmulator.h \ + $$ANGLE_DIR/src/compiler/translator/BuiltInFunctionEmulatorGLSL.h \ + $$ANGLE_DIR/src/compiler/translator/BuiltInFunctionEmulatorHLSL.h \ $$ANGLE_DIR/src/compiler/translator/Common.h \ - $$ANGLE_DIR/src/compiler/translator/Compiler.h \ $$ANGLE_DIR/src/compiler/translator/compilerdebug.h \ + $$ANGLE_DIR/src/compiler/translator/Compiler.h \ $$ANGLE_DIR/src/compiler/translator/ConstantUnion.h \ - $$ANGLE_DIR/src/compiler/translator/depgraph/DependencyGraph.h \ $$ANGLE_DIR/src/compiler/translator/depgraph/DependencyGraphBuilder.h \ + $$ANGLE_DIR/src/compiler/translator/depgraph/DependencyGraph.h \ $$ANGLE_DIR/src/compiler/translator/depgraph/DependencyGraphOutput.h \ $$ANGLE_DIR/src/compiler/translator/DetectCallDepth.h \ $$ANGLE_DIR/src/compiler/translator/DetectDiscontinuity.h \ $$ANGLE_DIR/src/compiler/translator/Diagnostics.h \ $$ANGLE_DIR/src/compiler/translator/DirectiveHandler.h \ $$ANGLE_DIR/src/compiler/translator/ExtensionBehavior.h \ + $$ANGLE_DIR/src/compiler/translator/EmulatePrecision.h \ $$ANGLE_DIR/src/compiler/translator/FlagStd140Structs.h \ $$ANGLE_DIR/src/compiler/translator/ForLoopUnroll.h \ $$ANGLE_DIR/src/compiler/translator/HashNames.h \ $$ANGLE_DIR/src/compiler/translator/InfoSink.h \ - $$ANGLE_DIR/src/compiler/translator/Initialize.h \ $$ANGLE_DIR/src/compiler/translator/InitializeDll.h \ + $$ANGLE_DIR/src/compiler/translator/Initialize.h \ $$ANGLE_DIR/src/compiler/translator/InitializeParseContext.h \ $$ANGLE_DIR/src/compiler/translator/InitializeVariables.h \ $$ANGLE_DIR/src/compiler/translator/intermediate.h \ @@ -51,21 +53,23 @@ HEADERS += \ $$ANGLE_DIR/src/compiler/translator/MMap.h \ $$ANGLE_DIR/src/compiler/translator/NodeSearch.h \ $$ANGLE_DIR/src/compiler/translator/osinclude.h \ + $$ANGLE_DIR/src/compiler/translator/Operator.h \ $$ANGLE_DIR/src/compiler/translator/OutputESSL.h \ - $$ANGLE_DIR/src/compiler/translator/OutputGLSL.h \ $$ANGLE_DIR/src/compiler/translator/OutputGLSLBase.h \ + $$ANGLE_DIR/src/compiler/translator/OutputGLSL.h \ $$ANGLE_DIR/src/compiler/translator/OutputHLSL.h \ $$ANGLE_DIR/src/compiler/translator/ParseContext.h \ $$ANGLE_DIR/src/compiler/translator/PoolAlloc.h \ $$ANGLE_DIR/src/compiler/translator/Pragma.h \ $$ANGLE_DIR/src/compiler/translator/QualifierAlive.h \ $$ANGLE_DIR/src/compiler/translator/RegenerateStructNames.h \ - $$ANGLE_DIR/src/compiler/translator/RemoveTree.h \ + $$ANGLE_DIR/src/compiler/translator/RemoveSwitchFallThrough.h \ $$ANGLE_DIR/src/compiler/translator/RenameFunction.h \ $$ANGLE_DIR/src/compiler/translator/RewriteElseBlocks.h \ $$ANGLE_DIR/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.h \ $$ANGLE_DIR/src/compiler/translator/SearchSymbol.h \ $$ANGLE_DIR/src/compiler/translator/ShHandle.h \ + $$ANGLE_DIR/src/compiler/translator/SimplifyArrayAssignment.h \ $$ANGLE_DIR/src/compiler/translator/StructureHLSL.h \ $$ANGLE_DIR/src/compiler/translator/SymbolTable.h \ $$ANGLE_DIR/src/compiler/translator/timing/RestrictFragmentShaderTiming.h \ @@ -74,13 +78,14 @@ HEADERS += \ $$ANGLE_DIR/src/compiler/translator/TranslatorGLSL.h \ $$ANGLE_DIR/src/compiler/translator/TranslatorHLSL.h \ $$ANGLE_DIR/src/compiler/translator/Types.h \ - $$ANGLE_DIR/src/compiler/translator/UnfoldShortCircuit.h \ $$ANGLE_DIR/src/compiler/translator/UnfoldShortCircuitAST.h \ + $$ANGLE_DIR/src/compiler/translator/UnfoldShortCircuit.h \ $$ANGLE_DIR/src/compiler/translator/UniformHLSL.h \ - $$ANGLE_DIR/src/compiler/translator/UtilsHLSL.h \ $$ANGLE_DIR/src/compiler/translator/util.h \ + $$ANGLE_DIR/src/compiler/translator/UtilsHLSL.h \ $$ANGLE_DIR/src/compiler/translator/ValidateLimitations.h \ $$ANGLE_DIR/src/compiler/translator/ValidateOutputs.h \ + $$ANGLE_DIR/src/compiler/translator/ValidateSwitch.h \ $$ANGLE_DIR/src/compiler/translator/VariableInfo.h \ $$ANGLE_DIR/src/compiler/translator/VariablePacker.h \ $$ANGLE_DIR/src/compiler/translator/VersionGLSL.h \ @@ -89,7 +94,11 @@ HEADERS += \ SOURCES += \ $$ANGLE_DIR/src/common/tls.cpp \ + $$ANGLE_DIR/src/compiler/translator/blocklayout.cpp \ + $$ANGLE_DIR/src/compiler/translator/blocklayoutHLSL.cpp \ $$ANGLE_DIR/src/compiler/translator/BuiltInFunctionEmulator.cpp \ + $$ANGLE_DIR/src/compiler/translator/BuiltInFunctionEmulatorGLSL.cpp \ + $$ANGLE_DIR/src/compiler/translator/BuiltInFunctionEmulatorHLSL.cpp \ $$ANGLE_DIR/src/compiler/translator/CodeGen.cpp \ $$ANGLE_DIR/src/compiler/translator/Compiler.cpp \ $$ANGLE_DIR/src/compiler/translator/compilerdebug.cpp \ @@ -101,6 +110,7 @@ SOURCES += \ $$ANGLE_DIR/src/compiler/translator/DetectDiscontinuity.cpp \ $$ANGLE_DIR/src/compiler/translator/Diagnostics.cpp \ $$ANGLE_DIR/src/compiler/translator/DirectiveHandler.cpp \ + $$ANGLE_DIR/src/compiler/translator/EmulatePrecision.cpp \ $$ANGLE_DIR/src/compiler/translator/FlagStd140Structs.cpp \ $$ANGLE_DIR/src/compiler/translator/ForLoopUnroll.cpp \ $$ANGLE_DIR/src/compiler/translator/InfoSink.cpp \ @@ -113,6 +123,7 @@ SOURCES += \ $$ANGLE_DIR/src/compiler/translator/intermOut.cpp \ $$ANGLE_DIR/src/compiler/translator/IntermTraverse.cpp \ $$ANGLE_DIR/src/compiler/translator/LoopInfo.cpp \ + $$ANGLE_DIR/src/compiler/translator/Operator.cpp \ $$ANGLE_DIR/src/compiler/translator/OutputESSL.cpp \ $$ANGLE_DIR/src/compiler/translator/OutputGLSL.cpp \ $$ANGLE_DIR/src/compiler/translator/OutputGLSLBase.cpp \ @@ -122,12 +133,13 @@ SOURCES += \ $$ANGLE_DIR/src/compiler/translator/PoolAlloc.cpp \ $$ANGLE_DIR/src/compiler/translator/QualifierAlive.cpp \ $$ANGLE_DIR/src/compiler/translator/RegenerateStructNames.cpp \ - $$ANGLE_DIR/src/compiler/translator/RemoveTree.cpp \ + $$ANGLE_DIR/src/compiler/translator/RemoveSwitchFallThrough.cpp \ $$ANGLE_DIR/src/compiler/translator/RewriteElseBlocks.cpp \ $$ANGLE_DIR/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.cpp \ $$ANGLE_DIR/src/compiler/translator/SearchSymbol.cpp \ $$ANGLE_DIR/src/compiler/translator/ShaderLang.cpp \ $$ANGLE_DIR/src/compiler/translator/ShaderVars.cpp \ + $$ANGLE_DIR/src/compiler/translator/SimplifyArrayAssignment.cpp \ $$ANGLE_DIR/src/compiler/translator/StructureHLSL.cpp \ $$ANGLE_DIR/src/compiler/translator/SymbolTable.cpp \ $$ANGLE_DIR/src/compiler/translator/timing/RestrictFragmentShaderTiming.cpp \ @@ -143,6 +155,7 @@ SOURCES += \ $$ANGLE_DIR/src/compiler/translator/util.cpp \ $$ANGLE_DIR/src/compiler/translator/ValidateLimitations.cpp \ $$ANGLE_DIR/src/compiler/translator/ValidateOutputs.cpp \ + $$ANGLE_DIR/src/compiler/translator/ValidateSwitch.cpp \ $$ANGLE_DIR/src/compiler/translator/VariableInfo.cpp \ $$ANGLE_DIR/src/compiler/translator/VariablePacker.cpp \ $$ANGLE_DIR/src/compiler/translator/VersionGLSL.cpp \ @@ -157,7 +170,7 @@ flex.dependency_type = TYPE_C flex.variable_out = GENERATED_SOURCES QMAKE_EXTRA_COMPILERS += flex -bison.commands = $$addGnuPath(bison) --no-lines --skeleton=yacc.c --defines=${QMAKE_FILE_BASE}_tab.h \ +bison.commands = $$addGnuPath(win_bison) --no-lines --skeleton=yacc.c --defines=${QMAKE_FILE_BASE}_tab.h \ --output=${QMAKE_FILE_BASE}_tab.cpp ${QMAKE_FILE_NAME} bison.output = ${QMAKE_FILE_BASE}_tab.h bison.input = BISON_SOURCES diff --git a/src/angle/src/config.pri b/src/angle/src/config.pri index 9a7bc8a68c..0d75245ec5 100644 --- a/src/angle/src/config.pri +++ b/src/angle/src/config.pri @@ -37,8 +37,6 @@ DEFINES += _WINDOWS \ NOMINMAX \ WIN32_LEAN_AND_MEAN=1 -!winrt: DEFINES += ANGLE_ENABLE_D3D9 ANGLE_SKIP_DXGI_1_2_CHECK - CONFIG += angle_d3d11 # Remove to disable D3D11 renderer equals(QMAKE_TARGET_OS, xp): CONFIG -= angle_d3d11 @@ -70,11 +68,12 @@ msvc { # 4245: 'conversion' : conversion from 'type1' to 'type2', signed/unsigned mismatch # 4267: coversion from 'size_t' to 'int', possible loss of data # 4275: non - DLL-interface classkey 'identifier' used as base for DLL-interface classkey 'identifier' + # 4480: nonstandard extension used: specifying underlying type for enum # 4512: 'class' : assignment operator could not be generated # 4702: unreachable code # 4996: Function call with parameters that may be unsafe QMAKE_CFLAGS_WARN_ON -= -W3 - QMAKE_CFLAGS_WARN_ON += -W4 -wd"4100" -wd"4127" -wd"4189" -wd"4239" -wd"4244" -wd"4245" -wd"4267" -wd"4275" -wd"4512" -wd"4702" -wd"4996" + QMAKE_CFLAGS_WARN_ON += -W4 -wd"4100" -wd"4127" -wd"4189" -wd"4239" -wd"4244" -wd"4245" -wd"4267" -wd"4275" -wd"4512" -wd"4702" -wd"4996" -wd"4480" # Optimizations # /Oy: Omits frame pointer (x86 only). # /Gy: Enables function-level linking. diff --git a/src/angle/src/libEGL/libEGL.pro b/src/angle/src/libEGL/libEGL.pro index a16249309f..94fcebda6b 100644 --- a/src/angle/src/libEGL/libEGL.pro +++ b/src/angle/src/libEGL/libEGL.pro @@ -5,40 +5,13 @@ winrt: LIBS_PRIVATE += -ld3d11 LIBS_PRIVATE += -ldxguid -L$$QT_BUILD_TREE/lib -l$$qtLibraryTarget(libGLESv2) +DEFINES += GL_APICALL= GL_GLEXT_PROTOTYPES= EGLAPI= LIBEGL_IMPLEMENTATION + HEADERS += \ - $$ANGLE_DIR/src/common/NativeWindow.h \ - $$ANGLE_DIR/src/libEGL/AttributeMap.h \ - $$ANGLE_DIR/src/libEGL/Config.h \ - $$ANGLE_DIR/src/libEGL/Display.h \ - $$ANGLE_DIR/src/libEGL/Error.h \ - $$ANGLE_DIR/src/libEGL/main.h \ - $$ANGLE_DIR/src/libEGL/resource.h \ - $$ANGLE_DIR/src/libEGL/ShaderCache.h \ - $$ANGLE_DIR/src/libEGL/Surface.h + $$ANGLE_DIR/src/libEGL/resource.h SOURCES += \ - $$ANGLE_DIR/src/libEGL/AttributeMap.cpp \ - $$ANGLE_DIR/src/libEGL/Config.cpp \ - $$ANGLE_DIR/src/libEGL/Display.cpp \ - $$ANGLE_DIR/src/libEGL/Error.cpp \ - $$ANGLE_DIR/src/libEGL/libEGL.cpp \ - $$ANGLE_DIR/src/libEGL/main.cpp \ - $$ANGLE_DIR/src/libEGL/Surface.cpp - -!winrt { - SOURCES += \ - $$ANGLE_DIR/src/common/win32/NativeWindow.cpp -} else { - HEADERS += \ - $$ANGLE_DIR/src/common/winrt/CoreWindowNativeWindow.h \ - $$ANGLE_DIR/src/common/winrt/InspectableNativeWindow.h \ - $$ANGLE_DIR/src/common/winrt/SwapChainPanelNativeWindow.h - - SOURCES += \ - $$ANGLE_DIR/src/common/winrt/CoreWindowNativeWindow.cpp \ - $$ANGLE_DIR/src/common/winrt/InspectableNativeWindow.cpp \ - $$ANGLE_DIR/src/common/winrt/SwapChainPanelNativeWindow.cpp -} + $$ANGLE_DIR/src/libEGL/libEGL.cpp !static { DEF_FILE = $$ANGLE_DIR/src/libEGL/$${TARGET}.def diff --git a/src/angle/src/libGLESv2/libGLESv2.pro b/src/angle/src/libGLESv2/libGLESv2.pro index 705768d17d..a783318bb1 100644 --- a/src/angle/src/libGLESv2/libGLESv2.pro +++ b/src/angle/src/libGLESv2/libGLESv2.pro @@ -1,7 +1,7 @@ CONFIG += simd installed include(../common/common.pri) -INCLUDEPATH += $$OUT_PWD/.. $$ANGLE_DIR/src/libGLESv2 +INCLUDEPATH += $$OUT_PWD/.. $$ANGLE_DIR/src/libANGLE # Remember to adapt tools/configure/configureapp.cpp if the Direct X version changes. !winrt: \ @@ -20,237 +20,310 @@ for(libname, STATICLIBS) { PRE_TARGETDEPS += $$staticlib } +DEFINES += LIBANGLE_IMPLEMENTATION LIBGLESV2_IMPLEMENTATION GL_APICALL= GL_GLEXT_PROTOTYPES= EGLAPI= ANGLE_ENABLE_D3D11 +!winrt: DEFINES += ANGLE_ENABLE_D3D9 ANGLE_SKIP_DXGI_1_2_CHECK + HEADERS += \ $$ANGLE_DIR/src/common/blocklayout.h \ + $$ANGLE_DIR/src/common/NativeWindow.h \ $$ANGLE_DIR/src/common/shadervars.h \ $$ANGLE_DIR/src/common/utilities.h \ - $$ANGLE_DIR/src/common/NativeWindow.h \ - $$ANGLE_DIR/src/libGLESv2/angletypes.h \ - $$ANGLE_DIR/src/libGLESv2/BinaryStream.h \ - $$ANGLE_DIR/src/libGLESv2/Buffer.h \ - $$ANGLE_DIR/src/libGLESv2/Caps.h \ - $$ANGLE_DIR/src/libGLESv2/Context.h \ - $$ANGLE_DIR/src/libGLESv2/Data.h \ - $$ANGLE_DIR/src/libGLESv2/Error.h \ - $$ANGLE_DIR/src/libGLESv2/Fence.h \ - $$ANGLE_DIR/src/libGLESv2/formatutils.h \ - $$ANGLE_DIR/src/libGLESv2/Framebuffer.h \ - $$ANGLE_DIR/src/libGLESv2/FramebufferAttachment.h \ - $$ANGLE_DIR/src/libGLESv2/HandleAllocator.h \ - $$ANGLE_DIR/src/libGLESv2/ImageIndex.h \ - $$ANGLE_DIR/src/libGLESv2/main.h \ - $$ANGLE_DIR/src/libGLESv2/Program.h \ - $$ANGLE_DIR/src/libGLESv2/ProgramBinary.h \ - $$ANGLE_DIR/src/libGLESv2/Query.h \ - $$ANGLE_DIR/src/libGLESv2/queryconversions.h \ - $$ANGLE_DIR/src/libGLESv2/Renderbuffer.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/BufferImpl.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/copyimage.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/copyvertex.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/BufferD3D.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/DynamicHLSL.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/HLSLCompiler.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/ImageD3D.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/IndexBuffer.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/IndexDataManager.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/MemoryBuffer.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/ProgramD3D.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/RenderbufferD3D.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/RendererD3D.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/ShaderD3D.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/TextureD3D.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/TextureStorage.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/TransformFeedbackD3D.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/VertexArrayImpl.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/VertexBuffer.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/vertexconversion.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/VertexDataManager.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/FenceImpl.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/generatemip.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/Image.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/imageformats.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/IndexCacheRange.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/loadimage.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/ProgramImpl.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/QueryImpl.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/RenderbufferImpl.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/Renderer.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/RenderTarget.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/ShaderExecutable.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/ShaderImpl.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/SwapChain.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/TextureImpl.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/TextureFeedbackImpl.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/VertexDeclarationCache.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/Workarounds.h \ + $$ANGLE_DIR/src/common/MemoryBuffer.h \ + $$ANGLE_DIR/src/common/angleutils.h \ + $$ANGLE_DIR/src/common/debug.h \ + $$ANGLE_DIR/src/common/event_tracer.h \ + $$ANGLE_DIR/src/libANGLE/angletypes.h \ + $$ANGLE_DIR/src/libANGLE/AttributeMap.h \ + $$ANGLE_DIR/src/libANGLE/BinaryStream.h \ + $$ANGLE_DIR/src/libANGLE/Buffer.h \ + $$ANGLE_DIR/src/libANGLE/Caps.h \ + $$ANGLE_DIR/src/libANGLE/Compiler.h \ + $$ANGLE_DIR/src/libANGLE/Config.h \ + $$ANGLE_DIR/src/libANGLE/Constants.h \ + $$ANGLE_DIR/src/libANGLE/Context.h \ + $$ANGLE_DIR/src/libANGLE/Data.h \ + $$ANGLE_DIR/src/libANGLE/Display.h \ + $$ANGLE_DIR/src/libANGLE/Error.h \ + $$ANGLE_DIR/src/libANGLE/features.h \ + $$ANGLE_DIR/src/libANGLE/Fence.h \ + $$ANGLE_DIR/src/libANGLE/formatutils.h \ + $$ANGLE_DIR/src/libANGLE/Framebuffer.h \ + $$ANGLE_DIR/src/libANGLE/FramebufferAttachment.h \ + $$ANGLE_DIR/src/libANGLE/HandleAllocator.h \ + $$ANGLE_DIR/src/libANGLE/ImageIndex.h \ + $$ANGLE_DIR/src/libANGLE/Program.h \ + $$ANGLE_DIR/src/libANGLE/Query.h \ + $$ANGLE_DIR/src/libANGLE/queryconversions.h \ + $$ANGLE_DIR/src/libANGLE/RefCountObject.h \ + $$ANGLE_DIR/src/libANGLE/Renderbuffer.h \ + $$ANGLE_DIR/src/libANGLE/ResourceManager.h \ + $$ANGLE_DIR/src/libANGLE/Sampler.h \ + $$ANGLE_DIR/src/libANGLE/Shader.h \ + $$ANGLE_DIR/src/libANGLE/State.h \ + $$ANGLE_DIR/src/libANGLE/Surface.h \ + $$ANGLE_DIR/src/libANGLE/Texture.h \ + $$ANGLE_DIR/src/libANGLE/TransformFeedback.h \ + $$ANGLE_DIR/src/libANGLE/Uniform.h \ + $$ANGLE_DIR/src/libANGLE/validationEGL.h \ + $$ANGLE_DIR/src/libANGLE/validationES.h \ + $$ANGLE_DIR/src/libANGLE/validationES2.h \ + $$ANGLE_DIR/src/libANGLE/validationES3.h \ + $$ANGLE_DIR/src/libANGLE/VertexArray.h \ + $$ANGLE_DIR/src/libANGLE/VertexAttribute.h \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/BufferD3D.h \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/CompilerD3D.h \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/copyimage.h \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/DisplayD3D.h \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/DynamicHLSL.h \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/formatutilsD3D.h \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/FramebufferD3D.h \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/generatemip.h \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/HLSLCompiler.h \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/ImageD3D.h \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/imageformats.h \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/IndexBuffer.h \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/IndexDataManager.h \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/loadimage.h \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/ProgramD3D.h \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/RenderbufferD3D.h \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/RendererD3D.h \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/RenderTargetD3D.h \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/ShaderD3D.h \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/ShaderExecutableD3D.h \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/SurfaceD3D.h \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/SwapChainD3D.h \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/TextureD3D.h \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/TextureStorage.h \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/TransformFeedbackD3D.h \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/VertexBuffer.h \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/VertexDataManager.h \ + $$ANGLE_DIR/src/libANGLE/renderer/BufferImpl.h \ + $$ANGLE_DIR/src/libANGLE/renderer/CompilerImpl.h \ + $$ANGLE_DIR/src/libANGLE/renderer/DisplayImpl.h \ + $$ANGLE_DIR/src/libANGLE/renderer/FenceNVImpl.h \ + $$ANGLE_DIR/src/libANGLE/renderer/FenceSyncImpl.h \ + $$ANGLE_DIR/src/libANGLE/renderer/FramebufferImpl.h \ + $$ANGLE_DIR/src/libANGLE/renderer/Image.h \ + $$ANGLE_DIR/src/libANGLE/renderer/ImplFactory.h \ + $$ANGLE_DIR/src/libANGLE/renderer/IndexRangeCache.h \ + $$ANGLE_DIR/src/libANGLE/renderer/ProgramImpl.h \ + $$ANGLE_DIR/src/libANGLE/renderer/QueryImpl.h \ + $$ANGLE_DIR/src/libANGLE/renderer/RenderbufferImpl.h \ + $$ANGLE_DIR/src/libANGLE/renderer/Renderer.h \ + $$ANGLE_DIR/src/libANGLE/renderer/ShaderImpl.h \ + $$ANGLE_DIR/src/libANGLE/renderer/SurfaceImpl.h \ + $$ANGLE_DIR/src/libANGLE/renderer/TextureImpl.h \ + $$ANGLE_DIR/src/libANGLE/renderer/TransformFeedbackImpl.h \ + $$ANGLE_DIR/src/libANGLE/renderer/VertexArrayImpl.h \ + $$ANGLE_DIR/src/libANGLE/renderer/Workarounds.h \ + $$ANGLE_DIR/src/libANGLE/resource.h \ + $$ANGLE_DIR/src/libANGLE/ResourceManager.h \ + $$ANGLE_DIR/src/libANGLE/Sampler.h \ + $$ANGLE_DIR/src/libANGLE/Shader.h \ + $$ANGLE_DIR/src/libANGLE/State.h \ + $$ANGLE_DIR/src/libANGLE/Texture.h \ + $$ANGLE_DIR/src/libANGLE/TransformFeedback.h \ + $$ANGLE_DIR/src/libANGLE/Uniform.h \ + $$ANGLE_DIR/src/libANGLE/validationES2.h \ + $$ANGLE_DIR/src/libANGLE/validationES3.h \ + $$ANGLE_DIR/src/libANGLE/validationES.h \ + $$ANGLE_DIR/src/libANGLE/VertexArray.h \ + $$ANGLE_DIR/src/libANGLE/VertexAttribute.h \ + $$ANGLE_DIR/src/libANGLE/vertexconversion.h \ + $$ANGLE_DIR/src/libGLESv2/entry_points_egl.h \ + $$ANGLE_DIR/src/libGLESv2/entry_points_egl_ext.h \ + $$ANGLE_DIR/src/libGLESv2/entry_points_gles_2_0.h \ + $$ANGLE_DIR/src/libGLESv2/entry_points_gles_2_0_ext.h \ + $$ANGLE_DIR/src/libGLESv2/entry_points_gles_3_0.h \ + $$ANGLE_DIR/src/libGLESv2/entry_points_gles_3_0_ext.h \ + $$ANGLE_DIR/src/libGLESv2/global_state.h \ $$ANGLE_DIR/src/libGLESv2/resource.h \ - $$ANGLE_DIR/src/libGLESv2/ResourceManager.h \ - $$ANGLE_DIR/src/libGLESv2/Sampler.h \ - $$ANGLE_DIR/src/libGLESv2/Shader.h \ - $$ANGLE_DIR/src/libGLESv2/State.h \ - $$ANGLE_DIR/src/libGLESv2/Texture.h \ - $$ANGLE_DIR/src/libGLESv2/TransformFeedback.h \ - $$ANGLE_DIR/src/libGLESv2/Uniform.h \ - $$ANGLE_DIR/src/libGLESv2/validationES.h \ - $$ANGLE_DIR/src/libGLESv2/validationES2.h \ - $$ANGLE_DIR/src/libGLESv2/validationES3.h \ - $$ANGLE_DIR/src/libGLESv2/VertexArray.h \ - $$ANGLE_DIR/src/libGLESv2/VertexAttribute.h \ - $$ANGLE_DIR/src/libGLESv2/vertexconversion.h \ - $$ANGLE_DIR/src/third_party/murmurhash/MurmurHash3.h \ + $$ANGLE_DIR/src/third_party/murmurhash/MurmurHash3.h SOURCES += \ - $$ANGLE_DIR/src/common/blocklayout.cpp \ $$ANGLE_DIR/src/common/mathutil.cpp \ $$ANGLE_DIR/src/common/utilities.cpp \ + $$ANGLE_DIR/src/common/MemoryBuffer.cpp \ + $$ANGLE_DIR/src/common/angleutils.cpp \ + $$ANGLE_DIR/src/common/debug.cpp \ + $$ANGLE_DIR/src/common/event_tracer.cpp \ $$ANGLE_DIR/src/third_party/murmurhash/MurmurHash3.cpp \ - $$ANGLE_DIR/src/libGLESv2/angletypes.cpp \ - $$ANGLE_DIR/src/libGLESv2/Buffer.cpp \ - $$ANGLE_DIR/src/libGLESv2/Caps.cpp \ - $$ANGLE_DIR/src/libGLESv2/Context.cpp \ - $$ANGLE_DIR/src/libGLESv2/Data.cpp \ - $$ANGLE_DIR/src/libGLESv2/Error.cpp \ - $$ANGLE_DIR/src/libGLESv2/Fence.cpp \ - $$ANGLE_DIR/src/libGLESv2/Float16ToFloat32.cpp \ - $$ANGLE_DIR/src/libGLESv2/Framebuffer.cpp \ - $$ANGLE_DIR/src/libGLESv2/FramebufferAttachment.cpp \ - $$ANGLE_DIR/src/libGLESv2/formatutils.cpp \ - $$ANGLE_DIR/src/libGLESv2/HandleAllocator.cpp \ - $$ANGLE_DIR/src/libGLESv2/ImageIndex.cpp \ - $$ANGLE_DIR/src/libGLESv2/libGLESv2.cpp \ - $$ANGLE_DIR/src/libGLESv2/main.cpp \ - $$ANGLE_DIR/src/libGLESv2/Program.cpp \ - $$ANGLE_DIR/src/libGLESv2/ProgramBinary.cpp \ - $$ANGLE_DIR/src/libGLESv2/Query.cpp \ - $$ANGLE_DIR/src/libGLESv2/queryconversions.cpp \ - $$ANGLE_DIR/src/libGLESv2/Renderbuffer.cpp \ - $$ANGLE_DIR/src/libGLESv2/ResourceManager.cpp \ - $$ANGLE_DIR/src/libGLESv2/Sampler.cpp \ - $$ANGLE_DIR/src/libGLESv2/Shader.cpp \ - $$ANGLE_DIR/src/libGLESv2/State.cpp \ - $$ANGLE_DIR/src/libGLESv2/Texture.cpp \ - $$ANGLE_DIR/src/libGLESv2/TransformFeedback.cpp \ - $$ANGLE_DIR/src/libGLESv2/Uniform.cpp \ - $$ANGLE_DIR/src/libGLESv2/validationES.cpp \ - $$ANGLE_DIR/src/libGLESv2/validationES2.cpp \ - $$ANGLE_DIR/src/libGLESv2/validationES3.cpp \ - $$ANGLE_DIR/src/libGLESv2/VertexArray.cpp \ - $$ANGLE_DIR/src/libGLESv2/VertexAttribute.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/copyimage.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/loadimage.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/Image.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/IndexRangeCache.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/ProgramImpl.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/RenderbufferImpl.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/Renderer.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/RenderTarget.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/BufferD3D.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/DynamicHLSL.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/ImageD3D.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/IndexBuffer.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/IndexDataManager.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/MemoryBuffer.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/ProgramD3D.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/RenderbufferD3D.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/RendererD3D.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/ShaderD3D.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/TextureD3D.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/TextureStorage.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/TransformFeedbackD3D.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/VertexBuffer.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/VertexDataManager.cpp + $$ANGLE_DIR/src/libANGLE/angletypes.cpp \ + $$ANGLE_DIR/src/libANGLE/AttributeMap.cpp \ + $$ANGLE_DIR/src/libANGLE/Buffer.cpp \ + $$ANGLE_DIR/src/libANGLE/Caps.cpp \ + $$ANGLE_DIR/src/libANGLE/Compiler.cpp \ + $$ANGLE_DIR/src/libANGLE/Config.cpp \ + $$ANGLE_DIR/src/libANGLE/Context.cpp \ + $$ANGLE_DIR/src/libANGLE/Data.cpp \ + $$ANGLE_DIR/src/libANGLE/Display.cpp \ + $$ANGLE_DIR/src/libANGLE/Error.cpp \ + $$ANGLE_DIR/src/libANGLE/Fence.cpp \ + $$ANGLE_DIR/src/libANGLE/Float16ToFloat32.cpp \ + $$ANGLE_DIR/src/libANGLE/formatutils.cpp \ + $$ANGLE_DIR/src/libANGLE/Framebuffer.cpp \ + $$ANGLE_DIR/src/libANGLE/FramebufferAttachment.cpp \ + $$ANGLE_DIR/src/libANGLE/HandleAllocator.cpp \ + $$ANGLE_DIR/src/libANGLE/ImageIndex.cpp \ + $$ANGLE_DIR/src/libANGLE/Platform.cpp \ + $$ANGLE_DIR/src/libANGLE/Program.cpp \ + $$ANGLE_DIR/src/libANGLE/Query.cpp \ + $$ANGLE_DIR/src/libANGLE/queryconversions.cpp \ + $$ANGLE_DIR/src/libANGLE/RefCountObject.cpp \ + $$ANGLE_DIR/src/libANGLE/Renderbuffer.cpp \ + $$ANGLE_DIR/src/libANGLE/ResourceManager.cpp \ + $$ANGLE_DIR/src/libANGLE/Sampler.cpp \ + $$ANGLE_DIR/src/libANGLE/Shader.cpp \ + $$ANGLE_DIR/src/libANGLE/State.cpp \ + $$ANGLE_DIR/src/libANGLE/Surface.cpp \ + $$ANGLE_DIR/src/libANGLE/Texture.cpp \ + $$ANGLE_DIR/src/libANGLE/TransformFeedback.cpp \ + $$ANGLE_DIR/src/libANGLE/Uniform.cpp \ + $$ANGLE_DIR/src/libANGLE/validationEGL.cpp \ + $$ANGLE_DIR/src/libANGLE/validationES.cpp \ + $$ANGLE_DIR/src/libANGLE/validationES2.cpp \ + $$ANGLE_DIR/src/libANGLE/validationES3.cpp \ + $$ANGLE_DIR/src/libANGLE/VertexArray.cpp \ + $$ANGLE_DIR/src/libANGLE/VertexAttribute.cpp \ + $$ANGLE_DIR/src/libANGLE/renderer/DisplayImpl.cpp \ + $$ANGLE_DIR/src/libANGLE/renderer/IndexRangeCache.cpp \ + $$ANGLE_DIR/src/libANGLE/renderer/ProgramImpl.cpp \ + $$ANGLE_DIR/src/libANGLE/renderer/RenderbufferImpl.cpp \ + $$ANGLE_DIR/src/libANGLE/renderer/Renderer.cpp \ + $$ANGLE_DIR/src/libANGLE/renderer/SurfaceImpl.cpp \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/BufferD3D.cpp \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/CompilerD3D.cpp \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/copyimage.cpp \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/DisplayD3D.cpp \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/DynamicHLSL.cpp \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/formatutilsD3D.cpp \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/FramebufferD3D.cpp \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/HLSLCompiler.cpp \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/ImageD3D.cpp \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/IndexBuffer.cpp \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/IndexDataManager.cpp \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/loadimage.cpp \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/loadimageSSE2.cpp \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/ProgramD3D.cpp \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/RenderbufferD3D.cpp \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/RendererD3D.cpp \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/RenderTargetD3D.cpp \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/ShaderD3D.cpp \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/ShaderExecutableD3D.cpp \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/SurfaceD3D.cpp \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/TextureD3D.cpp \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/TextureStorage.cpp \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/TransformFeedbackD3D.cpp \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/VertexBuffer.cpp \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/VertexDataManager.cpp \ + $$ANGLE_DIR/src/libGLESv2/entry_points_egl.cpp \ + $$ANGLE_DIR/src/libGLESv2/entry_points_egl_ext.cpp \ + $$ANGLE_DIR/src/libGLESv2/entry_points_gles_2_0.cpp \ + $$ANGLE_DIR/src/libGLESv2/entry_points_gles_2_0_ext.cpp \ + $$ANGLE_DIR/src/libGLESv2/entry_points_gles_3_0.cpp \ + $$ANGLE_DIR/src/libGLESv2/entry_points_gles_3_0_ext.cpp \ + $$ANGLE_DIR/src/libGLESv2/global_state.cpp \ + $$ANGLE_DIR/src/libGLESv2/libGLESv2.cpp + angle_d3d11 { HEADERS += \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/Blit11.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/Buffer11.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/Clear11.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/Fence11.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/formatutils11.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/Image11.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/IndexBuffer11.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/Query11.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/RenderStateCache.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/ShaderExecutable11.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.h + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/Blit11.h \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/Buffer11.h \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/Clear11.h \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/Fence11.h \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.h \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/formatutils11.h \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/Image11.h \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.h \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.h \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.h \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/Query11.h \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/Renderer11.h \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.h \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.h \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.h \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.h \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/Trim11.h \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.h SOURCES += \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/Buffer11.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/Fence11.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/formatutils11.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/Image11.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/IndexBuffer11.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/Query11.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/RenderStateCache.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/ShaderExecutable11.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.cpp + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/Blit11.cpp \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/Fence11.cpp \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/formatutils11.cpp \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/Image11.cpp \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.cpp \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.cpp \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.cpp \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/Query11.cpp \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.cpp \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.cpp \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.cpp \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/Trim11.cpp \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.cpp } -SSE2_SOURCES += $$ANGLE_DIR/src/libGLESv2/renderer/loadimageSSE2.cpp - !winrt { HEADERS += \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d9/Blit9.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d9/Buffer9.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d9/Fence9.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d9/formatutils9.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d9/Image9.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d9/IndexBuffer9.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d9/Query9.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d9/Renderer9.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d9/RenderTarget9.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d9/ShaderExecutable9.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.h \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d9/VertexBuffer9.h \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/Blit9.h \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/Buffer9.h \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/DebugAnnotator9.h \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/Fence9.h \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.h \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/formatutils9.h \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/Image9.h \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.h \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/Query9.h \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/Renderer9.h \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.h \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.h \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.h \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/SwapChain9.h \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.h \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.h \ $$ANGLE_DIR/src/third_party/systeminfo/SystemInfo.h SOURCES += \ - $$ANGLE_DIR/src/common/win32/NativeWindow.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d9/Blit9.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d9/Buffer9.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d9/Fence9.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d9/formatutils9.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d9/Image9.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d9/IndexBuffer9.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d9/Query9.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d9/RenderTarget9.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d9/ShaderExecutable9.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d9/VertexBuffer9.cpp \ - $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d9/VertexDeclarationCache.cpp \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/Blit9.cpp \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/Buffer9.cpp \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/DebugAnnotator9.cpp \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/Fence9.cpp \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/formatutils9.cpp \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/Image9.cpp \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.cpp \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/Query9.cpp \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.cpp \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.cpp \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.cpp \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/SwapChain9.cpp \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.cpp \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.cpp \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.cpp \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow.cpp \ $$ANGLE_DIR/src/third_party/systeminfo/SystemInfo.cpp } else { HEADERS += \ - $$ANGLE_DIR/src/common/winrt/CoreWindowNativeWindow.h \ - $$ANGLE_DIR/src/common/winrt/InspectableNativeWindow.h \ - $$ANGLE_DIR/src/common/winrt/SwapChainPanelNativeWindow.h + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.h SOURCES += \ - $$ANGLE_DIR/src/common/winrt/CoreWindowNativeWindow.cpp \ - $$ANGLE_DIR/src/common/winrt/InspectableNativeWindow.cpp \ - $$ANGLE_DIR/src/common/winrt/SwapChainPanelNativeWindow.cpp + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.cpp \ + $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.cpp } !static { @@ -259,87 +332,234 @@ SSE2_SOURCES += $$ANGLE_DIR/src/libGLESv2/renderer/loadimageSSE2.cpp } float_converter.target = float_converter -float_converter.commands = python $$ANGLE_DIR/src/libGLESv2/Float16ToFloat32.py \ - > $$ANGLE_DIR/src/libGLESv2/Float16ToFloat32.cpp +float_converter.commands = python $$ANGLE_DIR/src/libANGLE/Float16ToFloat32.py \ + > $$ANGLE_DIR/src/libANGLE/Float16ToFloat32.cpp QMAKE_EXTRA_TARGETS += float_converter -# Generate the shader header files. -SHADER9_INPUT_DIR = $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d9/shaders -SHADER11_INPUT_DIR = $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/shaders +# HLSL shaders +BLITVS = $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/shaders/Blit.vs +standardvs.input = BLITVS +standardvs.type = vs_2_0 +standardvs.output = standardvs.h +flipyvs.input = BLITVS +flipyvs.type = vs_2_0 +flipyvs.output = flipyvs.h + +BLITPS = $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/shaders/Blit.ps +passthroughps.input = BLITPS +passthroughps.type = ps_2_0 +passthroughps.output = passthroughps.h +luminanceps.input = BLITPS +luminanceps.type = ps_2_0 +luminanceps.output = luminanceps.h +componentmaskps.input = BLITPS +componentmaskps.type = ps_2_0 +componentmaskps.output = componentmaskps.h -BLITPS_INPUT = $$SHADER9_INPUT_DIR/Blit.ps -BLITPS.shaders = PS_passthrough PS_luminance PS_componentmask -BLITPS.profile = 2_0 +PASSTHROUGH2D = $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/shaders/Passthrough2D11.hlsl +VS_Passthrough2D.input = PASSTHROUGH2D +VS_Passthrough2D.type = vs_4_0_level_9_3 +VS_Passthrough2D.output = passthrough2d11vs.h +PS_PassthroughRGBA2D.input = PASSTHROUGH2D +PS_PassthroughRGBA2D.type = ps_4_0_level_9_3 +PS_PassthroughRGBA2D.output = passthroughrgba2d11ps.h +PS_PassthroughRGB2D.input = PASSTHROUGH2D +PS_PassthroughRGB2D.type = ps_4_0_level_9_3 +PS_PassthroughRGB2D.output = passthroughrgb2d11ps.h +PS_PassthroughRG2D.input = PASSTHROUGH2D +PS_PassthroughRG2D.type = ps_4_0_level_9_3 +PS_PassthroughRG2D.output = passthroughrg2d11ps.h +PS_PassthroughR2D.input = PASSTHROUGH2D +PS_PassthroughR2D.type = ps_4_0_level_9_3 +PS_PassthroughR2D.output = passthroughr2d11ps.h +PS_PassthroughLum2D.input = PASSTHROUGH2D +PS_PassthroughLum2D.type = ps_4_0_level_9_3 +PS_PassthroughLum2D.output = passthroughlum2d11ps.h +PS_PassthroughLumAlpha2D.input = PASSTHROUGH2D +PS_PassthroughLumAlpha2D.type = ps_4_0_level_9_3 +PS_PassthroughLumAlpha2D.output = passthroughlumalpha2d11ps.h +PS_PassthroughDepth2D.input = PASSTHROUGH2D +PS_PassthroughDepth2D.type = ps_4_0 +PS_PassthroughDepth2D.output = passthroughdepth2d11ps.h +PS_PassthroughRGBA2DUI.input = PASSTHROUGH2D +PS_PassthroughRGBA2DUI.type = ps_4_0 +PS_PassthroughRGBA2DUI.output = passthroughrgba2dui11ps.h +PS_PassthroughRGBA2DI.input = PASSTHROUGH2D +PS_PassthroughRGBA2DI.type = ps_4_0 +PS_PassthroughRGBA2DI.output = passthroughrgba2di11ps.h +PS_PassthroughRGB2DUI.input = PASSTHROUGH2D +PS_PassthroughRGB2DUI.type = ps_4_0 +PS_PassthroughRGB2DUI.output = passthroughrgb2dui11ps.h +PS_PassthroughRGB2DI.input = PASSTHROUGH2D +PS_PassthroughRGB2DI.type = ps_4_0 +PS_PassthroughRGB2DI.output = passthroughrgb2di11ps.h +PS_PassthroughRG2DUI.input = PASSTHROUGH2D +PS_PassthroughRG2DUI.type = ps_4_0 +PS_PassthroughRG2DUI.output = passthroughrg2dui11ps.h +PS_PassthroughRG2DI.input = PASSTHROUGH2D +PS_PassthroughRG2DI.type = ps_4_0 +PS_PassthroughRG2DI.output = passthroughrg2di11ps.h +PS_PassthroughR2DUI.input = PASSTHROUGH2D +PS_PassthroughR2DUI.type = ps_4_0 +PS_PassthroughR2DUI.output = passthroughr2dui11ps.h +PS_PassthroughR2DI.input = PASSTHROUGH2D +PS_PassthroughR2DI.type = ps_4_0 +PS_PassthroughR2DI.output = passthroughr2di11ps.h -BLITVS_INPUT = $$SHADER9_INPUT_DIR/Blit.vs -BLITVS.shaders = VS_standard VS_flipy -BLITVS.profile = 2_0 +CLEAR = $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/shaders/Clear11.hlsl +VS_ClearFloat.input = CLEAR +VS_ClearFloat.type = vs_4_0_level_9_3 +VS_ClearFloat.output = clearfloat11vs.h +PS_ClearFloat_FL9.input = CLEAR +PS_ClearFloat_FL9.type = ps_4_0_level_9_3 +PS_ClearFloat_FL9.output = clearfloat11_fl9ps.h +PS_ClearFloat.input = CLEAR +PS_ClearFloat.type = ps_4_0 +PS_ClearFloat.output = clearfloat11ps.h +VS_ClearUint.input = CLEAR +VS_ClearUint.type = vs_4_0 +VS_ClearUint.output = clearuint11vs.h +PS_ClearUint.input = CLEAR +PS_ClearUint.type = ps_4_0 +PS_ClearUint.output = clearuint11ps.h +VS_ClearSint.input = CLEAR +VS_ClearSint.type = vs_4_0 +VS_ClearSint.output = clearsint11vs.h +PS_ClearSint.input = CLEAR +PS_ClearSint.type = ps_4_0 +PS_ClearSint.output = clearsint11ps.h -BUFFERTOTEXTURE_INPUT = $$SHADER11_INPUT_DIR/BufferToTexture11.hlsl -BUFFERTOTEXTURE.shaders = \ - PS_BufferToTexture_4F PS_BufferToTexture_4I PS_BufferToTexture_4UI \ - VS_BufferToTexture GS_BufferToTexture -BUFFERTOTEXTURE.profile = 4_0 +PASSTHROUGH3D = $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/shaders/Passthrough3D11.hlsl +VS_Passthrough3D.input = PASSTHROUGH3D +VS_Passthrough3D.type = vs_4_0 +VS_Passthrough3D.output = passthrough3d11vs.h +GS_Passthrough3D.input = PASSTHROUGH3D +GS_Passthrough3D.type = gs_4_0 +GS_Passthrough3D.output = passthrough3d11gs.h +PS_PassthroughRGBA3D.input = PASSTHROUGH3D +PS_PassthroughRGBA3D.type = ps_4_0 +PS_PassthroughRGBA3D.output = passthroughrgba3d11ps.h +PS_PassthroughRGBA3DUI.input = PASSTHROUGH3D +PS_PassthroughRGBA3DUI.type = ps_4_0 +PS_PassthroughRGBA3DUI.output = passthroughrgba3dui11ps.h +PS_PassthroughRGBA3DI.input = PASSTHROUGH3D +PS_PassthroughRGBA3DI.type = ps_4_0 +PS_PassthroughRGBA3DI.output = passthroughrgba3di11ps.h +PS_PassthroughRGB3D.input = PASSTHROUGH3D +PS_PassthroughRGB3D.type = ps_4_0 +PS_PassthroughRGB3D.output = passthroughrgb3d11ps.h +PS_PassthroughRGB3DUI.input = PASSTHROUGH3D +PS_PassthroughRGB3DUI.type = ps_4_0 +PS_PassthroughRGB3DUI.output = passthroughrgb3dui11ps.h +PS_PassthroughRGB3DI.input = PASSTHROUGH3D +PS_PassthroughRGB3DI.type = ps_4_0 +PS_PassthroughRGB3DI.output = passthroughrgb3di11ps.h +PS_PassthroughRG3D.input = PASSTHROUGH3D +PS_PassthroughRG3D.type = ps_4_0 +PS_PassthroughRG3D.output = passthroughrg3d11ps.h +PS_PassthroughRG3DUI.input = PASSTHROUGH3D +PS_PassthroughRG3DUI.type = ps_4_0 +PS_PassthroughRG3DUI.output = passthroughrg3dui11ps.h +PS_PassthroughRG3DI.input = PASSTHROUGH3D +PS_PassthroughRG3DI.type = ps_4_0 +PS_PassthroughRG3DI.output = passthroughrg3di11ps.h +PS_PassthroughR3D.input = PASSTHROUGH3D +PS_PassthroughR3D.type = ps_4_0 +PS_PassthroughR3D.output = passthroughr3d11ps.h +PS_PassthroughR3DUI.input = PASSTHROUGH3D +PS_PassthroughR3DUI.type = ps_4_0 +PS_PassthroughR3DUI.output = passthroughr3dui11ps.h +PS_PassthroughR3DI.input = PASSTHROUGH3D +PS_PassthroughR3DI.type = ps_4_0 +PS_PassthroughR3DI.output = passthroughr3di11ps.h +PS_PassthroughLum3D.input = PASSTHROUGH3D +PS_PassthroughLum3D.type = ps_4_0 +PS_PassthroughLum3D.output = passthroughlum3d11ps.h +PS_PassthroughLumAlpha3D.input = PASSTHROUGH3D +PS_PassthroughLumAlpha3D.type = ps_4_0 +PS_PassthroughLumAlpha3D.output = passthroughlumalpha3d11ps.h -CLEAR_INPUT = $$SHADER11_INPUT_DIR/Clear11.hlsl -CLEAR.shaders = \ - PS_ClearUint PS_ClearSint \ - VS_ClearUint VS_ClearSint -CLEAR.shaders_compat = PS_ClearFloat VS_ClearFloat -CLEAR.profile = 4_0 +SWIZZLE = $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/shaders/Swizzle11.hlsl +PS_SwizzleF2D.input = SWIZZLE +PS_SwizzleF2D.type = ps_4_0 +PS_SwizzleF2D.output = swizzlef2dps.h +PS_SwizzleI2D.input = SWIZZLE +PS_SwizzleI2D.type = ps_4_0 +PS_SwizzleI2D.output = swizzlei2dps.h +PS_SwizzleUI2D.input = SWIZZLE +PS_SwizzleUI2D.type = ps_4_0 +PS_SwizzleUI2D.output = swizzleui2dps.h +PS_SwizzleF3D.input = SWIZZLE +PS_SwizzleF3D.type = ps_4_0 +PS_SwizzleF3D.output = swizzlef3dps.h +PS_SwizzleI3D.input = SWIZZLE +PS_SwizzleI3D.type = ps_4_0 +PS_SwizzleI3D.output = swizzlei3dps.h +PS_SwizzleUI3D.input = SWIZZLE +PS_SwizzleUI3D.type = ps_4_0 +PS_SwizzleUI3D.output = swizzleui3dps.h +PS_SwizzleF2DArray.input = SWIZZLE +PS_SwizzleF2DArray.type = ps_4_0 +PS_SwizzleF2DArray.output = swizzlef2darrayps.h +PS_SwizzleI2DArray.input = SWIZZLE +PS_SwizzleI2DArray.type = ps_4_0 +PS_SwizzleI2DArray.output = swizzlei2darrayps.h +PS_SwizzleUI2DArray.input = SWIZZLE +PS_SwizzleUI2DArray.type = ps_4_0 +PS_SwizzleUI2DArray.output = swizzleui2darrayps.h -PASSTHROUGH2D_INPUT = $$SHADER11_INPUT_DIR/Passthrough2D11.hlsl -PASSTHROUGH2D.shaders = \ - PS_PassthroughRGBA2DUI PS_PassthroughRGBA2DI \ - PS_PassthroughRGB2DUI PS_PassthroughRGB2DI \ - PS_PassthroughRG2DUI PS_PassthroughRG2DI \ - PS_PassthroughR2DUI PS_PassthroughR2DI \ - PS_PassthroughDepth2D -PASSTHROUGH2D.shaders_compat = \ - PS_PassthroughRGBA2D PS_PassthroughRGB2D \ - PS_PassthroughRG2D PS_PassthroughR2D \ - PS_PassthroughLum2D PS_PassthroughLumAlpha2D \ - VS_Passthrough2D -PASSTHROUGH2D.profile = 4_0 +BUFFERTOTEXTURE = $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/shaders/BufferToTexture11.hlsl +VS_BufferToTexture.input = BUFFERTOTEXTURE +VS_BufferToTexture.type = vs_4_0 +VS_BufferToTexture.output = buffertotexture11_vs.h +GS_BufferToTexture.input = BUFFERTOTEXTURE +GS_BufferToTexture.type = gs_4_0 +GS_BufferToTexture.output = buffertotexture11_gs.h +PS_BufferToTexture_4F.input = BUFFERTOTEXTURE +PS_BufferToTexture_4F.type = ps_4_0 +PS_BufferToTexture_4F.output = buffertotexture11_ps_4f.h +PS_BufferToTexture_4I.input = BUFFERTOTEXTURE +PS_BufferToTexture_4I.type = ps_4_0 +PS_BufferToTexture_4I.output = buffertotexture11_ps_4i.h +PS_BufferToTexture_4UI.input = BUFFERTOTEXTURE +PS_BufferToTexture_4UI.type = ps_4_0 +PS_BufferToTexture_4UI.output = buffertotexture11_ps_4ui.h -PASSTHROUGH3D_INPUT = $$SHADER11_INPUT_DIR/Passthrough3D11.hlsl -PASSTHROUGH3D.shaders = \ +# D3D11 +angle_d3d11: SHADERS = VS_Passthrough2D \ + PS_PassthroughRGB2D PS_PassthroughRGB2DUI PS_PassthroughRGB2DI \ + PS_PassthroughRGBA2D PS_PassthroughRGBA2DUI PS_PassthroughRGBA2DI \ + PS_PassthroughRG2D PS_PassthroughRG2DUI PS_PassthroughRG2DI \ + PS_PassthroughR2D PS_PassthroughR2DUI PS_PassthroughR2DI \ + PS_PassthroughLum2D PS_PassthroughLumAlpha2D PS_PassthroughDepth2D \ + VS_ClearFloat VS_ClearUint VS_ClearSint \ + PS_ClearFloat PS_ClearFloat_FL9 PS_ClearUint PS_ClearSint \ + VS_Passthrough3D GS_Passthrough3D \ PS_PassthroughRGBA3D PS_PassthroughRGBA3DUI PS_PassthroughRGBA3DI \ PS_PassthroughRGB3D PS_PassthroughRGB3DUI PS_PassthroughRGB3DI \ PS_PassthroughRG3D PS_PassthroughRG3DUI PS_PassthroughRG3DI \ PS_PassthroughR3D PS_PassthroughR3DUI PS_PassthroughR3DI \ PS_PassthroughLum3D PS_PassthroughLumAlpha3D \ - VS_Passthrough3D GS_Passthrough3D -PASSTHROUGH3D.profile = 4_0 - -SWIZZLE_INPUT = $$SHADER11_INPUT_DIR/Swizzle11.hlsl -SWIZZLE.shaders = \ - PS_SwizzleI2D PS_SwizzleUI2D \ + PS_SwizzleF2D PS_SwizzleI2D PS_SwizzleUI2D \ PS_SwizzleF3D PS_SwizzleI3D PS_SwizzleUI3D \ - PS_SwizzleF2DArray PS_SwizzleI2DArray PS_SwizzleUI2DArray -SWIZZLE.shaders_compat = PS_SwizzleF2D -SWIZZLE.profile = 4_0 + PS_SwizzleF2DArray PS_SwizzleI2DArray PS_SwizzleUI2DArray \ + VS_BufferToTexture GS_BufferToTexture \ + PS_BufferToTexture_4F PS_BufferToTexture_4I PS_BufferToTexture_4UI -angle_d3d11: FXC_JOBS = BUFFERTOTEXTURE CLEAR PASSTHROUGH2D PASSTHROUGH3D SWIZZLE -!winrt: FXC_JOBS += BLITPS BLITVS +# D3D9 +!winrt: SHADERS += standardvs flipyvs passthroughps luminanceps componentmaskps -for (JOB, FXC_JOBS) { - INPUT = $${JOB}_INPUT - OUT_DIR = $$OUT_PWD/$$relative_path($$dirname($$INPUT), $$ANGLE_DIR/src/libGLESv2)/compiled - SHADERS_COMPAT = $$eval($${JOB}.shaders_compat) - SHADERS = $$eval($${JOB}.shaders) $$SHADERS_COMPAT - for(SHADER, SHADERS) { - TYPE = $$lower($$section(SHADER, _, 0, 0)) - PROFILE = $${TYPE}_$$eval($${JOB}.profile) - contains(SHADERS_COMPAT, $$SHADER): PROFILE = $${PROFILE}_level_9_1 - fxc_$${SHADER}_$${PROFILE}.commands = $$FXC /nologo /E $${SHADER} /T $${PROFILE} /Fh ${QMAKE_FILE_OUT} ${QMAKE_FILE_NAME} - fxc_$${SHADER}_$${PROFILE}.output = $$OUT_DIR/$$section(SHADER, _, 1)$${TYPE}.h - fxc_$${SHADER}_$${PROFILE}.input = $$INPUT - fxc_$${SHADER}_$${PROFILE}.dependency_type = TYPE_C - fxc_$${SHADER}_$${PROFILE}.variable_out = HEADERS - fxc_$${SHADER}_$${PROFILE}.CONFIG += target_predeps - QMAKE_EXTRA_COMPILERS += fxc_$${SHADER}_$${PROFILE} - } +# Generate headers +for (SHADER, SHADERS) { + INPUT = $$eval($${SHADER}.input) + OUT_DIR = $$OUT_PWD/libANGLE/$$relative_path($$dirname($$INPUT), $$ANGLE_DIR/src/libANGLE)/compiled + fxc_$${SHADER}.commands = $$FXC /nologo /E $${SHADER} /T $$eval($${SHADER}.type) /Fh ${QMAKE_FILE_OUT} ${QMAKE_FILE_NAME} + fxc_$${SHADER}.output = $$OUT_DIR/$$eval($${SHADER}.output) + fxc_$${SHADER}.input = $$INPUT + fxc_$${SHADER}.dependency_type = TYPE_C + fxc_$${SHADER}.variable_out = HEADERS + fxc_$${SHADER}.CONFIG += target_predeps + QMAKE_EXTRA_COMPILERS += fxc_$${SHADER} } khr_headers.files = $$ANGLE_DIR/include/KHR/khrplatform.h -- cgit v1.2.3